diff -druNp --no-dereference linux-libre-3.4.86-gnu1/arch/arm/boot/compressed/head.S linux-libre-3.4.87-gnu1/arch/arm/boot/compressed/head.S
--- linux-libre-3.4.86-gnu1/arch/arm/boot/compressed/head.S	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/arch/arm/boot/compressed/head.S	2014-04-14 09:45:17.000000000 -0400
@@ -10,6 +10,7 @@
  */
 #include <linux/linkage.h>
 
+	.arch	armv7-a
 /*
  * Debugging stuff
  *
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/arch/arm/boot/compressed/head-sa1100.S linux-libre-3.4.87-gnu1/arch/arm/boot/compressed/head-sa1100.S
--- linux-libre-3.4.86-gnu1/arch/arm/boot/compressed/head-sa1100.S	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/arch/arm/boot/compressed/head-sa1100.S	2014-04-14 09:45:17.000000000 -0400
@@ -11,6 +11,7 @@
 #include <asm/mach-types.h>
 
 		.section        ".start", "ax"
+		.arch	armv4
 
 __SA1100_start:
 
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/arch/arm/boot/compressed/head-shark.S linux-libre-3.4.87-gnu1/arch/arm/boot/compressed/head-shark.S
--- linux-libre-3.4.86-gnu1/arch/arm/boot/compressed/head-shark.S	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/arch/arm/boot/compressed/head-shark.S	2014-04-14 09:45:17.000000000 -0400
@@ -18,6 +18,7 @@
 	
 		.section	".start", "ax"
 
+		.arch armv4
 		b	__beginning
 	
 __ofw_data:	.long	0				@ the number of memory blocks
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/arch/arm/boot/compressed/Makefile linux-libre-3.4.87-gnu1/arch/arm/boot/compressed/Makefile
--- linux-libre-3.4.86-gnu1/arch/arm/boot/compressed/Makefile	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/arch/arm/boot/compressed/Makefile	2014-04-14 09:45:17.000000000 -0400
@@ -126,7 +126,6 @@ KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CF
 endif
 
 ccflags-y := -fpic -fno-builtin -I$(obj)
-asflags-y := -Wa,-march=all
 
 # Supply kernel BSS size to the decompressor via a linker symbol.
 KBSS_SZ = $(shell $(CROSS_COMPILE)size $(obj)/../../../../vmlinux | \
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/arch/arm/boot/dts/imx51-babbage.dts linux-libre-3.4.87-gnu1/arch/arm/boot/dts/imx51-babbage.dts
--- linux-libre-3.4.86-gnu1/arch/arm/boot/dts/imx51-babbage.dts	2014-04-04 04:40:44.000000000 -0400
+++ linux-libre-3.4.87-gnu1/arch/arm/boot/dts/imx51-babbage.dts	2014-04-14 14:21:23.000000000 -0400
@@ -29,8 +29,8 @@
 		aips@70000000 { /* aips-1 */
 			spba@70000000 {
 				esdhc@70004000 { /* ESDHC1 */
-					fsl,cd-internal;
-					fsl,wp-internal;
+					fsl,cd-controller;
+					fsl,wp-controller;
 					status = "okay";
 				};
 
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/arch/arm/include/asm/a.out-core.h linux-libre-3.4.87-gnu1/arch/arm/include/asm/a.out-core.h
--- linux-libre-3.4.86-gnu1/arch/arm/include/asm/a.out-core.h	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/arch/arm/include/asm/a.out-core.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,45 +0,0 @@
-/* a.out coredump register dumper
- *
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
- */
-
-#ifndef _ASM_A_OUT_CORE_H
-#define _ASM_A_OUT_CORE_H
-
-#ifdef __KERNEL__
-
-#include <linux/user.h>
-#include <linux/elfcore.h>
-
-/*
- * fill in the user structure for an a.out core dump
- */
-static inline void aout_dump_thread(struct pt_regs *regs, struct user *dump)
-{
-	struct task_struct *tsk = current;
-
-	dump->magic = CMAGIC;
-	dump->start_code = tsk->mm->start_code;
-	dump->start_stack = regs->ARM_sp & ~(PAGE_SIZE - 1);
-
-	dump->u_tsize = (tsk->mm->end_code - tsk->mm->start_code) >> PAGE_SHIFT;
-	dump->u_dsize = (tsk->mm->brk - tsk->mm->start_data + PAGE_SIZE - 1) >> PAGE_SHIFT;
-	dump->u_ssize = 0;
-
-	memset(dump->u_debugreg, 0, sizeof(dump->u_debugreg));
-
-	if (dump->start_stack < 0x04000000)
-		dump->u_ssize = (0x04000000 - dump->start_stack) >> PAGE_SHIFT;
-
-	dump->regs = *regs;
-	dump->u_fpvalid = dump_fpu (regs, &dump->u_fp);
-}
-
-#endif /* __KERNEL__ */
-#endif /* _ASM_A_OUT_CORE_H */
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/arch/arm/include/asm/a.out.h linux-libre-3.4.87-gnu1/arch/arm/include/asm/a.out.h
--- linux-libre-3.4.86-gnu1/arch/arm/include/asm/a.out.h	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/arch/arm/include/asm/a.out.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,34 +0,0 @@
-#ifndef __ARM_A_OUT_H__
-#define __ARM_A_OUT_H__
-
-#include <linux/personality.h>
-#include <linux/types.h>
-
-struct exec
-{
-  __u32 a_info;		/* Use macros N_MAGIC, etc for access */
-  __u32 a_text;		/* length of text, in bytes */
-  __u32 a_data;		/* length of data, in bytes */
-  __u32 a_bss;		/* length of uninitialized data area for file, in bytes */
-  __u32 a_syms;		/* length of symbol table data in file, in bytes */
-  __u32 a_entry;	/* start address */
-  __u32 a_trsize;	/* length of relocation info for text, in bytes */
-  __u32 a_drsize;	/* length of relocation info for data, in bytes */
-};
-
-/*
- * This is always the same
- */
-#define N_TXTADDR(a)	(0x00008000)
-
-#define N_TRSIZE(a)	((a).a_trsize)
-#define N_DRSIZE(a)	((a).a_drsize)
-#define N_SYMSIZE(a)	((a).a_syms)
-
-#define M_ARM 103
-
-#ifndef LIBRARY_START_TEXT
-#define LIBRARY_START_TEXT	(0x00c00000)
-#endif
-
-#endif /* __A_OUT_GNU_H__ */
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/arch/arm/include/asm/processor.h linux-libre-3.4.87-gnu1/arch/arm/include/asm/processor.h
--- linux-libre-3.4.86-gnu1/arch/arm/include/asm/processor.h	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/arch/arm/include/asm/processor.h	2014-04-14 09:45:17.000000000 -0400
@@ -54,7 +54,6 @@ struct thread_struct {
 
 #define start_thread(regs,pc,sp)					\
 ({									\
-	unsigned long *stack = (unsigned long *)sp;			\
 	memset(regs->uregs, 0, sizeof(regs->uregs));			\
 	if (current->personality & ADDR_LIMIT_32BIT)			\
 		regs->ARM_cpsr = USR_MODE;				\
@@ -65,9 +64,6 @@ struct thread_struct {
 	regs->ARM_cpsr |= PSR_ENDSTATE;					\
 	regs->ARM_pc = pc & ~1;		/* pc */			\
 	regs->ARM_sp = sp;		/* sp */			\
-	regs->ARM_r2 = stack[2];	/* r2 (envp) */			\
-	regs->ARM_r1 = stack[1];	/* r1 (argv) */			\
-	regs->ARM_r0 = stack[0];	/* r0 (argc) */			\
 	nommu_start_thread(regs);					\
 })
 
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/arch/arm/Kconfig linux-libre-3.4.87-gnu1/arch/arm/Kconfig
--- linux-libre-3.4.86-gnu1/arch/arm/Kconfig	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/arch/arm/Kconfig	2014-04-14 09:45:17.000000000 -0400
@@ -1,7 +1,6 @@
 config ARM
 	bool
 	default y
-	select HAVE_AOUT
 	select HAVE_DMA_API_DEBUG
 	select HAVE_IDE if PCI || ISA || PCMCIA
 	select HAVE_MEMBLOCK
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/arch/arm/kernel/head.S linux-libre-3.4.87-gnu1/arch/arm/kernel/head.S
--- linux-libre-3.4.86-gnu1/arch/arm/kernel/head.S	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/arch/arm/kernel/head.S	2014-04-14 09:45:17.000000000 -0400
@@ -254,6 +254,7 @@ __create_page_tables:
 	/*
 	 * Then map boot params address in r2 or the first 1MB (2MB with LPAE)
 	 * of ram if boot params address is not specified.
+	 * We map 2 sections in case the ATAGs/DTB crosses a section boundary.
 	 */
 	mov	r0, r2, lsr #SECTION_SHIFT
 	movs	r0, r0, lsl #SECTION_SHIFT
@@ -262,6 +263,8 @@ __create_page_tables:
 	add	r3, r3, #PAGE_OFFSET
 	add	r3, r4, r3, lsr #(SECTION_SHIFT - PMD_ORDER)
 	orr	r6, r7, r0
+	str	r6, [r3], #1 << PMD_ORDER
+	add	r6, r6, #1 << SECTION_SHIFT
 	str	r6, [r3]
 
 #ifdef CONFIG_DEBUG_LL
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/arch/arm/kernel/topology.c linux-libre-3.4.87-gnu1/arch/arm/kernel/topology.c
--- linux-libre-3.4.86-gnu1/arch/arm/kernel/topology.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/arch/arm/kernel/topology.c	2014-04-14 09:45:17.000000000 -0400
@@ -13,6 +13,7 @@
 
 #include <linux/cpu.h>
 #include <linux/cpumask.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/percpu.h>
 #include <linux/node.h>
@@ -42,6 +43,7 @@
 #define MPIDR_LEVEL2_SHIFT 16
 
 struct cputopo_arm cpu_topology[NR_CPUS];
+EXPORT_SYMBOL_GPL(cpu_topology);
 
 const struct cpumask *cpu_coregroup_mask(int cpu)
 {
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/arch/arm/mach-dove/common.c linux-libre-3.4.87-gnu1/arch/arm/mach-dove/common.c
--- linux-libre-3.4.86-gnu1/arch/arm/mach-dove/common.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/arch/arm/mach-dove/common.c	2014-04-14 09:45:17.000000000 -0400
@@ -90,7 +90,7 @@ void __init dove_ge00_init(struct mv643x
 {
 	orion_ge00_init(eth_data,
 			DOVE_GE00_PHYS_BASE, IRQ_DOVE_GE00_SUM,
-			0, get_tclk());
+			0, get_tclk(), 1600);
 }
 
 /*****************************************************************************
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/arch/arm/mach-footbridge/common.c linux-libre-3.4.87-gnu1/arch/arm/mach-footbridge/common.c
--- linux-libre-3.4.86-gnu1/arch/arm/mach-footbridge/common.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/arch/arm/mach-footbridge/common.c	2014-04-14 09:45:17.000000000 -0400
@@ -15,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/spinlock.h>
+#include <video/vga.h>
  
 #include <asm/pgtable.h>
 #include <asm/page.h>
@@ -198,6 +199,8 @@ void __init footbridge_map_io(void)
 	 */
 	if (footbridge_cfn_mode())
 		iotable_init(ebsa285_host_io_desc, ARRAY_SIZE(ebsa285_host_io_desc));
+
+	vga_base = PCIMEM_BASE;
 }
 
 void footbridge_restart(char mode, const char *cmd)
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/arch/arm/mach-footbridge/dc21285.c linux-libre-3.4.87-gnu1/arch/arm/mach-footbridge/dc21285.c
--- linux-libre-3.4.86-gnu1/arch/arm/mach-footbridge/dc21285.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/arch/arm/mach-footbridge/dc21285.c	2014-04-14 09:45:17.000000000 -0400
@@ -18,7 +18,6 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/spinlock.h>
-#include <video/vga.h>
 
 #include <asm/irq.h>
 #include <asm/mach/pci.h>
@@ -298,7 +297,6 @@ void __init dc21285_preinit(void)
 	int cfn_mode;
 
 	pcibios_min_mem = 0x81000000;
-	vga_base = PCIMEM_BASE;
 
 	mem_size = (unsigned int)high_memory - PAGE_OFFSET;
 	for (mem_mask = 0x00100000; mem_mask < 0x10000000; mem_mask <<= 1)
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/arch/arm/mach-kirkwood/common.c linux-libre-3.4.87-gnu1/arch/arm/mach-kirkwood/common.c
--- linux-libre-3.4.86-gnu1/arch/arm/mach-kirkwood/common.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/arch/arm/mach-kirkwood/common.c	2014-04-14 09:45:17.000000000 -0400
@@ -87,7 +87,7 @@ void __init kirkwood_ge00_init(struct mv
 
 	orion_ge00_init(eth_data,
 			GE00_PHYS_BASE, IRQ_KIRKWOOD_GE00_SUM,
-			IRQ_KIRKWOOD_GE00_ERR, kirkwood_tclk);
+			IRQ_KIRKWOOD_GE00_ERR, kirkwood_tclk, 1600);
 }
 
 
@@ -101,7 +101,7 @@ void __init kirkwood_ge01_init(struct mv
 
 	orion_ge01_init(eth_data,
 			GE01_PHYS_BASE, IRQ_KIRKWOOD_GE01_SUM,
-			IRQ_KIRKWOOD_GE01_ERR, kirkwood_tclk);
+			IRQ_KIRKWOOD_GE01_ERR, kirkwood_tclk, 1600);
 }
 
 
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/arch/arm/mach-mv78xx0/common.c linux-libre-3.4.87-gnu1/arch/arm/mach-mv78xx0/common.c
--- linux-libre-3.4.86-gnu1/arch/arm/mach-mv78xx0/common.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/arch/arm/mach-mv78xx0/common.c	2014-04-14 09:45:17.000000000 -0400
@@ -199,7 +199,8 @@ void __init mv78xx0_ge00_init(struct mv6
 {
 	orion_ge00_init(eth_data,
 			GE00_PHYS_BASE, IRQ_MV78XX0_GE00_SUM,
-			IRQ_MV78XX0_GE_ERR, get_tclk());
+			IRQ_MV78XX0_GE_ERR, get_tclk(),
+			MV643XX_TX_CSUM_DEFAULT_LIMIT);
 }
 
 
@@ -210,7 +211,8 @@ void __init mv78xx0_ge01_init(struct mv6
 {
 	orion_ge01_init(eth_data,
 			GE01_PHYS_BASE, IRQ_MV78XX0_GE01_SUM,
-			NO_IRQ, get_tclk());
+			NO_IRQ, get_tclk(),
+			MV643XX_TX_CSUM_DEFAULT_LIMIT);
 }
 
 
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/arch/arm/mach-orion5x/common.c linux-libre-3.4.87-gnu1/arch/arm/mach-orion5x/common.c
--- linux-libre-3.4.86-gnu1/arch/arm/mach-orion5x/common.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/arch/arm/mach-orion5x/common.c	2014-04-14 09:45:17.000000000 -0400
@@ -95,7 +95,8 @@ void __init orion5x_eth_init(struct mv64
 {
 	orion_ge00_init(eth_data,
 			ORION5X_ETH_PHYS_BASE, IRQ_ORION5X_ETH_SUM,
-			IRQ_ORION5X_ETH_ERR, orion5x_tclk);
+			IRQ_ORION5X_ETH_ERR, orion5x_tclk,
+			MV643XX_TX_CSUM_DEFAULT_LIMIT);
 }
 
 
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/arch/arm/mach-pxa/reset.c linux-libre-3.4.87-gnu1/arch/arm/mach-pxa/reset.c
--- linux-libre-3.4.86-gnu1/arch/arm/mach-pxa/reset.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/arch/arm/mach-pxa/reset.c	2014-04-14 09:45:17.000000000 -0400
@@ -13,6 +13,7 @@
 
 #include <mach/regs-ost.h>
 #include <mach/reset.h>
+#include <mach/smemc.h>
 
 unsigned int reset_status;
 EXPORT_SYMBOL(reset_status);
@@ -80,6 +81,12 @@ static void do_hw_reset(void)
 	OWER = OWER_WME;
 	OSSR = OSSR_M3;
 	OSMR3 = OSCR + 368640;	/* ... in 100 ms */
+	/*
+	 * SDRAM hangs on watchdog reset on Marvell PXA270 (erratum 71)
+	 * we put SDRAM into self-refresh to prevent that
+	 */
+	while (1)
+		writel_relaxed(MDREFR_SLFRSH, MDREFR);
 }
 
 void pxa_restart(char mode, const char *cmd)
@@ -103,4 +110,3 @@ void pxa_restart(char mode, const char *
 		break;
 	}
 }
-
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/arch/arm/mach-u300/include/mach/u300-regs.h linux-libre-3.4.87-gnu1/arch/arm/mach-u300/include/mach/u300-regs.h
--- linux-libre-3.4.86-gnu1/arch/arm/mach-u300/include/mach/u300-regs.h	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/arch/arm/mach-u300/include/mach/u300-regs.h	2014-04-14 09:45:17.000000000 -0400
@@ -101,7 +101,7 @@
 
 #ifdef CONFIG_MACH_U300_BS335
 /* Fast UART1 on U335 only */
-#define U300_UART1_BASE			(U300_SLOW_PER_PHYS_BASE+0x7000)
+#define U300_UART1_BASE			(U300_FAST_PER_PHYS_BASE+0x7000)
 #endif
 
 /*
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/arch/arm/mach-w90x900/include/mach/entry-macro.S linux-libre-3.4.87-gnu1/arch/arm/mach-w90x900/include/mach/entry-macro.S
--- linux-libre-3.4.86-gnu1/arch/arm/mach-w90x900/include/mach/entry-macro.S	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/arch/arm/mach-w90x900/include/mach/entry-macro.S	2014-04-14 09:45:17.000000000 -0400
@@ -19,8 +19,8 @@
 
 		mov	\base, #AIC_BA
 
-		ldr	\irqnr, [ \base, #AIC_IPER]
-		ldr	\irqnr, [ \base, #AIC_ISNR]
+		ldr	\irqnr, [\base, #AIC_IPER]
+		ldr	\irqnr, [\base, #AIC_ISNR]
 		cmp	\irqnr, #0
 
 	.endm
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/arch/arm/plat-orion/common.c linux-libre-3.4.87-gnu1/arch/arm/plat-orion/common.c
--- linux-libre-3.4.86-gnu1/arch/arm/plat-orion/common.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/arch/arm/plat-orion/common.c	2014-04-14 09:45:17.000000000 -0400
@@ -261,10 +261,12 @@ void __init orion_ge00_init(struct mv643
 			    unsigned long mapbase,
 			    unsigned long irq,
 			    unsigned long irq_err,
-			    int tclk)
+			    int tclk,
+			    unsigned int tx_csum_limit)
 {
 	fill_resources(&orion_ge00_shared, orion_ge00_shared_resources,
 		       mapbase + 0x2000, SZ_16K - 1, irq_err);
+	orion_ge00_shared_data.tx_csum_limit = tx_csum_limit;
 	ge_complete(&orion_ge00_shared_data, tclk,
 		    orion_ge00_resources, irq, &orion_ge00_shared,
 		    eth_data, &orion_ge00);
@@ -314,10 +316,12 @@ void __init orion_ge01_init(struct mv643
 			    unsigned long mapbase,
 			    unsigned long irq,
 			    unsigned long irq_err,
-			    int tclk)
+			    int tclk,
+			    unsigned int tx_csum_limit)
 {
 	fill_resources(&orion_ge01_shared, orion_ge01_shared_resources,
 		       mapbase + 0x2000, SZ_16K - 1, irq_err);
+	orion_ge01_shared_data.tx_csum_limit = tx_csum_limit;
 	ge_complete(&orion_ge01_shared_data, tclk,
 		    orion_ge01_resources, irq, &orion_ge01_shared,
 		    eth_data, &orion_ge01);
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/arch/arm/plat-orion/include/plat/common.h linux-libre-3.4.87-gnu1/arch/arm/plat-orion/include/plat/common.h
--- linux-libre-3.4.86-gnu1/arch/arm/plat-orion/include/plat/common.h	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/arch/arm/plat-orion/include/plat/common.h	2014-04-14 09:45:17.000000000 -0400
@@ -40,13 +40,15 @@ void __init orion_ge00_init(struct mv643
 			    unsigned long mapbase,
 			    unsigned long irq,
 			    unsigned long irq_err,
-			    int tclk);
+			    int tclk,
+			    unsigned int tx_csum_limit);
 
 void __init orion_ge01_init(struct mv643xx_eth_platform_data *eth_data,
 			    unsigned long mapbase,
 			    unsigned long irq,
 			    unsigned long irq_err,
-			    int tclk);
+			    int tclk,
+			    unsigned int tx_csum_limit);
 
 void __init orion_ge10_init(struct mv643xx_eth_platform_data *eth_data,
 			    unsigned long mapbase,
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/arch/mips/include/asm/jump_label.h linux-libre-3.4.87-gnu1/arch/mips/include/asm/jump_label.h
--- linux-libre-3.4.86-gnu1/arch/mips/include/asm/jump_label.h	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/arch/mips/include/asm/jump_label.h	2014-04-14 09:45:17.000000000 -0400
@@ -22,7 +22,7 @@
 
 static __always_inline bool arch_static_branch(struct static_key *key)
 {
-	asm goto("1:\tnop\n\t"
+	asm_volatile_goto("1:\tnop\n\t"
 		"nop\n\t"
 		".pushsection __jump_table,  \"aw\"\n\t"
 		WORD_INSN " 1b, %l[l_yes], %0\n\t"
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/arch/powerpc/include/asm/jump_label.h linux-libre-3.4.87-gnu1/arch/powerpc/include/asm/jump_label.h
--- linux-libre-3.4.86-gnu1/arch/powerpc/include/asm/jump_label.h	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/arch/powerpc/include/asm/jump_label.h	2014-04-14 09:45:17.000000000 -0400
@@ -19,7 +19,7 @@
 
 static __always_inline bool arch_static_branch(struct static_key *key)
 {
-	asm goto("1:\n\t"
+	asm_volatile_goto("1:\n\t"
 		 "nop\n\t"
 		 ".pushsection __jump_table,  \"aw\"\n\t"
 		 JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t"
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/arch/s390/include/asm/jump_label.h linux-libre-3.4.87-gnu1/arch/s390/include/asm/jump_label.h
--- linux-libre-3.4.86-gnu1/arch/s390/include/asm/jump_label.h	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/arch/s390/include/asm/jump_label.h	2014-04-14 09:45:17.000000000 -0400
@@ -15,7 +15,7 @@
 
 static __always_inline bool arch_static_branch(struct static_key *key)
 {
-	asm goto("0:	brcl 0,0\n"
+	asm_volatile_goto("0:	brcl 0,0\n"
 		".pushsection __jump_table, \"aw\"\n"
 		ASM_ALIGN "\n"
 		ASM_PTR " 0b, %l[label], %0\n"
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/arch/sparc/include/asm/jump_label.h linux-libre-3.4.87-gnu1/arch/sparc/include/asm/jump_label.h
--- linux-libre-3.4.86-gnu1/arch/sparc/include/asm/jump_label.h	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/arch/sparc/include/asm/jump_label.h	2014-04-14 09:45:17.000000000 -0400
@@ -9,7 +9,7 @@
 
 static __always_inline bool arch_static_branch(struct static_key *key)
 {
-		asm goto("1:\n\t"
+		asm_volatile_goto("1:\n\t"
 			 "nop\n\t"
 			 "nop\n\t"
 			 ".pushsection __jump_table,  \"aw\"\n\t"
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/arch/x86/include/asm/cpufeature.h linux-libre-3.4.87-gnu1/arch/x86/include/asm/cpufeature.h
--- linux-libre-3.4.86-gnu1/arch/x86/include/asm/cpufeature.h	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/arch/x86/include/asm/cpufeature.h	2014-04-14 09:45:17.000000000 -0400
@@ -342,7 +342,7 @@ extern const char * const x86_power_flag
 static __always_inline __pure bool __static_cpu_has(u16 bit)
 {
 #if __GNUC__ > 4 || __GNUC_MINOR__ >= 5
-		asm goto("1: jmp %l[t_no]\n"
+		asm_volatile_goto("1: jmp %l[t_no]\n"
 			 "2:\n"
 			 ".section .altinstructions,\"a\"\n"
 			 " .long 1b - .\n"
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/arch/x86/include/asm/jump_label.h linux-libre-3.4.87-gnu1/arch/x86/include/asm/jump_label.h
--- linux-libre-3.4.86-gnu1/arch/x86/include/asm/jump_label.h	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/arch/x86/include/asm/jump_label.h	2014-04-14 09:45:17.000000000 -0400
@@ -13,7 +13,7 @@
 
 static __always_inline bool arch_static_branch(struct static_key *key)
 {
-	asm goto("1:"
+	asm_volatile_goto("1:"
 		STATIC_KEY_INITIAL_NOP
 		".pushsection __jump_table,  \"aw\" \n\t"
 		_ASM_ALIGN "\n\t"
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt linux-libre-3.4.87-gnu1/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
--- linux-libre-3.4.86-gnu1/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt	2014-04-14 09:45:17.000000000 -0400
@@ -10,8 +10,8 @@ Required properties:
 
 Optional properties:
 - fsl,card-wired : Indicate the card is wired to host permanently
-- fsl,cd-internal : Indicate to use controller internal card detection
-- fsl,wp-internal : Indicate to use controller internal write protection
+- fsl,cd-controller : Indicate to use controller internal card detection
+- fsl,wp-controller : Indicate to use controller internal write protection
 - cd-gpios : Specify GPIOs for card detection
 - wp-gpios : Specify GPIOs for write protection
 
@@ -21,8 +21,8 @@ esdhc@70004000 {
 	compatible = "fsl,imx51-esdhc";
 	reg = <0x70004000 0x4000>;
 	interrupts = <1>;
-	fsl,cd-internal;
-	fsl,wp-internal;
+	fsl,cd-controller;
+	fsl,wp-controller;
 };
 
 esdhc@70008000 {
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/Documentation/hwmon/coretemp linux-libre-3.4.87-gnu1/Documentation/hwmon/coretemp
--- linux-libre-3.4.86-gnu1/Documentation/hwmon/coretemp	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/Documentation/hwmon/coretemp	2014-04-14 09:45:17.000000000 -0400
@@ -6,7 +6,9 @@ Supported chips:
     Prefix: 'coretemp'
     CPUID: family 0x6, models 0xe (Pentium M DC), 0xf (Core 2 DC 65nm),
                               0x16 (Core 2 SC 65nm), 0x17 (Penryn 45nm),
-                              0x1a (Nehalem), 0x1c (Atom), 0x1e (Lynnfield)
+                              0x1a (Nehalem), 0x1c (Atom), 0x1e (Lynnfield),
+                              0x26 (Tunnel Creek Atom), 0x27 (Medfield Atom),
+                              0x36 (Cedar Trail Atom)
     Datasheet: Intel 64 and IA-32 Architectures Software Developer's Manual
                Volume 3A: System Programming Guide
                http://softwarecommunity.intel.com/Wiki/Mobility/720.htm
@@ -65,6 +67,11 @@ Process		Processor					TjMax(C)
 		U3400						105
 		P4505/P4500 					90
 
+32nm		Atom Processors
+		Z2460						90
+		D2700/2550/2500					100
+		N2850/2800/2650/2600				100
+
 45nm		Xeon Processors 5400 Quad-Core
 		X5492, X5482, X5472, X5470, X5460, X5450	85
 		E5472, E5462, E5450/40/30/20/10/05		85
@@ -85,6 +92,9 @@ Process		Processor					TjMax(C)
 		N475/470/455/450				100
 		N280/270					90
 		330/230						125
+		E680/660/640/620				90
+		E680T/660T/640T/620T				110
+		CE4170/4150/4110				110
 
 45nm		Core2 Processors
 		Solo ULV SU3500/3300				100
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/ata/ahci.c linux-libre-3.4.87-gnu1/drivers/ata/ahci.c
--- linux-libre-3.4.86-gnu1/drivers/ata/ahci.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/ata/ahci.c	2014-04-14 09:45:17.000000000 -0400
@@ -292,6 +292,19 @@ static const struct pci_device_id ahci_p
 	{ PCI_VDEVICE(INTEL, 0x1f37), board_ahci }, /* Avoton RAID */
 	{ PCI_VDEVICE(INTEL, 0x1f3e), board_ahci }, /* Avoton RAID */
 	{ PCI_VDEVICE(INTEL, 0x1f3f), board_ahci }, /* Avoton RAID */
+	{ PCI_VDEVICE(INTEL, 0x8d02), board_ahci }, /* Wellsburg AHCI */
+	{ PCI_VDEVICE(INTEL, 0x8d04), board_ahci }, /* Wellsburg RAID */
+	{ PCI_VDEVICE(INTEL, 0x8d06), board_ahci }, /* Wellsburg RAID */
+	{ PCI_VDEVICE(INTEL, 0x8d0e), board_ahci }, /* Wellsburg RAID */
+	{ PCI_VDEVICE(INTEL, 0x8d62), board_ahci }, /* Wellsburg AHCI */
+	{ PCI_VDEVICE(INTEL, 0x8d64), board_ahci }, /* Wellsburg RAID */
+	{ PCI_VDEVICE(INTEL, 0x8d66), board_ahci }, /* Wellsburg RAID */
+	{ PCI_VDEVICE(INTEL, 0x8d6e), board_ahci }, /* Wellsburg RAID */
+	{ PCI_VDEVICE(INTEL, 0x23a3), board_ahci }, /* Coleto Creek AHCI */
+	{ PCI_VDEVICE(INTEL, 0x9c83), board_ahci }, /* Wildcat Point-LP AHCI */
+	{ 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 */
 
 	/* 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,
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/cpufreq/powernow-k6.c linux-libre-3.4.87-gnu1/drivers/cpufreq/powernow-k6.c
--- linux-libre-3.4.86-gnu1/drivers/cpufreq/powernow-k6.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/cpufreq/powernow-k6.c	2014-04-14 09:45:17.000000000 -0400
@@ -26,41 +26,108 @@
 static unsigned int                     busfreq;   /* FSB, in 10 kHz */
 static unsigned int                     max_multiplier;
 
+static unsigned int			param_busfreq = 0;
+static unsigned int			param_max_multiplier = 0;
+
+module_param_named(max_multiplier, param_max_multiplier, uint, S_IRUGO);
+MODULE_PARM_DESC(max_multiplier, "Maximum multiplier (allowed values: 20 30 35 40 45 50 55 60)");
+
+module_param_named(bus_frequency, param_busfreq, uint, S_IRUGO);
+MODULE_PARM_DESC(bus_frequency, "Bus frequency in kHz");
 
 /* Clock ratio multiplied by 10 - see table 27 in AMD#23446 */
 static struct cpufreq_frequency_table clock_ratio[] = {
-	{45,  /* 000 -> 4.5x */ 0},
+	{60,  /* 110 -> 6.0x */ 0},
+	{55,  /* 011 -> 5.5x */ 0},
 	{50,  /* 001 -> 5.0x */ 0},
+	{45,  /* 000 -> 4.5x */ 0},
 	{40,  /* 010 -> 4.0x */ 0},
-	{55,  /* 011 -> 5.5x */ 0},
-	{20,  /* 100 -> 2.0x */ 0},
-	{30,  /* 101 -> 3.0x */ 0},
-	{60,  /* 110 -> 6.0x */ 0},
 	{35,  /* 111 -> 3.5x */ 0},
+	{30,  /* 101 -> 3.0x */ 0},
+	{20,  /* 100 -> 2.0x */ 0},
 	{0, CPUFREQ_TABLE_END}
 };
 
+static const u8 index_to_register[8] = { 6, 3, 1, 0, 2, 7, 5, 4 };
+static const u8 register_to_index[8] = { 3, 2, 4, 1, 7, 6, 0, 5 };
+
+static const struct {
+	unsigned freq;
+	unsigned mult;
+} usual_frequency_table[] = {
+	{ 400000, 40 },	// 100   * 4
+	{ 450000, 45 }, // 100   * 4.5
+	{ 475000, 50 }, //  95   * 5
+	{ 500000, 50 }, // 100   * 5
+	{ 506250, 45 }, // 112.5 * 4.5
+	{ 533500, 55 }, //  97   * 5.5
+	{ 550000, 55 }, // 100   * 5.5
+	{ 562500, 50 }, // 112.5 * 5
+	{ 570000, 60 }, //  95   * 6
+	{ 600000, 60 }, // 100   * 6
+	{ 618750, 55 }, // 112.5 * 5.5
+	{ 660000, 55 }, // 120   * 5.5
+	{ 675000, 60 }, // 112.5 * 6
+	{ 720000, 60 }, // 120   * 6
+};
+
+#define FREQ_RANGE		3000
 
 /**
  * powernow_k6_get_cpu_multiplier - returns the current FSB multiplier
  *
- *   Returns the current setting of the frequency multiplier. Core clock
+ * Returns the current setting of the frequency multiplier. Core clock
  * speed is frequency of the Front-Side Bus multiplied with this value.
  */
 static int powernow_k6_get_cpu_multiplier(void)
 {
-	u64 invalue = 0;
+	unsigned long invalue = 0;
 	u32 msrval;
 
+	local_irq_disable();
+
 	msrval = POWERNOW_IOPORT + 0x1;
 	wrmsr(MSR_K6_EPMR, msrval, 0); /* enable the PowerNow port */
 	invalue = inl(POWERNOW_IOPORT + 0x8);
 	msrval = POWERNOW_IOPORT + 0x0;
 	wrmsr(MSR_K6_EPMR, msrval, 0); /* disable it again */
 
-	return clock_ratio[(invalue >> 5)&7].index;
+	local_irq_enable();
+
+	return clock_ratio[register_to_index[(invalue >> 5)&7]].index;
 }
 
+static void powernow_k6_set_cpu_multiplier(unsigned int best_i)
+{
+	unsigned long outvalue, invalue;
+	unsigned long msrval;
+	unsigned long cr0;
+
+	/* we now need to transform best_i to the BVC format, see AMD#23446 */
+
+	/*
+	 * The processor doesn't respond to inquiry cycles while changing the
+	 * frequency, so we must disable cache.
+	 */
+	local_irq_disable();
+	cr0 = read_cr0();
+	write_cr0(cr0 | X86_CR0_CD);
+	wbinvd();
+
+	outvalue = (1<<12) | (1<<10) | (1<<9) | (index_to_register[best_i]<<5);
+
+	msrval = POWERNOW_IOPORT + 0x1;
+	wrmsr(MSR_K6_EPMR, msrval, 0); /* enable the PowerNow port */
+	invalue = inl(POWERNOW_IOPORT + 0x8);
+	invalue = invalue & 0x1f;
+	outvalue = outvalue | invalue;
+	outl(outvalue, (POWERNOW_IOPORT + 0x8));
+	msrval = POWERNOW_IOPORT + 0x0;
+	wrmsr(MSR_K6_EPMR, msrval, 0); /* disable it again */
+
+	write_cr0(cr0);
+	local_irq_enable();
+}
 
 /**
  * powernow_k6_set_state - set the PowerNow! multiplier
@@ -70,8 +137,6 @@ static int powernow_k6_get_cpu_multiplie
  */
 static void powernow_k6_set_state(unsigned int best_i)
 {
-	unsigned long outvalue = 0, invalue = 0;
-	unsigned long msrval;
 	struct cpufreq_freqs freqs;
 
 	if (clock_ratio[best_i].index > max_multiplier) {
@@ -85,18 +150,7 @@ static void powernow_k6_set_state(unsign
 
 	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 
-	/* we now need to transform best_i to the BVC format, see AMD#23446 */
-
-	outvalue = (1<<12) | (1<<10) | (1<<9) | (best_i<<5);
-
-	msrval = POWERNOW_IOPORT + 0x1;
-	wrmsr(MSR_K6_EPMR, msrval, 0); /* enable the PowerNow port */
-	invalue = inl(POWERNOW_IOPORT + 0x8);
-	invalue = invalue & 0xf;
-	outvalue = outvalue | invalue;
-	outl(outvalue , (POWERNOW_IOPORT + 0x8));
-	msrval = POWERNOW_IOPORT + 0x0;
-	wrmsr(MSR_K6_EPMR, msrval, 0); /* disable it again */
+	powernow_k6_set_cpu_multiplier(best_i);
 
 	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 
@@ -141,18 +195,57 @@ static int powernow_k6_target(struct cpu
 	return 0;
 }
 
-
 static int powernow_k6_cpu_init(struct cpufreq_policy *policy)
 {
 	unsigned int i, f;
 	int result;
+	unsigned khz;
 
 	if (policy->cpu != 0)
 		return -ENODEV;
 
-	/* get frequencies */
-	max_multiplier = powernow_k6_get_cpu_multiplier();
-	busfreq = cpu_khz / max_multiplier;
+	max_multiplier = 0;
+	khz = cpu_khz;
+	for (i = 0; i < ARRAY_SIZE(usual_frequency_table); i++) {
+		if (khz >= usual_frequency_table[i].freq - FREQ_RANGE &&
+		    khz <= usual_frequency_table[i].freq + FREQ_RANGE) {
+			khz = usual_frequency_table[i].freq;
+			max_multiplier = usual_frequency_table[i].mult;
+			break;
+		}
+	}
+	if (param_max_multiplier) {
+		for (i = 0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) {
+			if (clock_ratio[i].index == param_max_multiplier) {
+				max_multiplier = param_max_multiplier;
+				goto have_max_multiplier;
+			}
+		}
+		printk(KERN_ERR "powernow-k6: invalid max_multiplier parameter, valid parameters 20, 30, 35, 40, 45, 50, 55, 60\n");
+		return -EINVAL;
+	}
+
+	if (!max_multiplier) {
+		printk(KERN_WARNING "powernow-k6: unknown frequency %u, cannot determine current multiplier\n", khz);
+		printk(KERN_WARNING "powernow-k6: use module parameters max_multiplier and bus_frequency\n");
+		return -EOPNOTSUPP;
+	}
+
+have_max_multiplier:
+	param_max_multiplier = max_multiplier;
+
+	if (param_busfreq) {
+		if (param_busfreq >= 50000 && param_busfreq <= 150000) {
+			busfreq = param_busfreq / 10;
+			goto have_busfreq;
+		}
+		printk(KERN_ERR "powernow-k6: invalid bus_frequency parameter, allowed range 50000 - 150000 kHz\n");
+		return -EINVAL;
+	}
+
+	busfreq = khz / max_multiplier;
+have_busfreq:
+	param_busfreq = busfreq * 10;
 
 	/* table init */
 	for (i = 0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) {
@@ -164,7 +257,7 @@ static int powernow_k6_cpu_init(struct c
 	}
 
 	/* cpuinfo and default policy values */
-	policy->cpuinfo.transition_latency = 200000;
+	policy->cpuinfo.transition_latency = 500000;
 	policy->cur = busfreq * max_multiplier;
 
 	result = cpufreq_frequency_table_cpuinfo(policy, clock_ratio);
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/edac/sb_edac.c linux-libre-3.4.87-gnu1/drivers/edac/sb_edac.c
--- linux-libre-3.4.86-gnu1/drivers/edac/sb_edac.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/edac/sb_edac.c	2014-04-14 09:45:17.000000000 -0400
@@ -555,7 +555,8 @@ static int get_dimm_config(const struct
 {
 	struct sbridge_pvt *pvt = mci->pvt_info;
 	struct csrow_info *csr;
-	int i, j, banks, ranks, rows, cols, size, npages;
+	unsigned i, j, banks, ranks, rows, cols, npages;
+	u64 size;
 	int csrow = 0;
 	unsigned long last_page = 0;
 	u32 reg;
@@ -627,10 +628,10 @@ static int get_dimm_config(const struct
 				cols = numcol(mtr);
 
 				/* DDR3 has 8 I/O banks */
-				size = (rows * cols * banks * ranks) >> (20 - 3);
+				size = ((u64)rows * cols * banks * ranks) >> (20 - 3);
 				npages = MiB_TO_PAGES(size);
 
-				debugf0("mc#%d: channel %d, dimm %d, %d Mb (%d pages) bank: %d, rank: %d, row: %#x, col: %#x\n",
+				debugf0("mc#%d: channel %d, dimm %d, %Ld Mb (%d pages) bank: %d, rank: %d, row: %#x, col: %#x\n",
 					pvt->sbridge_dev->mc, i, j,
 					size, npages,
 					banks, ranks, rows, cols);
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/hid/hid-apple.c linux-libre-3.4.87-gnu1/drivers/hid/hid-apple.c
--- linux-libre-3.4.86-gnu1/drivers/hid/hid-apple.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/hid/hid-apple.c	2014-04-14 09:45:17.000000000 -0400
@@ -480,6 +480,9 @@ static const struct hid_device_id apple_
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO),
 		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
 			APPLE_ISO_KEYBOARD },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
+				USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI),
+		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS),
 		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI),
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/hid/hid-core.c linux-libre-3.4.87-gnu1/drivers/hid/hid-core.c
--- linux-libre-3.4.86-gnu1/drivers/hid/hid-core.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/hid/hid-core.c	2014-04-14 09:45:17.000000000 -0400
@@ -222,9 +222,9 @@ static int hid_add_field(struct hid_pars
 {
 	struct hid_report *report;
 	struct hid_field *field;
-	int usages;
+	unsigned usages;
 	unsigned offset;
-	int i;
+	unsigned i;
 
 	report = hid_register_report(parser->device, report_type, parser->global.report_id);
 	if (!report) {
@@ -244,7 +244,8 @@ static int hid_add_field(struct hid_pars
 	if (!parser->local.usage_index) /* Ignore padding fields */
 		return 0;
 
-	usages = max_t(int, parser->local.usage_index, parser->global.report_count);
+	usages = max_t(unsigned, parser->local.usage_index,
+				 parser->global.report_count);
 
 	field = hid_register_field(report, usages, parser->global.report_count);
 	if (!field)
@@ -255,7 +256,7 @@ static int hid_add_field(struct hid_pars
 	field->application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION);
 
 	for (i = 0; i < usages; i++) {
-		int j = i;
+		unsigned j = i;
 		/* Duplicate the last usage we parsed if we have excess values */
 		if (i >= parser->local.usage_index)
 			j = parser->local.usage_index - 1;
@@ -1099,7 +1100,7 @@ static struct hid_report *hid_get_report
 	return report;
 }
 
-void hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
+int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
 		int interrupt)
 {
 	struct hid_report_enum *report_enum = hid->report_enum + type;
@@ -1107,10 +1108,11 @@ void hid_report_raw_event(struct hid_dev
 	unsigned int a;
 	int rsize, csize = size;
 	u8 *cdata = data;
+	int ret = 0;
 
 	report = hid_get_report(report_enum, data);
 	if (!report)
-		return;
+		goto out;
 
 	if (report_enum->numbered) {
 		cdata++;
@@ -1130,14 +1132,19 @@ void hid_report_raw_event(struct hid_dev
 
 	if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event)
 		hid->hiddev_report_event(hid, report);
-	if (hid->claimed & HID_CLAIMED_HIDRAW)
-		hidraw_report_event(hid, data, size);
+	if (hid->claimed & HID_CLAIMED_HIDRAW) {
+		ret = hidraw_report_event(hid, data, size);
+		if (ret)
+			goto out;
+	}
 
 	for (a = 0; a < report->maxfield; a++)
 		hid_input_field(hid, report->field[a], cdata, interrupt);
 
 	if (hid->claimed & HID_CLAIMED_INPUT)
 		hidinput_report_event(hid, report);
+out:
+	return ret;
 }
 EXPORT_SYMBOL_GPL(hid_report_raw_event);
 
@@ -1214,7 +1221,7 @@ nomem:
 		}
 	}
 
-	hid_report_raw_event(hid, type, data, size, interrupt);
+	ret = hid_report_raw_event(hid, type, data, size, interrupt);
 
 unlock:
 	up(&hid->driver_lock);
@@ -1612,6 +1619,7 @@ static const struct hid_device_id hid_ha
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER) },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, USB_DEVICE_ID_MTP) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM, USB_DEVICE_ID_MTP_STM) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_SITRONIX, USB_DEVICE_ID_MTP_SITRONIX) },
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/hid/hid-ids.h linux-libre-3.4.87-gnu1/drivers/hid/hid-ids.h
--- linux-libre-3.4.86-gnu1/drivers/hid/hid-ids.h	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/hid/hid-ids.h	2014-04-14 09:45:17.000000000 -0400
@@ -293,6 +293,12 @@
 #define USB_VENDOR_ID_FRUCTEL	0x25B6
 #define USB_DEVICE_ID_GAMETEL_MT_MODE	0x0002
 
+#define USB_VENDOR_ID_FORMOSA          0x147a
+#define USB_DEVICE_ID_FORMOSA_IR_RECEIVER      0xe03e
+
+#define USB_VENDOR_ID_FREESCALE		0x15A2
+#define USB_DEVICE_ID_FREESCALE_MX28	0x004F
+
 #define USB_VENDOR_ID_GAMERON		0x0810
 #define USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR	0x0001
 #define USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR	0x0002
@@ -553,6 +559,9 @@
 #define USB_VENDOR_ID_MONTEREY		0x0566
 #define USB_DEVICE_ID_GENIUS_KB29E	0x3004
 
+#define USB_VENDOR_ID_MSI		0x1770
+#define USB_DEVICE_ID_MSI_GX680R_LED_PANEL	0xff00
+
 #define USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR 0x0400
 #define USB_DEVICE_ID_N_S_HARMONY	0xc359
 
@@ -679,6 +688,7 @@
 
 #define USB_VENDOR_ID_SONY			0x054c
 #define USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE	0x024b
+#define USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE	0x0374
 #define USB_DEVICE_ID_SONY_PS3_CONTROLLER	0x0268
 #define USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER	0x042f
 
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/hid/hid-input.c linux-libre-3.4.87-gnu1/drivers/hid/hid-input.c
--- linux-libre-3.4.86-gnu1/drivers/hid/hid-input.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/hid/hid-input.c	2014-04-14 09:45:17.000000000 -0400
@@ -459,6 +459,10 @@ static void hidinput_configure_usage(str
 	if (field->flags & HID_MAIN_ITEM_CONSTANT)
 		goto ignore;
 
+	/* Ignore if report count is out of bounds. */
+	if (field->report_count < 1)
+		goto ignore;
+
 	/* only LED usages are supported in output fields */
 	if (field->report_type == HID_OUTPUT_REPORT &&
 			(usage->hid & HID_USAGE_PAGE) != HID_UP_LED) {
@@ -1119,7 +1123,12 @@ static void report_features(struct hid_d
 
 	rep_enum = &hid->report_enum[HID_FEATURE_REPORT];
 	list_for_each_entry(rep, &rep_enum->report_list, list)
-		for (i = 0; i < rep->maxfield; i++)
+		for (i = 0; i < rep->maxfield; i++) {
+
+			/* Ignore if report count is out of bounds. */
+			if (rep->field[i]->report_count < 1)
+				continue;
+
 			for (j = 0; j < rep->field[i]->maxusage; j++) {
 				/* Verify if Battery Strength feature is available */
 				hidinput_setup_battery(hid, HID_FEATURE_REPORT, rep->field[i]);
@@ -1128,6 +1137,7 @@ static void report_features(struct hid_d
 					drv->feature_mapping(hid, rep->field[i],
 							     rep->field[i]->usage + j);
 			}
+		}
 }
 
 /*
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/hid/hid-multitouch.c linux-libre-3.4.87-gnu1/drivers/hid/hid-multitouch.c
--- linux-libre-3.4.86-gnu1/drivers/hid/hid-multitouch.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/hid/hid-multitouch.c	2014-04-14 09:45:17.000000000 -0400
@@ -82,8 +82,8 @@ struct mt_device {
 					   multitouch fields */
 	unsigned last_field_index;	/* last field index of the report */
 	unsigned last_slot_field;	/* the last field of a slot */
-	__s8 inputmode;		/* InputMode HID feature, -1 if non-existent */
-	__s8 maxcontact_report_id;	/* Maximum Contact Number HID feature,
+	__s16 inputmode;		/* InputMode HID feature, -1 if non-existent */
+	__s16 maxcontact_report_id;	/* Maximum Contact Number HID feature,
 				   -1 if non-existent */
 	__u8 num_received;	/* how many contacts we received */
 	__u8 num_expected;	/* expected last contact index */
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/hid/hidraw.c linux-libre-3.4.87-gnu1/drivers/hid/hidraw.c
--- linux-libre-3.4.86-gnu1/drivers/hid/hidraw.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/hid/hidraw.c	2014-04-14 09:45:17.000000000 -0400
@@ -87,13 +87,16 @@ static ssize_t hidraw_read(struct file *
 		len = list->buffer[list->tail].len > count ?
 			count : list->buffer[list->tail].len;
 
-		if (copy_to_user(buffer, list->buffer[list->tail].value, len)) {
-			ret = -EFAULT;
-			goto out;
+		if (list->buffer[list->tail].value) {
+			if (copy_to_user(buffer, list->buffer[list->tail].value, len)) {
+				ret = -EFAULT;
+				goto out;
+			}
+			ret = len;
 		}
-		ret = len;
 
 		kfree(list->buffer[list->tail].value);
+		list->buffer[list->tail].value = NULL;
 		list->tail = (list->tail + 1) & (HIDRAW_BUFFER_SIZE - 1);
 	}
 out:
@@ -110,7 +113,7 @@ static ssize_t hidraw_send_report(struct
 	__u8 *buf;
 	int ret = 0;
 
-	if (!hidraw_table[minor]) {
+	if (!hidraw_table[minor] || !hidraw_table[minor]->exist) {
 		ret = -ENODEV;
 		goto out;
 	}
@@ -258,7 +261,7 @@ static int hidraw_open(struct inode *ino
 	}
 
 	mutex_lock(&minors_lock);
-	if (!hidraw_table[minor]) {
+	if (!hidraw_table[minor] || !hidraw_table[minor]->exist) {
 		err = -ENODEV;
 		goto out_unlock;
 	}
@@ -292,35 +295,38 @@ out:
 
 }
 
+static void drop_ref(struct hidraw *hidraw, int exists_bit)
+{
+	if (exists_bit) {
+		hid_hw_close(hidraw->hid);
+		hidraw->exist = 0;
+		if (hidraw->open)
+			wake_up_interruptible(&hidraw->wait);
+	} else {
+		--hidraw->open;
+	}
+
+	if (!hidraw->open && !hidraw->exist) {
+		device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
+		hidraw_table[hidraw->minor] = NULL;
+		kfree(hidraw);
+	}
+}
+
 static int hidraw_release(struct inode * inode, struct file * file)
 {
 	unsigned int minor = iminor(inode);
-	struct hidraw *dev;
 	struct hidraw_list *list = file->private_data;
-	int ret;
 
 	mutex_lock(&minors_lock);
-	if (!hidraw_table[minor]) {
-		ret = -ENODEV;
-		goto unlock;
-	}
 
 	list_del(&list->node);
-	dev = hidraw_table[minor];
-	if (!--dev->open) {
-		if (list->hidraw->exist) {
-			hid_hw_power(dev->hid, PM_HINT_NORMAL);
-			hid_hw_close(dev->hid);
-		} else {
-			kfree(list->hidraw);
-		}
-	}
 	kfree(list);
-	ret = 0;
-unlock:
-	mutex_unlock(&minors_lock);
 
-	return ret;
+	drop_ref(hidraw_table[minor], 0);
+
+	mutex_unlock(&minors_lock);
+	return 0;
 }
 
 static long hidraw_ioctl(struct file *file, unsigned int cmd,
@@ -437,19 +443,29 @@ static const struct file_operations hidr
 	.llseek =	noop_llseek,
 };
 
-void hidraw_report_event(struct hid_device *hid, u8 *data, int len)
+int hidraw_report_event(struct hid_device *hid, u8 *data, int len)
 {
 	struct hidraw *dev = hid->hidraw;
 	struct hidraw_list *list;
+	int ret = 0;
 
 	list_for_each_entry(list, &dev->list, node) {
-		list->buffer[list->head].value = kmemdup(data, len, GFP_ATOMIC);
+		int new_head = (list->head + 1) & (HIDRAW_BUFFER_SIZE - 1);
+
+		if (new_head == list->tail)
+			continue;
+
+		if (!(list->buffer[list->head].value = kmemdup(data, len, GFP_ATOMIC))) {
+			ret = -ENOMEM;
+			break;
+		}
 		list->buffer[list->head].len = len;
-		list->head = (list->head + 1) & (HIDRAW_BUFFER_SIZE - 1);
+		list->head = new_head;
 		kill_fasync(&list->fasync, SIGIO, POLL_IN);
 	}
 
 	wake_up_interruptible(&dev->wait);
+	return ret;
 }
 EXPORT_SYMBOL_GPL(hidraw_report_event);
 
@@ -514,18 +530,9 @@ void hidraw_disconnect(struct hid_device
 	struct hidraw *hidraw = hid->hidraw;
 
 	mutex_lock(&minors_lock);
-	hidraw->exist = 0;
 
-	device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
-
-	hidraw_table[hidraw->minor] = NULL;
+	drop_ref(hidraw, 1);
 
-	if (hidraw->open) {
-		hid_hw_close(hid);
-		wake_up_interruptible(&hidraw->wait);
-	} else {
-		kfree(hidraw);
-	}
 	mutex_unlock(&minors_lock);
 }
 EXPORT_SYMBOL_GPL(hidraw_disconnect);
@@ -542,21 +549,28 @@ int __init hidraw_init(void)
 
 	if (result < 0) {
 		pr_warn("can't get major number\n");
-		result = 0;
 		goto out;
 	}
 
 	hidraw_class = class_create(THIS_MODULE, "hidraw");
 	if (IS_ERR(hidraw_class)) {
 		result = PTR_ERR(hidraw_class);
-		unregister_chrdev(hidraw_major, "hidraw");
-		goto out;
+		goto error_cdev;
 	}
 
         cdev_init(&hidraw_cdev, &hidraw_ops);
-        cdev_add(&hidraw_cdev, dev_id, HIDRAW_MAX_DEVICES);
+	result = cdev_add(&hidraw_cdev, dev_id, HIDRAW_MAX_DEVICES);
+	if (result < 0)
+		goto error_class;
+
 out:
 	return result;
+
+error_class:
+	class_destroy(hidraw_class);
+error_cdev:
+	unregister_chrdev_region(dev_id, HIDRAW_MAX_DEVICES);
+	goto out;
 }
 
 void hidraw_exit(void)
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/hid/hid-sony.c linux-libre-3.4.87-gnu1/drivers/hid/hid-sony.c
--- linux-libre-3.4.86-gnu1/drivers/hid/hid-sony.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/hid/hid-sony.c	2014-04-14 09:45:17.000000000 -0400
@@ -44,9 +44,19 @@ static __u8 *sony_report_fixup(struct hi
 {
 	struct sony_sc *sc = hid_get_drvdata(hdev);
 
-	if ((sc->quirks & VAIO_RDESC_CONSTANT) &&
-			*rsize >= 56 && rdesc[54] == 0x81 && rdesc[55] == 0x07) {
-		hid_info(hdev, "Fixing up Sony Vaio VGX report descriptor\n");
+	/*
+	 * Some Sony RF receivers wrongly declare the mouse pointer as a
+	 * a constant non-data variable.
+	 */
+	if ((sc->quirks & VAIO_RDESC_CONSTANT) && *rsize >= 56 &&
+	    /* usage page: generic desktop controls */
+	    /* rdesc[0] == 0x05 && rdesc[1] == 0x01 && */
+	    /* usage: mouse */
+	    rdesc[2] == 0x09 && rdesc[3] == 0x02 &&
+	    /* input (usage page for x,y axes): constant, variable, relative */
+	    rdesc[54] == 0x81 && rdesc[55] == 0x07) {
+		hid_info(hdev, "Fixing up Sony RF Receiver report descriptor\n");
+		/* input: data, variable, relative */
 		rdesc[55] = 0x06;
 	}
 
@@ -218,6 +228,8 @@ static const struct hid_device_id sony_d
 		.driver_data = SIXAXIS_CONTROLLER_BT },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE),
 		.driver_data = VAIO_RDESC_CONSTANT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE),
+		.driver_data = VAIO_RDESC_CONSTANT },
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, sony_devices);
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/hid/usbhid/hid-quirks.c linux-libre-3.4.87-gnu1/drivers/hid/usbhid/hid-quirks.c
--- linux-libre-3.4.86-gnu1/drivers/hid/usbhid/hid-quirks.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/hid/usbhid/hid-quirks.c	2014-04-14 09:45:17.000000000 -0400
@@ -70,7 +70,10 @@ static const struct hid_blacklist {
 	{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
+	{ USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS },
+	{ USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_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_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS },
 	{ USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1, HID_QUIRK_NO_INIT_REPORTS },
 	{ USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2, HID_QUIRK_NO_INIT_REPORTS },
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/hwmon/applesmc.c linux-libre-3.4.87-gnu1/drivers/hwmon/applesmc.c
--- linux-libre-3.4.86-gnu1/drivers/hwmon/applesmc.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/hwmon/applesmc.c	2014-04-14 09:45:17.000000000 -0400
@@ -212,6 +212,7 @@ static int send_argument(const char *key
 
 static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len)
 {
+	u8 status, data = 0;
 	int i;
 
 	if (send_command(cmd) || send_argument(key)) {
@@ -219,6 +220,7 @@ static int read_smc(u8 cmd, const char *
 		return -EIO;
 	}
 
+	/* This has no effect on newer (2012) SMCs */
 	outb(len, APPLESMC_DATA_PORT);
 
 	for (i = 0; i < len; i++) {
@@ -229,6 +231,17 @@ static int read_smc(u8 cmd, const char *
 		buffer[i] = inb(APPLESMC_DATA_PORT);
 	}
 
+	/* Read the data port until bit0 is cleared */
+	for (i = 0; i < 16; i++) {
+		udelay(APPLESMC_MIN_WAIT);
+		status = inb(APPLESMC_CMD_PORT);
+		if (!(status & 0x01))
+			break;
+		data = inb(APPLESMC_DATA_PORT);
+	}
+	if (i)
+		pr_warn("flushed %d bytes, last value is: %d\n", i, data);
+
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/hwmon/coretemp.c linux-libre-3.4.87-gnu1/drivers/hwmon/coretemp.c
--- linux-libre-3.4.86-gnu1/drivers/hwmon/coretemp.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/hwmon/coretemp.c	2014-04-14 09:45:17.000000000 -0400
@@ -191,6 +191,27 @@ static ssize_t show_temp(struct device *
 	return tdata->valid ? sprintf(buf, "%d\n", tdata->temp) : -EAGAIN;
 }
 
+struct tjmax {
+	char const *id;
+	int tjmax;
+};
+
+static struct tjmax __cpuinitconst tjmax_table[] = {
+	{ "CPU D410", 100000 },
+	{ "CPU D425", 100000 },
+	{ "CPU D510", 100000 },
+	{ "CPU D525", 100000 },
+	{ "CPU N450", 100000 },
+	{ "CPU N455", 100000 },
+	{ "CPU N470", 100000 },
+	{ "CPU N475", 100000 },
+	{ "CPU  230", 100000 },		/* Model 0x1c, stepping 2	*/
+	{ "CPU  330", 125000 },		/* Model 0x1c, stepping 2	*/
+	{ "CPU CE4110", 110000 },	/* Model 0x1c, stepping 10	*/
+	{ "CPU CE4150", 110000 },	/* Model 0x1c, stepping 10	*/
+	{ "CPU CE4170", 110000 },	/* Model 0x1c, stepping 10	*/
+};
+
 static int __cpuinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id,
 				  struct device *dev)
 {
@@ -202,6 +223,13 @@ static int __cpuinit adjust_tjmax(struct
 	int err;
 	u32 eax, edx;
 	struct pci_dev *host_bridge;
+	int i;
+
+	/* explicit tjmax table entries override heuristics */
+	for (i = 0; i < ARRAY_SIZE(tjmax_table); i++) {
+		if (strstr(c->x86_model_id, tjmax_table[i].id))
+			return tjmax_table[i].tjmax;
+	}
 
 	/* Early chips have no MSR for TjMax */
 
@@ -210,7 +238,8 @@ static int __cpuinit adjust_tjmax(struct
 
 	/* Atom CPUs */
 
-	if (c->x86_model == 0x1c) {
+	if (c->x86_model == 0x1c || c->x86_model == 0x26
+	    || c->x86_model == 0x27) {
 		usemsr_ee = 0;
 
 		host_bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0));
@@ -223,6 +252,9 @@ static int __cpuinit adjust_tjmax(struct
 			tjmax = 90000;
 
 		pci_dev_put(host_bridge);
+	} else if (c->x86_model == 0x36) {
+		usemsr_ee = 0;
+		tjmax = 100000;
 	}
 
 	if (c->x86_model > 0xe && usemsr_ee) {
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/hwmon/lm78.c linux-libre-3.4.87-gnu1/drivers/hwmon/lm78.c
--- linux-libre-3.4.86-gnu1/drivers/hwmon/lm78.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/hwmon/lm78.c	2014-04-14 09:45:17.000000000 -0400
@@ -94,6 +94,8 @@ static inline u8 FAN_TO_REG(long rpm, in
 {
 	if (rpm <= 0)
 		return 255;
+	if (rpm > 1350000)
+		return 1;
 	return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
 }
 
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/hwmon/sis5595.c linux-libre-3.4.87-gnu1/drivers/hwmon/sis5595.c
--- linux-libre-3.4.86-gnu1/drivers/hwmon/sis5595.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/hwmon/sis5595.c	2014-04-14 09:45:17.000000000 -0400
@@ -141,6 +141,8 @@ static inline u8 FAN_TO_REG(long rpm, in
 {
 	if (rpm <= 0)
 		return 255;
+	if (rpm > 1350000)
+		return 1;
 	return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
 }
 
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/hwmon/vt8231.c linux-libre-3.4.87-gnu1/drivers/hwmon/vt8231.c
--- linux-libre-3.4.86-gnu1/drivers/hwmon/vt8231.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/hwmon/vt8231.c	2014-04-14 09:45:17.000000000 -0400
@@ -145,7 +145,7 @@ static const u8 regtempmin[] = { 0x3a, 0
  */
 static inline u8 FAN_TO_REG(long rpm, int div)
 {
-	if (rpm == 0)
+	if (rpm <= 0 || rpm > 1310720)
 		return 0;
 	return SENSORS_LIMIT(1310720 / (rpm * div), 1, 255);
 }
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/idle/intel_idle.c linux-libre-3.4.87-gnu1/drivers/idle/intel_idle.c
--- linux-libre-3.4.86-gnu1/drivers/idle/intel_idle.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/idle/intel_idle.c	2014-04-14 09:45:17.000000000 -0400
@@ -594,8 +594,9 @@ static int __init intel_idle_init(void)
 	intel_idle_cpuidle_driver_init();
 	retval = cpuidle_register_driver(&intel_idle_driver);
 	if (retval) {
+		struct cpuidle_driver *drv = cpuidle_get_driver();
 		printk(KERN_DEBUG PREFIX "intel_idle yielding to %s",
-			cpuidle_get_driver()->name);
+			drv ? drv->name : "none");
 		return retval;
 	}
 
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/media/dvb/dvb-core/dmxdev.c linux-libre-3.4.87-gnu1/drivers/media/dvb/dvb-core/dmxdev.c
--- linux-libre-3.4.86-gnu1/drivers/media/dvb/dvb-core/dmxdev.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/media/dvb/dvb-core/dmxdev.c	2014-04-14 09:45:17.000000000 -0400
@@ -379,10 +379,8 @@ static int dvb_dmxdev_section_callback(c
 		ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer2,
 					      buffer2_len);
 	}
-	if (ret < 0) {
-		dvb_ringbuffer_flush(&dmxdevfilter->buffer);
+	if (ret < 0)
 		dmxdevfilter->buffer.error = ret;
-	}
 	if (dmxdevfilter->params.sec.flags & DMX_ONESHOT)
 		dmxdevfilter->state = DMXDEV_STATE_DONE;
 	spin_unlock(&dmxdevfilter->dev->lock);
@@ -418,10 +416,8 @@ static int dvb_dmxdev_ts_callback(const
 	ret = dvb_dmxdev_buffer_write(buffer, buffer1, buffer1_len);
 	if (ret == buffer1_len)
 		ret = dvb_dmxdev_buffer_write(buffer, buffer2, buffer2_len);
-	if (ret < 0) {
-		dvb_ringbuffer_flush(buffer);
+	if (ret < 0)
 		buffer->error = ret;
-	}
 	spin_unlock(&dmxdevfilter->dev->lock);
 	wake_up(&buffer->queue);
 	return 0;
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/media/video/gspca/kinect.c linux-libre-3.4.87-gnu1/drivers/media/video/gspca/kinect.c
--- linux-libre-3.4.86-gnu1/drivers/media/video/gspca/kinect.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/media/video/gspca/kinect.c	2014-04-14 09:45:17.000000000 -0400
@@ -390,6 +390,7 @@ static const struct sd_desc sd_desc = {
 /* -- module initialisation -- */
 static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x045e, 0x02ae)},
+	{USB_DEVICE(0x045e, 0x02bf)},
 	{}
 };
 
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/media/video/hdpvr/hdpvr-core.c linux-libre-3.4.87-gnu1/drivers/media/video/hdpvr/hdpvr-core.c
--- linux-libre-3.4.86-gnu1/drivers/media/video/hdpvr/hdpvr-core.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/media/video/hdpvr/hdpvr-core.c	2014-04-14 09:45:17.000000000 -0400
@@ -309,6 +309,11 @@ static int hdpvr_probe(struct usb_interf
 
 	dev->workqueue = 0;
 
+	/* init video transfer queues first of all */
+	/* to prevent oops in hdpvr_delete() on error paths */
+	INIT_LIST_HEAD(&dev->free_buff_list);
+	INIT_LIST_HEAD(&dev->rec_buff_list);
+
 	/* register v4l2_device early so it can be used for printks */
 	if (v4l2_device_register(&interface->dev, &dev->v4l2_dev)) {
 		err("v4l2_device_register failed");
@@ -331,10 +336,6 @@ static int hdpvr_probe(struct usb_interf
 	if (!dev->workqueue)
 		goto error;
 
-	/* init video transfer queues */
-	INIT_LIST_HEAD(&dev->free_buff_list);
-	INIT_LIST_HEAD(&dev->rec_buff_list);
-
 	dev->options = hdpvr_default_options;
 
 	if (default_video_input < HDPVR_VIDEO_INPUTS)
@@ -385,12 +386,6 @@ static int hdpvr_probe(struct usb_interf
 	}
 	mutex_unlock(&dev->io_mutex);
 
-	if (hdpvr_register_videodev(dev, &interface->dev,
-				    video_nr[atomic_inc_return(&dev_nr)])) {
-		v4l2_err(&dev->v4l2_dev, "registering videodev failed\n");
-		goto error;
-	}
-
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 	retval = hdpvr_register_i2c_adapter(dev);
 	if (retval < 0) {
@@ -411,6 +406,13 @@ static int hdpvr_probe(struct usb_interf
 	}
 #endif
 
+	retval = hdpvr_register_videodev(dev, &interface->dev,
+				    video_nr[atomic_inc_return(&dev_nr)]);
+	if (retval < 0) {
+		v4l2_err(&dev->v4l2_dev, "registering videodev failed\n");
+		goto reg_fail;
+	}
+
 	/* let the user know what node this device is now attached to */
 	v4l2_info(&dev->v4l2_dev, "device now attached to %s\n",
 		  video_device_node_name(dev->video_dev));
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/media/video/omap/omap_vout.c linux-libre-3.4.87-gnu1/drivers/media/video/omap/omap_vout.c
--- linux-libre-3.4.86-gnu1/drivers/media/video/omap/omap_vout.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/media/video/omap/omap_vout.c	2014-04-14 09:45:17.000000000 -0400
@@ -206,19 +206,21 @@ static u32 omap_vout_uservirt_to_phys(u3
 	struct vm_area_struct *vma;
 	struct mm_struct *mm = current->mm;
 
-	vma = find_vma(mm, virtp);
 	/* For kernel direct-mapped memory, take the easy way */
-	if (virtp >= PAGE_OFFSET) {
-		physp = virt_to_phys((void *) virtp);
-	} else if (vma && (vma->vm_flags & VM_IO) && vma->vm_pgoff) {
+	if (virtp >= PAGE_OFFSET)
+		return virt_to_phys((void *) virtp);
+
+	down_read(&current->mm->mmap_sem);
+	vma = find_vma(mm, virtp);
+	if (vma && (vma->vm_flags & VM_IO) && vma->vm_pgoff) {
 		/* this will catch, kernel-allocated, mmaped-to-usermode
 		   addresses */
 		physp = (vma->vm_pgoff << PAGE_SHIFT) + (virtp - vma->vm_start);
+		up_read(&current->mm->mmap_sem);
 	} else {
 		/* otherwise, use get_user_pages() for general userland pages */
 		int res, nr_pages = 1;
 		struct page *pages;
-		down_read(&current->mm->mmap_sem);
 
 		res = get_user_pages(current, current->mm, virtp, nr_pages, 1,
 				0, &pages, NULL);
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/media/video/saa7164/saa7164-core.c linux-libre-3.4.87-gnu1/drivers/media/video/saa7164/saa7164-core.c
--- linux-libre-3.4.86-gnu1/drivers/media/video/saa7164/saa7164-core.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/media/video/saa7164/saa7164-core.c	2014-04-14 09:45:17.000000000 -0400
@@ -1386,9 +1386,11 @@ static int __devinit saa7164_initdev(str
 		if (fw_debug) {
 			dev->kthread = kthread_run(saa7164_thread_function, dev,
 				"saa7164 debug");
-			if (!dev->kthread)
+			if (IS_ERR(dev->kthread)) {
+				dev->kthread = NULL;
 				printk(KERN_ERR "%s() Failed to create "
 					"debug kernel thread\n", __func__);
+			}
 		}
 
 	} /* != BOARD_UNKNOWN */
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/media/video/v4l2-device.c linux-libre-3.4.87-gnu1/drivers/media/video/v4l2-device.c
--- linux-libre-3.4.86-gnu1/drivers/media/video/v4l2-device.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/media/video/v4l2-device.c	2014-04-14 09:45:17.000000000 -0400
@@ -159,31 +159,21 @@ int v4l2_device_register_subdev(struct v
 	sd->v4l2_dev = v4l2_dev;
 	if (sd->internal_ops && sd->internal_ops->registered) {
 		err = sd->internal_ops->registered(sd);
-		if (err) {
-			module_put(sd->owner);
-			return err;
-		}
+		if (err)
+			goto error_module;
 	}
 
 	/* This just returns 0 if either of the two args is NULL */
 	err = v4l2_ctrl_add_handler(v4l2_dev->ctrl_handler, sd->ctrl_handler);
-	if (err) {
-		if (sd->internal_ops && sd->internal_ops->unregistered)
-			sd->internal_ops->unregistered(sd);
-		module_put(sd->owner);
-		return err;
-	}
+	if (err)
+		goto error_unregister;
 
 #if defined(CONFIG_MEDIA_CONTROLLER)
 	/* Register the entity. */
 	if (v4l2_dev->mdev) {
 		err = media_device_register_entity(v4l2_dev->mdev, entity);
-		if (err < 0) {
-			if (sd->internal_ops && sd->internal_ops->unregistered)
-				sd->internal_ops->unregistered(sd);
-			module_put(sd->owner);
-			return err;
-		}
+		if (err < 0)
+			goto error_unregister;
 	}
 #endif
 
@@ -192,6 +182,14 @@ int v4l2_device_register_subdev(struct v
 	spin_unlock(&v4l2_dev->lock);
 
 	return 0;
+
+error_unregister:
+	if (sd->internal_ops && sd->internal_ops->unregistered)
+		sd->internal_ops->unregistered(sd);
+error_module:
+	module_put(sd->owner);
+	sd->v4l2_dev = NULL;
+	return err;
 }
 EXPORT_SYMBOL_GPL(v4l2_device_register_subdev);
 
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/mmc/host/mxs-mmc.c linux-libre-3.4.87-gnu1/drivers/mmc/host/mxs-mmc.c
--- linux-libre-3.4.86-gnu1/drivers/mmc/host/mxs-mmc.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/mmc/host/mxs-mmc.c	2014-04-14 09:45:17.000000000 -0400
@@ -639,10 +639,6 @@ static void mxs_mmc_enable_sdio_irq(stru
 		       host->base + HW_SSP_CTRL0 + MXS_SET_ADDR);
 		writel(BM_SSP_CTRL1_SDIO_IRQ_EN,
 		       host->base + HW_SSP_CTRL1 + MXS_SET_ADDR);
-
-		if (readl(host->base + HW_SSP_STATUS) & BM_SSP_STATUS_SDIO_IRQ)
-			mmc_signal_sdio_irq(host->mmc);
-
 	} else {
 		writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK,
 		       host->base + HW_SSP_CTRL0 + MXS_CLR_ADDR);
@@ -651,6 +647,10 @@ static void mxs_mmc_enable_sdio_irq(stru
 	}
 
 	spin_unlock_irqrestore(&host->lock, flags);
+
+	if (enable && readl(host->base + HW_SSP_STATUS) & BM_SSP_STATUS_SDIO_IRQ)
+		mmc_signal_sdio_irq(host->mmc);
+
 }
 
 static const struct mmc_host_ops mxs_mmc_ops = {
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/net/ethernet/broadcom/tg3.c linux-libre-3.4.87-gnu1/drivers/net/ethernet/broadcom/tg3.c
--- linux-libre-3.4.86-gnu1/drivers/net/ethernet/broadcom/tg3.c	2014-04-04 04:45:28.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/net/ethernet/broadcom/tg3.c	2014-04-14 14:26:05.000000000 -0400
@@ -1622,6 +1622,9 @@ static int tg3_poll_fw(struct tg3 *tp)
 	int i;
 	u32 val;
 
+	if (tg3_flag(tp, NO_FWARE_REPORTED))
+		return 0;
+
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
 		/* Wait up to 20ms for init done. */
 		for (i = 0; i < 200; i++) {
@@ -2728,6 +2731,31 @@ static int tg3_5700_link_polarity(struct
 	return 0;
 }
 
+static bool tg3_phy_power_bug(struct tg3 *tp)
+{
+	switch (GET_ASIC_REV(tp->pci_chip_rev_id)) {
+	case ASIC_REV_5700:
+	case ASIC_REV_5704:
+		return true;
+	case ASIC_REV_5780:
+		if (tp->phy_flags & TG3_PHYFLG_MII_SERDES)
+			return true;
+		return false;
+	case ASIC_REV_5717:
+		if (!tp->pci_fn)
+			return true;
+		return false;
+	case ASIC_REV_5719:
+	case ASIC_REV_5720:
+		if ((tp->phy_flags & TG3_PHYFLG_PHY_SERDES) &&
+		    !tp->pci_fn)
+			return true;
+		return false;
+	}
+
+	return false;
+}
+
 static void tg3_power_down_phy(struct tg3 *tp, bool do_low_power)
 {
 	u32 val;
@@ -2784,12 +2812,7 @@ static void tg3_power_down_phy(struct tg
 	/* The PHY should not be powered down on some chips because
 	 * of bugs.
 	 */
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
-	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
-	    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 &&
-	     (tp->phy_flags & TG3_PHYFLG_MII_SERDES)) ||
-	    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 &&
-	     !tp->pci_fn))
+	if (tg3_phy_power_bug(tp))
 		return;
 
 	if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX ||
@@ -8516,6 +8539,14 @@ static void tg3_rss_write_indir_tbl(stru
 	}
 }
 
+static inline u32 tg3_lso_rd_dma_workaround_bit(struct tg3 *tp)
+{
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
+		return TG3_LSO_RD_DMA_TX_LENGTH_WA_5719;
+	else
+		return TG3_LSO_RD_DMA_TX_LENGTH_WA_5720;
+}
+
 /* tp->lock is held. */
 static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
 {
@@ -9152,6 +9183,20 @@ static int tg3_reset_hw(struct tg3 *tp,
 	tw32_f(RDMAC_MODE, rdmac_mode);
 	udelay(40);
 
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) {
+		for (i = 0; i < TG3_NUM_RDMA_CHANNELS; i++) {
+			if (tr32(TG3_RDMA_LENGTH + (i << 2)) > TG3_MAX_MTU(tp))
+				break;
+		}
+		if (i < TG3_NUM_RDMA_CHANNELS) {
+			val = tr32(TG3_LSO_RD_DMA_CRPTEN_CTRL);
+			val |= tg3_lso_rd_dma_workaround_bit(tp);
+			tw32(TG3_LSO_RD_DMA_CRPTEN_CTRL, val);
+			tg3_flag_set(tp, 5719_5720_RDMA_BUG);
+		}
+	}
+
 	tw32(RCVDCC_MODE, RCVDCC_MODE_ENABLE | RCVDCC_MODE_ATTN_ENABLE);
 	if (!tg3_flag(tp, 5705_PLUS))
 		tw32(MBFREE_MODE, MBFREE_MODE_ENABLE);
@@ -9373,6 +9418,13 @@ static int tg3_reset_hw(struct tg3 *tp,
  */
 static int tg3_init_hw(struct tg3 *tp, int reset_phy)
 {
+	/* Chip may have been just powered on. If so, the boot code may still
+	 * be running initialization. Wait for it to finish to avoid races in
+	 * accessing the hardware.
+	 */
+	tg3_enable_register_access(tp);
+	tg3_poll_fw(tp);
+
 	tg3_switch_clocks(tp);
 
 	tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0);
@@ -9407,6 +9459,16 @@ static void tg3_periodic_fetch_stats(str
 	TG3_STAT_ADD32(&sp->tx_ucast_packets, MAC_TX_STATS_UCAST);
 	TG3_STAT_ADD32(&sp->tx_mcast_packets, MAC_TX_STATS_MCAST);
 	TG3_STAT_ADD32(&sp->tx_bcast_packets, MAC_TX_STATS_BCAST);
+	if (unlikely(tg3_flag(tp, 5719_5720_RDMA_BUG) &&
+		     (sp->tx_ucast_packets.low + sp->tx_mcast_packets.low +
+		      sp->tx_bcast_packets.low) > TG3_NUM_RDMA_CHANNELS)) {
+		u32 val;
+
+		val = tr32(TG3_LSO_RD_DMA_CRPTEN_CTRL);
+		val &= ~tg3_lso_rd_dma_workaround_bit(tp);
+		tw32(TG3_LSO_RD_DMA_CRPTEN_CTRL, val);
+		tg3_flag_clear(tp, 5719_5720_RDMA_BUG);
+	}
 
 	TG3_STAT_ADD32(&sp->rx_octets, MAC_RX_STATS_OCTETS);
 	TG3_STAT_ADD32(&sp->rx_fragments, MAC_RX_STATS_FRAGMENTS);
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/net/ethernet/broadcom/tg3.h linux-libre-3.4.87-gnu1/drivers/net/ethernet/broadcom/tg3.h
--- linux-libre-3.4.86-gnu1/drivers/net/ethernet/broadcom/tg3.h	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/net/ethernet/broadcom/tg3.h	2014-04-14 09:45:17.000000000 -0400
@@ -1376,7 +1376,12 @@
 #define TG3_LSO_RD_DMA_CRPTEN_CTRL	0x00004910
 #define TG3_LSO_RD_DMA_CRPTEN_CTRL_BLEN_BD_4K	 0x00030000
 #define TG3_LSO_RD_DMA_CRPTEN_CTRL_BLEN_LSO_4K	 0x000c0000
-/* 0x4914 --> 0x4c00 unused */
+#define TG3_LSO_RD_DMA_TX_LENGTH_WA_5719	 0x02000000
+#define TG3_LSO_RD_DMA_TX_LENGTH_WA_5720	 0x00200000
+/* 0x4914 --> 0x4be0 unused */
+
+#define TG3_NUM_RDMA_CHANNELS		4
+#define TG3_RDMA_LENGTH			0x00004be0
 
 /* Write DMA control registers */
 #define WDMAC_MODE			0x00004c00
@@ -2924,6 +2929,7 @@ enum TG3_FLAGS {
 	TG3_FLAG_L1PLLPD_EN,
 	TG3_FLAG_APE_HAS_NCSI,
 	TG3_FLAG_4K_FIFO_LIMIT,
+	TG3_FLAG_5719_5720_RDMA_BUG,
 	TG3_FLAG_RESET_TASK_PENDING,
 	TG3_FLAG_5705_PLUS,
 	TG3_FLAG_IS_5788,
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c linux-libre-3.4.87-gnu1/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
--- linux-libre-3.4.86-gnu1/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c	2014-04-14 09:45:17.000000000 -0400
@@ -3592,7 +3592,7 @@ static u16 ar9003_hw_ant_ctrl_chain_get(
 static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
 {
 	int chain;
-	u32 regval;
+	u32 regval, value;
 	u32 ant_div_ctl1;
 	static const u32 switch_chain_reg[AR9300_MAX_CHAINS] = {
 			AR_PHY_SWITCH_CHAIN_0,
@@ -3600,7 +3600,11 @@ static void ar9003_hw_ant_ctrl_apply(str
 			AR_PHY_SWITCH_CHAIN_2,
 	};
 
-	u32 value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz);
+	if (AR_SREV_9485(ah) && (ar9003_hw_get_rx_gain_idx(ah) == 0))
+		ath9k_hw_cfg_output(ah, AR9300_EXT_LNA_CTL_GPIO_AR9485,
+				    AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED);
+
+	value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz);
 
 	if (AR_SREV_9462(ah)) {
 		REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM,
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/net/wireless/ath/ath9k/ar9003_hw.c linux-libre-3.4.87-gnu1/drivers/net/wireless/ath/ath9k/ar9003_hw.c
--- linux-libre-3.4.86-gnu1/drivers/net/wireless/ath/ath9k/ar9003_hw.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/net/wireless/ath/ath9k/ar9003_hw.c	2014-04-14 09:45:17.000000000 -0400
@@ -33,9 +33,6 @@
  */
 static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
 {
-#define PCIE_PLL_ON_CREQ_DIS_L1_2P0 \
-		ar9462_pciephy_pll_on_clkreq_disable_L1_2p0
-
 #define AR9462_BB_CTX_COEFJ(x)	\
 		ar9462_##x##_baseband_core_txfir_coeff_japan_2484
 
@@ -312,13 +309,13 @@ static void ar9003_hw_init_mode_regs(str
 
 		/* Awake -> Sleep Setting */
 		INIT_INI_ARRAY(&ah->iniPcieSerdes,
-				PCIE_PLL_ON_CREQ_DIS_L1_2P0,
-				ARRAY_SIZE(PCIE_PLL_ON_CREQ_DIS_L1_2P0),
+				ar9462_pciephy_clkreq_disable_L1_2p0,
+				ARRAY_SIZE(ar9462_pciephy_clkreq_disable_L1_2p0),
 				2);
 		/* Sleep -> Awake Setting */
 		INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
-				PCIE_PLL_ON_CREQ_DIS_L1_2P0,
-				ARRAY_SIZE(PCIE_PLL_ON_CREQ_DIS_L1_2P0),
+				ar9462_pciephy_clkreq_disable_L1_2p0,
+				ARRAY_SIZE(ar9462_pciephy_clkreq_disable_L1_2p0),
 				2);
 
 		/* Fast clock modal settings */
@@ -637,8 +634,8 @@ static void ar9003_rx_gain_table_mode0(s
 				2);
 	else if (AR_SREV_9485_11(ah))
 		INIT_INI_ARRAY(&ah->iniModesRxGain,
-				ar9485Common_wo_xlna_rx_gain_1_1,
-				ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1),
+			       ar9485_common_rx_gain_1_1,
+			       ARRAY_SIZE(ar9485_common_rx_gain_1_1),
 				2);
 	else if (AR_SREV_9580(ah))
 		INIT_INI_ARRAY(&ah->iniModesRxGain,
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/net/wireless/ath/ath9k/ar9003_phy.c linux-libre-3.4.87-gnu1/drivers/net/wireless/ath/ath9k/ar9003_phy.c
--- linux-libre-3.4.86-gnu1/drivers/net/wireless/ath/ath9k/ar9003_phy.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/net/wireless/ath/ath9k/ar9003_phy.c	2014-04-14 09:45:17.000000000 -0400
@@ -545,33 +545,20 @@ static void ar9003_hw_init_bb(struct ath
 
 void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx)
 {
-	switch (rx) {
-	case 0x5:
+	if (ah->caps.tx_chainmask == 5 || ah->caps.rx_chainmask == 5)
 		REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
 			    AR_PHY_SWAP_ALT_CHAIN);
-	case 0x3:
-	case 0x1:
-	case 0x2:
-	case 0x7:
-		REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx);
-		REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx);
-		break;
-	default:
-		break;
-	}
+
+	REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx);
+	REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx);
 
 	if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && (tx == 0x7))
-		REG_WRITE(ah, AR_SELFGEN_MASK, 0x3);
+		tx = 3;
 	else if (AR_SREV_9462(ah))
 		/* xxx only when MCI support is enabled */
-		REG_WRITE(ah, AR_SELFGEN_MASK, 0x3);
-	else
-		REG_WRITE(ah, AR_SELFGEN_MASK, tx);
+		tx = 3;
 
-	if (tx == 0x5) {
-		REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
-			    AR_PHY_SWAP_ALT_CHAIN);
-	}
+	REG_WRITE(ah, AR_SELFGEN_MASK, tx);
 }
 
 /*
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/net/wireless/ath/ath9k/ar9003_phy.h linux-libre-3.4.87-gnu1/drivers/net/wireless/ath/ath9k/ar9003_phy.h
--- linux-libre-3.4.86-gnu1/drivers/net/wireless/ath/ath9k/ar9003_phy.h	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/net/wireless/ath/ath9k/ar9003_phy.h	2014-04-14 09:45:17.000000000 -0400
@@ -339,6 +339,8 @@
 
 #define AR_PHY_CCA_NOM_VAL_9330_2GHZ          -118
 
+#define AR9300_EXT_LNA_CTL_GPIO_AR9485 9
+
 /*
  * AGC Field Definitions
  */
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/net/wireless/ath/ath9k/calib.c linux-libre-3.4.87-gnu1/drivers/net/wireless/ath/ath9k/calib.c
--- linux-libre-3.4.86-gnu1/drivers/net/wireless/ath/ath9k/calib.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/net/wireless/ath/ath9k/calib.c	2014-04-14 09:45:17.000000000 -0400
@@ -410,6 +410,7 @@ void ath9k_init_nfcal_hist_buffer(struct
 
 	ah->caldata->channel = chan->channel;
 	ah->caldata->channelFlags = chan->channelFlags & ~CHANNEL_CW_INT;
+	ah->caldata->chanmode = chan->chanmode;
 	h = ah->caldata->nfCalHist;
 	default_nf = ath9k_hw_get_default_nf(ah, chan);
 	for (i = 0; i < NUM_NF_READINGS; i++) {
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c linux-libre-3.4.87-gnu1/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
--- linux-libre-3.4.86-gnu1/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c	2014-04-14 09:45:17.000000000 -0400
@@ -1077,15 +1077,19 @@ static bool ath9k_rx_prepare(struct ath9
 
 	last_rssi = priv->rx.last_rssi;
 
-	if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
-		rxbuf->rxstatus.rs_rssi = ATH_EP_RND(last_rssi,
-						     ATH_RSSI_EP_MULTIPLIER);
+	if (ieee80211_is_beacon(hdr->frame_control) &&
+	    !is_zero_ether_addr(common->curbssid) &&
+	    compare_ether_addr(hdr->addr3, common->curbssid) == 0) {
+		s8 rssi = rxbuf->rxstatus.rs_rssi;
 
-	if (rxbuf->rxstatus.rs_rssi < 0)
-		rxbuf->rxstatus.rs_rssi = 0;
+		if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
+			rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER);
 
-	if (ieee80211_is_beacon(fc))
-		priv->ah->stats.avgbrssi = rxbuf->rxstatus.rs_rssi;
+		if (rssi < 0)
+			rssi = 0;
+
+		priv->ah->stats.avgbrssi = rssi;
+	}
 
 	rx_status->mactime = be64_to_cpu(rxbuf->rxstatus.rs_tstamp);
 	rx_status->band = hw->conf.channel->band;
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/net/wireless/ath/ath9k/htc.h linux-libre-3.4.87-gnu1/drivers/net/wireless/ath/ath9k/htc.h
--- linux-libre-3.4.86-gnu1/drivers/net/wireless/ath/ath9k/htc.h	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/net/wireless/ath/ath9k/htc.h	2014-04-14 09:45:17.000000000 -0400
@@ -22,6 +22,7 @@
 #include <linux/firmware.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
+#include <linux/etherdevice.h>
 #include <linux/leds.h>
 #include <linux/slab.h>
 #include <net/mac80211.h>
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/net/wireless/ath/ath9k/hw.c linux-libre-3.4.87-gnu1/drivers/net/wireless/ath/ath9k/hw.c
--- linux-libre-3.4.86-gnu1/drivers/net/wireless/ath/ath9k/hw.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/net/wireless/ath/ath9k/hw.c	2014-04-14 09:45:17.000000000 -0400
@@ -1628,7 +1628,8 @@ int ath9k_hw_reset(struct ath_hw *ah, st
 	if (caldata &&
 	    (chan->channel != caldata->channel ||
 	     (chan->channelFlags & ~CHANNEL_CW_INT) !=
-	     (caldata->channelFlags & ~CHANNEL_CW_INT))) {
+	     (caldata->channelFlags & ~CHANNEL_CW_INT) ||
+	     chan->chanmode != caldata->chanmode)) {
 		/* Operating channel changed, reset channel calibration data */
 		memset(caldata, 0, sizeof(*caldata));
 		ath9k_init_nfcal_hist_buffer(ah, chan);
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/net/wireless/ath/ath9k/hw.h linux-libre-3.4.87-gnu1/drivers/net/wireless/ath/ath9k/hw.h
--- linux-libre-3.4.86-gnu1/drivers/net/wireless/ath/ath9k/hw.h	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/net/wireless/ath/ath9k/hw.h	2014-04-14 09:45:17.000000000 -0400
@@ -361,6 +361,7 @@ struct ath9k_rtt_hist {
 struct ath9k_hw_cal_data {
 	u16 channel;
 	u32 channelFlags;
+	u32 chanmode;
 	int32_t CalValid;
 	int8_t iCoff;
 	int8_t qCoff;
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/net/wireless/ath/ath9k/main.c linux-libre-3.4.87-gnu1/drivers/net/wireless/ath/ath9k/main.c
--- linux-libre-3.4.86-gnu1/drivers/net/wireless/ath/ath9k/main.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/net/wireless/ath/ath9k/main.c	2014-04-14 09:45:17.000000000 -0400
@@ -1614,13 +1614,6 @@ static int ath9k_config(struct ieee80211
 		ath_update_survey_stats(sc);
 		spin_unlock_irqrestore(&common->cc_lock, flags);
 
-		/*
-		 * Preserve the current channel values, before updating
-		 * the same channel
-		 */
-		if (ah->curchan && (old_pos == pos))
-			ath9k_hw_getnf(ah, ah->curchan);
-
 		ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos],
 					  curchan, conf->channel_type);
 
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/pps/clients/pps-ldisc.c linux-libre-3.4.87-gnu1/drivers/pps/clients/pps-ldisc.c
--- linux-libre-3.4.86-gnu1/drivers/pps/clients/pps-ldisc.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/pps/clients/pps-ldisc.c	2014-04-14 09:45:17.000000000 -0400
@@ -31,7 +31,7 @@
 static void pps_tty_dcd_change(struct tty_struct *tty, unsigned int status,
 				struct pps_event_time *ts)
 {
-	struct pps_device *pps = (struct pps_device *)tty->disc_data;
+	struct pps_device *pps = pps_lookup_dev(tty);
 
 	BUG_ON(pps == NULL);
 
@@ -67,9 +67,9 @@ static int pps_tty_open(struct tty_struc
 		pr_err("cannot register PPS source \"%s\"\n", info.path);
 		return -ENOMEM;
 	}
-	tty->disc_data = pps;
+	pps->lookup_cookie = tty;
 
-	/* Should open N_TTY ldisc too */
+	/* Now open the base class N_TTY ldisc */
 	ret = alias_n_tty_open(tty);
 	if (ret < 0) {
 		pr_err("cannot open tty ldisc \"%s\"\n", info.path);
@@ -81,7 +81,6 @@ static int pps_tty_open(struct tty_struc
 	return 0;
 
 err_unregister:
-	tty->disc_data = NULL;
 	pps_unregister_source(pps);
 	return ret;
 }
@@ -90,11 +89,10 @@ static void (*alias_n_tty_close)(struct
 
 static void pps_tty_close(struct tty_struct *tty)
 {
-	struct pps_device *pps = (struct pps_device *)tty->disc_data;
+	struct pps_device *pps = pps_lookup_dev(tty);
 
 	alias_n_tty_close(tty);
 
-	tty->disc_data = NULL;
 	dev_info(pps->dev, "removed\n");
 	pps_unregister_source(pps);
 }
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/pps/pps.c linux-libre-3.4.87-gnu1/drivers/pps/pps.c
--- linux-libre-3.4.86-gnu1/drivers/pps/pps.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/pps/pps.c	2014-04-14 09:45:17.000000000 -0400
@@ -247,12 +247,15 @@ static int pps_cdev_open(struct inode *i
 	struct pps_device *pps = container_of(inode->i_cdev,
 						struct pps_device, cdev);
 	file->private_data = pps;
-
+	kobject_get(&pps->dev->kobj);
 	return 0;
 }
 
 static int pps_cdev_release(struct inode *inode, struct file *file)
 {
+	struct pps_device *pps = container_of(inode->i_cdev,
+						struct pps_device, cdev);
+	kobject_put(&pps->dev->kobj);
 	return 0;
 }
 
@@ -274,8 +277,10 @@ static void pps_device_destruct(struct d
 {
 	struct pps_device *pps = dev_get_drvdata(dev);
 
-	/* release id here to protect others from using it while it's
-	 * still in use */
+	cdev_del(&pps->cdev);
+
+	/* Now we can release the ID for re-use */
+	pr_debug("deallocating pps%d\n", pps->id);
 	mutex_lock(&pps_idr_lock);
 	idr_remove(&pps_idr, pps->id);
 	mutex_unlock(&pps_idr_lock);
@@ -330,6 +335,7 @@ int pps_register_cdev(struct pps_device
 	if (IS_ERR(pps->dev))
 		goto del_cdev;
 
+	/* Override the release function with our own */
 	pps->dev->release = pps_device_destruct;
 
 	pr_debug("source %s got cdev (%d:%d)\n", pps->info.name,
@@ -350,11 +356,44 @@ free_idr:
 
 void pps_unregister_cdev(struct pps_device *pps)
 {
+	pr_debug("unregistering pps%d\n", pps->id);
+	pps->lookup_cookie = NULL;
 	device_destroy(pps_class, pps->dev->devt);
-	cdev_del(&pps->cdev);
 }
 
 /*
+ * Look up a pps device by magic cookie.
+ * The cookie is usually a pointer to some enclosing device, but this
+ * code doesn't care; you should never be dereferencing it.
+ *
+ * This is a bit of a kludge that is currently used only by the PPS
+ * serial line discipline.  It may need to be tweaked when a second user
+ * is found.
+ *
+ * There is no function interface for setting the lookup_cookie field.
+ * It's initialized to NULL when the pps device is created, and if a
+ * client wants to use it, just fill it in afterward.
+ *
+ * The cookie is automatically set to NULL in pps_unregister_source()
+ * so that it will not be used again, even if the pps device cannot
+ * be removed from the idr due to pending references holding the minor
+ * number in use.
+ */
+struct pps_device *pps_lookup_dev(void const *cookie)
+{
+	struct pps_device *pps;
+	unsigned id;
+
+	rcu_read_lock();
+	idr_for_each_entry(&pps_idr, pps, id)
+		if (cookie == pps->lookup_cookie)
+			break;
+	rcu_read_unlock();
+	return pps;
+}
+EXPORT_SYMBOL(pps_lookup_dev);
+
+/*
  * Module stuff
  */
 
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/usb/core/driver.c linux-libre-3.4.87-gnu1/drivers/usb/core/driver.c
--- linux-libre-3.4.86-gnu1/drivers/usb/core/driver.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/usb/core/driver.c	2014-04-14 09:45:17.000000000 -0400
@@ -530,22 +530,10 @@ int usb_match_device(struct usb_device *
 }
 
 /* returns 0 if no match, 1 if match */
-int usb_match_one_id(struct usb_interface *interface,
-		     const struct usb_device_id *id)
+int usb_match_one_id_intf(struct usb_device *dev,
+			  struct usb_host_interface *intf,
+			  const struct usb_device_id *id)
 {
-	struct usb_host_interface *intf;
-	struct usb_device *dev;
-
-	/* proc_connectinfo in devio.c may call us with id == NULL. */
-	if (id == NULL)
-		return 0;
-
-	intf = interface->cur_altsetting;
-	dev = interface_to_usbdev(interface);
-
-	if (!usb_match_device(dev, id))
-		return 0;
-
 	/* The interface class, subclass, and protocol should never be
 	 * checked for a match if the device class is Vendor Specific,
 	 * unless the match record specifies the Vendor ID. */
@@ -570,6 +558,26 @@ int usb_match_one_id(struct usb_interfac
 
 	return 1;
 }
+
+/* returns 0 if no match, 1 if match */
+int usb_match_one_id(struct usb_interface *interface,
+		     const struct usb_device_id *id)
+{
+	struct usb_host_interface *intf;
+	struct usb_device *dev;
+
+	/* proc_connectinfo in devio.c may call us with id == NULL. */
+	if (id == NULL)
+		return 0;
+
+	intf = interface->cur_altsetting;
+	dev = interface_to_usbdev(interface);
+
+	if (!usb_match_device(dev, id))
+		return 0;
+
+	return usb_match_one_id_intf(dev, intf, id);
+}
 EXPORT_SYMBOL_GPL(usb_match_one_id);
 
 /**
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/usb/core/hub.c linux-libre-3.4.87-gnu1/drivers/usb/core/hub.c
--- linux-libre-3.4.86-gnu1/drivers/usb/core/hub.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/usb/core/hub.c	2014-04-14 09:45:17.000000000 -0400
@@ -920,6 +920,11 @@ static void hub_activate(struct usb_hub
 			clear_port_feature(hub->hdev, port1,
 					USB_PORT_FEAT_C_ENABLE);
 		}
+		if (portchange & USB_PORT_STAT_C_RESET) {
+			need_debounce_delay = true;
+			clear_port_feature(hub->hdev, port1,
+					USB_PORT_FEAT_C_RESET);
+		}
 		if ((portchange & USB_PORT_STAT_C_BH_RESET) &&
 				hub_is_superspeed(hub->hdev)) {
 			need_debounce_delay = true;
@@ -1916,7 +1921,7 @@ static int usb_enumerate_device(struct u
 		if (err < 0) {
 			dev_err(&udev->dev, "can't read configurations, error %d\n",
 				err);
-			goto fail;
+			return err;
 		}
 	}
 
@@ -1927,8 +1932,12 @@ static int usb_enumerate_device(struct u
 	udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber);
 
 	err = usb_enumerate_device_otg(udev);
-fail:
-	return err;
+	if (err < 0)
+		return err;
+
+	usb_detect_interface_quirks(udev);
+
+	return 0;
 }
 
 static void set_usb_port_removable(struct usb_device *udev)
@@ -4135,6 +4144,12 @@ static int usb_reset_and_verify_device(s
 	}
 	parent_hub = hdev_to_hub(parent_hdev);
 
+	/* Disable USB2 hardware LPM.
+	 * It will be re-enabled by the enumeration process.
+	 */
+	if (udev->usb2_hw_lpm_enabled == 1)
+		usb_set_usb2_hardware_lpm(udev, 0);
+
 	set_bit(port1, parent_hub->busy_bits);
 	for (i = 0; i < SET_CONFIG_TRIES; ++i) {
 
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/usb/core/quirks.c linux-libre-3.4.87-gnu1/drivers/usb/core/quirks.c
--- linux-libre-3.4.86-gnu1/drivers/usb/core/quirks.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/usb/core/quirks.c	2014-04-14 09:45:17.000000000 -0400
@@ -15,17 +15,22 @@
 #include <linux/usb/quirks.h>
 #include "usb.h"
 
-/* List of quirky USB devices.  Please keep this list ordered by:
+/* Lists of quirky USB devices, split in device quirks and interface quirks.
+ * Device quirks are applied at the very beginning of the enumeration process,
+ * right after reading the device descriptor. They can thus only match on device
+ * information.
+ *
+ * Interface quirks are applied after reading all the configuration descriptors.
+ * They can match on both device and interface information.
+ *
+ * Note that the DELAY_INIT and HONOR_BNUMINTERFACES quirks do not make sense as
+ * interface quirks, as they only influence the enumeration process which is run
+ * before processing the interface quirks.
+ *
+ * Please keep the lists ordered by:
  * 	1) Vendor ID
  * 	2) Product ID
  * 	3) Class ID
- *
- * as we want specific devices to be overridden first, and only after that, any
- * class specific quirks.
- *
- * Right now the logic aborts if it finds a valid device in the table, we might
- * want to change that in the future if it turns out that a whole class of
- * devices is broken...
  */
 static const struct usb_device_id usb_quirk_list[] = {
 	/* CBM - Flash disk */
@@ -38,53 +43,26 @@ static const struct usb_device_id usb_qu
 	/* Creative SB Audigy 2 NX */
 	{ USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME },
 
-	/* Logitech Webcam C200 */
-	{ USB_DEVICE(0x046d, 0x0802), .driver_info = USB_QUIRK_RESET_RESUME },
-
-	/* Logitech Webcam C250 */
-	{ USB_DEVICE(0x046d, 0x0804), .driver_info = USB_QUIRK_RESET_RESUME },
-
-	/* Logitech Webcam C300 */
-	{ USB_DEVICE(0x046d, 0x0805), .driver_info = USB_QUIRK_RESET_RESUME },
-
-	/* Logitech Webcam B/C500 */
-	{ USB_DEVICE(0x046d, 0x0807), .driver_info = USB_QUIRK_RESET_RESUME },
-
-	/* Logitech Webcam C600 */
-	{ USB_DEVICE(0x046d, 0x0808), .driver_info = USB_QUIRK_RESET_RESUME },
-
-	/* Logitech Webcam Pro 9000 */
-	{ USB_DEVICE(0x046d, 0x0809), .driver_info = USB_QUIRK_RESET_RESUME },
-
-	/* Logitech Webcam C905 */
-	{ USB_DEVICE(0x046d, 0x080a), .driver_info = USB_QUIRK_RESET_RESUME },
-
-	/* Logitech Webcam C210 */
-	{ USB_DEVICE(0x046d, 0x0819), .driver_info = USB_QUIRK_RESET_RESUME },
-
-	/* Logitech Webcam C260 */
-	{ USB_DEVICE(0x046d, 0x081a), .driver_info = USB_QUIRK_RESET_RESUME },
-
-	/* Logitech Webcam C310 */
-	{ USB_DEVICE(0x046d, 0x081b), .driver_info = USB_QUIRK_RESET_RESUME },
+	/* Microsoft LifeCam-VX700 v2.0 */
+	{ USB_DEVICE(0x045e, 0x0770), .driver_info = USB_QUIRK_RESET_RESUME },
 
-	/* Logitech Webcam C910 */
-	{ USB_DEVICE(0x046d, 0x0821), .driver_info = USB_QUIRK_RESET_RESUME },
+	/* Logitech Quickcam Fusion */
+	{ USB_DEVICE(0x046d, 0x08c1), .driver_info = USB_QUIRK_RESET_RESUME },
 
-	/* Logitech Webcam C160 */
-	{ USB_DEVICE(0x046d, 0x0824), .driver_info = USB_QUIRK_RESET_RESUME },
+	/* Logitech Quickcam Orbit MP */
+	{ USB_DEVICE(0x046d, 0x08c2), .driver_info = USB_QUIRK_RESET_RESUME },
 
-	/* Logitech Webcam C270 */
-	{ USB_DEVICE(0x046d, 0x0825), .driver_info = USB_QUIRK_RESET_RESUME },
+	/* Logitech Quickcam Pro for Notebook */
+	{ USB_DEVICE(0x046d, 0x08c3), .driver_info = USB_QUIRK_RESET_RESUME },
 
-	/* Logitech Quickcam Pro 9000 */
-	{ USB_DEVICE(0x046d, 0x0990), .driver_info = USB_QUIRK_RESET_RESUME },
+	/* Logitech Quickcam Pro 5000 */
+	{ USB_DEVICE(0x046d, 0x08c5), .driver_info = USB_QUIRK_RESET_RESUME },
 
-	/* Logitech Quickcam E3500 */
-	{ USB_DEVICE(0x046d, 0x09a4), .driver_info = USB_QUIRK_RESET_RESUME },
+	/* Logitech Quickcam OEM Dell Notebook */
+	{ USB_DEVICE(0x046d, 0x08c6), .driver_info = USB_QUIRK_RESET_RESUME },
 
-	/* Logitech Quickcam Vision Pro */
-	{ USB_DEVICE(0x046d, 0x09a6), .driver_info = USB_QUIRK_RESET_RESUME },
+	/* Logitech Quickcam OEM Cisco VT Camera II */
+	{ USB_DEVICE(0x046d, 0x08c7), .driver_info = USB_QUIRK_RESET_RESUME },
 
 	/* Logitech Harmony 700-series */
 	{ USB_DEVICE(0x046d, 0xc122), .driver_info = USB_QUIRK_DELAY_INIT },
@@ -175,16 +153,57 @@ static const struct usb_device_id usb_qu
 	{ }  /* terminating entry must be last */
 };
 
-static const struct usb_device_id *find_id(struct usb_device *udev)
+static const struct usb_device_id usb_interface_quirk_list[] = {
+	/* Logitech UVC Cameras */
+	{ USB_VENDOR_AND_INTERFACE_INFO(0x046d, USB_CLASS_VIDEO, 1, 0),
+	  .driver_info = USB_QUIRK_RESET_RESUME },
+
+	{ }  /* terminating entry must be last */
+};
+
+static bool usb_match_any_interface(struct usb_device *udev,
+				    const struct usb_device_id *id)
 {
-	const struct usb_device_id *id = usb_quirk_list;
+	unsigned int i;
 
-	for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass ||
-			id->driver_info; id++) {
-		if (usb_match_device(udev, id))
-			return id;
+	for (i = 0; i < udev->descriptor.bNumConfigurations; ++i) {
+		struct usb_host_config *cfg = &udev->config[i];
+		unsigned int j;
+
+		for (j = 0; j < cfg->desc.bNumInterfaces; ++j) {
+			struct usb_interface_cache *cache;
+			struct usb_host_interface *intf;
+
+			cache = cfg->intf_cache[j];
+			if (cache->num_altsetting == 0)
+				continue;
+
+			intf = &cache->altsetting[0];
+			if (usb_match_one_id_intf(udev, intf, id))
+				return true;
+		}
 	}
-	return NULL;
+
+	return false;
+}
+
+static u32 __usb_detect_quirks(struct usb_device *udev,
+			       const struct usb_device_id *id)
+{
+	u32 quirks = 0;
+
+	for (; id->match_flags; id++) {
+		if (!usb_match_device(udev, id))
+			continue;
+
+		if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_INFO) &&
+		    !usb_match_any_interface(udev, id))
+			continue;
+
+		quirks |= (u32)(id->driver_info);
+	}
+
+	return quirks;
 }
 
 /*
@@ -192,14 +211,10 @@ static const struct usb_device_id *find_
  */
 void usb_detect_quirks(struct usb_device *udev)
 {
-	const struct usb_device_id *id = usb_quirk_list;
-
-	id = find_id(udev);
-	if (id)
-		udev->quirks = (u32)(id->driver_info);
+	udev->quirks = __usb_detect_quirks(udev, usb_quirk_list);
 	if (udev->quirks)
 		dev_dbg(&udev->dev, "USB quirks for this device: %x\n",
-				udev->quirks);
+			udev->quirks);
 
 	/* For the present, all devices default to USB-PERSIST enabled */
 #if 0		/* was: #ifdef CONFIG_PM */
@@ -216,3 +231,16 @@ void usb_detect_quirks(struct usb_device
 		udev->persist_enabled = 1;
 #endif	/* CONFIG_PM */
 }
+
+void usb_detect_interface_quirks(struct usb_device *udev)
+{
+	u32 quirks;
+
+	quirks = __usb_detect_quirks(udev, usb_interface_quirk_list);
+	if (quirks == 0)
+		return;
+
+	dev_dbg(&udev->dev, "USB interface quirks for this device: %x\n",
+		quirks);
+	udev->quirks |= quirks;
+}
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/usb/core/usb.h linux-libre-3.4.87-gnu1/drivers/usb/core/usb.h
--- linux-libre-3.4.86-gnu1/drivers/usb/core/usb.h	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/usb/core/usb.h	2014-04-14 09:45:17.000000000 -0400
@@ -24,6 +24,7 @@ extern void usb_disable_device(struct us
 extern int usb_deauthorize_device(struct usb_device *);
 extern int usb_authorize_device(struct usb_device *);
 extern void usb_detect_quirks(struct usb_device *udev);
+extern void usb_detect_interface_quirks(struct usb_device *udev);
 extern int usb_remove_device(struct usb_device *udev);
 
 extern int usb_get_device_descriptor(struct usb_device *dev,
@@ -35,6 +36,9 @@ extern int usb_set_configuration(struct
 extern int usb_choose_configuration(struct usb_device *udev);
 
 extern void usb_kick_khubd(struct usb_device *dev);
+extern int usb_match_one_id_intf(struct usb_device *dev,
+				 struct usb_host_interface *intf,
+				 const struct usb_device_id *id);
 extern int usb_match_device(struct usb_device *dev,
 			    const struct usb_device_id *id);
 extern void usb_forced_unbind_intf(struct usb_interface *intf);
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/usb/dwc3/dwc3-pci.c linux-libre-3.4.87-gnu1/drivers/usb/dwc3/dwc3-pci.c
--- linux-libre-3.4.86-gnu1/drivers/usb/dwc3/dwc3-pci.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/usb/dwc3/dwc3-pci.c	2014-04-14 09:45:17.000000000 -0400
@@ -47,6 +47,8 @@
 /* FIXME define these in <linux/pci_ids.h> */
 #define PCI_VENDOR_ID_SYNOPSYS		0x16c3
 #define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3	0xabcd
+#define PCI_DEVICE_ID_INTEL_BYT		0x0f37
+#define PCI_DEVICE_ID_INTEL_MRFLD	0x119e
 
 struct dwc3_pci {
 	struct device		*dev;
@@ -155,6 +157,8 @@ static DEFINE_PCI_DEVICE_TABLE(dwc3_pci_
 		PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS,
 				PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3),
 	},
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT), },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MRFLD), },
 	{  }	/* Terminating Entry */
 };
 MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table);
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/usb/dwc3/gadget.c linux-libre-3.4.87-gnu1/drivers/usb/dwc3/gadget.c
--- linux-libre-3.4.86-gnu1/drivers/usb/dwc3/gadget.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/usb/dwc3/gadget.c	2014-04-14 09:45:17.000000000 -0400
@@ -1483,10 +1483,19 @@ static void dwc3_gadget_free_endpoints(s
 
 	for (epnum = 0; epnum < DWC3_ENDPOINTS_NUM; epnum++) {
 		dep = dwc->eps[epnum];
-		dwc3_free_trb_pool(dep);
-
-		if (epnum != 0 && epnum != 1)
+		/*
+		 * Physical endpoints 0 and 1 are special; they form the
+		 * bi-directional USB endpoint 0.
+		 *
+		 * For those two physical endpoints, we don't allocate a TRB
+		 * pool nor do we add them the endpoints list. Due to that, we
+		 * shouldn't do these two operations otherwise we would end up
+		 * with all sorts of bugs when removing dwc3.ko.
+		 */
+		if (epnum != 0 && epnum != 1) {
+			dwc3_free_trb_pool(dep);
 			list_del(&dep->endpoint.ep_list);
+		}
 
 		kfree(dep);
 	}
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/usb/host/ehci-pci.c linux-libre-3.4.87-gnu1/drivers/usb/host/ehci-pci.c
--- linux-libre-3.4.86-gnu1/drivers/usb/host/ehci-pci.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/usb/host/ehci-pci.c	2014-04-14 09:45:17.000000000 -0400
@@ -549,7 +549,7 @@ static struct pci_driver ehci_pci_driver
 	.remove =	usb_hcd_pci_remove,
 	.shutdown = 	usb_hcd_pci_shutdown,
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
 	.driver =	{
 		.pm =	&usb_hcd_pci_pm_ops
 	},
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/usb/host/ehci-q.c linux-libre-3.4.87-gnu1/drivers/usb/host/ehci-q.c
--- linux-libre-3.4.86-gnu1/drivers/usb/host/ehci-q.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/usb/host/ehci-q.c	2014-04-14 09:45:17.000000000 -0400
@@ -264,18 +264,14 @@ ehci_urb_done(struct ehci_hcd *ehci, str
 __releases(ehci->lock)
 __acquires(ehci->lock)
 {
-	if (likely (urb->hcpriv != NULL)) {
-		struct ehci_qh	*qh = (struct ehci_qh *) urb->hcpriv;
-
-		/* S-mask in a QH means it's an interrupt urb */
-		if ((qh->hw->hw_info2 & cpu_to_hc32(ehci, QH_SMASK)) != 0) {
-
-			/* ... update hc-wide periodic stats (for usbfs) */
-			ehci_to_hcd(ehci)->self.bandwidth_int_reqs--;
-		}
-		qh_put (qh);
+	if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {
+		/* ... update hc-wide periodic stats */
+		ehci_to_hcd(ehci)->self.bandwidth_int_reqs--;
 	}
 
+	if (usb_pipetype(urb->pipe) != PIPE_ISOCHRONOUS)
+		qh_put((struct ehci_qh *) urb->hcpriv);
+
 	if (unlikely(urb->unlinked)) {
 		COUNT(ehci->stats.unlink);
 	} else {
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/usb/host/ehci-sched.c linux-libre-3.4.87-gnu1/drivers/usb/host/ehci-sched.c
--- linux-libre-3.4.86-gnu1/drivers/usb/host/ehci-sched.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/usb/host/ehci-sched.c	2014-04-14 09:45:17.000000000 -0400
@@ -1684,7 +1684,7 @@ itd_link_urb (
 
 	/* don't need that schedule data any more */
 	iso_sched_free (stream, iso_sched);
-	urb->hcpriv = NULL;
+	urb->hcpriv = stream;
 
 	timer_action (ehci, TIMER_IO_WATCHDOG);
 	return enable_periodic(ehci);
@@ -2094,7 +2094,7 @@ sitd_link_urb (
 
 	/* don't need that schedule data any more */
 	iso_sched_free (stream, sched);
-	urb->hcpriv = NULL;
+	urb->hcpriv = stream;
 
 	timer_action (ehci, TIMER_IO_WATCHDOG);
 	return enable_periodic(ehci);
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/usb/host/ohci-pci.c linux-libre-3.4.87-gnu1/drivers/usb/host/ohci-pci.c
--- linux-libre-3.4.86-gnu1/drivers/usb/host/ohci-pci.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/usb/host/ohci-pci.c	2014-04-14 09:45:17.000000000 -0400
@@ -414,7 +414,7 @@ static struct pci_driver ohci_pci_driver
 	.remove =	usb_hcd_pci_remove,
 	.shutdown =	usb_hcd_pci_shutdown,
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
 	.driver =	{
 		.pm =	&usb_hcd_pci_pm_ops
 	},
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/usb/host/uhci-pci.c linux-libre-3.4.87-gnu1/drivers/usb/host/uhci-pci.c
--- linux-libre-3.4.86-gnu1/drivers/usb/host/uhci-pci.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/usb/host/uhci-pci.c	2014-04-14 09:45:17.000000000 -0400
@@ -293,7 +293,7 @@ static struct pci_driver uhci_pci_driver
 	.remove =	usb_hcd_pci_remove,
 	.shutdown =	uhci_shutdown,
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
 	.driver =	{
 		.pm =	&usb_hcd_pci_pm_ops
 	},
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/usb/host/xhci.c linux-libre-3.4.87-gnu1/drivers/usb/host/xhci.c
--- linux-libre-3.4.86-gnu1/drivers/usb/host/xhci.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/usb/host/xhci.c	2014-04-14 09:45:17.000000000 -0400
@@ -779,12 +779,19 @@ void xhci_shutdown(struct usb_hcd *hcd)
 
 	spin_lock_irq(&xhci->lock);
 	xhci_halt(xhci);
+	/* Workaround for spurious wakeups at shutdown with HSW */
+	if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
+		xhci_reset(xhci);
 	spin_unlock_irq(&xhci->lock);
 
 	xhci_cleanup_msix(xhci);
 
 	xhci_dbg(xhci, "xhci_shutdown completed - status = %x\n",
 		    xhci_readl(xhci, &xhci->op_regs->status));
+
+	/* Yet another workaround for spurious wakeups at shutdown with HSW */
+	if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
+		pci_set_power_state(to_pci_dev(hcd->self.controller), PCI_D3hot);
 }
 
 #ifdef CONFIG_PM
@@ -886,6 +893,7 @@ static void xhci_clear_command_ring(stru
 int xhci_suspend(struct xhci_hcd *xhci)
 {
 	int			rc = 0;
+	unsigned int		delay = XHCI_MAX_HALT_USEC;
 	struct usb_hcd		*hcd = xhci_to_hcd(xhci);
 	u32			command;
 
@@ -904,8 +912,12 @@ int xhci_suspend(struct xhci_hcd *xhci)
 	command = xhci_readl(xhci, &xhci->op_regs->command);
 	command &= ~CMD_RUN;
 	xhci_writel(xhci, command, &xhci->op_regs->command);
+
+	/* Some chips from Fresco Logic need an extraordinary delay */
+	delay *= (xhci->quirks & XHCI_SLOW_SUSPEND) ? 10 : 1;
+
 	if (handshake(xhci, &xhci->op_regs->status,
-		      STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC)) {
+		      STS_HALT, STS_HALT, delay)) {
 		xhci_warn(xhci, "WARN: xHC CMD_RUN timeout\n");
 		spin_unlock_irq(&xhci->lock);
 		return -ETIMEDOUT;
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/usb/host/xhci.h linux-libre-3.4.87-gnu1/drivers/usb/host/xhci.h
--- linux-libre-3.4.86-gnu1/drivers/usb/host/xhci.h	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/usb/host/xhci.h	2014-04-14 09:45:17.000000000 -0400
@@ -1509,6 +1509,8 @@ struct xhci_hcd {
 #define XHCI_COMP_MODE_QUIRK	(1 << 14)
 #define XHCI_AVOID_BEI		(1 << 15)
 #define XHCI_PLAT		(1 << 16)
+#define XHCI_SLOW_SUSPEND	(1 << 17)
+#define XHCI_SPURIOUS_WAKEUP	(1 << 18)
 	unsigned int		num_active_eps;
 	unsigned int		limit_active_eps;
 	/* There are two roothubs to keep track of bus suspend info for */
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/usb/host/xhci-hub.c linux-libre-3.4.87-gnu1/drivers/usb/host/xhci-hub.c
--- linux-libre-3.4.86-gnu1/drivers/usb/host/xhci-hub.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/usb/host/xhci-hub.c	2014-04-14 09:45:17.000000000 -0400
@@ -1048,20 +1048,6 @@ int xhci_bus_suspend(struct usb_hcd *hcd
 		t1 = xhci_port_state_to_neutral(t1);
 		if (t1 != t2)
 			xhci_writel(xhci, t2, port_array[port_index]);
-
-		if (hcd->speed != HCD_USB3) {
-			/* enable remote wake up for USB 2.0 */
-			__le32 __iomem *addr;
-			u32 tmp;
-
-			/* Add one to the port status register address to get
-			 * the port power control register address.
-			 */
-			addr = port_array[port_index] + 1;
-			tmp = xhci_readl(xhci, addr);
-			tmp |= PORT_RWE;
-			xhci_writel(xhci, tmp, addr);
-		}
 	}
 	hcd->state = HC_STATE_SUSPENDED;
 	bus_state->next_statechange = jiffies + msecs_to_jiffies(10);
@@ -1140,20 +1126,6 @@ int xhci_bus_resume(struct usb_hcd *hcd)
 				xhci_ring_device(xhci, slot_id);
 		} else
 			xhci_writel(xhci, temp, port_array[port_index]);
-
-		if (hcd->speed != HCD_USB3) {
-			/* disable remote wake up for USB 2.0 */
-			__le32 __iomem *addr;
-			u32 tmp;
-
-			/* Add one to the port status register address to get
-			 * the port power control register address.
-			 */
-			addr = port_array[port_index] + 1;
-			tmp = xhci_readl(xhci, addr);
-			tmp &= ~PORT_RWE;
-			xhci_writel(xhci, tmp, addr);
-		}
 	}
 
 	(void) xhci_readl(xhci, &xhci->op_regs->command);
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/usb/host/xhci-pci.c linux-libre-3.4.87-gnu1/drivers/usb/host/xhci-pci.c
--- linux-libre-3.4.86-gnu1/drivers/usb/host/xhci-pci.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/usb/host/xhci-pci.c	2014-04-14 09:45:17.000000000 -0400
@@ -34,6 +34,9 @@
 #define PCI_VENDOR_ID_ETRON		0x1b6f
 #define PCI_DEVICE_ID_ASROCK_P67	0x7023
 
+#define PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI	0x8c31
+#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI	0x9c31
+
 static const char hcd_name[] = "xhci_hcd";
 
 /* called after powerup, by probe or system-pm "wakeup" */
@@ -67,6 +70,14 @@ static void xhci_pci_quirks(struct devic
 			xhci_dbg(xhci, "QUIRK: Fresco Logic xHC needs configure"
 					" endpoint cmd after reset endpoint\n");
 		}
+		if (pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK &&
+				pdev->revision == 0x4) {
+			xhci->quirks |= XHCI_SLOW_SUSPEND;
+			xhci_dbg(xhci,
+				"QUIRK: Fresco Logic xHC revision %u"
+				"must be suspended extra slowly",
+				pdev->revision);
+		}
 		/* Fresco Logic confirms: all revisions of this chip do not
 		 * support MSI, even though some of them claim to in their PCI
 		 * capabilities.
@@ -103,6 +114,20 @@ static void xhci_pci_quirks(struct devic
 		xhci->quirks |= XHCI_SPURIOUS_REBOOT;
 		xhci->quirks |= XHCI_AVOID_BEI;
 	}
+	if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
+	    (pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI ||
+	     pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI)) {
+		/* Workaround for occasional spurious wakeups from S5 (or
+		 * any other sleep) on Haswell machines with LPT and LPT-LP
+		 * with the new Intel BIOS
+		 */
+		/* Limit the quirk to only known vendors, as this triggers
+		 * yet another BIOS bug on some other machines
+		 * https://bugzilla.kernel.org/show_bug.cgi?id=66171
+		 */
+		if (pdev->subsystem_vendor == PCI_VENDOR_ID_HP)
+			xhci->quirks |= XHCI_SPURIOUS_WAKEUP;
+	}
 	if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
 			pdev->device == PCI_DEVICE_ID_ASROCK_P67) {
 		xhci->quirks |= XHCI_RESET_ON_RESUME;
@@ -207,6 +232,11 @@ static void xhci_pci_remove(struct pci_d
 		usb_put_hcd(xhci->shared_hcd);
 	}
 	usb_hcd_pci_remove(dev);
+
+	/* Workaround for spurious wakeups at shutdown with HSW */
+	if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
+		pci_set_power_state(dev, PCI_D3hot);
+
 	kfree(xhci);
 }
 
@@ -335,7 +365,7 @@ static struct pci_driver xhci_pci_driver
 	/* suspend and resume implemented later */
 
 	.shutdown = 	usb_hcd_pci_shutdown,
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
 	.driver = {
 		.pm = &usb_hcd_pci_pm_ops
 	},
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/usb/misc/adutux.c linux-libre-3.4.87-gnu1/drivers/usb/misc/adutux.c
--- linux-libre-3.4.86-gnu1/drivers/usb/misc/adutux.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/usb/misc/adutux.c	2014-04-14 09:45:17.000000000 -0400
@@ -829,7 +829,7 @@ static int adu_probe(struct usb_interfac
 
 	/* let the user know what node this device is now attached to */
 	dev_info(&interface->dev, "ADU%d %s now attached to /dev/usb/adutux%d\n",
-		 udev->descriptor.idProduct, dev->serial_number,
+		 le16_to_cpu(udev->descriptor.idProduct), dev->serial_number,
 		 (dev->minor - ADU_MINOR_BASE));
 exit:
 	dbg(2," %s : leave, return value %p (dev)", __func__, dev);
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/usb/serial/ark3116.c linux-libre-3.4.87-gnu1/drivers/usb/serial/ark3116.c
--- linux-libre-3.4.86-gnu1/drivers/usb/serial/ark3116.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/usb/serial/ark3116.c	2014-04-14 09:45:17.000000000 -0400
@@ -68,7 +68,6 @@ static int is_irda(struct usb_serial *se
 }
 
 struct ark3116_private {
-	wait_queue_head_t       delta_msr_wait;
 	struct async_icount	icount;
 	int			irda;	/* 1 for irda device */
 
@@ -148,7 +147,6 @@ static int ark3116_attach(struct usb_ser
 	if (!priv)
 		return -ENOMEM;
 
-	init_waitqueue_head(&priv->delta_msr_wait);
 	mutex_init(&priv->hw_lock);
 	spin_lock_init(&priv->status_lock);
 
@@ -460,10 +458,14 @@ static int ark3116_ioctl(struct tty_stru
 	case TIOCMIWAIT:
 		for (;;) {
 			struct async_icount prev = priv->icount;
-			interruptible_sleep_on(&priv->delta_msr_wait);
+			interruptible_sleep_on(&port->delta_msr_wait);
 			/* see if a signal did it */
 			if (signal_pending(current))
 				return -ERESTARTSYS;
+
+			if (port->serial->disconnected)
+				return -EIO;
+
 			if ((prev.rng == priv->icount.rng) &&
 			    (prev.dsr == priv->icount.dsr) &&
 			    (prev.dcd == priv->icount.dcd) &&
@@ -584,7 +586,7 @@ static void ark3116_update_msr(struct us
 			priv->icount.dcd++;
 		if (msr & UART_MSR_TERI)
 			priv->icount.rng++;
-		wake_up_interruptible(&priv->delta_msr_wait);
+		wake_up_interruptible(&port->delta_msr_wait);
 	}
 }
 
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/usb/serial/ch341.c linux-libre-3.4.87-gnu1/drivers/usb/serial/ch341.c
--- linux-libre-3.4.86-gnu1/drivers/usb/serial/ch341.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/usb/serial/ch341.c	2014-04-14 09:45:17.000000000 -0400
@@ -82,7 +82,6 @@ MODULE_DEVICE_TABLE(usb, id_table);
 
 struct ch341_private {
 	spinlock_t lock; /* access lock */
-	wait_queue_head_t delta_msr_wait; /* wait queue for modem status */
 	unsigned baud_rate; /* set baud rate */
 	u8 line_control; /* set line control value RTS/DTR */
 	u8 line_status; /* active status of modem control inputs */
@@ -262,7 +261,6 @@ static int ch341_attach(struct usb_seria
 		return -ENOMEM;
 
 	spin_lock_init(&priv->lock);
-	init_waitqueue_head(&priv->delta_msr_wait);
 	priv->baud_rate = DEFAULT_BAUD_RATE;
 	priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR;
 
@@ -299,7 +297,7 @@ static void ch341_dtr_rts(struct usb_ser
 		priv->line_control &= ~(CH341_BIT_RTS | CH341_BIT_DTR);
 	spin_unlock_irqrestore(&priv->lock, flags);
 	ch341_set_handshake(port->serial->dev, priv->line_control);
-	wake_up_interruptible(&priv->delta_msr_wait);
+	wake_up_interruptible(&port->delta_msr_wait);
 }
 
 static void ch341_close(struct usb_serial_port *port)
@@ -502,7 +500,7 @@ static void ch341_read_int_callback(stru
 			tty_kref_put(tty);
 		}
 
-		wake_up_interruptible(&priv->delta_msr_wait);
+		wake_up_interruptible(&port->delta_msr_wait);
 	}
 
 exit:
@@ -528,11 +526,14 @@ static int wait_modem_info(struct usb_se
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	while (!multi_change) {
-		interruptible_sleep_on(&priv->delta_msr_wait);
+		interruptible_sleep_on(&port->delta_msr_wait);
 		/* see if a signal did it */
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 
+		if (port->serial->disconnected)
+			return -EIO;
+
 		spin_lock_irqsave(&priv->lock, flags);
 		status = priv->line_status;
 		multi_change = priv->multi_status_change;
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/usb/serial/cypress_m8.c linux-libre-3.4.87-gnu1/drivers/usb/serial/cypress_m8.c
--- linux-libre-3.4.86-gnu1/drivers/usb/serial/cypress_m8.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/usb/serial/cypress_m8.c	2014-04-14 09:45:17.000000000 -0400
@@ -125,7 +125,6 @@ struct cypress_private {
 	int baud_rate;			   /* stores current baud rate in
 					      integer form */
 	int isthrottled;		   /* if throttled, discard reads */
-	wait_queue_head_t delta_msr_wait;  /* used for TIOCMIWAIT */
 	char prev_status, diff_status;	   /* used for TIOCMIWAIT */
 	/* we pass a pointer to this as the argument sent to
 	   cypress_set_termios old_termios */
@@ -475,7 +474,6 @@ static int generic_startup(struct usb_se
 		kfree(priv);
 		return -ENOMEM;
 	}
-	init_waitqueue_head(&priv->delta_msr_wait);
 
 	/* Skip reset for FRWD device. It is a workaound:
 	   device hangs if it receives SET_CONFIGURE in Configured
@@ -919,12 +917,16 @@ static int cypress_ioctl(struct tty_stru
 	switch (cmd) {
 	/* This code comes from drivers/char/serial.c and ftdi_sio.c */
 	case TIOCMIWAIT:
-		while (priv != NULL) {
-			interruptible_sleep_on(&priv->delta_msr_wait);
+		for (;;) {
+			interruptible_sleep_on(&port->delta_msr_wait);
 			/* see if a signal did it */
 			if (signal_pending(current))
 				return -ERESTARTSYS;
-			else {
+
+			if (port->serial->disconnected)
+				return -EIO;
+
+			{
 				char diff = priv->diff_status;
 				if (diff == 0)
 					return -EIO; /* no change => error */
@@ -1250,7 +1252,7 @@ static void cypress_read_int_callback(st
 	if (priv->current_status != priv->prev_status) {
 		priv->diff_status |= priv->current_status ^
 			priv->prev_status;
-		wake_up_interruptible(&priv->delta_msr_wait);
+		wake_up_interruptible(&port->delta_msr_wait);
 		priv->prev_status = priv->current_status;
 	}
 	spin_unlock_irqrestore(&priv->lock, flags);
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/usb/serial/ftdi_sio.c linux-libre-3.4.87-gnu1/drivers/usb/serial/ftdi_sio.c
--- linux-libre-3.4.86-gnu1/drivers/usb/serial/ftdi_sio.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/usb/serial/ftdi_sio.c	2014-04-14 09:45:17.000000000 -0400
@@ -74,9 +74,7 @@ struct ftdi_private {
 	int flags;		/* some ASYNC_xxxx flags are supported */
 	unsigned long last_dtr_rts;	/* saved modem control outputs */
 	struct async_icount	icount;
-	wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
 	char prev_status;        /* Used for TIOCMIWAIT */
-	bool dev_gone;        /* Used to abort TIOCMIWAIT */
 	char transmit_empty;	/* If transmitter is empty or not */
 	struct usb_serial_port *port;
 	__u16 interface;	/* FT2232C, FT2232H or FT4232H port interface
@@ -1746,10 +1744,8 @@ static int ftdi_sio_port_probe(struct us
 	kref_init(&priv->kref);
 	mutex_init(&priv->cfg_lock);
 	memset(&priv->icount, 0x00, sizeof(priv->icount));
-	init_waitqueue_head(&priv->delta_msr_wait);
 
 	priv->flags = ASYNC_LOW_LATENCY;
-	priv->dev_gone = false;
 
 	if (quirk && quirk->port_probe)
 		quirk->port_probe(priv);
@@ -1859,8 +1855,11 @@ static int ftdi_8u2232c_probe(struct usb
 }
 
 /*
- * First and second port on STMCLiteadaptors is reserved for JTAG interface
- * and the forth port for pio
+ * First two ports on JTAG adaptors using an FT4232 such as STMicroelectronics's
+ * ST Micro Connect Lite are reserved for JTAG or other non-UART interfaces and
+ * can be accessed from userspace.
+ * The next two ports are enabled as UARTs by default, where port 2 is
+ * a conventional RS-232 UART.
  */
 static int ftdi_stmclite_probe(struct usb_serial *serial)
 {
@@ -1869,12 +1868,13 @@ static int ftdi_stmclite_probe(struct us
 
 	dbg("%s", __func__);
 
-	if (interface == udev->actconfig->interface[2])
-		return 0;
-
-	dev_info(&udev->dev, "Ignoring serial port reserved for JTAG\n");
+	if (interface == udev->actconfig->interface[0] ||
+	    interface == udev->actconfig->interface[1]) {
+		dev_info(&udev->dev, "Ignoring serial port reserved for JTAG\n");
+		return -ENODEV;
+	}
 
-	return -ENODEV;
+	return 0;
 }
 
 /*
@@ -1908,8 +1908,7 @@ static int ftdi_sio_port_remove(struct u
 
 	dbg("%s", __func__);
 
-	priv->dev_gone = true;
-	wake_up_interruptible_all(&priv->delta_msr_wait);
+	wake_up_interruptible(&port->delta_msr_wait);
 
 	remove_sysfs_attrs(port);
 
@@ -2064,7 +2063,7 @@ static int ftdi_process_packet(struct tt
 		if (diff_status & FTDI_RS0_RLSD)
 			priv->icount.dcd++;
 
-		wake_up_interruptible_all(&priv->delta_msr_wait);
+		wake_up_interruptible(&port->delta_msr_wait);
 		priv->prev_status = status;
 	}
 
@@ -2202,6 +2201,20 @@ static void ftdi_set_termios(struct tty_
 		termios->c_cflag |= CRTSCTS;
 	}
 
+	/*
+	 * All FTDI UART chips are limited to CS7/8. We won't pretend to
+	 * support CS5/6 and revert the CSIZE setting instead.
+	 */
+	if ((C_CSIZE(tty) != CS8) && (C_CSIZE(tty) != CS7)) {
+		dev_warn(&port->dev, "requested CSIZE setting not supported\n");
+
+		termios->c_cflag &= ~CSIZE;
+		if (old_termios)
+			termios->c_cflag |= old_termios->c_cflag & CSIZE;
+		else
+			termios->c_cflag |= CS8;
+	}
+
 	cflag = termios->c_cflag;
 
 	if (!old_termios)
@@ -2238,13 +2251,16 @@ no_skip:
 	} else {
 		urb_value |= FTDI_SIO_SET_DATA_PARITY_NONE;
 	}
-	if (cflag & CSIZE) {
-		switch (cflag & CSIZE) {
-		case CS7: urb_value |= 7; dbg("Setting CS7"); break;
-		case CS8: urb_value |= 8; dbg("Setting CS8"); break;
-		default:
-			dev_err(&port->dev, "CSIZE was set but not CS7-CS8\n");
-		}
+	switch (cflag & CSIZE) {
+	case CS7:
+		urb_value |= 7;
+		dev_dbg(&port->dev, "Setting CS7\n");
+		break;
+	default:
+	case CS8:
+		urb_value |= 8;
+		dev_dbg(&port->dev, "Setting CS8\n");
+		break;
 	}
 
 	/* This is needed by the break command since it uses the same command
@@ -2467,11 +2483,15 @@ static int ftdi_ioctl(struct tty_struct
 	 */
 	case TIOCMIWAIT:
 		cprev = priv->icount;
-		while (!priv->dev_gone) {
-			interruptible_sleep_on(&priv->delta_msr_wait);
+		for (;;) {
+			interruptible_sleep_on(&port->delta_msr_wait);
 			/* see if a signal did it */
 			if (signal_pending(current))
 				return -ERESTARTSYS;
+
+			if (port->serial->disconnected)
+				return -EIO;
+
 			cnow = priv->icount;
 			if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
 			    ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
@@ -2481,8 +2501,6 @@ static int ftdi_ioctl(struct tty_struct
 			}
 			cprev = cnow;
 		}
-		return -EIO;
-		break;
 	case TIOCSERGETLSR:
 		return get_lsr_info(port, (struct serial_struct __user *)arg);
 		break;
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/usb/serial/io_edgeport.c linux-libre-3.4.87-gnu1/drivers/usb/serial/io_edgeport.c
--- linux-libre-3.4.86-gnu1/drivers/usb/serial/io_edgeport.c	2014-04-04 04:51:08.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/usb/serial/io_edgeport.c	2014-04-14 14:31:46.000000000 -0400
@@ -114,7 +114,6 @@ struct edgeport_port {
 	wait_queue_head_t	wait_chase;		/* for handling sleeping while waiting for chase to finish */
 	wait_queue_head_t	wait_open;		/* for handling sleeping while waiting for open to finish */
 	wait_queue_head_t	wait_command;		/* for handling sleeping while waiting for command to finish */
-	wait_queue_head_t	delta_msr_wait;		/* for handling sleeping while waiting for msr change to happen */
 
 	struct async_icount	icount;
 	struct usb_serial_port	*port;			/* loop back to the owner of this object */
@@ -884,7 +883,6 @@ static int edge_open(struct tty_struct *
 	/* initialize our wait queues */
 	init_waitqueue_head(&edge_port->wait_open);
 	init_waitqueue_head(&edge_port->wait_chase);
-	init_waitqueue_head(&edge_port->delta_msr_wait);
 	init_waitqueue_head(&edge_port->wait_command);
 
 	/* initialize our icount structure */
@@ -1701,13 +1699,17 @@ static int edge_ioctl(struct tty_struct
 		dbg("%s (%d) TIOCMIWAIT", __func__,  port->number);
 		cprev = edge_port->icount;
 		while (1) {
-			prepare_to_wait(&edge_port->delta_msr_wait,
+			prepare_to_wait(&port->delta_msr_wait,
 						&wait, TASK_INTERRUPTIBLE);
 			schedule();
-			finish_wait(&edge_port->delta_msr_wait, &wait);
+			finish_wait(&port->delta_msr_wait, &wait);
 			/* see if a signal did it */
 			if (signal_pending(current))
 				return -ERESTARTSYS;
+
+			if (port->serial->disconnected)
+				return -EIO;
+
 			cnow = edge_port->icount;
 			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
 			    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
@@ -2088,7 +2090,7 @@ static void handle_new_msr(struct edgepo
 			icount->dcd++;
 		if (newMsr & EDGEPORT_MSR_DELTA_RI)
 			icount->rng++;
-		wake_up_interruptible(&edge_port->delta_msr_wait);
+		wake_up_interruptible(&edge_port->port->delta_msr_wait);
 	}
 
 	/* Save the new modem status */
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/usb/serial/io_ti.c linux-libre-3.4.87-gnu1/drivers/usb/serial/io_ti.c
--- linux-libre-3.4.86-gnu1/drivers/usb/serial/io_ti.c	2014-04-04 04:51:13.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/usb/serial/io_ti.c	2014-04-14 14:31:51.000000000 -0400
@@ -91,9 +91,6 @@ struct edgeport_port {
 	int close_pending;
 	int lsr_event;
 	struct async_icount	icount;
-	wait_queue_head_t	delta_msr_wait;	/* for handling sleeping while
-						   waiting for msr change to
-						   happen */
 	struct edgeport_serial	*edge_serial;
 	struct usb_serial_port	*port;
 	__u8 bUartMode;		/* Port type, 0: RS232, etc. */
@@ -1549,7 +1546,7 @@ static void handle_new_msr(struct edgepo
 			icount->dcd++;
 		if (msr & EDGEPORT_MSR_DELTA_RI)
 			icount->rng++;
-		wake_up_interruptible(&edge_port->delta_msr_wait);
+		wake_up_interruptible(&edge_port->port->delta_msr_wait);
 	}
 
 	/* Save the new modem status */
@@ -1867,7 +1864,6 @@ static int edge_open(struct tty_struct *
 	dev = port->serial->dev;
 
 	memset(&(edge_port->icount), 0x00, sizeof(edge_port->icount));
-	init_waitqueue_head(&edge_port->delta_msr_wait);
 
 	/* turn off loopback */
 	status = ti_do_config(edge_port, UMPC_SET_CLR_LOOPBACK, 0);
@@ -2553,10 +2549,14 @@ static int edge_ioctl(struct tty_struct
 		dbg("%s - (%d) TIOCMIWAIT", __func__, port->number);
 		cprev = edge_port->icount;
 		while (1) {
-			interruptible_sleep_on(&edge_port->delta_msr_wait);
+			interruptible_sleep_on(&port->delta_msr_wait);
 			/* see if a signal did it */
 			if (signal_pending(current))
 				return -ERESTARTSYS;
+
+			if (port->serial->disconnected)
+				return -EIO;
+
 			cnow = edge_port->icount;
 			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
 			    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/usb/serial/keyspan.c linux-libre-3.4.87-gnu1/drivers/usb/serial/keyspan.c
--- linux-libre-3.4.86-gnu1/drivers/usb/serial/keyspan.c	2014-04-04 04:50:57.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/usb/serial/keyspan.c	2014-04-14 14:31:35.000000000 -0400
@@ -2486,7 +2486,7 @@ static int keyspan_startup(struct usb_se
 	if (d_details == NULL) {
 		dev_err(&serial->dev->dev, "%s - unknown product id %x\n",
 		    __func__, le16_to_cpu(serial->dev->descriptor.idProduct));
-		return 1;
+		return -ENODEV;
 	}
 
 	/* Setup private data for serial driver */
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/usb/serial/mct_u232.c linux-libre-3.4.87-gnu1/drivers/usb/serial/mct_u232.c
--- linux-libre-3.4.86-gnu1/drivers/usb/serial/mct_u232.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/usb/serial/mct_u232.c	2014-04-14 09:45:17.000000000 -0400
@@ -126,8 +126,6 @@ struct mct_u232_private {
 	unsigned char	     last_msr;      /* Modem Status Register */
 	unsigned int	     rx_flags;      /* Throttling flags */
 	struct async_icount  icount;
-	wait_queue_head_t    msr_wait;	/* for handling sleeping while waiting
-						for msr change to happen */
 };
 
 #define THROTTLED		0x01
@@ -407,7 +405,6 @@ static int mct_u232_startup(struct usb_s
 	if (!priv)
 		return -ENOMEM;
 	spin_lock_init(&priv->lock);
-	init_waitqueue_head(&priv->msr_wait);
 	usb_set_serial_port_data(serial->port[0], priv);
 
 	init_waitqueue_head(&serial->port[0]->write_wait);
@@ -631,7 +628,7 @@ static void mct_u232_read_int_callback(s
 		tty_kref_put(tty);
 	}
 #endif
-	wake_up_interruptible(&priv->msr_wait);
+	wake_up_interruptible(&port->delta_msr_wait);
 	spin_unlock_irqrestore(&priv->lock, flags);
 exit:
 	retval = usb_submit_urb(urb, GFP_ATOMIC);
@@ -852,13 +849,17 @@ static int  mct_u232_ioctl(struct tty_st
 		cprev = mct_u232_port->icount;
 		spin_unlock_irqrestore(&mct_u232_port->lock, flags);
 		for ( ; ; ) {
-			prepare_to_wait(&mct_u232_port->msr_wait,
+			prepare_to_wait(&port->delta_msr_wait,
 					&wait, TASK_INTERRUPTIBLE);
 			schedule();
-			finish_wait(&mct_u232_port->msr_wait, &wait);
+			finish_wait(&port->delta_msr_wait, &wait);
 			/* see if a signal did it */
 			if (signal_pending(current))
 				return -ERESTARTSYS;
+
+			if (port->serial->disconnected)
+				return -EIO;
+
 			spin_lock_irqsave(&mct_u232_port->lock, flags);
 			cnow = mct_u232_port->icount;
 			spin_unlock_irqrestore(&mct_u232_port->lock, flags);
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/usb/serial/mos7840.c linux-libre-3.4.87-gnu1/drivers/usb/serial/mos7840.c
--- linux-libre-3.4.86-gnu1/drivers/usb/serial/mos7840.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/usb/serial/mos7840.c	2014-04-14 09:45:17.000000000 -0400
@@ -185,6 +185,10 @@
 #define URB_TRANSFER_BUFFER_SIZE        32	/* URB Size  */
 
 
+enum mos7840_flag {
+	MOS7840_FLAG_CTRL_BUSY,
+};
+
 static const struct usb_device_id moschip_port_id_table[] = {
 	{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)},
 	{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)},
@@ -240,7 +244,6 @@ struct moschip_port {
 	char open;
 	char open_ports;
 	wait_queue_head_t wait_chase;	/* for handling sleeping while waiting for chase to finish */
-	wait_queue_head_t delta_msr_wait;	/* for handling sleeping while waiting for msr change to happen */
 	int delta_msr_cond;
 	struct async_icount icount;
 	struct usb_serial_port *port;	/* loop back to the owner of this object */
@@ -259,6 +262,8 @@ struct moschip_port {
 	struct urb *write_urb_pool[NUM_URBS];
 	char busy[NUM_URBS];
 	bool read_urb_busy;
+
+	unsigned long flags;
 };
 
 
@@ -453,6 +458,9 @@ static void mos7840_handle_new_msr(struc
 			icount->rng++;
 			smp_wmb();
 		}
+
+		mos7840_port->delta_msr_cond = 1;
+		wake_up_interruptible(&port->port->delta_msr_wait);
 	}
 }
 
@@ -517,11 +525,11 @@ static void mos7840_control_callback(str
 		/* this urb is terminated, clean up */
 		dbg("%s - urb shutting down with status: %d", __func__,
 		    status);
-		return;
+		goto out;
 	default:
 		dbg("%s - nonzero urb status received: %d", __func__,
 		    status);
-		return;
+		goto out;
 	}
 
 	dbg("%s urb buffer size is %d", __func__, urb->actual_length);
@@ -534,6 +542,8 @@ static void mos7840_control_callback(str
 		mos7840_handle_new_msr(mos7840_port, regval);
 	else if (mos7840_port->MsrLsr == 1)
 		mos7840_handle_new_lsr(mos7840_port, regval);
+out:
+	clear_bit_unlock(MOS7840_FLAG_CTRL_BUSY, &mos7840_port->flags);
 }
 
 static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg,
@@ -544,6 +554,9 @@ static int mos7840_get_reg(struct moschi
 	unsigned char *buffer = mcs->ctrl_buf;
 	int ret;
 
+	if (test_and_set_bit_lock(MOS7840_FLAG_CTRL_BUSY, &mcs->flags))
+		return -EBUSY;
+
 	dr->bRequestType = MCS_RD_RTYPE;
 	dr->bRequest = MCS_RDREQ;
 	dr->wValue = cpu_to_le16(Wval);	/* 0 */
@@ -555,6 +568,9 @@ static int mos7840_get_reg(struct moschi
 			     mos7840_control_callback, mcs);
 	mcs->control_urb->transfer_buffer_length = 2;
 	ret = usb_submit_urb(mcs->control_urb, GFP_ATOMIC);
+	if (ret)
+		clear_bit_unlock(MOS7840_FLAG_CTRL_BUSY, &mcs->flags);
+
 	return ret;
 }
 
@@ -921,20 +937,20 @@ static int mos7840_open(struct tty_struc
 	status = mos7840_get_reg_sync(port, mos7840_port->SpRegOffset, &Data);
 	if (status < 0) {
 		dbg("Reading Spreg failed");
-		return -1;
+		goto err;
 	}
 	Data |= 0x80;
 	status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data);
 	if (status < 0) {
 		dbg("writing Spreg failed");
-		return -1;
+		goto err;
 	}
 
 	Data &= ~0x80;
 	status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data);
 	if (status < 0) {
 		dbg("writing Spreg failed");
-		return -1;
+		goto err;
 	}
 	/* End of block to be checked */
 
@@ -943,7 +959,7 @@ static int mos7840_open(struct tty_struc
 									&Data);
 	if (status < 0) {
 		dbg("Reading Controlreg failed");
-		return -1;
+		goto err;
 	}
 	Data |= 0x08;		/* Driver done bit */
 	Data |= 0x20;		/* rx_disable */
@@ -951,7 +967,7 @@ static int mos7840_open(struct tty_struc
 				mos7840_port->ControlRegOffset, Data);
 	if (status < 0) {
 		dbg("writing Controlreg failed");
-		return -1;
+		goto err;
 	}
 	/* do register settings here */
 	/* Set all regs to the device default values. */
@@ -962,21 +978,21 @@ static int mos7840_open(struct tty_struc
 	status = mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
 	if (status < 0) {
 		dbg("disabling interrupts failed");
-		return -1;
+		goto err;
 	}
 	/* Set FIFO_CONTROL_REGISTER to the default value */
 	Data = 0x00;
 	status = mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data);
 	if (status < 0) {
 		dbg("Writing FIFO_CONTROL_REGISTER  failed");
-		return -1;
+		goto err;
 	}
 
 	Data = 0xcf;
 	status = mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data);
 	if (status < 0) {
 		dbg("Writing FIFO_CONTROL_REGISTER  failed");
-		return -1;
+		goto err;
 	}
 
 	Data = 0x03;
@@ -1113,7 +1129,6 @@ static int mos7840_open(struct tty_struc
 
 	/* initialize our wait queues */
 	init_waitqueue_head(&mos7840_port->wait_chase);
-	init_waitqueue_head(&mos7840_port->delta_msr_wait);
 
 	/* initialize our icount structure */
 	memset(&(mos7840_port->icount), 0x00, sizeof(mos7840_port->icount));
@@ -1133,7 +1148,15 @@ static int mos7840_open(struct tty_struc
 	dbg ("%s leave", __func__);
 
 	return 0;
-
+err:
+	for (j = 0; j < NUM_URBS; ++j) {
+		urb = mos7840_port->write_urb_pool[j];
+		if (!urb)
+			continue;
+		kfree(urb->transfer_buffer);
+		usb_free_urb(urb);
+	}
+	return status;
 }
 
 /*****************************************************************************
@@ -2074,8 +2097,6 @@ static void mos7840_change_port_settings
 			mos7840_port->read_urb_busy = false;
 		}
 	}
-	wake_up(&mos7840_port->delta_msr_wait);
-	mos7840_port->delta_msr_cond = 1;
 	dbg("mos7840_change_port_settings mos7840_port->shadowLCR is End %x",
 	    mos7840_port->shadowLCR);
 }
@@ -2284,13 +2305,18 @@ static int mos7840_ioctl(struct tty_stru
 		while (1) {
 			/* interruptible_sleep_on(&mos7840_port->delta_msr_wait); */
 			mos7840_port->delta_msr_cond = 0;
-			wait_event_interruptible(mos7840_port->delta_msr_wait,
-						 (mos7840_port->
+			wait_event_interruptible(port->delta_msr_wait,
+						 (port->serial->disconnected ||
+						  mos7840_port->
 						  delta_msr_cond == 1));
 
 			/* see if a signal did it */
 			if (signal_pending(current))
 				return -ERESTARTSYS;
+
+			if (port->serial->disconnected)
+				return -EIO;
+
 			cnow = mos7840_port->icount;
 			smp_rmb();
 			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/usb/serial/oti6858.c linux-libre-3.4.87-gnu1/drivers/usb/serial/oti6858.c
--- linux-libre-3.4.86-gnu1/drivers/usb/serial/oti6858.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/usb/serial/oti6858.c	2014-04-14 09:45:17.000000000 -0400
@@ -198,7 +198,6 @@ struct oti6858_private {
 	u8 setup_done;
 	struct delayed_work delayed_setup_work;
 
-	wait_queue_head_t intr_wait;
 	struct usb_serial_port *port;   /* USB port with which associated */
 };
 
@@ -356,7 +355,6 @@ static int oti6858_startup(struct usb_se
 			break;
 
 		spin_lock_init(&priv->lock);
-		init_waitqueue_head(&priv->intr_wait);
 /*		INIT_WORK(&priv->setup_work, setup_line, serial->port[i]); */
 /*		INIT_WORK(&priv->write_work, send_data, serial->port[i]); */
 		priv->port = port;
@@ -703,11 +701,15 @@ static int wait_modem_info(struct usb_se
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	while (1) {
-		wait_event_interruptible(priv->intr_wait,
+		wait_event_interruptible(port->delta_msr_wait,
+					port->serial->disconnected ||
 					priv->status.pin_state != prev);
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 
+		if (port->serial->disconnected)
+			return -EIO;
+
 		spin_lock_irqsave(&priv->lock, flags);
 		status = priv->status.pin_state & PIN_MASK;
 		spin_unlock_irqrestore(&priv->lock, flags);
@@ -819,7 +821,7 @@ static void oti6858_read_int_callback(st
 
 		if (!priv->transient) {
 			if (xs->pin_state != priv->status.pin_state)
-				wake_up_interruptible(&priv->intr_wait);
+				wake_up_interruptible(&port->delta_msr_wait);
 			memcpy(&priv->status, xs, OTI6858_CTRL_PKT_SIZE);
 		}
 
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/usb/serial/pl2303.c linux-libre-3.4.87-gnu1/drivers/usb/serial/pl2303.c
--- linux-libre-3.4.86-gnu1/drivers/usb/serial/pl2303.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/usb/serial/pl2303.c	2014-04-14 09:45:17.000000000 -0400
@@ -149,7 +149,6 @@ enum pl2303_type {
 
 struct pl2303_private {
 	spinlock_t lock;
-	wait_queue_head_t delta_msr_wait;
 	u8 line_control;
 	u8 line_status;
 	enum pl2303_type type;
@@ -203,7 +202,6 @@ static int pl2303_startup(struct usb_ser
 		if (!priv)
 			goto cleanup;
 		spin_lock_init(&priv->lock);
-		init_waitqueue_head(&priv->delta_msr_wait);
 		priv->type = type;
 		usb_set_serial_port_data(serial->port[i], priv);
 	}
@@ -271,7 +269,7 @@ static void pl2303_set_termios(struct tt
 	   serial settings even to the same values as before. Thus
 	   we actually need to filter in this specific case */
 
-	if (!tty_termios_hw_change(tty->termios, old_termios))
+	if (old_termios && !tty_termios_hw_change(tty->termios, old_termios))
 		return;
 
 	cflag = tty->termios->c_cflag;
@@ -280,7 +278,8 @@ static void pl2303_set_termios(struct tt
 	if (!buf) {
 		dev_err(&port->dev, "%s - out of memory.\n", __func__);
 		/* Report back no change occurred */
-		*tty->termios = *old_termios;
+		if (old_termios)
+			*tty->termios = *old_termios;
 		return;
 	}
 
@@ -418,7 +417,7 @@ static void pl2303_set_termios(struct tt
 	control = priv->line_control;
 	if ((cflag & CBAUD) == B0)
 		priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
-	else if ((old_termios->c_cflag & CBAUD) == B0)
+	else if (old_termios && (old_termios->c_cflag & CBAUD) == B0)
 		priv->line_control |= (CONTROL_DTR | CONTROL_RTS);
 	if (control != priv->line_control) {
 		control = priv->line_control;
@@ -479,7 +478,6 @@ static void pl2303_close(struct usb_seri
 
 static int pl2303_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
-	struct ktermios tmp_termios;
 	struct usb_serial *serial = port->serial;
 	struct pl2303_private *priv = usb_get_serial_port_data(port);
 	int result;
@@ -497,7 +495,7 @@ static int pl2303_open(struct tty_struct
 
 	/* Setup termios */
 	if (tty)
-		pl2303_set_termios(tty, port, &tmp_termios);
+		pl2303_set_termios(tty, port, NULL);
 
 	dbg("%s - submitting interrupt urb", __func__);
 	result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
@@ -595,11 +593,14 @@ static int wait_modem_info(struct usb_se
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	while (1) {
-		interruptible_sleep_on(&priv->delta_msr_wait);
+		interruptible_sleep_on(&port->delta_msr_wait);
 		/* see if a signal did it */
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 
+		if (port->serial->disconnected)
+			return -EIO;
+
 		spin_lock_irqsave(&priv->lock, flags);
 		status = priv->line_status;
 		spin_unlock_irqrestore(&priv->lock, flags);
@@ -721,7 +722,7 @@ static void pl2303_update_line_status(st
 	spin_unlock_irqrestore(&priv->lock, flags);
 	if (priv->line_status & UART_BREAK_ERROR)
 		usb_serial_handle_break(port);
-	wake_up_interruptible(&priv->delta_msr_wait);
+	wake_up_interruptible(&port->delta_msr_wait);
 
 	tty = tty_port_tty_get(&port->port);
 	if (!tty)
@@ -788,7 +789,7 @@ static void pl2303_process_read_urb(stru
 	line_status = priv->line_status;
 	priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
 	spin_unlock_irqrestore(&priv->lock, flags);
-	wake_up_interruptible(&priv->delta_msr_wait);
+	wake_up_interruptible(&port->delta_msr_wait);
 
 	if (!urb->actual_length)
 		return;
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/usb/serial/qcserial.c linux-libre-3.4.87-gnu1/drivers/usb/serial/qcserial.c
--- linux-libre-3.4.86-gnu1/drivers/usb/serial/qcserial.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/usb/serial/qcserial.c	2014-04-14 09:45:17.000000000 -0400
@@ -121,6 +121,7 @@ static const struct usb_device_id id_tab
 	{USB_DEVICE(0x1199, 0x9019)},	/* Sierra Wireless Gobi 3000 Modem device */
 	{USB_DEVICE(0x12D1, 0x14F0)},	/* Sony Gobi 3000 QDL */
 	{USB_DEVICE(0x12D1, 0x14F1)},	/* Sony Gobi 3000 Composite */
+	{USB_DEVICE(0x0AF0, 0x8120)},	/* Option GTM681W */
 	{ }				/* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, id_table);
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/usb/serial/spcp8x5.c linux-libre-3.4.87-gnu1/drivers/usb/serial/spcp8x5.c
--- linux-libre-3.4.86-gnu1/drivers/usb/serial/spcp8x5.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/usb/serial/spcp8x5.c	2014-04-14 09:45:17.000000000 -0400
@@ -162,7 +162,6 @@ static struct usb_driver spcp8x5_driver
 struct spcp8x5_private {
 	spinlock_t 	lock;
 	enum spcp8x5_type	type;
-	wait_queue_head_t	delta_msr_wait;
 	u8 			line_control;
 	u8 			line_status;
 };
@@ -196,7 +195,6 @@ static int spcp8x5_startup(struct usb_se
 			goto cleanup;
 
 		spin_lock_init(&priv->lock);
-		init_waitqueue_head(&priv->delta_msr_wait);
 		priv->type = type;
 		usb_set_serial_port_data(serial->port[i] , priv);
 	}
@@ -339,7 +337,6 @@ static void spcp8x5_set_termios(struct t
 	struct spcp8x5_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
 	unsigned int cflag = tty->termios->c_cflag;
-	unsigned int old_cflag = old_termios->c_cflag;
 	unsigned short uartdata;
 	unsigned char buf[2] = {0, 0};
 	int baud;
@@ -348,15 +345,15 @@ static void spcp8x5_set_termios(struct t
 
 
 	/* check that they really want us to change something */
-	if (!tty_termios_hw_change(tty->termios, old_termios))
+	if (old_termios && !tty_termios_hw_change(tty->termios, old_termios))
 		return;
 
 	/* set DTR/RTS active */
 	spin_lock_irqsave(&priv->lock, flags);
 	control = priv->line_control;
-	if ((old_cflag & CBAUD) == B0) {
+	if (old_termios && (old_termios->c_cflag & CBAUD) == B0) {
 		priv->line_control |= MCR_DTR;
-		if (!(old_cflag & CRTSCTS))
+		if (!(old_termios->c_cflag & CRTSCTS))
 			priv->line_control |= MCR_RTS;
 	}
 	if (control != priv->line_control) {
@@ -444,7 +441,6 @@ static void spcp8x5_set_termios(struct t
  * status of the device. */
 static int spcp8x5_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
-	struct ktermios tmp_termios;
 	struct usb_serial *serial = port->serial;
 	struct spcp8x5_private *priv = usb_get_serial_port_data(port);
 	int ret;
@@ -467,7 +463,7 @@ static int spcp8x5_open(struct tty_struc
 
 	/* Setup termios */
 	if (tty)
-		spcp8x5_set_termios(tty, port, &tmp_termios);
+		spcp8x5_set_termios(tty, port, NULL);
 
 	spcp8x5_get_msr(serial->dev, &status, priv->type);
 
@@ -499,7 +495,7 @@ static void spcp8x5_process_read_urb(str
 	priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
 	spin_unlock_irqrestore(&priv->lock, flags);
 	/* wake up the wait for termios */
-	wake_up_interruptible(&priv->delta_msr_wait);
+	wake_up_interruptible(&port->delta_msr_wait);
 
 	if (!urb->actual_length)
 		return;
@@ -549,12 +545,15 @@ static int spcp8x5_wait_modem_info(struc
 
 	while (1) {
 		/* wake up in bulk read */
-		interruptible_sleep_on(&priv->delta_msr_wait);
+		interruptible_sleep_on(&port->delta_msr_wait);
 
 		/* see if a signal did it */
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 
+		if (port->serial->disconnected)
+			return -EIO;
+
 		spin_lock_irqsave(&priv->lock, flags);
 		status = priv->line_status;
 		spin_unlock_irqrestore(&priv->lock, flags);
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/usb/serial/ssu100.c linux-libre-3.4.87-gnu1/drivers/usb/serial/ssu100.c
--- linux-libre-3.4.86-gnu1/drivers/usb/serial/ssu100.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/usb/serial/ssu100.c	2014-04-14 09:45:17.000000000 -0400
@@ -77,7 +77,6 @@ struct ssu100_port_private {
 	spinlock_t status_lock;
 	u8 shadowLSR;
 	u8 shadowMSR;
-	wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
 	struct async_icount icount;
 };
 
@@ -386,8 +385,9 @@ static int wait_modem_info(struct usb_se
 	spin_unlock_irqrestore(&priv->status_lock, flags);
 
 	while (1) {
-		wait_event_interruptible(priv->delta_msr_wait,
-					 ((priv->icount.rng != prev.rng) ||
+		wait_event_interruptible(port->delta_msr_wait,
+					 (port->serial->disconnected ||
+					  (priv->icount.rng != prev.rng) ||
 					  (priv->icount.dsr != prev.dsr) ||
 					  (priv->icount.dcd != prev.dcd) ||
 					  (priv->icount.cts != prev.cts)));
@@ -395,6 +395,9 @@ static int wait_modem_info(struct usb_se
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 
+		if (port->serial->disconnected)
+			return -EIO;
+
 		spin_lock_irqsave(&priv->status_lock, flags);
 		cur = priv->icount;
 		spin_unlock_irqrestore(&priv->status_lock, flags);
@@ -477,7 +480,6 @@ static int ssu100_attach(struct usb_seri
 	}
 
 	spin_lock_init(&priv->status_lock);
-	init_waitqueue_head(&priv->delta_msr_wait);
 	usb_set_serial_port_data(port, priv);
 
 	return ssu100_initdevice(serial->dev);
@@ -563,7 +565,7 @@ static void ssu100_update_msr(struct usb
 			priv->icount.dcd++;
 		if (msr & UART_MSR_TERI)
 			priv->icount.rng++;
-		wake_up_interruptible(&priv->delta_msr_wait);
+		wake_up_interruptible(&port->delta_msr_wait);
 	}
 }
 
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/usb/serial/ti_usb_3410_5052.c linux-libre-3.4.87-gnu1/drivers/usb/serial/ti_usb_3410_5052.c
--- linux-libre-3.4.86-gnu1/drivers/usb/serial/ti_usb_3410_5052.c	2014-04-04 04:51:15.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/usb/serial/ti_usb_3410_5052.c	2014-04-14 14:31:54.000000000 -0400
@@ -75,7 +75,6 @@ struct ti_port {
 	int			tp_flags;
 	int			tp_closing_wait;/* in .01 secs */
 	struct async_icount	tp_icount;
-	wait_queue_head_t	tp_msr_wait;	/* wait for msr change */
 	wait_queue_head_t	tp_write_wait;
 	struct ti_device	*tp_tdev;
 	struct usb_serial_port	*tp_port;
@@ -424,7 +423,6 @@ static int ti_startup(struct usb_serial
 		tport->tp_uart_base_addr = (i == 0 ?
 				TI_UART1_BASE_ADDR : TI_UART2_BASE_ADDR);
 		tport->tp_closing_wait = closing_wait;
-		init_waitqueue_head(&tport->tp_msr_wait);
 		init_waitqueue_head(&tport->tp_write_wait);
 		if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE,
 								GFP_KERNEL)) {
@@ -821,9 +819,13 @@ static int ti_ioctl(struct tty_struct *t
 		dbg("%s - (%d) TIOCMIWAIT", __func__, port->number);
 		cprev = tport->tp_icount;
 		while (1) {
-			interruptible_sleep_on(&tport->tp_msr_wait);
+			interruptible_sleep_on(&port->delta_msr_wait);
 			if (signal_pending(current))
 				return -ERESTARTSYS;
+
+			if (port->serial->disconnected)
+				return -EIO;
+
 			cnow = tport->tp_icount;
 			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
 			    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
@@ -1452,7 +1454,7 @@ static void ti_handle_new_msr(struct ti_
 			icount->dcd++;
 		if (msr & TI_MSR_DELTA_RI)
 			icount->rng++;
-		wake_up_interruptible(&tport->tp_msr_wait);
+		wake_up_interruptible(&tport->tp_port->delta_msr_wait);
 		spin_unlock_irqrestore(&tport->tp_lock, flags);
 	}
 
@@ -1679,12 +1681,13 @@ static int ti_download_firmware(struct t
 
 	dbg("%s\n", __func__);
 	/* try ID specific firmware first, then try generic firmware */
-	sprintf(buf, "/*(DEBLOBBED)*/", dev->descriptor.idVendor,
-	    dev->descriptor.idProduct);
+	sprintf(buf, "/*(DEBLOBBED)*/",
+			le16_to_cpu(dev->descriptor.idVendor),
+			le16_to_cpu(dev->descriptor.idProduct));
 	if ((status = reject_firmware(&fw_p, buf, &dev->dev)) != 0) {
 		buf[0] = '\0';
-		if (dev->descriptor.idVendor == MTS_VENDOR_ID) {
-			switch (dev->descriptor.idProduct) {
+		if (le16_to_cpu(dev->descriptor.idVendor) == MTS_VENDOR_ID) {
+			switch (le16_to_cpu(dev->descriptor.idProduct)) {
 			case MTS_CDMA_PRODUCT_ID:
 				strcpy(buf, "/*(DEBLOBBED)*/");
 				break;
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/usb/serial/usb-serial.c linux-libre-3.4.87-gnu1/drivers/usb/serial/usb-serial.c
--- linux-libre-3.4.86-gnu1/drivers/usb/serial/usb-serial.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/usb/serial/usb-serial.c	2014-04-14 09:45:17.000000000 -0400
@@ -908,6 +908,7 @@ int usb_serial_probe(struct usb_interfac
 		port->port.ops = &serial_port_ops;
 		port->serial = serial;
 		spin_lock_init(&port->lock);
+		init_waitqueue_head(&port->delta_msr_wait);
 		/* Keep this for private driver use for the moment but
 		   should probably go away */
 		INIT_WORK(&port->work, usb_serial_port_work);
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/usb/wusbcore/wa-rpipe.c linux-libre-3.4.87-gnu1/drivers/usb/wusbcore/wa-rpipe.c
--- linux-libre-3.4.86-gnu1/drivers/usb/wusbcore/wa-rpipe.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/usb/wusbcore/wa-rpipe.c	2014-04-14 09:45:17.000000000 -0400
@@ -332,7 +332,10 @@ static int rpipe_aim(struct wa_rpipe *rp
 	/* FIXME: compute so seg_size > ep->maxpktsize */
 	rpipe->descr.wBlocks = cpu_to_le16(16);		/* given */
 	/* ep0 maxpktsize is 0x200 (WUSB1.0[4.8.1]) */
-	rpipe->descr.wMaxPacketSize = cpu_to_le16(ep->desc.wMaxPacketSize);
+	if (usb_endpoint_xfer_isoc(&ep->desc))
+		rpipe->descr.wMaxPacketSize = epcd->wOverTheAirPacketSize;
+	else
+		rpipe->descr.wMaxPacketSize = ep->desc.wMaxPacketSize;
 	rpipe->descr.bHSHubAddress = 0;			/* reserved: zero */
 	rpipe->descr.bHSHubPort = wusb_port_no_to_idx(urb->dev->portnum);
 	/* FIXME: use maximum speed as supported or recommended by device */
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/usb/wusbcore/wa-xfer.c linux-libre-3.4.87-gnu1/drivers/usb/wusbcore/wa-xfer.c
--- linux-libre-3.4.86-gnu1/drivers/usb/wusbcore/wa-xfer.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/usb/wusbcore/wa-xfer.c	2014-04-14 09:45:17.000000000 -0400
@@ -90,7 +90,8 @@
 #include "wusbhc.h"
 
 enum {
-	WA_SEGS_MAX = 255,
+	/* [WUSB] section 8.3.3 allocates 7 bits for the segment index. */
+	WA_SEGS_MAX = 128,
 };
 
 enum wa_seg_status {
@@ -444,7 +445,7 @@ static ssize_t __wa_xfer_setup_sizes(str
 	xfer->seg_size = (xfer->seg_size / maxpktsize) * maxpktsize;
 	xfer->segs = (urb->transfer_buffer_length + xfer->seg_size - 1)
 		/ xfer->seg_size;
-	if (xfer->segs >= WA_SEGS_MAX) {
+	if (xfer->segs > WA_SEGS_MAX) {
 		dev_err(dev, "BUG? ops, number of segments %d bigger than %d\n",
 			(int)(urb->transfer_buffer_length / xfer->seg_size),
 			WA_SEGS_MAX);
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/drivers/video/omap2/omapfb/omapfb-main.c linux-libre-3.4.87-gnu1/drivers/video/omap2/omapfb/omapfb-main.c
--- linux-libre-3.4.86-gnu1/drivers/video/omap2/omapfb/omapfb-main.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/drivers/video/omap2/omapfb/omapfb-main.c	2014-04-14 09:45:17.000000000 -0400
@@ -1187,7 +1187,7 @@ static int _setcolreg(struct fb_info *fb
 			break;
 
 		if (regno < 16) {
-			u16 pal;
+			u32 pal;
 			pal = ((red >> (16 - var->red.length)) <<
 					var->red.offset) |
 				((green >> (16 - var->green.length)) <<
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/fs/proc/array.c linux-libre-3.4.87-gnu1/fs/proc/array.c
--- linux-libre-3.4.86-gnu1/fs/proc/array.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/fs/proc/array.c	2014-04-14 09:45:17.000000000 -0400
@@ -204,7 +204,7 @@ static inline void task_state(struct seq
 	group_info = cred->group_info;
 	task_unlock(p);
 
-	for (g = 0; g < min(group_info->ngroups, NGROUPS_SMALL); g++)
+	for (g = 0; g < group_info->ngroups; g++)
 		seq_printf(m, "%d ", GROUP_AT(group_info, g));
 	put_cred(cred);
 
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/include/linux/compiler-gcc4.h linux-libre-3.4.87-gnu1/include/linux/compiler-gcc4.h
--- linux-libre-3.4.86-gnu1/include/linux/compiler-gcc4.h	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/include/linux/compiler-gcc4.h	2014-04-14 09:45:17.000000000 -0400
@@ -31,6 +31,22 @@
 
 #define __linktime_error(message) __attribute__((__error__(message)))
 
+/*
+ * GCC 'asm goto' miscompiles certain code sequences:
+ *
+ *   http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58670
+ *
+ * Work it around via a compiler barrier quirk suggested by Jakub Jelinek.
+ * Fixed in GCC 4.8.2 and later versions.
+ *
+ * (asm goto is automatically volatile - the naming reflects this.)
+ */
+#if GCC_VERSION <= 40801
+# define asm_volatile_goto(x...)	do { asm goto(x); asm (""); } while (0)
+#else
+# define asm_volatile_goto(x...)	do { asm goto(x); } while (0)
+#endif
+
 #if __GNUC_MINOR__ >= 5
 /*
  * Mark a position in code as unreachable.  This can be used to
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/include/linux/compiler-gcc.h linux-libre-3.4.87-gnu1/include/linux/compiler-gcc.h
--- linux-libre-3.4.86-gnu1/include/linux/compiler-gcc.h	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/include/linux/compiler-gcc.h	2014-04-14 09:45:17.000000000 -0400
@@ -5,6 +5,9 @@
 /*
  * Common definitions for all gcc versions go here.
  */
+#define GCC_VERSION (__GNUC__ * 10000 \
+		   + __GNUC_MINOR__ * 100 \
+		   + __GNUC_PATCHLEVEL__)
 
 
 /* Optimization barrier */
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/include/linux/hid.h linux-libre-3.4.87-gnu1/include/linux/hid.h
--- linux-libre-3.4.86-gnu1/include/linux/hid.h	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/include/linux/hid.h	2014-04-14 09:45:17.000000000 -0400
@@ -902,7 +902,7 @@ static inline int hid_hw_power(struct hi
 	return hdev->ll_driver->power ? hdev->ll_driver->power(hdev, level) : 0;
 }
 
-void hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
+int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
 		int interrupt);
 
 extern int hid_generic_init(void);
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/include/linux/hidraw.h linux-libre-3.4.87-gnu1/include/linux/hidraw.h
--- linux-libre-3.4.86-gnu1/include/linux/hidraw.h	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/include/linux/hidraw.h	2014-04-14 09:45:17.000000000 -0400
@@ -76,13 +76,13 @@ struct hidraw_list {
 #ifdef CONFIG_HIDRAW
 int hidraw_init(void);
 void hidraw_exit(void);
-void hidraw_report_event(struct hid_device *, u8 *, int);
+int hidraw_report_event(struct hid_device *, u8 *, int);
 int hidraw_connect(struct hid_device *);
 void hidraw_disconnect(struct hid_device *);
 #else
 static inline int hidraw_init(void) { return 0; }
 static inline void hidraw_exit(void) { }
-static inline void hidraw_report_event(struct hid_device *hid, u8 *data, int len) { }
+static inline int hidraw_report_event(struct hid_device *hid, u8 *data, int len) { return 0; }
 static inline int hidraw_connect(struct hid_device *hid) { return -1; }
 static inline void hidraw_disconnect(struct hid_device *hid) { }
 #endif
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/include/linux/idr.h linux-libre-3.4.87-gnu1/include/linux/idr.h
--- linux-libre-3.4.86-gnu1/include/linux/idr.h	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/include/linux/idr.h	2014-04-14 09:45:17.000000000 -0400
@@ -152,4 +152,15 @@ void ida_simple_remove(struct ida *ida,
 
 void __init idr_init_cache(void);
 
+/**
+ * idr_for_each_entry - iterate over an idr's elements of a given type
+ * @idp:     idr handle
+ * @entry:   the type * to use as cursor
+ * @id:      id entry's key
+ */
+#define idr_for_each_entry(idp, entry, id)				\
+	for (id = 0, entry = (typeof(entry))idr_get_next((idp), &(id)); \
+	     entry != NULL;                                             \
+	     ++id, entry = (typeof(entry))idr_get_next((idp), &(id)))
+
 #endif /* __IDR_H__ */
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/include/linux/msg.h linux-libre-3.4.87-gnu1/include/linux/msg.h
--- linux-libre-3.4.86-gnu1/include/linux/msg.h	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/include/linux/msg.h	2014-04-14 09:45:17.000000000 -0400
@@ -76,9 +76,9 @@ struct msginfo {
 
 /* one msg_msg structure for each message */
 struct msg_msg {
-	struct list_head m_list; 
-	long  m_type;          
-	int m_ts;           /* message text size */
+	struct list_head m_list;
+	long m_type;
+	size_t m_ts;		/* message text size */
 	struct msg_msgseg* next;
 	void *security;
 	/* the actual message follows immediately */
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/include/linux/mv643xx_eth.h linux-libre-3.4.87-gnu1/include/linux/mv643xx_eth.h
--- linux-libre-3.4.86-gnu1/include/linux/mv643xx_eth.h	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/include/linux/mv643xx_eth.h	2014-04-14 09:45:17.000000000 -0400
@@ -15,6 +15,8 @@
 #define MV643XX_ETH_SIZE_REG_4		0x2224
 #define MV643XX_ETH_BASE_ADDR_ENABLE_REG	0x2290
 
+#define MV643XX_TX_CSUM_DEFAULT_LIMIT	0
+
 struct mv643xx_eth_shared_platform_data {
 	struct mbus_dram_target_info	*dram;
 	struct platform_device	*shared_smi;
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/include/linux/pps_kernel.h linux-libre-3.4.87-gnu1/include/linux/pps_kernel.h
--- linux-libre-3.4.86-gnu1/include/linux/pps_kernel.h	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/include/linux/pps_kernel.h	2014-04-14 09:45:17.000000000 -0400
@@ -43,7 +43,7 @@ struct pps_source_info {
 			int event, void *data);	/* PPS echo function */
 
 	struct module *owner;
-	struct device *dev;
+	struct device *dev;		/* Parent device for device_create */
 };
 
 struct pps_event_time {
@@ -69,6 +69,7 @@ struct pps_device {
 	wait_queue_head_t queue;		/* PPS event queue */
 
 	unsigned int id;			/* PPS source unique ID */
+	void const *lookup_cookie;		/* pps_lookup_dev only */
 	struct cdev cdev;
 	struct device *dev;
 	struct fasync_struct *async_queue;	/* fasync method */
@@ -82,16 +83,26 @@ struct pps_device {
 extern struct device_attribute pps_attrs[];
 
 /*
+ * Internal functions.
+ *
+ * These are not actually part of the exported API, but this is a
+ * convenient header file to put them in.
+ */
+
+extern int pps_register_cdev(struct pps_device *pps);
+extern void pps_unregister_cdev(struct pps_device *pps);
+
+/*
  * Exported functions
  */
 
 extern struct pps_device *pps_register_source(
 		struct pps_source_info *info, int default_params);
 extern void pps_unregister_source(struct pps_device *pps);
-extern int pps_register_cdev(struct pps_device *pps);
-extern void pps_unregister_cdev(struct pps_device *pps);
 extern void pps_event(struct pps_device *pps,
 		struct pps_event_time *ts, int event, void *data);
+/* Look up a pps device by magic cookie */
+struct pps_device *pps_lookup_dev(void const *cookie);
 
 static inline void timespec_to_pps_ktime(struct pps_ktime *kt,
 		struct timespec ts)
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/include/linux/usb/hcd.h linux-libre-3.4.87-gnu1/include/linux/usb/hcd.h
--- linux-libre-3.4.86-gnu1/include/linux/usb/hcd.h	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/include/linux/usb/hcd.h	2014-04-14 09:45:17.000000000 -0400
@@ -393,7 +393,7 @@ extern int usb_hcd_pci_probe(struct pci_
 extern void usb_hcd_pci_remove(struct pci_dev *dev);
 extern void usb_hcd_pci_shutdown(struct pci_dev *dev);
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
 extern const struct dev_pm_ops usb_hcd_pci_pm_ops;
 #endif
 #endif /* CONFIG_PCI */
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/include/linux/usb/serial.h linux-libre-3.4.87-gnu1/include/linux/usb/serial.h
--- linux-libre-3.4.86-gnu1/include/linux/usb/serial.h	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/include/linux/usb/serial.h	2014-04-14 09:45:17.000000000 -0400
@@ -66,6 +66,7 @@
  *	port.
  * @flags: usb serial port flags
  * @write_wait: a wait_queue_head_t used by the port.
+ * @delta_msr_wait: modem-status-change wait queue
  * @work: work queue entry for the line discipline waking up.
  * @throttled: nonzero if the read urb is inactive to throttle the device
  * @throttle_req: nonzero if the tty wants to throttle us
@@ -112,6 +113,7 @@ struct usb_serial_port {
 
 	unsigned long		flags;
 	wait_queue_head_t	write_wait;
+	wait_queue_head_t	delta_msr_wait;
 	struct work_struct	work;
 	char			throttled;
 	char			throttle_req;
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/ipc/msgutil.c linux-libre-3.4.87-gnu1/ipc/msgutil.c
--- linux-libre-3.4.86-gnu1/ipc/msgutil.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/ipc/msgutil.c	2014-04-14 09:45:17.000000000 -0400
@@ -39,15 +39,15 @@ struct msg_msgseg {
 	/* the next part of the message follows immediately */
 };
 
-#define DATALEN_MSG	(PAGE_SIZE-sizeof(struct msg_msg))
-#define DATALEN_SEG	(PAGE_SIZE-sizeof(struct msg_msgseg))
+#define DATALEN_MSG	((size_t)PAGE_SIZE-sizeof(struct msg_msg))
+#define DATALEN_SEG	((size_t)PAGE_SIZE-sizeof(struct msg_msgseg))
 
-struct msg_msg *load_msg(const void __user *src, int len)
+struct msg_msg *load_msg(const void __user *src, size_t len)
 {
 	struct msg_msg *msg;
 	struct msg_msgseg **pseg;
 	int err;
-	int alen;
+	size_t alen;
 
 	alen = len;
 	if (alen > DATALEN_MSG)
@@ -101,9 +101,9 @@ out_err:
 	return ERR_PTR(err);
 }
 
-int store_msg(void __user *dest, struct msg_msg *msg, int len)
+int store_msg(void __user *dest, struct msg_msg *msg, size_t len)
 {
-	int alen;
+	size_t alen;
 	struct msg_msgseg *seg;
 
 	alen = len;
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/ipc/util.h linux-libre-3.4.87-gnu1/ipc/util.h
--- linux-libre-3.4.86-gnu1/ipc/util.h	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/ipc/util.h	2014-04-14 09:45:17.000000000 -0400
@@ -138,8 +138,8 @@ int ipc_parse_version (int *cmd);
 #endif
 
 extern void free_msg(struct msg_msg *msg);
-extern struct msg_msg *load_msg(const void __user *src, int len);
-extern int store_msg(void __user *dest, struct msg_msg *msg, int len);
+extern struct msg_msg *load_msg(const void __user *src, size_t len);
+extern int store_msg(void __user *dest, struct msg_msg *msg, size_t len);
 
 extern void recompute_msgmni(struct ipc_namespace *);
 
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/kernel/audit.c linux-libre-3.4.87-gnu1/kernel/audit.c
--- linux-libre-3.4.86-gnu1/kernel/audit.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/kernel/audit.c	2014-04-14 09:45:17.000000000 -0400
@@ -1168,7 +1168,7 @@ struct audit_buffer *audit_log_start(str
 
 			/* Wait for auditd to drain the queue a little */
 			DECLARE_WAITQUEUE(wait, current);
-			set_current_state(TASK_INTERRUPTIBLE);
+			set_current_state(TASK_UNINTERRUPTIBLE);
 			add_wait_queue(&audit_backlog_wait, &wait);
 
 			if (audit_backlog_limit &&
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/kernel/printk.c linux-libre-3.4.87-gnu1/kernel/printk.c
--- linux-libre-3.4.86-gnu1/kernel/printk.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/kernel/printk.c	2014-04-14 09:45:17.000000000 -0400
@@ -822,9 +822,9 @@ static int console_trylock_for_printk(un
 		}
 	}
 	printk_cpu = UINT_MAX;
+	raw_spin_unlock(&logbuf_lock);
 	if (wake)
 		up(&console_sem);
-	raw_spin_unlock(&logbuf_lock);
 	return retval;
 }
 static const char recursion_bug_msg [] =
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/kernel/workqueue.c linux-libre-3.4.87-gnu1/kernel/workqueue.c
--- linux-libre-3.4.86-gnu1/kernel/workqueue.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/kernel/workqueue.c	2014-04-14 09:45:17.000000000 -0400
@@ -1922,6 +1922,15 @@ __acquires(&gcwq->lock)
 		dump_stack();
 	}
 
+	/*
+	 * The following prevents a kworker from hogging CPU on !PREEMPT
+	 * kernels, where a requeueing work item waiting for something to
+	 * happen could deadlock with stop_machine as such work item could
+	 * indefinitely requeue itself while all other CPUs are trapped in
+	 * stop_machine.
+	 */
+	cond_resched();
+
 	spin_lock_irq(&gcwq->lock);
 
 	/* clear cpu intensive status */
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/lib/idr.c linux-libre-3.4.87-gnu1/lib/idr.c
--- linux-libre-3.4.86-gnu1/lib/idr.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/lib/idr.c	2014-04-14 09:45:17.000000000 -0400
@@ -39,6 +39,14 @@
 static struct kmem_cache *idr_layer_cache;
 static DEFINE_SPINLOCK(simple_ida_lock);
 
+/* the maximum ID which can be allocated given idr->layers */
+static int idr_max(int layers)
+{
+	int bits = min_t(int, layers * IDR_BITS, MAX_ID_SHIFT);
+
+	return (1 << bits) - 1;
+}
+
 static struct idr_layer *get_from_free_list(struct idr *idp)
 {
 	struct idr_layer *p;
@@ -223,7 +231,7 @@ build_up:
 	 * Add a new layer to the top of the tree if the requested
 	 * id is larger than the currently allocated space.
 	 */
-	while ((layers < (MAX_LEVEL - 1)) && (id >= (1 << (layers*IDR_BITS)))) {
+	while (id > idr_max(layers)) {
 		layers++;
 		if (!p->count) {
 			/* special case: if the tree is currently empty,
@@ -265,7 +273,7 @@ build_up:
 
 static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id)
 {
-	struct idr_layer *pa[MAX_LEVEL];
+	struct idr_layer *pa[MAX_LEVEL + 1];
 	int id;
 
 	id = idr_get_empty_slot(idp, starting_id, pa);
@@ -357,7 +365,7 @@ static void idr_remove_warning(int id)
 static void sub_remove(struct idr *idp, int shift, int id)
 {
 	struct idr_layer *p = idp->top;
-	struct idr_layer **pa[MAX_LEVEL];
+	struct idr_layer **pa[MAX_LEVEL + 1];
 	struct idr_layer ***paa = &pa[0];
 	struct idr_layer *to_free;
 	int n;
@@ -451,16 +459,16 @@ void idr_remove_all(struct idr *idp)
 	int n, id, max;
 	int bt_mask;
 	struct idr_layer *p;
-	struct idr_layer *pa[MAX_LEVEL];
+	struct idr_layer *pa[MAX_LEVEL + 1];
 	struct idr_layer **paa = &pa[0];
 
 	n = idp->layers * IDR_BITS;
 	p = idp->top;
 	rcu_assign_pointer(idp->top, NULL);
-	max = 1 << n;
+	max = idr_max(idp->layers);
 
 	id = 0;
-	while (id < max) {
+	while (id >= 0 && id <= max) {
 		while (n > IDR_BITS && p) {
 			n -= IDR_BITS;
 			*paa++ = p;
@@ -519,7 +527,7 @@ void *idr_find(struct idr *idp, int id)
 	/* Mask off upper bits we don't use for the search. */
 	id &= MAX_ID_MASK;
 
-	if (id >= (1 << n))
+	if (id > idr_max(p->layer + 1))
 		return NULL;
 	BUG_ON(n == 0);
 
@@ -555,15 +563,15 @@ int idr_for_each(struct idr *idp,
 {
 	int n, id, max, error = 0;
 	struct idr_layer *p;
-	struct idr_layer *pa[MAX_LEVEL];
+	struct idr_layer *pa[MAX_LEVEL + 1];
 	struct idr_layer **paa = &pa[0];
 
 	n = idp->layers * IDR_BITS;
 	p = rcu_dereference_raw(idp->top);
-	max = 1 << n;
+	max = idr_max(idp->layers);
 
 	id = 0;
-	while (id < max) {
+	while (id >= 0 && id <= max) {
 		while (n > 0 && p) {
 			n -= IDR_BITS;
 			*paa++ = p;
@@ -601,7 +609,7 @@ EXPORT_SYMBOL(idr_for_each);
  */
 void *idr_get_next(struct idr *idp, int *nextidp)
 {
-	struct idr_layer *p, *pa[MAX_LEVEL];
+	struct idr_layer *p, *pa[MAX_LEVEL + 1];
 	struct idr_layer **paa = &pa[0];
 	int id = *nextidp;
 	int n, max;
@@ -611,9 +619,9 @@ void *idr_get_next(struct idr *idp, int
 	if (!p)
 		return NULL;
 	n = (p->layer + 1) * IDR_BITS;
-	max = 1 << n;
+	max = idr_max(p->layer + 1);
 
-	while (id < max) {
+	while (id >= 0 && id <= max) {
 		while (n > 0 && p) {
 			n -= IDR_BITS;
 			*paa++ = p;
@@ -787,7 +795,7 @@ EXPORT_SYMBOL(ida_pre_get);
  */
 int ida_get_new_above(struct ida *ida, int starting_id, int *p_id)
 {
-	struct idr_layer *pa[MAX_LEVEL];
+	struct idr_layer *pa[MAX_LEVEL + 1];
 	struct ida_bitmap *bitmap;
 	unsigned long flags;
 	int idr_id = starting_id / IDA_BITMAP_BITS;
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/Makefile linux-libre-3.4.87-gnu1/Makefile
--- linux-libre-3.4.86-gnu1/Makefile	2014-04-04 04:38:47.000000000 -0400
+++ linux-libre-3.4.87-gnu1/Makefile	2014-04-14 14:19:57.000000000 -0400
@@ -1,6 +1,6 @@
 VERSION = 3
 PATCHLEVEL = 4
-SUBLEVEL = 86
+SUBLEVEL = 87
 EXTRAVERSION =-gnu1
 NAME = Saber-toothed Squirrel
 
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/security/selinux/hooks.c linux-libre-3.4.87-gnu1/security/selinux/hooks.c
--- linux-libre-3.4.86-gnu1/security/selinux/hooks.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/security/selinux/hooks.c	2014-04-14 09:45:17.000000000 -0400
@@ -1329,15 +1329,33 @@ static int inode_doinit_with_dentry(stru
 		isec->sid = sbsec->sid;
 
 		if ((sbsec->flags & SE_SBPROC) && !S_ISLNK(inode->i_mode)) {
-			if (opt_dentry) {
-				isec->sclass = inode_mode_to_security_class(inode->i_mode);
-				rc = selinux_proc_get_sid(opt_dentry,
-							  isec->sclass,
-							  &sid);
-				if (rc)
-					goto out_unlock;
-				isec->sid = sid;
-			}
+			/* We must have a dentry to determine the label on
+			 * procfs inodes */
+			if (opt_dentry)
+				/* Called from d_instantiate or
+				 * d_splice_alias. */
+				dentry = dget(opt_dentry);
+			else
+				/* Called from selinux_complete_init, try to
+				 * find a dentry. */
+				dentry = d_find_alias(inode);
+			/*
+			 * This can be hit on boot when a file is accessed
+			 * before the policy is loaded.  When we load policy we
+			 * may find inodes that have no dentry on the
+			 * sbsec->isec_head list.  No reason to complain as
+			 * these will get fixed up the next time we go through
+			 * inode_doinit() with a dentry, before these inodes
+			 * could be used again by userspace.
+			 */
+			if (!dentry)
+				goto out_unlock;
+			isec->sclass = inode_mode_to_security_class(inode->i_mode);
+			rc = selinux_proc_get_sid(dentry, isec->sclass, &sid);
+			dput(dentry);
+			if (rc)
+				goto out_unlock;
+			isec->sid = sid;
 		}
 		break;
 	}
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/sound/drivers/aloop.c linux-libre-3.4.87-gnu1/sound/drivers/aloop.c
--- linux-libre-3.4.86-gnu1/sound/drivers/aloop.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/sound/drivers/aloop.c	2014-04-14 09:45:17.000000000 -0400
@@ -287,12 +287,14 @@ static int loopback_trigger(struct snd_p
 			loopback_active_notify(dpcm);
 		break;
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
 		spin_lock(&cable->lock);	
 		cable->pause |= stream;
 		spin_unlock(&cable->lock);
 		loopback_timer_stop(dpcm);
 		break;
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+	case SNDRV_PCM_TRIGGER_RESUME:
 		spin_lock(&cable->lock);
 		dpcm->last_jiffies = jiffies;
 		cable->pause &= ~stream;
@@ -552,7 +554,8 @@ static snd_pcm_uframes_t loopback_pointe
 static struct snd_pcm_hardware loopback_pcm_hardware =
 {
 	.info =		(SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP |
-			 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE),
+			 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE |
+			 SNDRV_PCM_INFO_RESUME),
 	.formats =	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
 			 SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE |
 			 SNDRV_PCM_FMTBIT_FLOAT_LE | SNDRV_PCM_FMTBIT_FLOAT_BE),
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/sound/drivers/pcsp/pcsp.c linux-libre-3.4.87-gnu1/sound/drivers/pcsp/pcsp.c
--- linux-libre-3.4.86-gnu1/sound/drivers/pcsp/pcsp.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/sound/drivers/pcsp/pcsp.c	2014-04-14 09:45:17.000000000 -0400
@@ -187,8 +187,8 @@ static int __devinit pcsp_probe(struct p
 static int __devexit pcsp_remove(struct platform_device *dev)
 {
 	struct snd_pcsp *chip = platform_get_drvdata(dev);
-	alsa_card_pcsp_exit(chip);
 	pcspkr_input_remove(chip->input_dev);
+	alsa_card_pcsp_exit(chip);
 	platform_set_drvdata(dev, NULL);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/sound/i2c/other/ak4xxx-adda.c linux-libre-3.4.87-gnu1/sound/i2c/other/ak4xxx-adda.c
--- linux-libre-3.4.86-gnu1/sound/i2c/other/ak4xxx-adda.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/sound/i2c/other/ak4xxx-adda.c	2014-04-14 09:45:17.000000000 -0400
@@ -571,7 +571,7 @@ static int ak4xxx_capture_source_info(st
 	struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);
 	int mixer_ch = AK_GET_SHIFT(kcontrol->private_value);
 	const char **input_names;
-	int  num_names, idx;
+	unsigned int num_names, idx;
 
 	num_names = ak4xxx_capture_num_inputs(ak, mixer_ch);
 	if (!num_names)
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/sound/pci/hda/hda_intel.c linux-libre-3.4.87-gnu1/sound/pci/hda/hda_intel.c
--- linux-libre-3.4.86-gnu1/sound/pci/hda/hda_intel.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/sound/pci/hda/hda_intel.c	2014-04-14 09:45:17.000000000 -0400
@@ -582,29 +582,43 @@ static char *driver_short_names[] __devi
 #define get_azx_dev(substream) (substream->runtime->private_data)
 
 #ifdef CONFIG_X86
-static void __mark_pages_wc(struct azx *chip, void *addr, size_t size, bool on)
+static void __mark_pages_wc(struct azx *chip, struct snd_dma_buffer *dmab, bool on)
 {
+	int pages;
+
 	if (azx_snoop(chip))
 		return;
-	if (addr && size) {
-		int pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+	if (!dmab || !dmab->area || !dmab->bytes)
+		return;
+
+#ifdef CONFIG_SND_DMA_SGBUF
+	if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_SG) {
+		struct snd_sg_buf *sgbuf = dmab->private_data;
 		if (on)
-			set_memory_wc((unsigned long)addr, pages);
+			set_pages_array_wc(sgbuf->page_table, sgbuf->pages);
 		else
-			set_memory_wb((unsigned long)addr, pages);
+			set_pages_array_wb(sgbuf->page_table, sgbuf->pages);
+		return;
 	}
+#endif
+
+	pages = (dmab->bytes + PAGE_SIZE - 1) >> PAGE_SHIFT;
+	if (on)
+		set_memory_wc((unsigned long)dmab->area, pages);
+	else
+		set_memory_wb((unsigned long)dmab->area, pages);
 }
 
 static inline void mark_pages_wc(struct azx *chip, struct snd_dma_buffer *buf,
 				 bool on)
 {
-	__mark_pages_wc(chip, buf->area, buf->bytes, on);
+	__mark_pages_wc(chip, buf, on);
 }
 static inline void mark_runtime_wc(struct azx *chip, struct azx_dev *azx_dev,
-				   struct snd_pcm_runtime *runtime, bool on)
+				   struct snd_pcm_substream *substream, bool on)
 {
 	if (azx_dev->wc_marked != on) {
-		__mark_pages_wc(chip, runtime->dma_area, runtime->dma_bytes, on);
+		__mark_pages_wc(chip, substream->runtime->dma_buffer_p, on);
 		azx_dev->wc_marked = on;
 	}
 }
@@ -615,7 +629,7 @@ static inline void mark_pages_wc(struct
 {
 }
 static inline void mark_runtime_wc(struct azx *chip, struct azx_dev *azx_dev,
-				   struct snd_pcm_runtime *runtime, bool on)
+				   struct snd_pcm_substream *substream, bool on)
 {
 }
 #endif
@@ -1772,11 +1786,10 @@ static int azx_pcm_hw_params(struct snd_
 {
 	struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
 	struct azx *chip = apcm->chip;
-	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct azx_dev *azx_dev = get_azx_dev(substream);
 	int ret;
 
-	mark_runtime_wc(chip, azx_dev, runtime, false);
+	mark_runtime_wc(chip, azx_dev, substream, false);
 	azx_dev->bufsize = 0;
 	azx_dev->period_bytes = 0;
 	azx_dev->format_val = 0;
@@ -1784,7 +1797,7 @@ static int azx_pcm_hw_params(struct snd_
 					params_buffer_bytes(hw_params));
 	if (ret < 0)
 		return ret;
-	mark_runtime_wc(chip, azx_dev, runtime, true);
+	mark_runtime_wc(chip, azx_dev, substream, true);
 	return ret;
 }
 
@@ -1793,7 +1806,6 @@ static int azx_pcm_hw_free(struct snd_pc
 	struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
 	struct azx_dev *azx_dev = get_azx_dev(substream);
 	struct azx *chip = apcm->chip;
-	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream];
 
 	/* reset BDL address */
@@ -1806,7 +1818,7 @@ static int azx_pcm_hw_free(struct snd_pc
 
 	snd_hda_codec_cleanup(apcm->codec, hinfo, substream);
 
-	mark_runtime_wc(chip, azx_dev, runtime, false);
+	mark_runtime_wc(chip, azx_dev, substream, false);
 	return snd_pcm_lib_free_pages(substream);
 }
 
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/sound/pci/hda/patch_conexant.c linux-libre-3.4.87-gnu1/sound/pci/hda/patch_conexant.c
--- linux-libre-3.4.86-gnu1/sound/pci/hda/patch_conexant.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/sound/pci/hda/patch_conexant.c	2014-04-14 09:45:17.000000000 -0400
@@ -141,6 +141,7 @@ struct conexant_spec {
 	unsigned int hp_laptop:1;
 	unsigned int asus:1;
 	unsigned int pin_eapd_ctrls:1;
+	unsigned int fixup_stereo_dmic:1;
 
 	unsigned int adc_switching:1;
 
@@ -548,24 +549,12 @@ static int conexant_build_controls(struc
 	return 0;
 }
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static int conexant_suspend(struct hda_codec *codec, pm_message_t state)
-{
-	snd_hda_shutup_pins(codec);
-	return 0;
-}
-#endif
-
 static const struct hda_codec_ops conexant_patch_ops = {
 	.build_controls = conexant_build_controls,
 	.build_pcms = conexant_build_pcms,
 	.init = conexant_init,
 	.free = conexant_free,
 	.set_power_state = conexant_set_power,
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	.suspend = conexant_suspend,
-#endif
-	.reboot_notify = snd_hda_shutup_pins,
 };
 
 #ifdef CONFIG_SND_HDA_INPUT_BEEP
@@ -4083,9 +4072,9 @@ static int cx_auto_init(struct hda_codec
 
 static int cx_auto_add_volume_idx(struct hda_codec *codec, const char *basename,
 			      const char *dir, int cidx,
-			      hda_nid_t nid, int hda_dir, int amp_idx)
+			      hda_nid_t nid, int hda_dir, int amp_idx, int chs)
 {
-	static char name[32];
+	static char name[44];
 	static struct snd_kcontrol_new knew[] = {
 		HDA_CODEC_VOLUME(name, 0, 0, 0),
 		HDA_CODEC_MUTE(name, 0, 0, 0),
@@ -4095,7 +4084,7 @@ static int cx_auto_add_volume_idx(struct
 
 	for (i = 0; i < 2; i++) {
 		struct snd_kcontrol *kctl;
-		knew[i].private_value = HDA_COMPOSE_AMP_VAL(nid, 3, amp_idx,
+		knew[i].private_value = HDA_COMPOSE_AMP_VAL(nid, chs, amp_idx,
 							    hda_dir);
 		knew[i].subdevice = HDA_SUBDEV_AMP_FLAG;
 		knew[i].index = cidx;
@@ -4114,7 +4103,7 @@ static int cx_auto_add_volume_idx(struct
 }
 
 #define cx_auto_add_volume(codec, str, dir, cidx, nid, hda_dir)		\
-	cx_auto_add_volume_idx(codec, str, dir, cidx, nid, hda_dir, 0)
+	cx_auto_add_volume_idx(codec, str, dir, cidx, nid, hda_dir, 0, 3)
 
 #define cx_auto_add_pb_volume(codec, nid, str, idx)			\
 	cx_auto_add_volume(codec, str, " Playback", idx, nid, HDA_OUTPUT)
@@ -4184,6 +4173,36 @@ static int cx_auto_build_output_controls
 	return 0;
 }
 
+/* Returns zero if this is a normal stereo channel, and non-zero if it should
+   be split in two independent channels.
+   dest_label must be at least 44 characters. */
+static int cx_auto_get_rightch_label(struct hda_codec *codec, const char *label,
+				     char *dest_label, int nid)
+{
+	struct conexant_spec *spec = codec->spec;
+	int i;
+
+	if (!spec->fixup_stereo_dmic)
+		return 0;
+
+	for (i = 0; i < AUTO_CFG_MAX_INS; i++) {
+		int def_conf;
+		if (spec->autocfg.inputs[i].pin != nid)
+			continue;
+
+		if (spec->autocfg.inputs[i].type != AUTO_PIN_MIC)
+			return 0;
+		def_conf = snd_hda_codec_get_pincfg(codec, nid);
+		if (snd_hda_get_input_pin_attr(def_conf) != INPUT_PIN_ATTR_INT)
+			return 0;
+
+		/* Finally found the inverted internal mic! */
+		snprintf(dest_label, 44, "Inverted %s", label);
+		return 1;
+	}
+	return 0;
+}
+
 static int cx_auto_add_capture_volume(struct hda_codec *codec, hda_nid_t nid,
 				      const char *label, const char *pfx,
 				      int cidx)
@@ -4192,14 +4211,25 @@ static int cx_auto_add_capture_volume(st
 	int i;
 
 	for (i = 0; i < spec->num_adc_nids; i++) {
+		char rightch_label[44];
 		hda_nid_t adc_nid = spec->adc_nids[i];
 		int idx = get_input_connection(codec, adc_nid, nid);
 		if (idx < 0)
 			continue;
 		if (codec->single_adc_amp)
 			idx = 0;
+
+		if (cx_auto_get_rightch_label(codec, label, rightch_label, nid)) {
+			/* Make two independent kcontrols for left and right */
+			int err = cx_auto_add_volume_idx(codec, label, pfx,
+						cidx, adc_nid, HDA_INPUT, idx, 1);
+			if (err < 0)
+				return err;
+			return cx_auto_add_volume_idx(codec, rightch_label, pfx,
+							cidx, adc_nid, HDA_INPUT, idx, 2);
+		}
 		return cx_auto_add_volume_idx(codec, label, pfx,
-					      cidx, adc_nid, HDA_INPUT, idx);
+					      cidx, adc_nid, HDA_INPUT, idx, 3);
 	}
 	return 0;
 }
@@ -4212,9 +4242,19 @@ static int cx_auto_add_boost_volume(stru
 	int i, con;
 
 	nid = spec->imux_info[idx].pin;
-	if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)
+	if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) {
+		char rightch_label[44];
+		if (cx_auto_get_rightch_label(codec, label, rightch_label, nid)) {
+			int err = cx_auto_add_volume_idx(codec, label, " Boost",
+							 cidx, nid, HDA_INPUT, 0, 1);
+			if (err < 0)
+				return err;
+			return cx_auto_add_volume_idx(codec, rightch_label, " Boost",
+						      cidx, nid, HDA_INPUT, 0, 2);
+		}
 		return cx_auto_add_volume(codec, label, " Boost", cidx,
 					  nid, HDA_INPUT);
+	}
 	con = __select_input_connection(codec, spec->imux_info[idx].adc, nid,
 					&mux, false, 0);
 	if (con < 0)
@@ -4360,10 +4400,6 @@ static const struct hda_codec_ops cx_aut
 	.init = cx_auto_init,
 	.free = conexant_free,
 	.unsol_event = cx_auto_unsol_event,
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	.suspend = conexant_suspend,
-#endif
-	.reboot_notify = snd_hda_shutup_pins,
 };
 
 /*
@@ -4381,23 +4417,31 @@ static void apply_pincfg(struct hda_code
 
 }
 
-static void apply_pin_fixup(struct hda_codec *codec,
+enum {
+	CXT_PINCFG_LENOVO_X200,
+	CXT_PINCFG_LENOVO_TP410,
+	CXT_FIXUP_STEREO_DMIC
+};
+
+static void apply_fixup(struct hda_codec *codec,
 			    const struct snd_pci_quirk *quirk,
 			    const struct cxt_pincfg **table)
 {
+	 struct conexant_spec *spec = codec->spec;
+
 	quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk);
-	if (quirk) {
+	if (quirk && table[quirk->value]) {
 		snd_printdd(KERN_INFO "hda_codec: applying pincfg for %s\n",
 			    quirk->name);
 		apply_pincfg(codec, table[quirk->value]);
 	}
+	if (quirk->value == CXT_FIXUP_STEREO_DMIC) {
+		snd_printdd(KERN_INFO "hda_codec: applying internal mic workaround for %s\n",
+			    quirk->name);
+		spec->fixup_stereo_dmic = 1;
+	}
 }
 
-enum {
-	CXT_PINCFG_LENOVO_X200,
-	CXT_PINCFG_LENOVO_TP410,
-};
-
 /* ThinkPad X200 & co with cxt5051 */
 static const struct cxt_pincfg cxt_pincfg_lenovo_x200[] = {
 	{ 0x16, 0x042140ff }, /* HP (seq# overridden) */
@@ -4418,6 +4462,7 @@ static const struct cxt_pincfg cxt_pincf
 static const struct cxt_pincfg *cxt_pincfg_tbl[] = {
 	[CXT_PINCFG_LENOVO_X200] = cxt_pincfg_lenovo_x200,
 	[CXT_PINCFG_LENOVO_TP410] = cxt_pincfg_lenovo_tp410,
+	[CXT_FIXUP_STEREO_DMIC] = NULL,
 };
 
 static const struct snd_pci_quirk cxt5051_fixups[] = {
@@ -4431,6 +4476,7 @@ static const struct snd_pci_quirk cxt506
 	SND_PCI_QUIRK(0x17aa, 0x215f, "Lenovo T510", CXT_PINCFG_LENOVO_TP410),
 	SND_PCI_QUIRK(0x17aa, 0x21ce, "Lenovo T420", CXT_PINCFG_LENOVO_TP410),
 	SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520", CXT_PINCFG_LENOVO_TP410),
+	SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC),
 	{}
 };
 
@@ -4470,11 +4516,11 @@ static int patch_conexant_auto(struct hd
 	case 0x14f15051:
 		add_cx5051_fake_mutes(codec);
 		codec->pin_amp_workaround = 1;
-		apply_pin_fixup(codec, cxt5051_fixups, cxt_pincfg_tbl);
+		apply_fixup(codec, cxt5051_fixups, cxt_pincfg_tbl);
 		break;
 	default:
 		codec->pin_amp_workaround = 1;
-		apply_pin_fixup(codec, cxt5066_fixups, cxt_pincfg_tbl);
+		apply_fixup(codec, cxt5066_fixups, cxt_pincfg_tbl);
 	}
 
 	/* Show mute-led control only on HP laptops
@@ -4521,6 +4567,10 @@ static int patch_conexant_auto(struct hd
  */
 
 static const struct hda_codec_preset snd_hda_preset_conexant[] = {
+	{ .id = 0x14f11510, .name = "CX20751/2",
+	  .patch = patch_conexant_auto },
+	{ .id = 0x14f11511, .name = "CX20753/4",
+	  .patch = patch_conexant_auto },
 	{ .id = 0x14f15045, .name = "CX20549 (Venice)",
 	  .patch = patch_cxt5045 },
 	{ .id = 0x14f15047, .name = "CX20551 (Waikiki)",
@@ -4558,6 +4608,8 @@ static const struct hda_codec_preset snd
 	{} /* terminator */
 };
 
+MODULE_ALIAS("snd-hda-codec-id:14f11510");
+MODULE_ALIAS("snd-hda-codec-id:14f11511");
 MODULE_ALIAS("snd-hda-codec-id:14f15045");
 MODULE_ALIAS("snd-hda-codec-id:14f15047");
 MODULE_ALIAS("snd-hda-codec-id:14f15051");
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/sound/pci/hda/patch_hdmi.c linux-libre-3.4.87-gnu1/sound/pci/hda/patch_hdmi.c
--- linux-libre-3.4.86-gnu1/sound/pci/hda/patch_hdmi.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/sound/pci/hda/patch_hdmi.c	2014-04-14 09:45:17.000000000 -0400
@@ -425,9 +425,11 @@ static void hdmi_init_pin(struct hda_cod
 	if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP)
 		snd_hda_codec_write(codec, pin_nid, 0,
 				AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
-	/* Disable pin out until stream is active*/
+	/* Enable pin out: some machines with GM965 gets broken output when
+	 * the pin is disabled or changed while using with HDMI
+	 */
 	snd_hda_codec_write(codec, pin_nid, 0,
-			    AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
+			    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
 }
 
 static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t cvt_nid)
@@ -511,6 +513,17 @@ static int hdmi_channel_allocation(struc
 		}
 	}
 
+	if (!ca) {
+		/* if there was no match, select the regular ALSA channel
+		 * allocation with the matching number of channels */
+		for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
+			if (channels == channel_allocations[i].channels) {
+				ca = channel_allocations[i].ca_index;
+				break;
+			}
+		}
+	}
+
 	snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf));
 	snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n",
 		    ca, channels, buf);
@@ -908,7 +921,7 @@ static int hdmi_pcm_open(struct hda_pcm_
 	per_cvt->assigned = 1;
 	hinfo->nid = per_cvt->cvt_nid;
 
-	snd_hda_codec_write(codec, per_pin->pin_nid, 0,
+	snd_hda_codec_write_cache(codec, per_pin->pin_nid, 0,
 			    AC_VERB_SET_CONNECT_SEL,
 			    mux_idx);
 	snd_hda_spdif_ctls_assign(codec, pin_idx, per_cvt->cvt_nid);
@@ -1152,17 +1165,11 @@ static int generic_hdmi_playback_pcm_pre
 	struct hdmi_spec *spec = codec->spec;
 	int pin_idx = hinfo_to_pin_index(spec, hinfo);
 	hda_nid_t pin_nid = spec->pins[pin_idx].pin_nid;
-	int pinctl;
 
 	hdmi_set_channel_count(codec, cvt_nid, substream->runtime->channels);
 
 	hdmi_setup_audio_infoframe(codec, pin_idx, substream);
 
-	pinctl = snd_hda_codec_read(codec, pin_nid, 0,
-				    AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
-	snd_hda_codec_write(codec, pin_nid, 0,
-			    AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl | PIN_OUT);
-
 	return hdmi_setup_stream(codec, cvt_nid, pin_nid, stream_tag, format);
 }
 
@@ -1174,7 +1181,6 @@ static int generic_hdmi_playback_pcm_cle
 	int cvt_idx, pin_idx;
 	struct hdmi_spec_per_cvt *per_cvt;
 	struct hdmi_spec_per_pin *per_pin;
-	int pinctl;
 
 	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
 
@@ -1193,11 +1199,6 @@ static int generic_hdmi_playback_pcm_cle
 			return -EINVAL;
 		per_pin = &spec->pins[pin_idx];
 
-		pinctl = snd_hda_codec_read(codec, per_pin->pin_nid, 0,
-					    AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
-		snd_hda_codec_write(codec, per_pin->pin_nid, 0,
-				    AC_VERB_SET_PIN_WIDGET_CONTROL,
-				    pinctl & ~PIN_OUT);
 		snd_hda_spdif_ctls_unassign(codec, pin_idx);
 	}
 
@@ -1919,6 +1920,8 @@ static const struct hda_codec_preset snd
 { .id = 0x10de0042, .name = "GPU 42 HDMI/DP",	.patch = patch_generic_hdmi },
 { .id = 0x10de0043, .name = "GPU 43 HDMI/DP",	.patch = patch_generic_hdmi },
 { .id = 0x10de0044, .name = "GPU 44 HDMI/DP",	.patch = patch_generic_hdmi },
+{ .id = 0x10de0051, .name = "GPU 51 HDMI/DP",	.patch = patch_generic_hdmi },
+{ .id = 0x10de0060, .name = "GPU 60 HDMI/DP",	.patch = patch_generic_hdmi },
 { .id = 0x10de0067, .name = "MCP67 HDMI",	.patch = patch_nvhdmi_2ch },
 { .id = 0x10de8001, .name = "MCP73 HDMI",	.patch = patch_nvhdmi_2ch },
 { .id = 0x80860054, .name = "IbexPeak HDMI",	.patch = patch_generic_hdmi },
@@ -1965,6 +1968,8 @@ MODULE_ALIAS("snd-hda-codec-id:10de0041"
 MODULE_ALIAS("snd-hda-codec-id:10de0042");
 MODULE_ALIAS("snd-hda-codec-id:10de0043");
 MODULE_ALIAS("snd-hda-codec-id:10de0044");
+MODULE_ALIAS("snd-hda-codec-id:10de0051");
+MODULE_ALIAS("snd-hda-codec-id:10de0060");
 MODULE_ALIAS("snd-hda-codec-id:10de0067");
 MODULE_ALIAS("snd-hda-codec-id:10de8001");
 MODULE_ALIAS("snd-hda-codec-id:17e80047");
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/sound/pci/hda/patch_realtek.c linux-libre-3.4.87-gnu1/sound/pci/hda/patch_realtek.c
--- linux-libre-3.4.86-gnu1/sound/pci/hda/patch_realtek.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/sound/pci/hda/patch_realtek.c	2014-04-14 09:45:17.000000000 -0400
@@ -7031,6 +7031,7 @@ static int patch_alc680(struct hda_codec
  */
 static const struct hda_codec_preset snd_hda_preset_realtek[] = {
 	{ .id = 0x10ec0221, .name = "ALC221", .patch = patch_alc269 },
+	{ .id = 0x10ec0231, .name = "ALC231", .patch = patch_alc269 },
 	{ .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
 	{ .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
 	{ .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 },
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/sound/usb/6fire/comm.c linux-libre-3.4.87-gnu1/sound/usb/6fire/comm.c
--- linux-libre-3.4.86-gnu1/sound/usb/6fire/comm.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/sound/usb/6fire/comm.c	2014-04-14 09:45:17.000000000 -0400
@@ -110,19 +110,37 @@ static int usb6fire_comm_send_buffer(u8
 static int usb6fire_comm_write8(struct comm_runtime *rt, u8 request,
 		u8 reg, u8 value)
 {
-	u8 buffer[13]; /* 13: maximum length of message */
+	u8 *buffer;
+	int ret;
+
+	/* 13: maximum length of message */
+	buffer = kmalloc(13, GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
 
 	usb6fire_comm_init_buffer(buffer, 0x00, request, reg, value, 0x00);
-	return usb6fire_comm_send_buffer(buffer, rt->chip->dev);
+	ret = usb6fire_comm_send_buffer(buffer, rt->chip->dev);
+
+	kfree(buffer);
+	return ret;
 }
 
 static int usb6fire_comm_write16(struct comm_runtime *rt, u8 request,
 		u8 reg, u8 vl, u8 vh)
 {
-	u8 buffer[13]; /* 13: maximum length of message */
+	u8 *buffer;
+	int ret;
+
+	/* 13: maximum length of message */
+	buffer = kmalloc(13, GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
 
 	usb6fire_comm_init_buffer(buffer, 0x00, request, reg, vl, vh);
-	return usb6fire_comm_send_buffer(buffer, rt->chip->dev);
+	ret = usb6fire_comm_send_buffer(buffer, rt->chip->dev);
+
+	kfree(buffer);
+	return ret;
 }
 
 int __devinit usb6fire_comm_init(struct sfire_chip *chip)
@@ -135,6 +153,12 @@ int __devinit usb6fire_comm_init(struct
 	if (!rt)
 		return -ENOMEM;
 
+	rt->receiver_buffer = kzalloc(COMM_RECEIVER_BUFSIZE, GFP_KERNEL);
+	if (!rt->receiver_buffer) {
+		kfree(rt);
+		return -ENOMEM;
+	}
+
 	rt->serial = 1;
 	rt->chip = chip;
 	usb_init_urb(urb);
@@ -152,6 +176,7 @@ int __devinit usb6fire_comm_init(struct
 	urb->interval = 1;
 	ret = usb_submit_urb(urb, GFP_KERNEL);
 	if (ret < 0) {
+		kfree(rt->receiver_buffer);
 		kfree(rt);
 		snd_printk(KERN_ERR PREFIX "cannot create comm data receiver.");
 		return ret;
@@ -170,6 +195,9 @@ void usb6fire_comm_abort(struct sfire_ch
 
 void usb6fire_comm_destroy(struct sfire_chip *chip)
 {
-	kfree(chip->comm);
+	struct comm_runtime *rt = chip->comm;
+
+	kfree(rt->receiver_buffer);
+	kfree(rt);
 	chip->comm = NULL;
 }
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/sound/usb/6fire/comm.h linux-libre-3.4.87-gnu1/sound/usb/6fire/comm.h
--- linux-libre-3.4.86-gnu1/sound/usb/6fire/comm.h	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/sound/usb/6fire/comm.h	2014-04-14 09:45:17.000000000 -0400
@@ -24,7 +24,7 @@ struct comm_runtime {
 	struct sfire_chip *chip;
 
 	struct urb receiver;
-	u8 receiver_buffer[COMM_RECEIVER_BUFSIZE];
+	u8 *receiver_buffer;
 
 	u8 serial; /* urb serial */
 
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/sound/usb/6fire/midi.c linux-libre-3.4.87-gnu1/sound/usb/6fire/midi.c
--- linux-libre-3.4.86-gnu1/sound/usb/6fire/midi.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/sound/usb/6fire/midi.c	2014-04-14 09:45:17.000000000 -0400
@@ -19,6 +19,10 @@
 #include "chip.h"
 #include "comm.h"
 
+enum {
+	MIDI_BUFSIZE = 64
+};
+
 static void usb6fire_midi_out_handler(struct urb *urb)
 {
 	struct midi_runtime *rt = urb->context;
@@ -156,6 +160,12 @@ int __devinit usb6fire_midi_init(struct
 	if (!rt)
 		return -ENOMEM;
 
+	rt->out_buffer = kzalloc(MIDI_BUFSIZE, GFP_KERNEL);
+	if (!rt->out_buffer) {
+		kfree(rt);
+		return -ENOMEM;
+	}
+
 	rt->chip = chip;
 	rt->in_received = usb6fire_midi_in_received;
 	rt->out_buffer[0] = 0x80; /* 'send midi' command */
@@ -169,6 +179,7 @@ int __devinit usb6fire_midi_init(struct
 
 	ret = snd_rawmidi_new(chip->card, "6FireUSB", 0, 1, 1, &rt->instance);
 	if (ret < 0) {
+		kfree(rt->out_buffer);
 		kfree(rt);
 		snd_printk(KERN_ERR PREFIX "unable to create midi.\n");
 		return ret;
@@ -197,6 +208,9 @@ void usb6fire_midi_abort(struct sfire_ch
 
 void usb6fire_midi_destroy(struct sfire_chip *chip)
 {
-	kfree(chip->midi);
+	struct midi_runtime *rt = chip->midi;
+
+	kfree(rt->out_buffer);
+	kfree(rt);
 	chip->midi = NULL;
 }
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/sound/usb/6fire/midi.h linux-libre-3.4.87-gnu1/sound/usb/6fire/midi.h
--- linux-libre-3.4.86-gnu1/sound/usb/6fire/midi.h	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/sound/usb/6fire/midi.h	2014-04-14 09:45:17.000000000 -0400
@@ -16,10 +16,6 @@
 
 #include "common.h"
 
-enum {
-	MIDI_BUFSIZE = 64
-};
-
 struct midi_runtime {
 	struct sfire_chip *chip;
 	struct snd_rawmidi *instance;
@@ -32,7 +28,7 @@ struct midi_runtime {
 	struct snd_rawmidi_substream *out;
 	struct urb out_urb;
 	u8 out_serial; /* serial number of out packet */
-	u8 out_buffer[MIDI_BUFSIZE];
+	u8 *out_buffer;
 	int buffer_offset;
 
 	void (*in_received)(struct midi_runtime *rt, u8 *data, int length);
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/sound/usb/6fire/pcm.c linux-libre-3.4.87-gnu1/sound/usb/6fire/pcm.c
--- linux-libre-3.4.86-gnu1/sound/usb/6fire/pcm.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/sound/usb/6fire/pcm.c	2014-04-14 09:45:17.000000000 -0400
@@ -578,6 +578,33 @@ static void __devinit usb6fire_pcm_init_
 	urb->instance.number_of_packets = PCM_N_PACKETS_PER_URB;
 }
 
+static int usb6fire_pcm_buffers_init(struct pcm_runtime *rt)
+{
+	int i;
+
+	for (i = 0; i < PCM_N_URBS; i++) {
+		rt->out_urbs[i].buffer = kzalloc(PCM_N_PACKETS_PER_URB
+				* PCM_MAX_PACKET_SIZE, GFP_KERNEL);
+		if (!rt->out_urbs[i].buffer)
+			return -ENOMEM;
+		rt->in_urbs[i].buffer = kzalloc(PCM_N_PACKETS_PER_URB
+				* PCM_MAX_PACKET_SIZE, GFP_KERNEL);
+		if (!rt->in_urbs[i].buffer)
+			return -ENOMEM;
+	}
+	return 0;
+}
+
+static void usb6fire_pcm_buffers_destroy(struct pcm_runtime *rt)
+{
+	int i;
+
+	for (i = 0; i < PCM_N_URBS; i++) {
+		kfree(rt->out_urbs[i].buffer);
+		kfree(rt->in_urbs[i].buffer);
+	}
+}
+
 int __devinit usb6fire_pcm_init(struct sfire_chip *chip)
 {
 	int i;
@@ -589,6 +616,13 @@ int __devinit usb6fire_pcm_init(struct s
 	if (!rt)
 		return -ENOMEM;
 
+	ret = usb6fire_pcm_buffers_init(rt);
+	if (ret) {
+		usb6fire_pcm_buffers_destroy(rt);
+		kfree(rt);
+		return ret;
+	}
+
 	rt->chip = chip;
 	rt->stream_state = STREAM_DISABLED;
 	rt->rate = ARRAY_SIZE(rates);
@@ -610,6 +644,7 @@ int __devinit usb6fire_pcm_init(struct s
 
 	ret = snd_pcm_new(chip->card, "DMX6FireUSB", 0, 1, 1, &pcm);
 	if (ret < 0) {
+		usb6fire_pcm_buffers_destroy(rt);
 		kfree(rt);
 		snd_printk(KERN_ERR PREFIX "cannot create pcm instance.\n");
 		return ret;
@@ -625,6 +660,7 @@ int __devinit usb6fire_pcm_init(struct s
 			snd_dma_continuous_data(GFP_KERNEL),
 			MAX_BUFSIZE, MAX_BUFSIZE);
 	if (ret) {
+		usb6fire_pcm_buffers_destroy(rt);
 		kfree(rt);
 		snd_printk(KERN_ERR PREFIX
 				"error preallocating pcm buffers.\n");
@@ -669,6 +705,9 @@ void usb6fire_pcm_abort(struct sfire_chi
 
 void usb6fire_pcm_destroy(struct sfire_chip *chip)
 {
-	kfree(chip->pcm);
+	struct pcm_runtime *rt = chip->pcm;
+
+	usb6fire_pcm_buffers_destroy(rt);
+	kfree(rt);
 	chip->pcm = NULL;
 }
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/sound/usb/6fire/pcm.h linux-libre-3.4.87-gnu1/sound/usb/6fire/pcm.h
--- linux-libre-3.4.86-gnu1/sound/usb/6fire/pcm.h	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/sound/usb/6fire/pcm.h	2014-04-14 09:45:17.000000000 -0400
@@ -32,7 +32,7 @@ struct pcm_urb {
 	struct urb instance;
 	struct usb_iso_packet_descriptor packets[PCM_N_PACKETS_PER_URB];
 	/* END DO NOT SEPARATE */
-	u8 buffer[PCM_N_PACKETS_PER_URB * PCM_MAX_PACKET_SIZE];
+	u8 *buffer;
 
 	struct pcm_urb *peer;
 };
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/sound/usb/card.h linux-libre-3.4.87-gnu1/sound/usb/card.h
--- linux-libre-3.4.86-gnu1/sound/usb/card.h	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/sound/usb/card.h	2014-04-14 09:45:17.000000000 -0400
@@ -74,6 +74,7 @@ struct snd_usb_substream {
 	unsigned int fill_max: 1;	/* fill max packet size always */
 	unsigned int txfr_quirk:1;	/* allow sub-frame alignment */
 	unsigned int fmt_type;		/* USB audio format type (1-3) */
+	unsigned int pkt_offset_adj;	/* Bytes to drop from beginning of packets (for non-compliant devices) */
 
 	unsigned int running: 1;	/* running status */
 
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/sound/usb/endpoint.c linux-libre-3.4.87-gnu1/sound/usb/endpoint.c
--- linux-libre-3.4.86-gnu1/sound/usb/endpoint.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/sound/usb/endpoint.c	2014-04-14 09:45:17.000000000 -0400
@@ -458,7 +458,7 @@ static int retire_capture_urb(struct snd
 	stride = runtime->frame_bits >> 3;
 
 	for (i = 0; i < urb->number_of_packets; i++) {
-		cp = (unsigned char *)urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+		cp = (unsigned char *)urb->transfer_buffer + urb->iso_frame_desc[i].offset + subs->pkt_offset_adj;
 		if (urb->iso_frame_desc[i].status && printk_ratelimit()) {
 			snd_printdd("frame %d active: %d\n", i, urb->iso_frame_desc[i].status);
 			// continue;
@@ -898,6 +898,7 @@ void snd_usb_init_substream(struct snd_u
 	subs->speed = snd_usb_get_speed(subs->dev);
 	if (subs->speed >= USB_SPEED_HIGH)
 		subs->ops.prepare_sync = prepare_capture_sync_urb_hs;
+	subs->pkt_offset_adj = 0;
 
 	snd_usb_set_pcm_ops(as->pcm, stream);
 
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/sound/usb/mixer.c linux-libre-3.4.87-gnu1/sound/usb/mixer.c
--- linux-libre-3.4.86-gnu1/sound/usb/mixer.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/sound/usb/mixer.c	2014-04-14 09:45:17.000000000 -0400
@@ -720,8 +720,20 @@ static int check_input_term(struct mixer
 			return 0;
 		}
 		case UAC1_PROCESSING_UNIT:
-		case UAC1_EXTENSION_UNIT: {
+		case UAC1_EXTENSION_UNIT:
+		/* UAC2_PROCESSING_UNIT_V2 */
+		/* UAC2_EFFECT_UNIT */
+		case UAC2_EXTENSION_UNIT_V2: {
 			struct uac_processing_unit_descriptor *d = p1;
+
+			if (state->mixer->protocol == UAC_VERSION_2 &&
+				hdr[2] == UAC2_EFFECT_UNIT) {
+				/* UAC2/UAC1 unit IDs overlap here in an
+				 * uncompatible way. Ignore this unit for now.
+				 */
+				return 0;
+			}
+
 			if (d->bNrInPins) {
 				id = d->baSourceID[0];
 				break; /* continue to parse */
@@ -1964,6 +1976,8 @@ static int parse_audio_unit(struct mixer
 			return parse_audio_extension_unit(state, unitid, p1);
 		else /* UAC_VERSION_2 */
 			return parse_audio_processing_unit(state, unitid, p1);
+	case UAC2_EXTENSION_UNIT_V2:
+		return parse_audio_extension_unit(state, unitid, p1);
 	default:
 		snd_printk(KERN_ERR "usbaudio: unit %u: unexpected type 0x%02x\n", unitid, p1[2]);
 		return -EINVAL;
diff -druNp --no-dereference linux-libre-3.4.86-gnu1/sound/usb/quirks.c linux-libre-3.4.87-gnu1/sound/usb/quirks.c
--- linux-libre-3.4.86-gnu1/sound/usb/quirks.c	2014-04-03 14:59:21.000000000 -0400
+++ linux-libre-3.4.87-gnu1/sound/usb/quirks.c	2014-04-14 09:45:17.000000000 -0400
@@ -748,6 +748,7 @@ static void set_format_emu_quirk(struct
 		break;
 	}
 	snd_emuusb_set_samplerate(subs->stream->chip, emu_samplerate_id);
+	subs->pkt_offset_adj = (emu_samplerate_id >= EMU_QUIRK_SR_176400HZ) ? 4 : 0;
 }
 
 void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
