diff -druNp --no-dereference linux-libre-3.2.86-gnu1/arch/arm/include/asm/cputype.h linux-libre-3.2.87-gnu1/arch/arm/include/asm/cputype.h
--- linux-libre-3.2.86-gnu1/arch/arm/include/asm/cputype.h	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/arch/arm/include/asm/cputype.h	2017-03-15 22:19:00.000000000 -0400
@@ -25,6 +25,9 @@
 #define CPUID_EXT_ISAR4	"c2, 4"
 #define CPUID_EXT_ISAR5	"c2, 5"
 
+/* Qualcomm implemented cores */
+#define ARM_CPU_PART_SCORPION		0x510002d0
+
 extern unsigned int processor_id;
 
 #ifdef CONFIG_CPU_CP15
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/arch/arm/kernel/hw_breakpoint.c linux-libre-3.2.87-gnu1/arch/arm/kernel/hw_breakpoint.c
--- linux-libre-3.2.86-gnu1/arch/arm/kernel/hw_breakpoint.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/arch/arm/kernel/hw_breakpoint.c	2017-03-15 22:19:00.000000000 -0400
@@ -1001,6 +1001,22 @@ static int __init arch_hw_breakpoint_ini
 		return 0;
 	}
 
+	/*
+	 * Scorpion CPUs (at least those in APQ8060) seem to set DBGPRSR.SPD
+	 * whenever a WFI is issued, even if the core is not powered down, in
+	 * violation of the architecture.  When DBGPRSR.SPD is set, accesses to
+	 * breakpoint and watchpoint registers are treated as undefined, so
+	 * this results in boot time and runtime failures when these are
+	 * accessed and we unexpectedly take a trap.
+	 *
+	 * It's not clear if/how this can be worked around, so we blacklist
+	 * Scorpion CPUs to avoid these issues.
+	*/
+	if ((read_cpuid_id() & 0xff00fff0) == ARM_CPU_PART_SCORPION) {
+		pr_info("Scorpion CPU detected. Hardware breakpoints and watchpoints disabled\n");
+		return 0;
+	}
+
 	/* Determine how many BRPs/WRPs are available. */
 	core_num_brps = get_num_brps();
 	core_num_wrps = get_num_wrps();
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/arch/arm/kernel/ptrace.c linux-libre-3.2.87-gnu1/arch/arm/kernel/ptrace.c
--- linux-libre-3.2.86-gnu1/arch/arm/kernel/ptrace.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/arch/arm/kernel/ptrace.c	2017-03-15 22:19:00.000000000 -0400
@@ -593,7 +593,7 @@ static int gpr_set(struct task_struct *t
 		   const void *kbuf, const void __user *ubuf)
 {
 	int ret;
-	struct pt_regs newregs;
+	struct pt_regs newregs = *task_pt_regs(target);
 
 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 				 &newregs,
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/arch/cris/boot/rescue/Makefile linux-libre-3.2.87-gnu1/arch/cris/boot/rescue/Makefile
--- linux-libre-3.2.86-gnu1/arch/cris/boot/rescue/Makefile	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/arch/cris/boot/rescue/Makefile	2017-03-15 22:19:00.000000000 -0400
@@ -10,6 +10,9 @@
 
 asflags-y += $(LINUXINCLUDE)
 ccflags-y += -O2 $(LINUXINCLUDE)
+
+ifdef CONFIG_ETRAX_AXISFLASHMAP
+
 arch-$(CONFIG_ETRAX_ARCH_V10) = v10
 arch-$(CONFIG_ETRAX_ARCH_V32) = v32
 
@@ -28,6 +31,11 @@ $(obj)/rescue.bin: $(obj)/rescue.o FORCE
 	$(call if_changed,objcopy)
 	cp -p $(obj)/rescue.bin $(objtree)
 
+else
+$(obj)/rescue.bin:
+
+endif
+
 $(obj)/testrescue.bin: $(obj)/testrescue.o
 	$(OBJCOPY) $(OBJCOPYFLAGS) $(obj)/testrescue.o tr.bin
 # Pad it to 784 bytes
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/arch/parisc/include/asm/bitops.h linux-libre-3.2.87-gnu1/arch/parisc/include/asm/bitops.h
--- linux-libre-3.2.86-gnu1/arch/parisc/include/asm/bitops.h	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/arch/parisc/include/asm/bitops.h	2017-03-15 22:19:00.000000000 -0400
@@ -6,7 +6,7 @@
 #endif
 
 #include <linux/compiler.h>
-#include <asm/types.h>		/* for BITS_PER_LONG/SHIFT_PER_LONG */
+#include <asm/types.h>
 #include <asm/byteorder.h>
 #include <linux/atomic.h>
 
@@ -16,6 +16,12 @@
  * to include/asm-i386/bitops.h or kerneldoc
  */
 
+#if __BITS_PER_LONG == 64
+#define SHIFT_PER_LONG 6
+#else
+#define SHIFT_PER_LONG 5
+#endif
+
 #define CHOP_SHIFTCOUNT(x) (((unsigned long) (x)) & (BITS_PER_LONG - 1))
 
 
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/arch/parisc/include/asm/bitsperlong.h linux-libre-3.2.87-gnu1/arch/parisc/include/asm/bitsperlong.h
--- linux-libre-3.2.86-gnu1/arch/parisc/include/asm/bitsperlong.h	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/arch/parisc/include/asm/bitsperlong.h	2017-03-15 22:19:00.000000000 -0400
@@ -9,10 +9,8 @@
  */
 #if (defined(__KERNEL__) && defined(CONFIG_64BIT)) || defined (__LP64__)
 #define __BITS_PER_LONG 64
-#define SHIFT_PER_LONG 6
 #else
 #define __BITS_PER_LONG 32
-#define SHIFT_PER_LONG 5
 #endif
 
 #include <asm-generic/bitsperlong.h>
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/arch/parisc/include/asm/swab.h linux-libre-3.2.87-gnu1/arch/parisc/include/asm/swab.h
--- linux-libre-3.2.86-gnu1/arch/parisc/include/asm/swab.h	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/arch/parisc/include/asm/swab.h	2017-03-15 22:19:00.000000000 -0400
@@ -1,6 +1,7 @@
 #ifndef _PARISC_SWAB_H
 #define _PARISC_SWAB_H
 
+#include <asm/bitsperlong.h>
 #include <linux/types.h>
 #include <linux/compiler.h>
 
@@ -38,7 +39,7 @@ static inline __attribute_const__ __u32
 }
 #define __arch_swab32 __arch_swab32
 
-#if BITS_PER_LONG > 32
+#if __BITS_PER_LONG > 32
 /*
 ** From "PA-RISC 2.0 Architecture", HP Professional Books.
 ** See Appendix I page 8 , "Endian Byte Swapping".
@@ -61,6 +62,6 @@ static inline __attribute_const__ __u64
 	return x;
 }
 #define __arch_swab64 __arch_swab64
-#endif /* BITS_PER_LONG > 32 */
+#endif /* __BITS_PER_LONG > 32 */
 
 #endif /* _PARISC_SWAB_H */
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/arch/powerpc/boot/ps3.c linux-libre-3.2.87-gnu1/arch/powerpc/boot/ps3.c
--- linux-libre-3.2.86-gnu1/arch/powerpc/boot/ps3.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/arch/powerpc/boot/ps3.c	2017-03-15 22:19:00.000000000 -0400
@@ -119,13 +119,12 @@ void ps3_copy_vectors(void)
 	flush_cache((void *)0x100, 512);
 }
 
-void platform_init(unsigned long null_check)
+void platform_init(void)
 {
 	const u32 heapsize = 0x1000000 - (u32)_end; /* 16MiB */
 	void *chosen;
 	unsigned long ft_addr;
 	u64 rm_size;
-	unsigned long val;
 
 	console_ops.write = ps3_console_write;
 	platform_ops.exit = ps3_exit;
@@ -153,11 +152,6 @@ void platform_init(unsigned long null_ch
 
 	printf(" flat tree at 0x%lx\n\r", ft_addr);
 
-	val = *(unsigned long *)0;
-
-	if (val != null_check)
-		printf("null check failed: %lx != %lx\n\r", val, null_check);
-
 	((kernel_entry_t)0)(ft_addr, 0, NULL);
 
 	ps3_exit();
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/arch/powerpc/boot/ps3-head.S linux-libre-3.2.87-gnu1/arch/powerpc/boot/ps3-head.S
--- linux-libre-3.2.86-gnu1/arch/powerpc/boot/ps3-head.S	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/arch/powerpc/boot/ps3-head.S	2017-03-15 22:19:00.000000000 -0400
@@ -57,11 +57,6 @@ __system_reset_overlay:
 	bctr
 
 1:
-	/* Save the value at addr zero for a null pointer write check later. */
-
-	li	r4, 0
-	lwz	r3, 0(r4)
-
 	/* Primary delays then goes to _zimage_start in wrapper. */
 
 	or	31, 31, 31 /* db16cyc */
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/arch/powerpc/include/asm/ppc-opcode.h linux-libre-3.2.87-gnu1/arch/powerpc/include/asm/ppc-opcode.h
--- linux-libre-3.2.86-gnu1/arch/powerpc/include/asm/ppc-opcode.h	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/arch/powerpc/include/asm/ppc-opcode.h	2017-03-15 22:19:00.000000000 -0400
@@ -31,7 +31,7 @@
 #define PPC_INST_MCRXR			0x7c000400
 #define PPC_INST_MCRXR_MASK		0xfc0007fe
 #define PPC_INST_MFSPR_PVR		0x7c1f42a6
-#define PPC_INST_MFSPR_PVR_MASK		0xfc1fffff
+#define PPC_INST_MFSPR_PVR_MASK		0xfc1ffffe
 #define PPC_INST_MSGSND			0x7c00019c
 #define PPC_INST_NOP			0x60000000
 #define PPC_INST_POPCNTB		0x7c0000f4
@@ -42,9 +42,9 @@
 #define PPC_INST_RFDI			0x4c00004e
 #define PPC_INST_RFMCI			0x4c00004c
 #define PPC_INST_MFSPR_DSCR		0x7c1102a6
-#define PPC_INST_MFSPR_DSCR_MASK	0xfc1fffff
+#define PPC_INST_MFSPR_DSCR_MASK	0xfc1ffffe
 #define PPC_INST_MTSPR_DSCR		0x7c1103a6
-#define PPC_INST_MTSPR_DSCR_MASK	0xfc1fffff
+#define PPC_INST_MTSPR_DSCR_MASK	0xfc1ffffe
 
 #define PPC_INST_STRING			0x7c00042a
 #define PPC_INST_STRING_MASK		0xfc0007fe
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/arch/powerpc/kernel/ibmebus.c linux-libre-3.2.87-gnu1/arch/powerpc/kernel/ibmebus.c
--- linux-libre-3.2.86-gnu1/arch/powerpc/kernel/ibmebus.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/arch/powerpc/kernel/ibmebus.c	2017-03-15 22:19:00.000000000 -0400
@@ -179,6 +179,7 @@ static int ibmebus_create_device(struct
 static int ibmebus_create_devices(const struct of_device_id *matches)
 {
 	struct device_node *root, *child;
+	struct device *dev;
 	int ret = 0;
 
 	root = of_find_node_by_path("/");
@@ -187,9 +188,12 @@ static int ibmebus_create_devices(const
 		if (!of_match_node(matches, child))
 			continue;
 
-		if (bus_find_device(&ibmebus_bus_type, NULL, child,
-				    ibmebus_match_node))
+		dev = bus_find_device(&ibmebus_bus_type, NULL, child,
+				      ibmebus_match_node);
+		if (dev) {
+			put_device(dev);
 			continue;
+		}
 
 		ret = ibmebus_create_device(child);
 		if (ret) {
@@ -261,6 +265,7 @@ static ssize_t ibmebus_store_probe(struc
 				   const char *buf, size_t count)
 {
 	struct device_node *dn = NULL;
+	struct device *dev;
 	char *path;
 	ssize_t rc = 0;
 
@@ -268,8 +273,10 @@ static ssize_t ibmebus_store_probe(struc
 	if (!path)
 		return -ENOMEM;
 
-	if (bus_find_device(&ibmebus_bus_type, NULL, path,
-			    ibmebus_match_path)) {
+	dev = bus_find_device(&ibmebus_bus_type, NULL, path,
+			      ibmebus_match_path);
+	if (dev) {
+		put_device(dev);
 		printk(KERN_WARNING "%s: %s has already been probed\n",
 		       __func__, path);
 		rc = -EEXIST;
@@ -305,6 +312,7 @@ static ssize_t ibmebus_store_remove(stru
 	if ((dev = bus_find_device(&ibmebus_bus_type, NULL, path,
 				   ibmebus_match_path))) {
 		of_device_unregister(to_platform_device(dev));
+		put_device(dev);
 
 		kfree(path);
 		return count;
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/arch/powerpc/kernel/ptrace.c linux-libre-3.2.87-gnu1/arch/powerpc/kernel/ptrace.c
--- linux-libre-3.2.86-gnu1/arch/powerpc/kernel/ptrace.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/arch/powerpc/kernel/ptrace.c	2017-03-15 22:19:00.000000000 -0400
@@ -359,6 +359,10 @@ static int fpr_set(struct task_struct *t
 	flush_fp_to_thread(target);
 
 #ifdef CONFIG_VSX
+	for (i = 0; i < 32 ; i++)
+		buf[i] = target->thread.TS_FPR(i);
+	memcpy(&buf[32], &target->thread.fpscr, sizeof(double));
+
 	/* copy to local buffer then write that out */
 	i = user_regset_copyin(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
 	if (i)
@@ -501,6 +505,9 @@ static int vsr_set(struct task_struct *t
 
 	flush_vsx_to_thread(target);
 
+	for (i = 0; i < 32 ; i++)
+		buf[i] = target->thread.fpr[i][TS_VSRLOWOFFSET];
+
 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 				 buf, 0, 32 * sizeof(double));
 	for (i = 0; i < 32 ; i++)
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/arch/sparc/kernel/leon_kernel.c linux-libre-3.2.87-gnu1/arch/sparc/kernel/leon_kernel.c
--- linux-libre-3.2.86-gnu1/arch/sparc/kernel/leon_kernel.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/arch/sparc/kernel/leon_kernel.c	2017-03-15 22:19:00.000000000 -0400
@@ -288,37 +288,37 @@ void __init leon_init_timers(irq_handler
 
 	/* Find GPTIMER Timer Registers base address otherwise bail out. */
 	nnp = rootnp;
-	do {
-		np = of_find_node_by_name(nnp, "GAISLER_GPTIMER");
-		if (!np) {
-			np = of_find_node_by_name(nnp, "01_011");
-			if (!np)
-				goto bad;
-		}
 
-		ampopts = 0;
-		pp = of_find_property(np, "ampopts", &len);
-		if (pp) {
-			ampopts = *(int *)pp->value;
-			if (ampopts == 0) {
-				/* Skip this instance, resource already
-				 * allocated by other OS */
-				nnp = np;
-				continue;
-			}
+retry:
+	np = of_find_node_by_name(nnp, "GAISLER_GPTIMER");
+	if (!np) {
+		np = of_find_node_by_name(nnp, "01_011");
+		if (!np)
+			goto bad;
+	}
+
+	ampopts = 0;
+	pp = of_find_property(np, "ampopts", &len);
+	if (pp) {
+		ampopts = *(int *)pp->value;
+		if (ampopts == 0) {
+			/* Skip this instance, resource already
+			 * allocated by other OS */
+			nnp = np;
+			goto retry;
 		}
+	}
 
-		/* Select Timer-Instance on Timer Core. Default is zero */
-		leon3_gptimer_idx = ampopts & 0x7;
+	/* Select Timer-Instance on Timer Core. Default is zero */
+	leon3_gptimer_idx = ampopts & 0x7;
 
-		pp = of_find_property(np, "reg", &len);
-		if (pp)
-			leon3_gptimer_regs = *(struct leon3_gptimer_regs_map **)
-						pp->value;
-		pp = of_find_property(np, "interrupts", &len);
-		if (pp)
-			leon3_gptimer_irq = *(unsigned int *)pp->value;
-	} while (0);
+	pp = of_find_property(np, "reg", &len);
+	if (pp)
+		leon3_gptimer_regs = *(struct leon3_gptimer_regs_map **)
+					pp->value;
+	pp = of_find_property(np, "interrupts", &len);
+	if (pp)
+		leon3_gptimer_irq = *(unsigned int *)pp->value;
 
 	if (!(leon3_gptimer_regs && leon3_irqctrl_regs && leon3_gptimer_irq))
 		goto bad;
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/arch/x86/kernel/cpu/common.c linux-libre-3.2.87-gnu1/arch/x86/kernel/cpu/common.c
--- linux-libre-3.2.86-gnu1/arch/x86/kernel/cpu/common.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/arch/x86/kernel/cpu/common.c	2017-03-15 22:19:00.000000000 -0400
@@ -1012,7 +1012,7 @@ static __init int setup_disablecpuid(cha
 {
 	int bit;
 
-	if (get_option(&arg, &bit) && bit < NCAPINTS*32)
+	if (get_option(&arg, &bit) && bit >= 0 && bit < NCAPINTS * 32)
 		setup_clear_cpu_cap(bit);
 	else
 		return 0;
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/arch/x86/kvm/x86.c linux-libre-3.2.87-gnu1/arch/x86/kvm/x86.c
--- linux-libre-3.2.86-gnu1/arch/x86/kvm/x86.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/arch/x86/kvm/x86.c	2017-03-15 22:19:00.000000000 -0400
@@ -843,8 +843,7 @@ static u32 msrs_to_save[] = {
 #ifdef CONFIG_X86_64
 	MSR_CSTAR, MSR_KERNEL_GS_BASE, MSR_SYSCALL_MASK, MSR_LSTAR,
 #endif
-	MSR_IA32_TSC, MSR_IA32_CR_PAT, MSR_VM_HSAVE_PA,
-	MSR_TSC_AUX,
+	MSR_IA32_TSC, MSR_IA32_CR_PAT, MSR_VM_HSAVE_PA
 };
 
 static unsigned num_msrs_to_save;
@@ -3882,20 +3881,6 @@ static void kvm_init_msr_list(void)
 	for (i = j = KVM_SAVE_MSRS_BEGIN; i < ARRAY_SIZE(msrs_to_save); i++) {
 		if (rdmsr_safe(msrs_to_save[i], &dummy[0], &dummy[1]) < 0)
 			continue;
-
-		/*
-		 * Even MSRs that are valid in the host may not be exposed
-		 * to the guests in some cases.
-		 */
-		switch (msrs_to_save[i]) {
-		case MSR_TSC_AUX:
-			if (!kvm_x86_ops->rdtscp_supported())
-				continue;
-			break;
-		default:
-			break;
-		}
-
 		if (j < i)
 			msrs_to_save[j] = msrs_to_save[i];
 		j++;
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/crypto/algapi.c linux-libre-3.2.87-gnu1/crypto/algapi.c
--- linux-libre-3.2.86-gnu1/crypto/algapi.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/crypto/algapi.c	2017-03-15 22:19:00.000000000 -0400
@@ -354,6 +354,7 @@ int crypto_register_alg(struct crypto_al
 	struct crypto_larval *larval;
 	int err;
 
+	alg->cra_flags &= ~CRYPTO_ALG_DEAD;
 	err = crypto_check_alg(alg);
 	if (err)
 		return err;
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/ata/sata_mv.c linux-libre-3.2.87-gnu1/drivers/ata/sata_mv.c
--- linux-libre-3.2.86-gnu1/drivers/ata/sata_mv.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/ata/sata_mv.c	2017-03-15 22:19:00.000000000 -0400
@@ -4059,6 +4059,9 @@ static int mv_platform_probe(struct plat
 	host->iomap = NULL;
 	hpriv->base = devm_ioremap(&pdev->dev, res->start,
 				   resource_size(res));
+	if (!hpriv->base)
+		return -ENOMEM;
+
 	hpriv->base -= SATAHC0_REG_BASE;
 
 #if defined(CONFIG_HAVE_CLK)
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/base/dma-mapping.c linux-libre-3.2.87-gnu1/drivers/base/dma-mapping.c
--- linux-libre-3.2.86-gnu1/drivers/base/dma-mapping.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/base/dma-mapping.c	2017-03-15 22:19:00.000000000 -0400
@@ -106,13 +106,13 @@ void dmam_free_coherent(struct device *d
 EXPORT_SYMBOL(dmam_free_coherent);
 
 /**
- * dmam_alloc_non_coherent - Managed dma_alloc_non_coherent()
+ * dmam_alloc_non_coherent - Managed dma_alloc_noncoherent()
  * @dev: Device to allocate non_coherent memory for
  * @size: Size of allocation
  * @dma_handle: Out argument for allocated DMA handle
  * @gfp: Allocation flags
  *
- * Managed dma_alloc_non_coherent().  Memory allocated using this
+ * Managed dma_alloc_noncoherent().  Memory allocated using this
  * function will be automatically released on driver detach.
  *
  * RETURNS:
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/base/regmap/regcache-lzo.c linux-libre-3.2.87-gnu1/drivers/base/regmap/regcache-lzo.c
--- linux-libre-3.2.86-gnu1/drivers/base/regmap/regcache-lzo.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/base/regmap/regcache-lzo.c	2017-03-15 22:19:00.000000000 -0400
@@ -229,15 +229,13 @@ static int regcache_lzo_read(struct regm
 {
 	struct regcache_lzo_ctx *lzo_block, **lzo_blocks;
 	int ret, blkindex, blkpos;
-	size_t blksize, tmp_dst_len;
+	size_t tmp_dst_len;
 	void *tmp_dst;
 
 	/* index of the compressed lzo block */
 	blkindex = regcache_lzo_get_blkindex(map, reg);
 	/* register index within the decompressed block */
 	blkpos = regcache_lzo_get_blkpos(map, reg);
-	/* size of the compressed block */
-	blksize = regcache_lzo_get_blksize(map);
 	lzo_blocks = map->cache;
 	lzo_block = lzo_blocks[blkindex];
 
@@ -269,15 +267,13 @@ static int regcache_lzo_write(struct reg
 {
 	struct regcache_lzo_ctx *lzo_block, **lzo_blocks;
 	int ret, blkindex, blkpos;
-	size_t blksize, tmp_dst_len;
+	size_t tmp_dst_len;
 	void *tmp_dst;
 
 	/* index of the compressed lzo block */
 	blkindex = regcache_lzo_get_blkindex(map, reg);
 	/* register index within the decompressed block */
 	blkpos = regcache_lzo_get_blkpos(map, reg);
-	/* size of the compressed block */
-	blksize = regcache_lzo_get_blksize(map);
 	lzo_blocks = map->cache;
 	lzo_block = lzo_blocks[blkindex];
 
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/block/nbd.c linux-libre-3.2.87-gnu1/drivers/block/nbd.c
--- linux-libre-3.2.86-gnu1/drivers/block/nbd.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/block/nbd.c	2017-03-15 22:19:00.000000000 -0400
@@ -232,9 +232,10 @@ static inline int sock_send_bvec(struct
 /* always call with the tx_lock held */
 static int nbd_send_req(struct nbd_device *lo, struct request *req)
 {
-	int result, flags;
+	int result;
 	struct nbd_request request;
 	unsigned long size = blk_rq_bytes(req);
+	struct bio *bio;
 
 	request.magic = htonl(NBD_REQUEST_MAGIC);
 	request.type = htonl(nbd_cmd(req));
@@ -255,17 +256,19 @@ static int nbd_send_req(struct nbd_devic
 		goto error_out;
 	}
 
-	if (nbd_cmd(req) == NBD_CMD_WRITE) {
-		struct req_iterator iter;
+	if (nbd_cmd(req) != NBD_CMD_WRITE)
+		return 0;
+
+	bio = req->bio;
+	while (bio) {
+		struct bio *next = bio->bi_next;
+		int i;
 		struct bio_vec *bvec;
-		/*
-		 * we are really probing at internals to determine
-		 * whether to set MSG_MORE or not...
-		 */
-		rq_for_each_segment(bvec, req, iter) {
-			flags = 0;
-			if (!rq_iter_last(req, iter))
-				flags = MSG_MORE;
+
+		bio_for_each_segment(bvec, bio, i) {
+			bool is_last = !next && i == bio->bi_vcnt - 1;
+			int flags = is_last ? 0 : MSG_MORE;
+
 			dprintk(DBG_TX, "%s: request %p: sending %d bytes data\n",
 					lo->disk->disk_name, req, bvec->bv_len);
 			result = sock_send_bvec(lo, bvec, flags);
@@ -275,7 +278,16 @@ static int nbd_send_req(struct nbd_devic
 					result);
 				goto error_out;
 			}
+			/*
+			 * The completion might already have come in,
+			 * so break for the last one instead of letting
+			 * the iterator do it. This prevents use-after-free
+			 * of the bio.
+			 */
+			if (is_last)
+				break;
 		}
+		bio = next;
 	}
 	return 0;
 
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/crypto/caam/caamalg.c linux-libre-3.2.87-gnu1/drivers/crypto/caam/caamalg.c
--- linux-libre-3.2.86-gnu1/drivers/crypto/caam/caamalg.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/crypto/caam/caamalg.c	2017-03-15 22:19:00.000000000 -0400
@@ -419,7 +419,9 @@ static int aead_set_sh_desc(struct crypt
 
 	/* Will read cryptlen */
 	append_math_add(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
-	aead_append_src_dst(desc, FIFOLD_TYPE_MSG1OUT2);
+	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_BOTH | KEY_VLF |
+			     FIFOLD_TYPE_MSG1OUT2 | FIFOLD_TYPE_LASTBOTH);
+	append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | KEY_VLF);
 
 	/* Write ICV */
 	append_seq_store(desc, ctx->authsize, LDST_CLASS_2_CCB |
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/hid/hid-cypress.c linux-libre-3.2.87-gnu1/drivers/hid/hid-cypress.c
--- linux-libre-3.2.86-gnu1/drivers/hid/hid-cypress.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/hid/hid-cypress.c	2017-03-15 22:19:00.000000000 -0400
@@ -40,6 +40,9 @@ static __u8 *cp_report_fixup(struct hid_
 	if (!(quirks & CP_RDESC_SWAPPED_MIN_MAX))
 		return rdesc;
 
+	if (*rsize < 4)
+		return rdesc;
+
 	for (i = 0; i < *rsize - 4; i++)
 		if (rdesc[i] == 0x29 && rdesc[i + 2] == 0x19) {
 			__u8 tmp;
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/hwmon/ds620.c linux-libre-3.2.87-gnu1/drivers/hwmon/ds620.c
--- linux-libre-3.2.86-gnu1/drivers/hwmon/ds620.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/hwmon/ds620.c	2017-03-15 22:19:00.000000000 -0400
@@ -166,7 +166,7 @@ static ssize_t set_temp(struct device *d
 	if (res)
 		return res;
 
-	val = (val * 10 / 625) * 8;
+	val = (clamp_val(val, -128000, 128000) * 10 / 625) * 8;
 
 	mutex_lock(&data->update_lock);
 	data->temp[attr->index] = val;
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/i2c/i2c-dev.c linux-libre-3.2.87-gnu1/drivers/i2c/i2c-dev.c
--- linux-libre-3.2.86-gnu1/drivers/i2c/i2c-dev.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/i2c/i2c-dev.c	2017-03-15 22:19:00.000000000 -0400
@@ -310,7 +310,7 @@ static noinline int i2cdev_ioctl_smbus(s
 		unsigned long arg)
 {
 	struct i2c_smbus_ioctl_data data_arg;
-	union i2c_smbus_data temp;
+	union i2c_smbus_data temp = {};
 	int datasize, res;
 
 	if (copy_from_user(&data_arg,
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/infiniband/core/mad.c linux-libre-3.2.87-gnu1/drivers/infiniband/core/mad.c
--- linux-libre-3.2.86-gnu1/drivers/infiniband/core/mad.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/infiniband/core/mad.c	2017-03-15 22:19:00.000000000 -0400
@@ -1598,7 +1598,7 @@ find_mad_agent(struct ib_mad_port_privat
 			if (!class)
 				goto out;
 			if (convert_mgmt_class(mad->mad_hdr.mgmt_class) >=
-			    IB_MGMT_MAX_METHODS)
+			    ARRAY_SIZE(class->method_table))
 				goto out;
 			method = class->method_table[convert_mgmt_class(
 							mad->mad_hdr.mgmt_class)];
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/infiniband/core/multicast.c linux-libre-3.2.87-gnu1/drivers/infiniband/core/multicast.c
--- linux-libre-3.2.86-gnu1/drivers/infiniband/core/multicast.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/infiniband/core/multicast.c	2017-03-15 22:19:00.000000000 -0400
@@ -516,8 +516,11 @@ static void join_handler(int status, str
 	if (status)
 		process_join_error(group, status);
 	else {
-		ib_find_pkey(group->port->dev->device, group->port->port_num,
-			     be16_to_cpu(rec->pkey), &pkey_index);
+
+		if (ib_find_pkey(group->port->dev->device,
+				 group->port->port_num, be16_to_cpu(rec->pkey),
+				 &pkey_index))
+			pkey_index = MCAST_INVALID_PKEY_INDEX;
 
 		spin_lock_irq(&group->port->lock);
 		group->rec = *rec;
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/infiniband/hw/mlx4/main.c linux-libre-3.2.87-gnu1/drivers/infiniband/hw/mlx4/main.c
--- linux-libre-3.2.86-gnu1/drivers/infiniband/hw/mlx4/main.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/infiniband/hw/mlx4/main.c	2017-03-15 22:19:00.000000000 -0400
@@ -164,6 +164,7 @@ static int mlx4_ib_query_device(struct i
 	props->max_total_mcast_qp_attach = props->max_mcast_qp_attach *
 					   props->max_mcast_grp;
 	props->max_map_per_fmr = (1 << (32 - ilog2(dev->dev->caps.num_mpts))) - 1;
+	props->max_ah = INT_MAX;
 
 out:
 	kfree(in_mad);
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/input/serio/i8042-x86ia64io.h linux-libre-3.2.87-gnu1/drivers/input/serio/i8042-x86ia64io.h
--- linux-libre-3.2.86-gnu1/drivers/input/serio/i8042-x86ia64io.h	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/input/serio/i8042-x86ia64io.h	2017-03-15 22:19:00.000000000 -0400
@@ -211,6 +211,12 @@ static const struct dmi_system_id __init
 			DMI_MATCH(DMI_PRODUCT_VERSION, "Rev 1"),
 		},
 	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "PEGATRON CORPORATION"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "C15B"),
+		},
+	},
 	{ }
 };
 
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/iommu/amd_iommu.c linux-libre-3.2.87-gnu1/drivers/iommu/amd_iommu.c
--- linux-libre-3.2.86-gnu1/drivers/iommu/amd_iommu.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/iommu/amd_iommu.c	2017-03-15 22:19:00.000000000 -0400
@@ -641,7 +641,7 @@ again:
 	next_tail = (tail + sizeof(*cmd)) % iommu->cmd_buf_size;
 	left      = (head - next_tail) % iommu->cmd_buf_size;
 
-	if (left <= 2) {
+	if (left <= 0x20) {
 		struct iommu_cmd sync_cmd;
 		volatile u64 sem = 0;
 		int ret;
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/md/dm-crypt.c linux-libre-3.2.87-gnu1/drivers/md/dm-crypt.c
--- linux-libre-3.2.86-gnu1/drivers/md/dm-crypt.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/md/dm-crypt.c	2017-03-15 22:19:00.000000000 -0400
@@ -1322,12 +1322,15 @@ static int crypt_set_key(struct crypt_co
 	if (!cc->key_size && strcmp(key, "-"))
 		goto out;
 
+	/* clear the flag since following operations may invalidate previously valid key */
+	clear_bit(DM_CRYPT_KEY_VALID, &cc->flags);
+
 	if (cc->key_size && crypt_decode_key(cc->key, key, cc->key_size) < 0)
 		goto out;
 
-	set_bit(DM_CRYPT_KEY_VALID, &cc->flags);
-
 	r = crypt_setkey_allcpus(cc);
+	if (!r)
+		set_bit(DM_CRYPT_KEY_VALID, &cc->flags);
 
 out:
 	/* Hex key string not needed after here, so wipe it. */
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/media/dvb/siano/smsusb.c linux-libre-3.2.87-gnu1/drivers/media/dvb/siano/smsusb.c
--- linux-libre-3.2.86-gnu1/drivers/media/dvb/siano/smsusb.c	2017-02-27 03:22:52.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/media/dvb/siano/smsusb.c	2017-03-16 12:03:03.000000000 -0400
@@ -181,11 +181,20 @@ static int smsusb_start_streaming(struct
 static int smsusb_sendrequest(void *context, void *buffer, size_t size)
 {
 	struct smsusb_device_t *dev = (struct smsusb_device_t *) context;
-	int dummy;
+	struct SmsMsgHdr_ST *phdr;
+	int dummy, ret;
 
-	smsendian_handle_message_header((struct SmsMsgHdr_ST *)buffer);
-	return usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 2),
-			    buffer, size, &dummy, 1000);
+	phdr = kmalloc(size, GFP_KERNEL);
+	if (!phdr)
+		return -ENOMEM;
+	memcpy(phdr, buffer, size);
+
+	smsendian_handle_message_header((struct SmsMsgHdr_ST *)phdr);
+	ret = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 2),
+			    phdr, size, &dummy, 1000);
+
+	kfree(phdr);
+	return ret;
 }
 
 static char *smsusb1_fw_lkup[] = {
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/media/rc/ite-cir.c linux-libre-3.2.87-gnu1/drivers/media/rc/ite-cir.c
--- linux-libre-3.2.86-gnu1/drivers/media/rc/ite-cir.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/media/rc/ite-cir.c	2017-03-15 22:19:00.000000000 -0400
@@ -263,6 +263,8 @@ static void ite_set_carrier_params(struc
 
 			if (allowance > ITE_RXDCR_MAX)
 				allowance = ITE_RXDCR_MAX;
+
+			use_demodulator = true;
 		}
 	}
 
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/media/video/davinci/vpfe_capture.c linux-libre-3.2.87-gnu1/drivers/media/video/davinci/vpfe_capture.c
--- linux-libre-3.2.86-gnu1/drivers/media/video/davinci/vpfe_capture.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/media/video/davinci/vpfe_capture.c	2017-03-15 22:19:00.000000000 -0400
@@ -2002,6 +2002,7 @@ static __init int vpfe_probe(struct plat
 			v4l2_info(&vpfe_dev->v4l2_dev,
 				  "v4l2 sub device %s register fails\n",
 				  sdinfo->name);
+			ret = -ENXIO;
 			goto probe_sd_out;
 		}
 	}
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/mmc/host/mxs-mmc.c linux-libre-3.2.87-gnu1/drivers/mmc/host/mxs-mmc.c
--- linux-libre-3.2.86-gnu1/drivers/mmc/host/mxs-mmc.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/mmc/host/mxs-mmc.c	2017-03-15 22:19:00.000000000 -0400
@@ -386,6 +386,9 @@ static void mxs_mmc_ac(struct mxs_mmc_ho
 	cmd0 = BF_SSP(cmd->opcode, CMD0_CMD);
 	cmd1 = cmd->arg;
 
+	if (cmd->opcode == MMC_STOP_TRANSMISSION)
+		cmd0 |= BM_SSP_CMD0_APPEND_8CYC;
+
 	if (host->sdio_irq_en) {
 		ctrl0 |= BM_SSP_CTRL0_SDIO_IRQ_CHECK;
 		cmd0 |= BM_SSP_CMD0_CONT_CLKING_EN | BM_SSP_CMD0_SLOW_CLKING_EN;
@@ -487,8 +490,7 @@ static void mxs_mmc_adtc(struct mxs_mmc_
 		       host->base + HW_SSP_BLOCK_SIZE);
 	}
 
-	if ((cmd->opcode == MMC_STOP_TRANSMISSION) ||
-	    (cmd->opcode == SD_IO_RW_EXTENDED))
+	if (cmd->opcode == SD_IO_RW_EXTENDED)
 		cmd0 |= BM_SSP_CMD0_APPEND_8CYC;
 
 	cmd1 = cmd->arg;
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/net/can/ti_hecc.c linux-libre-3.2.87-gnu1/drivers/net/can/ti_hecc.c
--- linux-libre-3.2.86-gnu1/drivers/net/can/ti_hecc.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/net/can/ti_hecc.c	2017-03-15 22:19:00.000000000 -0400
@@ -942,7 +942,12 @@ static int ti_hecc_probe(struct platform
 	netif_napi_add(ndev, &priv->napi, ti_hecc_rx_poll,
 		HECC_DEF_NAPI_WEIGHT);
 
-	clk_enable(priv->clk);
+	err = clk_prepare_enable(priv->clk);
+	if (err) {
+		dev_err(&pdev->dev, "clk_prepare_enable() failed\n");
+		goto probe_exit_clk;
+	}
+
 	err = register_candev(ndev);
 	if (err) {
 		dev_err(&pdev->dev, "register_candev() failed\n");
@@ -972,7 +977,7 @@ static int __devexit ti_hecc_remove(stru
 	struct ti_hecc_priv *priv = netdev_priv(ndev);
 
 	unregister_candev(ndev);
-	clk_disable(priv->clk);
+	clk_disable_unprepare(priv->clk);
 	clk_put(priv->clk);
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	iounmap(priv->base);
@@ -998,7 +1003,7 @@ static int ti_hecc_suspend(struct platfo
 	hecc_set_bit(priv, HECC_CANMC, HECC_CANMC_PDR);
 	priv->can.state = CAN_STATE_SLEEPING;
 
-	clk_disable(priv->clk);
+	clk_disable_unprepare(priv->clk);
 
 	return 0;
 }
@@ -1007,8 +1012,11 @@ static int ti_hecc_resume(struct platfor
 {
 	struct net_device *dev = platform_get_drvdata(pdev);
 	struct ti_hecc_priv *priv = netdev_priv(dev);
+	int err;
 
-	clk_enable(priv->clk);
+	err = clk_prepare_enable(priv->clk);
+	if (err)
+		return err;
 
 	hecc_clear_bit(priv, HECC_CANMC, HECC_CANMC_PDR);
 	priv->can.state = CAN_STATE_ERROR_ACTIVE;
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/net/ethernet/korina.c linux-libre-3.2.87-gnu1/drivers/net/ethernet/korina.c
--- linux-libre-3.2.86-gnu1/drivers/net/ethernet/korina.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/net/ethernet/korina.c	2017-03-15 22:19:00.000000000 -0400
@@ -906,10 +906,10 @@ static void korina_restart_task(struct w
 				DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR,
 				&lp->rx_dma_regs->dmasm);
 
-	korina_free_ring(dev);
-
 	napi_disable(&lp->napi);
 
+	korina_free_ring(dev);
+
 	if (korina_init(dev) < 0) {
 		printk(KERN_ERR "%s: cannot restart device\n", dev->name);
 		return;
@@ -1070,12 +1070,12 @@ static int korina_close(struct net_devic
 	tmp = tmp | DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR;
 	writel(tmp, &lp->rx_dma_regs->dmasm);
 
-	korina_free_ring(dev);
-
 	napi_disable(&lp->napi);
 
 	cancel_work_sync(&lp->restart_task);
 
+	korina_free_ring(dev);
+
 	free_irq(lp->rx_irq, dev);
 	free_irq(lp->tx_irq, dev);
 	free_irq(lp->ovr_irq, dev);
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/net/ethernet/marvell/sky2.c linux-libre-3.2.87-gnu1/drivers/net/ethernet/marvell/sky2.c
--- linux-libre-3.2.86-gnu1/drivers/net/ethernet/marvell/sky2.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/net/ethernet/marvell/sky2.c	2017-03-15 22:19:00.000000000 -0400
@@ -5165,6 +5165,19 @@ static SIMPLE_DEV_PM_OPS(sky2_pm_ops, sk
 
 static void sky2_shutdown(struct pci_dev *pdev)
 {
+	struct sky2_hw *hw = pci_get_drvdata(pdev);
+	int port;
+
+	for (port = 0; port < hw->ports; port++) {
+		struct net_device *ndev = hw->dev[port];
+
+		rtnl_lock();
+		if (netif_running(ndev)) {
+			dev_close(ndev);
+			netif_device_detach(ndev);
+		}
+		rtnl_unlock();
+	}
 	sky2_suspend(&pdev->dev);
 	pci_wake_from_d3(pdev, device_may_wakeup(&pdev->dev));
 	pci_set_power_state(pdev, PCI_D3hot);
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/net/ethernet/mellanox/mlx4/cq.c linux-libre-3.2.87-gnu1/drivers/net/ethernet/mellanox/mlx4/cq.c
--- linux-libre-3.2.86-gnu1/drivers/net/ethernet/mellanox/mlx4/cq.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/net/ethernet/mellanox/mlx4/cq.c	2017-03-15 22:19:00.000000000 -0400
@@ -78,13 +78,19 @@ void mlx4_cq_completion(struct mlx4_dev
 {
 	struct mlx4_cq *cq;
 
+	rcu_read_lock();
 	cq = radix_tree_lookup(&mlx4_priv(dev)->cq_table.tree,
 			       cqn & (dev->caps.num_cqs - 1));
+	rcu_read_unlock();
+
 	if (!cq) {
 		mlx4_warn(dev, "Completion event for bogus CQ %08x\n", cqn);
 		return;
 	}
 
+	/* Acessing the CQ outside of rcu_read_lock is safe, because
+	 * the CQ is freed only after interrupt handling is completed.
+	 */
 	++cq->arm_sn;
 
 	cq->comp(cq);
@@ -95,23 +101,19 @@ void mlx4_cq_event(struct mlx4_dev *dev,
 	struct mlx4_cq_table *cq_table = &mlx4_priv(dev)->cq_table;
 	struct mlx4_cq *cq;
 
-	spin_lock(&cq_table->lock);
-
+	rcu_read_lock();
 	cq = radix_tree_lookup(&cq_table->tree, cqn & (dev->caps.num_cqs - 1));
-	if (cq)
-		atomic_inc(&cq->refcount);
-
-	spin_unlock(&cq_table->lock);
+	rcu_read_unlock();
 
 	if (!cq) {
-		mlx4_warn(dev, "Async event for bogus CQ %08x\n", cqn);
+		mlx4_dbg(dev, "Async event for bogus CQ %08x\n", cqn);
 		return;
 	}
 
+	/* Acessing the CQ outside of rcu_read_lock is safe, because
+	 * the CQ is freed only after interrupt handling is completed.
+	 */
 	cq->event(cq, event_type);
-
-	if (atomic_dec_and_test(&cq->refcount))
-		complete(&cq->free);
 }
 
 static int mlx4_SW2HW_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
@@ -216,9 +218,9 @@ int mlx4_cq_alloc(struct mlx4_dev *dev,
 	if (err)
 		goto err_put;
 
-	spin_lock_irq(&cq_table->lock);
+	spin_lock(&cq_table->lock);
 	err = radix_tree_insert(&cq_table->tree, cq->cqn, cq);
-	spin_unlock_irq(&cq_table->lock);
+	spin_unlock(&cq_table->lock);
 	if (err)
 		goto err_cmpt_put;
 
@@ -255,9 +257,9 @@ int mlx4_cq_alloc(struct mlx4_dev *dev,
 	return 0;
 
 err_radix:
-	spin_lock_irq(&cq_table->lock);
+	spin_lock(&cq_table->lock);
 	radix_tree_delete(&cq_table->tree, cq->cqn);
-	spin_unlock_irq(&cq_table->lock);
+	spin_unlock(&cq_table->lock);
 
 err_cmpt_put:
 	mlx4_table_put(dev, &cq_table->cmpt_table, cq->cqn);
@@ -282,11 +284,11 @@ void mlx4_cq_free(struct mlx4_dev *dev,
 	if (err)
 		mlx4_warn(dev, "HW2SW_CQ failed (%d) for CQN %06x\n", err, cq->cqn);
 
-	synchronize_irq(priv->eq_table.eq[cq->vector].irq);
-
-	spin_lock_irq(&cq_table->lock);
+	spin_lock(&cq_table->lock);
 	radix_tree_delete(&cq_table->tree, cq->cqn);
-	spin_unlock_irq(&cq_table->lock);
+	spin_unlock(&cq_table->lock);
+
+	synchronize_irq(priv->eq_table.eq[cq->vector].irq);
 
 	if (atomic_dec_and_test(&cq->refcount))
 		complete(&cq->free);
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/net/ethernet/mellanox/mlx4/en_rx.c linux-libre-3.2.87-gnu1/drivers/net/ethernet/mellanox/mlx4/en_rx.c
--- linux-libre-3.2.86-gnu1/drivers/net/ethernet/mellanox/mlx4/en_rx.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/net/ethernet/mellanox/mlx4/en_rx.c	2017-03-15 22:19:00.000000000 -0400
@@ -328,8 +328,14 @@ int mlx4_en_activate_rx_rings(struct mlx
 		ring->cqn = priv->rx_cq[ring_ind].mcq.cqn;
 
 		ring->stride = stride;
-		if (ring->stride <= TXBB_SIZE)
+		if (ring->stride <= TXBB_SIZE) {
+			/* Stamp first unused send wqe */
+			__be32 *ptr = (__be32 *)ring->buf;
+			__be32 stamp = cpu_to_be32(1 << STAMP_SHIFT);
+			*ptr = stamp;
+			/* Move pointer to start of rx section */
 			ring->buf += TXBB_SIZE;
+		}
 
 		ring->log_stride = ffs(ring->stride) - 1;
 		ring->buf_size = ring->size * ring->stride;
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/net/ethernet/mellanox/mlx4/icm.c linux-libre-3.2.87-gnu1/drivers/net/ethernet/mellanox/mlx4/icm.c
--- linux-libre-3.2.86-gnu1/drivers/net/ethernet/mellanox/mlx4/icm.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/net/ethernet/mellanox/mlx4/icm.c	2017-03-15 22:19:00.000000000 -0400
@@ -113,8 +113,13 @@ static int mlx4_alloc_icm_coherent(struc
 	if (!buf)
 		return -ENOMEM;
 
+	if (offset_in_page(buf)) {
+		dma_free_coherent(dev, PAGE_SIZE << order,
+				  buf, sg_dma_address(mem));
+		return -ENOMEM;
+	}
+
 	sg_set_buf(mem, buf, PAGE_SIZE << order);
-	BUG_ON(mem->offset);
 	sg_dma_len(mem) = PAGE_SIZE << order;
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/net/ethernet/xilinx/xilinx_emaclite.c linux-libre-3.2.87-gnu1/drivers/net/ethernet/xilinx/xilinx_emaclite.c
--- linux-libre-3.2.86-gnu1/drivers/net/ethernet/xilinx/xilinx_emaclite.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/net/ethernet/xilinx/xilinx_emaclite.c	2017-03-15 22:19:00.000000000 -0400
@@ -398,7 +398,7 @@ static int xemaclite_send_data(struct ne
  *
  * Return:	Total number of bytes received
  */
-static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data)
+static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data, int maxlen)
 {
 	void __iomem *addr;
 	u16 length, proto_type;
@@ -438,7 +438,7 @@ static u16 xemaclite_recv_data(struct ne
 
 	/* Check if received ethernet frame is a raw ethernet frame
 	 * or an IP packet or an ARP packet */
-	if (proto_type > (ETH_FRAME_LEN + ETH_FCS_LEN)) {
+	if (proto_type > ETH_DATA_LEN) {
 
 		if (proto_type == ETH_P_IP) {
 			length = ((ntohl(in_be32(addr +
@@ -446,6 +446,7 @@ static u16 xemaclite_recv_data(struct ne
 					XEL_RXBUFF_OFFSET)) >>
 					XEL_HEADER_SHIFT) &
 					XEL_RPLR_LENGTH_MASK);
+			length = min_t(u16, length, ETH_DATA_LEN);
 			length += ETH_HLEN + ETH_FCS_LEN;
 
 		} else if (proto_type == ETH_P_ARP)
@@ -458,6 +459,9 @@ static u16 xemaclite_recv_data(struct ne
 		/* Use the length in the frame, plus the header and trailer */
 		length = proto_type + ETH_HLEN + ETH_FCS_LEN;
 
+	if (WARN_ON(length > maxlen))
+		length = maxlen;
+
 	/* Read from the EmacLite device */
 	xemaclite_aligned_read((u32 __force *) (addr + XEL_RXBUFF_OFFSET),
 				data, length);
@@ -632,7 +636,7 @@ static void xemaclite_rx_handler(struct
 
 	skb_reserve(skb, 2);
 
-	len = xemaclite_recv_data(lp, (u8 *) skb->data);
+	len = xemaclite_recv_data(lp, (u8 *) skb->data, len);
 
 	if (!len) {
 		dev->stats.rx_errors++;
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/net/macvtap.c linux-libre-3.2.87-gnu1/drivers/net/macvtap.c
--- linux-libre-3.2.86-gnu1/drivers/net/macvtap.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/net/macvtap.c	2017-03-15 22:19:00.000000000 -0400
@@ -687,7 +687,7 @@ static ssize_t macvtap_get_user(struct m
 	size_t linear;
 
 	if (q->flags & IFF_VNET_HDR) {
-		vnet_hdr_len = q->vnet_hdr_sz;
+		vnet_hdr_len = ACCESS_ONCE(q->vnet_hdr_sz);
 
 		err = -EINVAL;
 		if (len < vnet_hdr_len)
@@ -817,7 +817,7 @@ static ssize_t macvtap_put_user(struct m
 
 	if (q->flags & IFF_VNET_HDR) {
 		struct virtio_net_hdr vnet_hdr;
-		vnet_hdr_len = q->vnet_hdr_sz;
+		vnet_hdr_len = ACCESS_ONCE(q->vnet_hdr_sz);
 		if ((len -= vnet_hdr_len) < 0)
 			return -EINVAL;
 
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/net/tun.c linux-libre-3.2.87-gnu1/drivers/net/tun.c
--- linux-libre-3.2.86-gnu1/drivers/net/tun.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/net/tun.c	2017-03-15 22:19:00.000000000 -0400
@@ -625,9 +625,11 @@ static ssize_t tun_get_user(struct tun_s
 	}
 
 	if (tun->flags & TUN_VNET_HDR) {
-		if (len < tun->vnet_hdr_sz)
+		int vnet_hdr_sz = ACCESS_ONCE(tun->vnet_hdr_sz);
+
+		if (len < vnet_hdr_sz)
 			return -EINVAL;
-		len -= tun->vnet_hdr_sz;
+		len -= vnet_hdr_sz;
 
 		if (memcpy_fromiovecend((void *)&gso, iv, offset, sizeof(gso)))
 			return -EFAULT;
@@ -638,7 +640,7 @@ static ssize_t tun_get_user(struct tun_s
 
 		if (gso.hdr_len > len)
 			return -EINVAL;
-		offset += tun->vnet_hdr_sz;
+		offset += vnet_hdr_sz;
 	}
 
 	if ((tun->flags & TUN_TYPE_MASK) == TUN_TAP_DEV) {
@@ -767,12 +769,16 @@ static ssize_t tun_put_user(struct tun_s
 {
 	struct tun_pi pi = { 0, skb->protocol };
 	ssize_t total = 0;
+	int vnet_hdr_sz = 0;
+
+	if (tun->flags & TUN_VNET_HDR)
+		vnet_hdr_sz = ACCESS_ONCE(tun->vnet_hdr_sz);
 
 	if (!(tun->flags & TUN_NO_PI)) {
 		if ((len -= sizeof(pi)) < 0)
 			return -EINVAL;
 
-		if (len < skb->len) {
+		if (len < skb->len + vnet_hdr_sz) {
 			/* Packet will be striped */
 			pi.flags |= TUN_PKT_STRIP;
 		}
@@ -782,9 +788,9 @@ static ssize_t tun_put_user(struct tun_s
 		total += sizeof(pi);
 	}
 
-	if (tun->flags & TUN_VNET_HDR) {
+	if (vnet_hdr_sz) {
 		struct virtio_net_hdr gso = { 0 }; /* no info leak */
-		if ((len -= tun->vnet_hdr_sz) < 0)
+		if ((len -= vnet_hdr_sz) < 0)
 			return -EINVAL;
 
 		if (skb_is_gso(skb)) {
@@ -827,7 +833,7 @@ static ssize_t tun_put_user(struct tun_s
 		if (unlikely(memcpy_toiovecend(iv, (void *)&gso, total,
 					       sizeof(gso))))
 			return -EFAULT;
-		total += tun->vnet_hdr_sz;
+		total += vnet_hdr_sz;
 	}
 
 	len = min_t(int, skb->len, len);
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/net/usb/catc.c linux-libre-3.2.87-gnu1/drivers/net/usb/catc.c
--- linux-libre-3.2.86-gnu1/drivers/net/usb/catc.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/net/usb/catc.c	2017-03-15 22:19:00.000000000 -0400
@@ -765,7 +765,7 @@ static int catc_probe(struct usb_interfa
 	struct net_device *netdev;
 	struct catc *catc;
 	u8 broadcast[6];
-	int i, pktsz;
+	int pktsz, ret;
 
 	if (usb_set_interface(usbdev,
 			intf->altsetting->desc.bInterfaceNumber, 1)) {
@@ -800,12 +800,8 @@ static int catc_probe(struct usb_interfa
 	if ((!catc->ctrl_urb) || (!catc->tx_urb) || 
 	    (!catc->rx_urb) || (!catc->irq_urb)) {
 		err("No free urbs available.");
-		usb_free_urb(catc->ctrl_urb);
-		usb_free_urb(catc->tx_urb);
-		usb_free_urb(catc->rx_urb);
-		usb_free_urb(catc->irq_urb);
-		free_netdev(netdev);
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto fail_free;
 	}
 
 	/* The F5U011 has the same vendor/product as the netmate but a device version of 0x130 */
@@ -833,15 +829,24 @@ static int catc_probe(struct usb_interfa
                 catc->irq_buf, 2, catc_irq_done, catc, 1);
 
 	if (!catc->is_f5u011) {
+		u32 *buf;
+		int i;
+
 		dbg("Checking memory size\n");
 
-		i = 0x12345678;
-		catc_write_mem(catc, 0x7a80, &i, 4);
-		i = 0x87654321;	
-		catc_write_mem(catc, 0xfa80, &i, 4);
-		catc_read_mem(catc, 0x7a80, &i, 4);
+		buf = kmalloc(4, GFP_KERNEL);
+		if (!buf) {
+			ret = -ENOMEM;
+			goto fail_free;
+		}
+
+		*buf = 0x12345678;
+		catc_write_mem(catc, 0x7a80, buf, 4);
+		*buf = 0x87654321;
+		catc_write_mem(catc, 0xfa80, buf, 4);
+		catc_read_mem(catc, 0x7a80, buf, 4);
 	  
-		switch (i) {
+		switch (*buf) {
 		case 0x12345678:
 			catc_set_reg(catc, TxBufCount, 8);
 			catc_set_reg(catc, RxBufCount, 32);
@@ -856,6 +861,8 @@ static int catc_probe(struct usb_interfa
 			dbg("32k Memory\n");
 			break;
 		}
+
+		kfree(buf);
 	  
 		dbg("Getting MAC from SEEROM.");
 	  
@@ -902,16 +909,21 @@ static int catc_probe(struct usb_interfa
 	usb_set_intfdata(intf, catc);
 
 	SET_NETDEV_DEV(netdev, &intf->dev);
-	if (register_netdev(netdev) != 0) {
-		usb_set_intfdata(intf, NULL);
-		usb_free_urb(catc->ctrl_urb);
-		usb_free_urb(catc->tx_urb);
-		usb_free_urb(catc->rx_urb);
-		usb_free_urb(catc->irq_urb);
-		free_netdev(netdev);
-		return -EIO;
-	}
+	ret = register_netdev(netdev);
+	if (ret)
+		goto fail_clear_intfdata;
+
 	return 0;
+
+fail_clear_intfdata:
+	usb_set_intfdata(intf, NULL);
+fail_free:
+	usb_free_urb(catc->ctrl_urb);
+	usb_free_urb(catc->tx_urb);
+	usb_free_urb(catc->rx_urb);
+	usb_free_urb(catc->irq_urb);
+	free_netdev(netdev);
+	return ret;
 }
 
 static void catc_disconnect(struct usb_interface *intf)
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/net/usb/rtl8150.c linux-libre-3.2.87-gnu1/drivers/net/usb/rtl8150.c
--- linux-libre-3.2.86-gnu1/drivers/net/usb/rtl8150.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/net/usb/rtl8150.c	2017-03-15 22:19:00.000000000 -0400
@@ -178,16 +178,36 @@ static const char driver_name [] = "rtl8
 */
 static int get_registers(rtl8150_t * dev, u16 indx, u16 size, void *data)
 {
-	return usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
-			       RTL8150_REQ_GET_REGS, RTL8150_REQT_READ,
-			       indx, 0, data, size, 500);
+	void *buf;
+	int ret;
+
+	buf = kmalloc(size, GFP_NOIO);
+	if (!buf)
+		return -ENOMEM;
+
+	ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
+			      RTL8150_REQ_GET_REGS, RTL8150_REQT_READ,
+			      indx, 0, buf, size, 500);
+	if (ret > 0 && ret <= size)
+		memcpy(data, buf, ret);
+	kfree(buf);
+	return ret;
 }
 
-static int set_registers(rtl8150_t * dev, u16 indx, u16 size, void *data)
+static int set_registers(rtl8150_t * dev, u16 indx, u16 size, const void *data)
 {
-	return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
-			       RTL8150_REQ_SET_REGS, RTL8150_REQT_WRITE,
-			       indx, 0, data, size, 500);
+	void *buf;
+	int ret;
+
+	buf = kmemdup(data, size, GFP_NOIO);
+	if (!buf)
+		return -ENOMEM;
+
+	ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
+			      RTL8150_REQ_SET_REGS, RTL8150_REQT_WRITE,
+			      indx, 0, buf, size, 500);
+	kfree(buf);
+	return ret;
 }
 
 static void ctrl_callback(struct urb *urb)
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/net/xen-netfront.c linux-libre-3.2.87-gnu1/drivers/net/xen-netfront.c
--- linux-libre-3.2.86-gnu1/drivers/net/xen-netfront.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/net/xen-netfront.c	2017-03-15 22:19:00.000000000 -0400
@@ -1404,6 +1404,8 @@ static void xennet_disconnect_backend(st
 	spin_unlock_irq(&info->tx_lock);
 	spin_unlock_bh(&info->rx_lock);
 
+	del_timer_sync(&info->rx_refill_timer);
+
 	if (info->netdev->irq)
 		unbind_from_irqhandler(info->netdev->irq, info->netdev);
 	info->evtchn = info->netdev->irq = 0;
@@ -1940,8 +1942,6 @@ static int __devexit xennet_remove(struc
 
 	unregister_netdev(info->netdev);
 
-	del_timer_sync(&info->rx_refill_timer);
-
 	free_percpu(info->stats);
 
 	free_netdev(info->netdev);
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/pci/hotplug/rpadlpar_core.c linux-libre-3.2.87-gnu1/drivers/pci/hotplug/rpadlpar_core.c
--- linux-libre-3.2.86-gnu1/drivers/pci/hotplug/rpadlpar_core.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/pci/hotplug/rpadlpar_core.c	2017-03-15 22:19:00.000000000 -0400
@@ -259,8 +259,13 @@ static int dlpar_add_phb(char *drc_name,
 
 static int dlpar_add_vio_slot(char *drc_name, struct device_node *dn)
 {
-	if (vio_find_node(dn))
+	struct vio_dev *vio_dev;
+
+	vio_dev = vio_find_node(dn);
+	if (vio_dev) {
+		put_device(&vio_dev->dev);
 		return -EINVAL;
+	}
 
 	if (!vio_register_device_node(dn)) {
 		printk(KERN_ERR
@@ -336,6 +341,9 @@ static int dlpar_remove_vio_slot(char *d
 		return -EINVAL;
 
 	vio_unregister_device(vio_dev);
+
+	put_device(&vio_dev->dev);
+
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/pci/pci.c linux-libre-3.2.87-gnu1/drivers/pci/pci.c
--- linux-libre-3.2.86-gnu1/drivers/pci/pci.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/pci/pci.c	2017-03-15 22:19:00.000000000 -0400
@@ -1763,6 +1763,10 @@ bool pci_dev_run_wake(struct pci_dev *de
 	if (!dev->pme_support)
 		return false;
 
+	/* PME-capable in principle, but not from the intended sleep state */
+	if (!pci_pme_capable(dev, pci_target_state(dev)))
+		return false;
+
 	while (bus->parent) {
 		struct pci_dev *bridge = bus->self;
 
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/platform/x86/intel_mid_powerbtn.c linux-libre-3.2.87-gnu1/drivers/platform/x86/intel_mid_powerbtn.c
--- linux-libre-3.2.86-gnu1/drivers/platform/x86/intel_mid_powerbtn.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/platform/x86/intel_mid_powerbtn.c	2017-03-15 22:19:00.000000000 -0400
@@ -72,7 +72,7 @@ static int __devinit mfld_pb_probe(struc
 
 	input_set_capability(input, EV_KEY, KEY_POWER);
 
-	error = request_threaded_irq(irq, NULL, mfld_pb_isr, 0,
+	error = request_threaded_irq(irq, NULL, mfld_pb_isr, IRQF_ONESHOT,
 			DRIVER_NAME, input);
 	if (error) {
 		dev_err(&pdev->dev, "Unable to request irq %d for mfld power"
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/s390/char/vmlogrdr.c linux-libre-3.2.87-gnu1/drivers/s390/char/vmlogrdr.c
--- linux-libre-3.2.86-gnu1/drivers/s390/char/vmlogrdr.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/s390/char/vmlogrdr.c	2017-03-15 22:19:00.000000000 -0400
@@ -876,7 +876,7 @@ static int __init vmlogrdr_init(void)
 		goto cleanup;
 
 	for (i=0; i < MAXMINOR; ++i ) {
-		sys_ser[i].buffer = (char *) get_zeroed_page(GFP_KERNEL);
+		sys_ser[i].buffer = (char *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
 		if (!sys_ser[i].buffer) {
 			rc = -ENOMEM;
 			break;
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/s390/scsi/zfcp_dbf.c linux-libre-3.2.87-gnu1/drivers/s390/scsi/zfcp_dbf.c
--- linux-libre-3.2.86-gnu1/drivers/s390/scsi/zfcp_dbf.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/s390/scsi/zfcp_dbf.c	2017-03-15 22:19:00.000000000 -0400
@@ -282,11 +282,12 @@ void zfcp_dbf_rec_trig(char *tag, struct
 
 
 /**
- * zfcp_dbf_rec_run - trace event related to running recovery
+ * zfcp_dbf_rec_run_lvl - trace event related to running recovery
+ * @level: trace level to be used for event
  * @tag: identifier for event
  * @erp: erp_action running
  */
-void zfcp_dbf_rec_run(char *tag, struct zfcp_erp_action *erp)
+void zfcp_dbf_rec_run_lvl(int level, char *tag, struct zfcp_erp_action *erp)
 {
 	struct zfcp_dbf *dbf = erp->adapter->dbf;
 	struct zfcp_dbf_rec *rec = &dbf->rec_buf;
@@ -312,11 +313,21 @@ void zfcp_dbf_rec_run(char *tag, struct
 	else
 		rec->u.run.rec_count = atomic_read(&erp->adapter->erp_counter);
 
-	debug_event(dbf->rec, 1, rec, sizeof(*rec));
+	debug_event(dbf->rec, level, rec, sizeof(*rec));
 	spin_unlock_irqrestore(&dbf->rec_lock, flags);
 }
 
 /**
+ * zfcp_dbf_rec_run - trace event related to running recovery
+ * @tag: identifier for event
+ * @erp: erp_action running
+ */
+void zfcp_dbf_rec_run(char *tag, struct zfcp_erp_action *erp)
+{
+	zfcp_dbf_rec_run_lvl(1, tag, erp);
+}
+
+/**
  * zfcp_dbf_rec_run_wka - trace wka port event with info like running recovery
  * @tag: identifier for event
  * @wka_port: well known address port
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/s390/scsi/zfcp_dbf.h linux-libre-3.2.87-gnu1/drivers/s390/scsi/zfcp_dbf.h
--- linux-libre-3.2.86-gnu1/drivers/s390/scsi/zfcp_dbf.h	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/s390/scsi/zfcp_dbf.h	2017-03-15 22:19:00.000000000 -0400
@@ -2,7 +2,7 @@
  * zfcp device driver
  * debug feature declarations
  *
- * Copyright IBM Corp. 2008, 2015
+ * Copyright IBM Corp. 2008, 2016
  */
 
 #ifndef ZFCP_DBF_H
@@ -283,6 +283,30 @@ struct zfcp_dbf {
 	struct zfcp_dbf_scsi		scsi_buf;
 };
 
+/**
+ * zfcp_dbf_hba_fsf_resp_suppress - true if we should not trace by default
+ * @req: request that has been completed
+ *
+ * Returns true if FCP response with only benign residual under count.
+ */
+static inline
+bool zfcp_dbf_hba_fsf_resp_suppress(struct zfcp_fsf_req *req)
+{
+	struct fsf_qtcb *qtcb = req->qtcb;
+	u32 fsf_stat = qtcb->header.fsf_status;
+	struct fcp_resp *fcp_rsp;
+	u8 rsp_flags, fr_status;
+
+	if (qtcb->prefix.qtcb_type != FSF_IO_COMMAND)
+		return false; /* not an FCP response */
+	fcp_rsp = (struct fcp_resp *)&qtcb->bottom.io.fcp_rsp;
+	rsp_flags = fcp_rsp->fr_flags;
+	fr_status = fcp_rsp->fr_status;
+	return (fsf_stat == FSF_FCP_RSP_AVAILABLE) &&
+		(rsp_flags == FCP_RESID_UNDER) &&
+		(fr_status == SAM_STAT_GOOD);
+}
+
 static inline
 void zfcp_dbf_hba_fsf_resp(char *tag, int level, struct zfcp_fsf_req *req)
 {
@@ -304,7 +328,9 @@ void zfcp_dbf_hba_fsf_response(struct zf
 		zfcp_dbf_hba_fsf_resp("fs_perr", 1, req);
 
 	} else if (qtcb->header.fsf_status != FSF_GOOD) {
-		zfcp_dbf_hba_fsf_resp("fs_ferr", 1, req);
+		zfcp_dbf_hba_fsf_resp("fs_ferr",
+				      zfcp_dbf_hba_fsf_resp_suppress(req)
+				      ? 5 : 1, req);
 
 	} else if ((req->fsf_command == FSF_QTCB_OPEN_PORT_WITH_DID) ||
 		   (req->fsf_command == FSF_QTCB_OPEN_LUN)) {
@@ -388,4 +414,15 @@ void zfcp_dbf_scsi_devreset(char *tag, s
 	_zfcp_dbf_scsi(tmp_tag, 1, scmnd, NULL);
 }
 
+/**
+ * zfcp_dbf_scsi_nullcmnd() - trace NULLify of SCSI command in dev/tgt-reset.
+ * @scmnd: SCSI command that was NULLified.
+ * @fsf_req: request that owned @scmnd.
+ */
+static inline void zfcp_dbf_scsi_nullcmnd(struct scsi_cmnd *scmnd,
+					  struct zfcp_fsf_req *fsf_req)
+{
+	_zfcp_dbf_scsi("scfc__1", 3, scmnd, fsf_req);
+}
+
 #endif /* ZFCP_DBF_H */
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/s390/scsi/zfcp_erp.c linux-libre-3.2.87-gnu1/drivers/s390/scsi/zfcp_erp.c
--- linux-libre-3.2.86-gnu1/drivers/s390/scsi/zfcp_erp.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/s390/scsi/zfcp_erp.c	2017-03-15 22:19:00.000000000 -0400
@@ -3,7 +3,7 @@
  *
  * Error Recovery Procedures (ERP).
  *
- * Copyright IBM Corp. 2002, 2015
+ * Copyright IBM Corp. 2002, 2016
  */
 
 #define KMSG_COMPONENT "zfcp"
@@ -1212,6 +1212,62 @@ static void zfcp_erp_action_dequeue(stru
 	}
 }
 
+/**
+ * zfcp_erp_try_rport_unblock - unblock rport if no more/new recovery
+ * @port: zfcp_port whose fc_rport we should try to unblock
+ */
+static void zfcp_erp_try_rport_unblock(struct zfcp_port *port)
+{
+	unsigned long flags;
+	struct zfcp_adapter *adapter = port->adapter;
+	int port_status;
+	struct Scsi_Host *shost = adapter->scsi_host;
+	struct scsi_device *sdev;
+
+	write_lock_irqsave(&adapter->erp_lock, flags);
+	port_status = atomic_read(&port->status);
+	if ((port_status & ZFCP_STATUS_COMMON_UNBLOCKED)    == 0 ||
+	    (port_status & (ZFCP_STATUS_COMMON_ERP_INUSE |
+			    ZFCP_STATUS_COMMON_ERP_FAILED)) != 0) {
+		/* new ERP of severity >= port triggered elsewhere meanwhile or
+		 * local link down (adapter erp_failed but not clear unblock)
+		 */
+		zfcp_dbf_rec_run_lvl(4, "ertru_p", &port->erp_action);
+		write_unlock_irqrestore(&adapter->erp_lock, flags);
+		return;
+	}
+	spin_lock(shost->host_lock);
+	__shost_for_each_device(sdev, shost) {
+		struct zfcp_scsi_dev *zsdev = sdev_to_zfcp(sdev);
+		int lun_status;
+
+		if (zsdev->port != port)
+			continue;
+		/* LUN under port of interest */
+		lun_status = atomic_read(&zsdev->status);
+		if ((lun_status & ZFCP_STATUS_COMMON_ERP_FAILED) != 0)
+			continue; /* unblock rport despite failed LUNs */
+		/* LUN recovery not given up yet [maybe follow-up pending] */
+		if ((lun_status & ZFCP_STATUS_COMMON_UNBLOCKED) == 0 ||
+		    (lun_status & ZFCP_STATUS_COMMON_ERP_INUSE) != 0) {
+			/* LUN blocked:
+			 * not yet unblocked [LUN recovery pending]
+			 * or meanwhile blocked [new LUN recovery triggered]
+			 */
+			zfcp_dbf_rec_run_lvl(4, "ertru_l", &zsdev->erp_action);
+			spin_unlock(shost->host_lock);
+			write_unlock_irqrestore(&adapter->erp_lock, flags);
+			return;
+		}
+	}
+	/* now port has no child or all children have completed recovery,
+	 * and no ERP of severity >= port was meanwhile triggered elsewhere
+	 */
+	zfcp_scsi_schedule_rport_register(port);
+	spin_unlock(shost->host_lock);
+	write_unlock_irqrestore(&adapter->erp_lock, flags);
+}
+
 static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result)
 {
 	struct zfcp_adapter *adapter = act->adapter;
@@ -1222,6 +1278,7 @@ static void zfcp_erp_action_cleanup(stru
 	case ZFCP_ERP_ACTION_REOPEN_LUN:
 		if (!(act->status & ZFCP_STATUS_ERP_NO_REF))
 			scsi_device_put(sdev);
+		zfcp_erp_try_rport_unblock(port);
 		break;
 
 	case ZFCP_ERP_ACTION_REOPEN_PORT:
@@ -1232,7 +1289,7 @@ static void zfcp_erp_action_cleanup(stru
 		 */
 		if (act->step != ZFCP_ERP_STEP_UNINITIALIZED)
 			if (result == ZFCP_ERP_SUCCEEDED)
-				zfcp_scsi_schedule_rport_register(port);
+				zfcp_erp_try_rport_unblock(port);
 		/* fall through */
 	case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
 		put_device(&port->dev);
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/s390/scsi/zfcp_ext.h linux-libre-3.2.87-gnu1/drivers/s390/scsi/zfcp_ext.h
--- linux-libre-3.2.86-gnu1/drivers/s390/scsi/zfcp_ext.h	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/s390/scsi/zfcp_ext.h	2017-03-15 22:19:00.000000000 -0400
@@ -3,7 +3,7 @@
  *
  * External function declarations.
  *
- * Copyright IBM Corp. 2002, 2015
+ * Copyright IBM Corp. 2002, 2016
  */
 
 #ifndef ZFCP_EXT_H
@@ -49,6 +49,8 @@ extern void zfcp_dbf_adapter_unregister(
 extern void zfcp_dbf_rec_trig(char *, struct zfcp_adapter *,
 			      struct zfcp_port *, struct scsi_device *, u8, u8);
 extern void zfcp_dbf_rec_run(char *, struct zfcp_erp_action *);
+extern void zfcp_dbf_rec_run_lvl(int level, char *tag,
+				 struct zfcp_erp_action *erp);
 extern void zfcp_dbf_rec_run_wka(char *, struct zfcp_fc_wka_port *, u64);
 extern void zfcp_dbf_hba_fsf_uss(char *, struct zfcp_fsf_req *);
 extern void zfcp_dbf_hba_fsf_res(char *, int, struct zfcp_fsf_req *);
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/s390/scsi/zfcp_fsf.c linux-libre-3.2.87-gnu1/drivers/s390/scsi/zfcp_fsf.c
--- linux-libre-3.2.86-gnu1/drivers/s390/scsi/zfcp_fsf.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/s390/scsi/zfcp_fsf.c	2017-03-15 22:19:00.000000000 -0400
@@ -1577,7 +1577,7 @@ out:
 int zfcp_fsf_open_wka_port(struct zfcp_fc_wka_port *wka_port)
 {
 	struct zfcp_qdio *qdio = wka_port->adapter->qdio;
-	struct zfcp_fsf_req *req = NULL;
+	struct zfcp_fsf_req *req;
 	int retval = -EIO;
 
 	spin_lock_irq(&qdio->req_q_lock);
@@ -1606,7 +1606,7 @@ int zfcp_fsf_open_wka_port(struct zfcp_f
 		zfcp_fsf_req_free(req);
 out:
 	spin_unlock_irq(&qdio->req_q_lock);
-	if (req && !IS_ERR(req))
+	if (!retval)
 		zfcp_dbf_rec_run_wka("fsowp_1", wka_port, req->req_id);
 	return retval;
 }
@@ -1632,7 +1632,7 @@ static void zfcp_fsf_close_wka_port_hand
 int zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *wka_port)
 {
 	struct zfcp_qdio *qdio = wka_port->adapter->qdio;
-	struct zfcp_fsf_req *req = NULL;
+	struct zfcp_fsf_req *req;
 	int retval = -EIO;
 
 	spin_lock_irq(&qdio->req_q_lock);
@@ -1661,7 +1661,7 @@ int zfcp_fsf_close_wka_port(struct zfcp_
 		zfcp_fsf_req_free(req);
 out:
 	spin_unlock_irq(&qdio->req_q_lock);
-	if (req && !IS_ERR(req))
+	if (!retval)
 		zfcp_dbf_rec_run_wka("fscwp_1", wka_port, req->req_id);
 	return retval;
 }
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/s390/scsi/zfcp_fsf.h linux-libre-3.2.87-gnu1/drivers/s390/scsi/zfcp_fsf.h
--- linux-libre-3.2.86-gnu1/drivers/s390/scsi/zfcp_fsf.h	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/s390/scsi/zfcp_fsf.h	2017-03-15 22:19:00.000000000 -0400
@@ -3,7 +3,7 @@
  *
  * Interface to the FSF support functions.
  *
- * Copyright IBM Corp. 2002, 2015
+ * Copyright IBM Corp. 2002, 2016
  */
 
 #ifndef FSF_H
@@ -86,6 +86,7 @@
 #define FSF_APP_TAG_CHECK_FAILURE		0x00000082
 #define FSF_REF_TAG_CHECK_FAILURE		0x00000083
 #define FSF_ADAPTER_STATUS_AVAILABLE		0x000000AD
+#define FSF_FCP_RSP_AVAILABLE			0x000000AF
 #define FSF_UNKNOWN_COMMAND			0x000000E2
 #define FSF_UNKNOWN_OP_SUBTYPE                  0x000000E3
 #define FSF_INVALID_COMMAND_OPTION              0x000000E5
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/s390/scsi/zfcp_reqlist.h linux-libre-3.2.87-gnu1/drivers/s390/scsi/zfcp_reqlist.h
--- linux-libre-3.2.86-gnu1/drivers/s390/scsi/zfcp_reqlist.h	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/s390/scsi/zfcp_reqlist.h	2017-03-15 22:19:00.000000000 -0400
@@ -4,7 +4,7 @@
  * Data structure and helper functions for tracking pending FSF
  * requests.
  *
- * Copyright IBM Corporation 2009
+ * Copyright IBM Corp. 2009, 2016
  */
 
 #ifndef ZFCP_REQLIST_H
@@ -180,4 +180,32 @@ static inline void zfcp_reqlist_move(str
 	spin_unlock_irqrestore(&rl->lock, flags);
 }
 
+/**
+ * zfcp_reqlist_apply_for_all() - apply a function to every request.
+ * @rl: the requestlist that contains the target requests.
+ * @f: the function to apply to each request; the first parameter of the
+ *     function will be the target-request; the second parameter is the same
+ *     pointer as given with the argument @data.
+ * @data: freely chosen argument; passed through to @f as second parameter.
+ *
+ * Uses :c:macro:`list_for_each_entry` to iterate over the lists in the hash-
+ * table (not a 'safe' variant, so don't modify the list).
+ *
+ * Holds @rl->lock over the entire request-iteration.
+ */
+static inline void
+zfcp_reqlist_apply_for_all(struct zfcp_reqlist *rl,
+			   void (*f)(struct zfcp_fsf_req *, void *), void *data)
+{
+	struct zfcp_fsf_req *req;
+	unsigned long flags;
+	unsigned int i;
+
+	spin_lock_irqsave(&rl->lock, flags);
+	for (i = 0; i < ZFCP_REQ_LIST_BUCKETS; i++)
+		list_for_each_entry(req, &rl->buckets[i], list)
+			f(req, data);
+	spin_unlock_irqrestore(&rl->lock, flags);
+}
+
 #endif /* ZFCP_REQLIST_H */
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/s390/scsi/zfcp_scsi.c linux-libre-3.2.87-gnu1/drivers/s390/scsi/zfcp_scsi.c
--- linux-libre-3.2.86-gnu1/drivers/s390/scsi/zfcp_scsi.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/s390/scsi/zfcp_scsi.c	2017-03-15 22:19:00.000000000 -0400
@@ -3,7 +3,7 @@
  *
  * Interface to Linux SCSI midlayer.
  *
- * Copyright IBM Corp. 2002, 2015
+ * Copyright IBM Corp. 2002, 2016
  */
 
 #define KMSG_COMPONENT "zfcp"
@@ -109,9 +109,7 @@ int zfcp_scsi_queuecommand(struct Scsi_H
 	}
 
 	if (unlikely(!(status & ZFCP_STATUS_COMMON_UNBLOCKED))) {
-		/* This could be either
-		 * open LUN pending: this is temporary, will result in
-		 *	open LUN or ERP_FAILED, so retry command
+		/* This could be
 		 * call to rport_delete pending: mimic retry from
 		 * 	fc_remote_port_chkready until rport is BLOCKED
 		 */
@@ -230,6 +228,57 @@ static int zfcp_scsi_eh_abort_handler(st
 	return retval;
 }
 
+struct zfcp_scsi_req_filter {
+	u8 tmf_scope;
+	u32 lun_handle;
+	u32 port_handle;
+};
+
+static void zfcp_scsi_forget_cmnd(struct zfcp_fsf_req *old_req, void *data)
+{
+	struct zfcp_scsi_req_filter *filter =
+		(struct zfcp_scsi_req_filter *)data;
+
+	/* already aborted - prevent side-effects - or not a SCSI command */
+	if (old_req->data == NULL || old_req->fsf_command != FSF_QTCB_FCP_CMND)
+		return;
+
+	/* (tmf_scope == FCP_TMF_TGT_RESET || tmf_scope == FCP_TMF_LUN_RESET) */
+	if (old_req->qtcb->header.port_handle != filter->port_handle)
+		return;
+
+	if (filter->tmf_scope == FCP_TMF_LUN_RESET &&
+	    old_req->qtcb->header.lun_handle != filter->lun_handle)
+		return;
+
+	zfcp_dbf_scsi_nullcmnd((struct scsi_cmnd *)old_req->data, old_req);
+	old_req->data = NULL;
+}
+
+static void zfcp_scsi_forget_cmnds(struct zfcp_scsi_dev *zsdev, u8 tm_flags)
+{
+	struct zfcp_adapter *adapter = zsdev->port->adapter;
+	struct zfcp_scsi_req_filter filter = {
+		.tmf_scope = FCP_TMF_TGT_RESET,
+		.port_handle = zsdev->port->handle,
+	};
+	unsigned long flags;
+
+	if (tm_flags == FCP_TMF_LUN_RESET) {
+		filter.tmf_scope = FCP_TMF_LUN_RESET;
+		filter.lun_handle = zsdev->lun_handle;
+	}
+
+	/*
+	 * abort_lock secures against other processings - in the abort-function
+	 * and normal cmnd-handler - of (struct zfcp_fsf_req *)->data
+	 */
+	write_lock_irqsave(&adapter->abort_lock, flags);
+	zfcp_reqlist_apply_for_all(adapter->req_list, zfcp_scsi_forget_cmnd,
+				   &filter);
+	write_unlock_irqrestore(&adapter->abort_lock, flags);
+}
+
 static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags)
 {
 	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device);
@@ -262,8 +311,10 @@ static int zfcp_task_mgmt_function(struc
 	if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) {
 		zfcp_dbf_scsi_devreset("fail", scpnt, tm_flags);
 		retval = FAILED;
-	} else
+	} else {
 		zfcp_dbf_scsi_devreset("okay", scpnt, tm_flags);
+		zfcp_scsi_forget_cmnds(zfcp_sdev, tm_flags);
+	}
 
 	zfcp_fsf_req_free(fsf_req);
 	return retval;
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/scsi/mvsas/mv_94xx.c linux-libre-3.2.87-gnu1/drivers/scsi/mvsas/mv_94xx.c
--- linux-libre-3.2.86-gnu1/drivers/scsi/mvsas/mv_94xx.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/scsi/mvsas/mv_94xx.c	2017-03-15 22:19:00.000000000 -0400
@@ -622,7 +622,7 @@ static void mvs_94xx_command_active(stru
 {
 	u32 tmp;
 	tmp = mvs_cr32(mvi, MVS_COMMAND_ACTIVE+(slot_idx >> 3));
-	if (tmp && 1 << (slot_idx % 32)) {
+	if (tmp & 1 << (slot_idx % 32)) {
 		mv_printk("command active %08X,  slot [%x].\n", tmp, slot_idx);
 		mvs_cw32(mvi, MVS_COMMAND_ACTIVE + (slot_idx >> 3),
 			1 << (slot_idx % 32));
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/scsi/scsi_sysfs.c linux-libre-3.2.87-gnu1/drivers/scsi/scsi_sysfs.c
--- linux-libre-3.2.86-gnu1/drivers/scsi/scsi_sysfs.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/scsi/scsi_sysfs.c	2017-03-15 22:19:00.000000000 -0400
@@ -864,10 +864,6 @@ int scsi_sysfs_add_sdev(struct scsi_devi
 	struct request_queue *rq = sdev->request_queue;
 	struct scsi_target *starget = sdev->sdev_target;
 
-	error = scsi_device_set_state(sdev, SDEV_RUNNING);
-	if (error)
-		return error;
-
 	error = scsi_target_add(starget);
 	if (error)
 		return error;
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/scsi/sg.c linux-libre-3.2.87-gnu1/drivers/scsi/sg.c
--- linux-libre-3.2.86-gnu1/drivers/scsi/sg.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/scsi/sg.c	2017-03-15 22:19:00.000000000 -0400
@@ -1710,6 +1710,10 @@ static int sg_start_req(Sg_request *srp,
 			iov_count = iov_shorten(iov, iov_count, hp->dxfer_len);
 			len = hp->dxfer_len;
 		}
+		if (len == 0) {
+			kfree(iov);
+			return -EINVAL;
+		}
 
 		res = blk_rq_map_user_iov(q, rq, md, (struct sg_iovec *)iov,
 					  iov_count,
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/ssb/pci.c linux-libre-3.2.87-gnu1/drivers/ssb/pci.c
--- linux-libre-3.2.86-gnu1/drivers/ssb/pci.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/ssb/pci.c	2017-03-15 22:19:00.000000000 -0400
@@ -713,6 +713,7 @@ static int ssb_pci_sprom_get(struct ssb_
 				ssb_printk(KERN_WARNING PFX "WARNING: Using"
 					   " fallback SPROM failed (err %d)\n",
 					   err);
+				goto out_free;
 			} else {
 				ssb_dprintk(KERN_DEBUG PFX "Using SPROM"
 					    " revision %d provided by"
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/staging/gma500/psb_drv.c linux-libre-3.2.87-gnu1/drivers/staging/gma500/psb_drv.c
--- linux-libre-3.2.86-gnu1/drivers/staging/gma500/psb_drv.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/staging/gma500/psb_drv.c	2017-03-15 22:19:00.000000000 -0400
@@ -1185,6 +1185,9 @@ static struct drm_driver driver = {
 		 .open = drm_open,
 		 .release = drm_release,
 		 .unlocked_ioctl = psb_unlocked_ioctl,
+#ifdef CONFIG_COMPAT
+		 .compat_ioctl = drm_compat_ioctl,
+#endif
 		 .mmap = drm_gem_mmap,
 		 .poll = drm_poll,
 		 .fasync = drm_fasync,
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/staging/hv/netvsc_drv.c linux-libre-3.2.87-gnu1/drivers/staging/hv/netvsc_drv.c
--- linux-libre-3.2.86-gnu1/drivers/staging/hv/netvsc_drv.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/staging/hv/netvsc_drv.c	2017-03-15 22:19:00.000000000 -0400
@@ -52,6 +52,9 @@ struct net_device_context {
 /* Need this many pages to handle worst case fragmented packet */
 #define PACKET_PAGES_HIWATER  (MAX_SKB_FRAGS + 2)
 
+/* Restrict GSO size to account for NVGRE */
+#define NETVSC_GSO_MAX_SIZE	62768
+
 static int ring_size = 128;
 module_param(ring_size, int, S_IRUGO);
 MODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)");
@@ -363,6 +366,7 @@ static int netvsc_probe(struct hv_device
 
 	SET_ETHTOOL_OPS(net, &ethtool_ops);
 	SET_NETDEV_DEV(net, &dev->device);
+	netif_set_gso_max_size(net, NETVSC_GSO_MAX_SIZE);
 
 	ret = register_netdev(net);
 	if (ret != 0) {
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/staging/iio/adc/ad7606_core.c linux-libre-3.2.87-gnu1/drivers/staging/iio/adc/ad7606_core.c
--- linux-libre-3.2.86-gnu1/drivers/staging/iio/adc/ad7606_core.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/staging/iio/adc/ad7606_core.c	2017-03-15 22:19:00.000000000 -0400
@@ -185,7 +185,7 @@ static ssize_t ad7606_store_oversampling
 	mutex_lock(&indio_dev->mlock);
 	gpio_set_value(st->pdata->gpio_os0, (ret >> 0) & 1);
 	gpio_set_value(st->pdata->gpio_os1, (ret >> 1) & 1);
-	gpio_set_value(st->pdata->gpio_os1, (ret >> 2) & 1);
+	gpio_set_value(st->pdata->gpio_os2, (ret >> 2) & 1);
 	st->oversampling = lval;
 	mutex_unlock(&indio_dev->mlock);
 
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/staging/vme/bridges/vme_ca91cx42.c linux-libre-3.2.87-gnu1/drivers/staging/vme/bridges/vme_ca91cx42.c
--- linux-libre-3.2.86-gnu1/drivers/staging/vme/bridges/vme_ca91cx42.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/staging/vme/bridges/vme_ca91cx42.c	2017-03-15 22:19:00.000000000 -0400
@@ -466,7 +466,7 @@ static int ca91cx42_slave_get(struct vme
 	vme_bound = ioread32(bridge->base + CA91CX42_VSI_BD[i]);
 	pci_offset = ioread32(bridge->base + CA91CX42_VSI_TO[i]);
 
-	*pci_base = (dma_addr_t)vme_base + pci_offset;
+	*pci_base = (dma_addr_t)*vme_base + pci_offset;
 	*size = (unsigned long long)((vme_bound - *vme_base) + granularity);
 
 	*enabled = 0;
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/target/iscsi/iscsi_target_tpg.c linux-libre-3.2.87-gnu1/drivers/target/iscsi/iscsi_target_tpg.c
--- linux-libre-3.2.86-gnu1/drivers/target/iscsi/iscsi_target_tpg.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/target/iscsi/iscsi_target_tpg.c	2017-03-15 22:19:00.000000000 -0400
@@ -253,7 +253,6 @@ err_out:
 		iscsi_release_param_list(tpg->param_list);
 		tpg->param_list = NULL;
 	}
-	kfree(tpg);
 	return -ENOMEM;
 }
 
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/thermal/thermal_sys.c linux-libre-3.2.87-gnu1/drivers/thermal/thermal_sys.c
--- linux-libre-3.2.86-gnu1/drivers/thermal/thermal_sys.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/thermal/thermal_sys.c	2017-03-15 22:19:00.000000000 -0400
@@ -486,7 +486,7 @@ temp_crit_show(struct device *dev, struc
 	long temperature;
 	int ret;
 
-	ret = tz->ops->get_trip_temp(tz, 0, &temperature);
+	ret = tz->ops->get_crit_temp(tz, &temperature);
 	if (ret)
 		return ret;
 
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/tty/n_hdlc.c linux-libre-3.2.87-gnu1/drivers/tty/n_hdlc.c
--- linux-libre-3.2.86-gnu1/drivers/tty/n_hdlc.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/tty/n_hdlc.c	2017-03-15 22:19:00.000000000 -0400
@@ -115,7 +115,7 @@
 #define DEFAULT_TX_BUF_COUNT 3
 
 struct n_hdlc_buf {
-	struct n_hdlc_buf *link;
+	struct list_head  list_item;
 	int		  count;
 	char		  buf[1];
 };
@@ -123,8 +123,7 @@ struct n_hdlc_buf {
 #define	N_HDLC_BUF_SIZE	(sizeof(struct n_hdlc_buf) + maxframe)
 
 struct n_hdlc_buf_list {
-	struct n_hdlc_buf *head;
-	struct n_hdlc_buf *tail;
+	struct list_head  list;
 	int		  count;
 	spinlock_t	  spinlock;
 };
@@ -137,7 +136,6 @@ struct n_hdlc_buf_list {
  * @backup_tty - TTY to use if tty gets closed
  * @tbusy - reentrancy flag for tx wakeup code
  * @woke_up - FIXME: describe this field
- * @tbuf - currently transmitting tx buffer
  * @tx_buf_list - list of pending transmit frame buffers
  * @rx_buf_list - list of received frame buffers
  * @tx_free_buf_list - list unused transmit frame buffers
@@ -150,7 +148,6 @@ struct n_hdlc {
 	struct tty_struct	*backup_tty;
 	int			tbusy;
 	int			woke_up;
-	struct n_hdlc_buf	*tbuf;
 	struct n_hdlc_buf_list	tx_buf_list;
 	struct n_hdlc_buf_list	rx_buf_list;
 	struct n_hdlc_buf_list	tx_free_buf_list;
@@ -160,7 +157,8 @@ struct n_hdlc {
 /*
  * HDLC buffer list manipulation functions
  */
-static void n_hdlc_buf_list_init(struct n_hdlc_buf_list *list);
+static void n_hdlc_buf_return(struct n_hdlc_buf_list *buf_list,
+						struct n_hdlc_buf *buf);
 static void n_hdlc_buf_put(struct n_hdlc_buf_list *list,
 			   struct n_hdlc_buf *buf);
 static struct n_hdlc_buf *n_hdlc_buf_get(struct n_hdlc_buf_list *list);
@@ -210,16 +208,9 @@ static void flush_tx_queue(struct tty_st
 {
 	struct n_hdlc *n_hdlc = tty2n_hdlc(tty);
 	struct n_hdlc_buf *buf;
-	unsigned long flags;
 
 	while ((buf = n_hdlc_buf_get(&n_hdlc->tx_buf_list)))
 		n_hdlc_buf_put(&n_hdlc->tx_free_buf_list, buf);
- 	spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock, flags);
-	if (n_hdlc->tbuf) {
-		n_hdlc_buf_put(&n_hdlc->tx_free_buf_list, n_hdlc->tbuf);
-		n_hdlc->tbuf = NULL;
-	}
-	spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags);
 }
 
 static struct tty_ldisc_ops n_hdlc_ldisc = {
@@ -285,7 +276,6 @@ static void n_hdlc_release(struct n_hdlc
 		} else
 			break;
 	}
-	kfree(n_hdlc->tbuf);
 	kfree(n_hdlc);
 	
 }	/* end of n_hdlc_release() */
@@ -404,13 +394,7 @@ static void n_hdlc_send_frames(struct n_
 	n_hdlc->woke_up = 0;
 	spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags);
 
-	/* get current transmit buffer or get new transmit */
-	/* buffer from list of pending transmit buffers */
-		
-	tbuf = n_hdlc->tbuf;
-	if (!tbuf)
-		tbuf = n_hdlc_buf_get(&n_hdlc->tx_buf_list);
-		
+	tbuf = n_hdlc_buf_get(&n_hdlc->tx_buf_list);
 	while (tbuf) {
 		if (debuglevel >= DEBUG_LEVEL_INFO)	
 			printk("%s(%d)sending frame %p, count=%d\n",
@@ -422,7 +406,7 @@ static void n_hdlc_send_frames(struct n_
 
 		/* rollback was possible and has been done */
 		if (actual == -ERESTARTSYS) {
-			n_hdlc->tbuf = tbuf;
+			n_hdlc_buf_return(&n_hdlc->tx_buf_list, tbuf);
 			break;
 		}
 		/* if transmit error, throw frame away by */
@@ -437,10 +421,7 @@ static void n_hdlc_send_frames(struct n_
 					
 			/* free current transmit buffer */
 			n_hdlc_buf_put(&n_hdlc->tx_free_buf_list, tbuf);
-			
-			/* this tx buffer is done */
-			n_hdlc->tbuf = NULL;
-			
+
 			/* wait up sleeping writers */
 			wake_up_interruptible(&tty->write_wait);
 	
@@ -450,10 +431,12 @@ static void n_hdlc_send_frames(struct n_
 			if (debuglevel >= DEBUG_LEVEL_INFO)	
 				printk("%s(%d)frame %p pending\n",
 					__FILE__,__LINE__,tbuf);
-					
-			/* buffer not accepted by driver */
-			/* set this buffer as pending buffer */
-			n_hdlc->tbuf = tbuf;
+
+			/*
+			 * the buffer was not accepted by driver,
+			 * return it back into tx queue
+			 */
+			n_hdlc_buf_return(&n_hdlc->tx_buf_list, tbuf);
 			break;
 		}
 	}
@@ -751,7 +734,8 @@ static int n_hdlc_tty_ioctl(struct tty_s
 	int error = 0;
 	int count;
 	unsigned long flags;
-	
+	struct n_hdlc_buf *buf = NULL;
+
 	if (debuglevel >= DEBUG_LEVEL_INFO)	
 		printk("%s(%d)n_hdlc_tty_ioctl() called %d\n",
 			__FILE__,__LINE__,cmd);
@@ -765,8 +749,10 @@ static int n_hdlc_tty_ioctl(struct tty_s
 		/* report count of read data available */
 		/* in next available frame (if any) */
 		spin_lock_irqsave(&n_hdlc->rx_buf_list.spinlock,flags);
-		if (n_hdlc->rx_buf_list.head)
-			count = n_hdlc->rx_buf_list.head->count;
+		buf = list_first_entry_or_null(&n_hdlc->rx_buf_list.list,
+						struct n_hdlc_buf, list_item);
+		if (buf)
+			count = buf->count;
 		else
 			count = 0;
 		spin_unlock_irqrestore(&n_hdlc->rx_buf_list.spinlock,flags);
@@ -778,8 +764,10 @@ static int n_hdlc_tty_ioctl(struct tty_s
 		count = tty_chars_in_buffer(tty);
 		/* add size of next output frame in queue */
 		spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock,flags);
-		if (n_hdlc->tx_buf_list.head)
-			count += n_hdlc->tx_buf_list.head->count;
+		buf = list_first_entry_or_null(&n_hdlc->tx_buf_list.list,
+						struct n_hdlc_buf, list_item);
+		if (buf)
+			count += buf->count;
 		spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock,flags);
 		error = put_user(count, (int __user *)arg);
 		break;
@@ -827,14 +815,14 @@ static unsigned int n_hdlc_tty_poll(stru
 		poll_wait(filp, &tty->write_wait, wait);
 
 		/* set bits for operations that won't block */
-		if (n_hdlc->rx_buf_list.head)
+		if (!list_empty(&n_hdlc->rx_buf_list.list))
 			mask |= POLLIN | POLLRDNORM;	/* readable */
 		if (test_bit(TTY_OTHER_CLOSED, &tty->flags))
 			mask |= POLLHUP;
 		if (tty_hung_up_p(filp))
 			mask |= POLLHUP;
 		if (!tty_is_writelocked(tty) &&
-				n_hdlc->tx_free_buf_list.head)
+				!list_empty(&n_hdlc->tx_free_buf_list.list))
 			mask |= POLLOUT | POLLWRNORM;	/* writable */
 	}
 	return mask;
@@ -856,11 +844,16 @@ static struct n_hdlc *n_hdlc_alloc(void)
 
 	memset(n_hdlc, 0, sizeof(*n_hdlc));
 
-	n_hdlc_buf_list_init(&n_hdlc->rx_free_buf_list);
-	n_hdlc_buf_list_init(&n_hdlc->tx_free_buf_list);
-	n_hdlc_buf_list_init(&n_hdlc->rx_buf_list);
-	n_hdlc_buf_list_init(&n_hdlc->tx_buf_list);
-	
+	spin_lock_init(&n_hdlc->rx_free_buf_list.spinlock);
+	spin_lock_init(&n_hdlc->tx_free_buf_list.spinlock);
+	spin_lock_init(&n_hdlc->rx_buf_list.spinlock);
+	spin_lock_init(&n_hdlc->tx_buf_list.spinlock);
+
+	INIT_LIST_HEAD(&n_hdlc->rx_free_buf_list.list);
+	INIT_LIST_HEAD(&n_hdlc->tx_free_buf_list.list);
+	INIT_LIST_HEAD(&n_hdlc->rx_buf_list.list);
+	INIT_LIST_HEAD(&n_hdlc->tx_buf_list.list);
+
 	/* allocate free rx buffer list */
 	for(i=0;i<DEFAULT_RX_BUF_COUNT;i++) {
 		buf = kmalloc(N_HDLC_BUF_SIZE, GFP_KERNEL);
@@ -888,63 +881,65 @@ static struct n_hdlc *n_hdlc_alloc(void)
 }	/* end of n_hdlc_alloc() */
 
 /**
- * n_hdlc_buf_list_init - initialize specified HDLC buffer list
- * @list - pointer to buffer list
+ * n_hdlc_buf_return - put the HDLC buffer after the head of the specified list
+ * @buf_list - pointer to the buffer list
+ * @buf - pointer to the buffer
  */
-static void n_hdlc_buf_list_init(struct n_hdlc_buf_list *list)
+static void n_hdlc_buf_return(struct n_hdlc_buf_list *buf_list,
+						struct n_hdlc_buf *buf)
 {
-	memset(list, 0, sizeof(*list));
-	spin_lock_init(&list->spinlock);
-}	/* end of n_hdlc_buf_list_init() */
+	unsigned long flags;
+
+	spin_lock_irqsave(&buf_list->spinlock, flags);
+
+	list_add(&buf->list_item, &buf_list->list);
+	buf_list->count++;
+
+	spin_unlock_irqrestore(&buf_list->spinlock, flags);
+}
 
 /**
  * n_hdlc_buf_put - add specified HDLC buffer to tail of specified list
- * @list - pointer to buffer list
+ * @buf_list - pointer to buffer list
  * @buf	- pointer to buffer
  */
-static void n_hdlc_buf_put(struct n_hdlc_buf_list *list,
+static void n_hdlc_buf_put(struct n_hdlc_buf_list *buf_list,
 			   struct n_hdlc_buf *buf)
 {
 	unsigned long flags;
-	spin_lock_irqsave(&list->spinlock,flags);
-	
-	buf->link=NULL;
-	if (list->tail)
-		list->tail->link = buf;
-	else
-		list->head = buf;
-	list->tail = buf;
-	(list->count)++;
-	
-	spin_unlock_irqrestore(&list->spinlock,flags);
-	
+
+	spin_lock_irqsave(&buf_list->spinlock, flags);
+
+	list_add_tail(&buf->list_item, &buf_list->list);
+	buf_list->count++;
+
+	spin_unlock_irqrestore(&buf_list->spinlock, flags);
 }	/* end of n_hdlc_buf_put() */
 
 /**
  * n_hdlc_buf_get - remove and return an HDLC buffer from list
- * @list - pointer to HDLC buffer list
+ * @buf_list - pointer to HDLC buffer list
  * 
  * Remove and return an HDLC buffer from the head of the specified HDLC buffer
  * list.
  * Returns a pointer to HDLC buffer if available, otherwise %NULL.
  */
-static struct n_hdlc_buf* n_hdlc_buf_get(struct n_hdlc_buf_list *list)
+static struct n_hdlc_buf *n_hdlc_buf_get(struct n_hdlc_buf_list *buf_list)
 {
 	unsigned long flags;
 	struct n_hdlc_buf *buf;
-	spin_lock_irqsave(&list->spinlock,flags);
-	
-	buf = list->head;
+
+	spin_lock_irqsave(&buf_list->spinlock, flags);
+
+	buf = list_first_entry_or_null(&buf_list->list,
+						struct n_hdlc_buf, list_item);
 	if (buf) {
-		list->head = buf->link;
-		(list->count)--;
+		list_del(&buf->list_item);
+		buf_list->count--;
 	}
-	if (!list->head)
-		list->tail = NULL;
-	
-	spin_unlock_irqrestore(&list->spinlock,flags);
+
+	spin_unlock_irqrestore(&buf_list->spinlock, flags);
 	return buf;
-	
 }	/* end of n_hdlc_buf_get() */
 
 static char hdlc_banner[] __initdata =
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/tty/sysrq.c linux-libre-3.2.87-gnu1/drivers/tty/sysrq.c
--- linux-libre-3.2.86-gnu1/drivers/tty/sysrq.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/tty/sysrq.c	2017-03-15 22:19:00.000000000 -0400
@@ -763,8 +763,8 @@ static const struct input_device_id sysr
 	{
 		.flags = INPUT_DEVICE_ID_MATCH_EVBIT |
 				INPUT_DEVICE_ID_MATCH_KEYBIT,
-		.evbit = { BIT_MASK(EV_KEY) },
-		.keybit = { BIT_MASK(KEY_LEFTALT) },
+		.evbit = { [BIT_WORD(EV_KEY)] = BIT_MASK(EV_KEY) },
+		.keybit = { [BIT_WORD(KEY_LEFTALT)] = BIT_MASK(KEY_LEFTALT) },
 	},
 	{ },
 };
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/usb/class/cdc-acm.c linux-libre-3.2.87-gnu1/drivers/usb/class/cdc-acm.c
--- linux-libre-3.2.86-gnu1/drivers/usb/class/cdc-acm.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/usb/class/cdc-acm.c	2017-03-15 22:19:00.000000000 -0400
@@ -1541,6 +1541,7 @@ static const struct usb_device_id acm_id
 	.driver_info = NO_UNION_NORMAL, /* has no union descriptor */
 	},
 	{ USB_DEVICE(0x2184, 0x001c) },	/* GW Instek AFG-2225 */
+	{ USB_DEVICE(0x2184, 0x0036) },	/* GW Instek AFG-125 */
 	{ USB_DEVICE(0x22b8, 0x6425), /* Motorola MOTOMAGX phones */
 	},
 	/* Motorola H24 HSPA module: */
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/usb/core/config.c linux-libre-3.2.87-gnu1/drivers/usb/core/config.c
--- linux-libre-3.2.86-gnu1/drivers/usb/core/config.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/usb/core/config.c	2017-03-15 22:19:00.000000000 -0400
@@ -207,6 +207,16 @@ static int usb_parse_endpoint(struct dev
 	if (ifp->desc.bNumEndpoints >= num_ep)
 		goto skip_to_next_endpoint_or_interface_descriptor;
 
+	/* Check for duplicate endpoint addresses */
+	for (i = 0; i < ifp->desc.bNumEndpoints; ++i) {
+		if (ifp->endpoint[i].desc.bEndpointAddress ==
+		    d->bEndpointAddress) {
+			dev_warn(ddev, "config %d interface %d altsetting %d has a duplicate endpoint with address 0x%X, skipping\n",
+			    cfgno, inum, asnum, d->bEndpointAddress);
+			goto skip_to_next_endpoint_or_interface_descriptor;
+		}
+	}
+
 	endpoint = &ifp->endpoint[ifp->desc.bNumEndpoints];
 	++ifp->desc.bNumEndpoints;
 
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/usb/core/quirks.c linux-libre-3.2.87-gnu1/drivers/usb/core/quirks.c
--- linux-libre-3.2.86-gnu1/drivers/usb/core/quirks.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/usb/core/quirks.c	2017-03-15 22:19:00.000000000 -0400
@@ -36,6 +36,10 @@ static const struct usb_device_id usb_qu
 	/* CBM - Flash disk */
 	{ USB_DEVICE(0x0204, 0x6025), .driver_info = USB_QUIRK_RESET_RESUME },
 
+	/* WORLDE easy key (easykey.25) MIDI controller  */
+	{ USB_DEVICE(0x0218, 0x0401), .driver_info =
+			USB_QUIRK_CONFIG_INTF_STRINGS },
+
 	/* HP 5300/5370C scanner */
 	{ USB_DEVICE(0x03f0, 0x0701), .driver_info =
 			USB_QUIRK_STRING_FETCH_255 },
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/usb/gadget/composite.c linux-libre-3.2.87-gnu1/drivers/usb/gadget/composite.c
--- linux-libre-3.2.86-gnu1/drivers/usb/gadget/composite.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/usb/gadget/composite.c	2017-03-15 22:19:00.000000000 -0400
@@ -156,7 +156,7 @@ int config_ep_by_speed(struct usb_gadget
 
 ep_found:
 	/* commit results */
-	_ep->maxpacket = usb_endpoint_maxp(chosen_desc);
+	_ep->maxpacket = usb_endpoint_maxp(chosen_desc) & 0x7ff;
 	_ep->desc = chosen_desc;
 	_ep->comp_desc = NULL;
 	_ep->maxburst = 0;
@@ -1126,9 +1126,7 @@ composite_setup(struct usb_gadget *gadge
 		value = min(w_length, (u16) 1);
 		break;
 
-	/* function drivers must handle get/set altsetting; if there's
-	 * no get() method, we know only altsetting zero works.
-	 */
+	/* function drivers must handle get/set altsetting */
 	case USB_REQ_SET_INTERFACE:
 		if (ctrl->bRequestType != USB_RECIP_INTERFACE)
 			goto unknown;
@@ -1137,7 +1135,13 @@ composite_setup(struct usb_gadget *gadge
 		f = cdev->config->interface[intf];
 		if (!f)
 			break;
-		if (w_value && !f->set_alt)
+
+		/*
+		 * If there's no get_alt() method, we know only altsetting zero
+		 * works. There is no need to check if set_alt() is not NULL
+		 * as we check this in usb_add_function().
+		 */
+		if (w_value && !f->get_alt)
 			break;
 		value = f->set_alt(f, w_index, w_value);
 		if (value == USB_GADGET_DELAYED_STATUS) {
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/usb/gadget/dummy_hcd.c linux-libre-3.2.87-gnu1/drivers/usb/gadget/dummy_hcd.c
--- linux-libre-3.2.86-gnu1/drivers/usb/gadget/dummy_hcd.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/usb/gadget/dummy_hcd.c	2017-03-15 22:19:00.000000000 -0400
@@ -261,7 +261,7 @@ static void nuke (struct dummy *dum, str
 static void
 stop_activity (struct dummy *dum)
 {
-	struct dummy_ep	*ep;
+	int i;
 
 	/* prevent any more requests */
 	dum->address = 0;
@@ -269,8 +269,8 @@ stop_activity (struct dummy *dum)
 	/* The timer is left running so that outstanding URBs can fail */
 
 	/* nuke any pending requests first, so driver i/o is quiesced */
-	list_for_each_entry (ep, &dum->gadget.ep_list, ep.ep_list)
-		nuke (dum, ep);
+	for (i = 0; i < DUMMY_ENDPOINTS; ++i)
+		nuke(dum, &dum->ep[i]);
 
 	/* driver now does any non-usb quiescing necessary */
 }
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/usb/gadget/inode.c linux-libre-3.2.87-gnu1/drivers/usb/gadget/inode.c
--- linux-libre-3.2.86-gnu1/drivers/usb/gadget/inode.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/usb/gadget/inode.c	2017-03-15 22:19:00.000000000 -0400
@@ -1196,7 +1196,7 @@ ep0_write (struct file *fd, const char _
 	/* data and/or status stage for control request */
 	} else if (dev->state == STATE_DEV_SETUP) {
 
-		/* IN DATA+STATUS caller makes len <= wLength */
+		len = min_t(size_t, len, dev->setup_wLength);
 		if (dev->setup_in) {
 			retval = setup_req (dev->gadget->ep0, dev->req, len);
 			if (retval == 0) {
@@ -1841,10 +1841,12 @@ static struct usb_gadget_driver probe_dr
  * such as configuration notifications.
  */
 
-static int is_valid_config (struct usb_config_descriptor *config)
+static int is_valid_config(struct usb_config_descriptor *config,
+		unsigned int total)
 {
 	return config->bDescriptorType == USB_DT_CONFIG
 		&& config->bLength == USB_DT_CONFIG_SIZE
+		&& total >= USB_DT_CONFIG_SIZE
 		&& config->bConfigurationValue != 0
 		&& (config->bmAttributes & USB_CONFIG_ATT_ONE) != 0
 		&& (config->bmAttributes & USB_CONFIG_ATT_WAKEUP) == 0;
@@ -1861,7 +1863,8 @@ dev_config (struct file *fd, const char
 	u32			tag;
 	char			*kbuf;
 
-	if (len < (USB_DT_CONFIG_SIZE + USB_DT_DEVICE_SIZE + 4))
+	if ((len < (USB_DT_CONFIG_SIZE + USB_DT_DEVICE_SIZE + 4)) ||
+	    (len > PAGE_SIZE * 4))
 		return -EINVAL;
 
 	/* we might need to change message format someday */
@@ -1885,7 +1888,8 @@ dev_config (struct file *fd, const char
 	/* full or low speed config */
 	dev->config = (void *) kbuf;
 	total = le16_to_cpu(dev->config->wTotalLength);
-	if (!is_valid_config (dev->config) || total >= length)
+	if (!is_valid_config(dev->config, total) ||
+			total > length - USB_DT_DEVICE_SIZE)
 		goto fail;
 	kbuf += total;
 	length -= total;
@@ -1894,10 +1898,13 @@ dev_config (struct file *fd, const char
 	if (kbuf [1] == USB_DT_CONFIG) {
 		dev->hs_config = (void *) kbuf;
 		total = le16_to_cpu(dev->hs_config->wTotalLength);
-		if (!is_valid_config (dev->hs_config) || total >= length)
+		if (!is_valid_config(dev->hs_config, total) ||
+				total > length - USB_DT_DEVICE_SIZE)
 			goto fail;
 		kbuf += total;
 		length -= total;
+	} else {
+		dev->hs_config = NULL;
 	}
 
 	/* could support multiple configs, using another encoding! */
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/usb/host/uhci-pci.c linux-libre-3.2.87-gnu1/drivers/usb/host/uhci-pci.c
--- linux-libre-3.2.86-gnu1/drivers/usb/host/uhci-pci.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/usb/host/uhci-pci.c	2017-03-15 22:19:00.000000000 -0400
@@ -129,6 +129,10 @@ static int uhci_pci_init(struct usb_hcd
 	if (to_pci_dev(uhci_dev(uhci))->vendor == PCI_VENDOR_ID_HP)
 		uhci->wait_for_hp = 1;
 
+	/* Intel controllers use non-PME wakeup signalling */
+	if (to_pci_dev(uhci_dev(uhci))->vendor == PCI_VENDOR_ID_INTEL)
+		device_set_run_wake(uhci_dev(uhci), 1);
+
 	/* Set up pointers to PCI-specific functions */
 	uhci->reset_hc = uhci_pci_reset_hc;
 	uhci->check_and_reset_hc = uhci_pci_check_and_reset_hc;
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/usb/host/xhci.c linux-libre-3.2.87-gnu1/drivers/usb/host/xhci.c
--- linux-libre-3.2.86-gnu1/drivers/usb/host/xhci.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/usb/host/xhci.c	2017-03-15 22:19:00.000000000 -0400
@@ -1549,18 +1549,6 @@ int xhci_urb_dequeue(struct usb_hcd *hcd
 		xhci_urb_free_priv(xhci, urb_priv);
 		return ret;
 	}
-	if ((xhci->xhc_state & XHCI_STATE_DYING) ||
-			(xhci->xhc_state & XHCI_STATE_HALTED)) {
-		xhci_dbg(xhci, "Ep 0x%x: URB %p to be canceled on "
-				"non-responsive xHCI host.\n",
-				urb->ep->desc.bEndpointAddress, urb);
-		/* Let the stop endpoint command watchdog timer (which set this
-		 * state) finish cleaning up the endpoint TD lists.  We must
-		 * have caught it in the middle of dropping a lock and giving
-		 * back an URB.
-		 */
-		goto done;
-	}
 
 	xhci_dbg(xhci, "Cancel URB %p\n", urb);
 	xhci_dbg(xhci, "Event ring:\n");
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/usb/host/xhci-mem.c linux-libre-3.2.87-gnu1/drivers/usb/host/xhci-mem.c
--- linux-libre-3.2.86-gnu1/drivers/usb/host/xhci-mem.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/usb/host/xhci-mem.c	2017-03-15 22:19:00.000000000 -0400
@@ -827,6 +827,40 @@ void xhci_free_virt_device(struct xhci_h
 	xhci->devs[slot_id] = NULL;
 }
 
+/*
+ * Free a virt_device structure.
+ * If the virt_device added a tt_info (a hub) and has children pointing to
+ * that tt_info, then free the child first. Recursive.
+ * We can't rely on udev at this point to find child-parent relationships.
+ */
+void xhci_free_virt_devices_depth_first(struct xhci_hcd *xhci, int slot_id)
+{
+	struct xhci_virt_device *vdev;
+	struct list_head *tt_list_head;
+	struct xhci_tt_bw_info *tt_info, *next;
+	int i;
+
+	vdev = xhci->devs[slot_id];
+	if (!vdev)
+		return;
+
+	tt_list_head = &(xhci->rh_bw[vdev->real_port - 1].tts);
+	list_for_each_entry_safe(tt_info, next, tt_list_head, tt_list) {
+		/* is this a hub device that added a tt_info to the tts list */
+		if (tt_info->slot_id == slot_id) {
+			/* are any devices using this tt_info? */
+			for (i = 1; i < HCS_MAX_SLOTS(xhci->hcs_params1); i++) {
+				vdev = xhci->devs[i];
+				if (vdev && (vdev->tt_info == tt_info))
+					xhci_free_virt_devices_depth_first(
+						xhci, i);
+			}
+		}
+	}
+	/* we are now at a leaf device */
+	xhci_free_virt_device(xhci, slot_id);
+}
+
 int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
 		struct usb_device *udev, gfp_t flags)
 {
@@ -1732,8 +1766,8 @@ void xhci_mem_cleanup(struct xhci_hcd *x
 		}
 	}
 
-	for (i = 1; i < MAX_HC_SLOTS; ++i)
-		xhci_free_virt_device(xhci, i);
+	for (i = HCS_MAX_SLOTS(xhci->hcs_params1); i > 0; i--)
+		xhci_free_virt_devices_depth_first(xhci, i);
 
 	if (xhci->segment_pool)
 		dma_pool_destroy(xhci->segment_pool);
@@ -2234,7 +2268,7 @@ int xhci_mem_init(struct xhci_hcd *xhci,
 	 * "physically contiguous and 64-byte (cache line) aligned".
 	 */
 	xhci->dcbaa = dma_alloc_coherent(dev, sizeof(*xhci->dcbaa), &dma,
-			GFP_KERNEL);
+			flags);
 	if (!xhci->dcbaa)
 		goto fail;
 	memset(xhci->dcbaa, 0, sizeof *(xhci->dcbaa));
@@ -2315,7 +2349,7 @@ int xhci_mem_init(struct xhci_hcd *xhci,
 
 	xhci->erst.entries = dma_alloc_coherent(dev,
 			sizeof(struct xhci_erst_entry) * ERST_NUM_SEGS, &dma,
-			GFP_KERNEL);
+			flags);
 	if (!xhci->erst.entries)
 		goto fail;
 	xhci_dbg(xhci, "// Allocated event ring segment table at 0x%llx\n",
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/usb/host/xhci-ring.c linux-libre-3.2.87-gnu1/drivers/usb/host/xhci-ring.c
--- linux-libre-3.2.86-gnu1/drivers/usb/host/xhci-ring.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/usb/host/xhci-ring.c	2017-03-15 22:19:00.000000000 -0400
@@ -969,12 +969,6 @@ void xhci_stop_endpoint_command_watchdog
 	spin_lock_irqsave(&xhci->lock, flags);
 
 	ep->stop_cmds_pending--;
-	if (xhci->xhc_state & XHCI_STATE_DYING) {
-		xhci_dbg(xhci, "Stop EP timer ran, but another timer marked "
-				"xHCI as DYING, exiting.\n");
-		spin_unlock_irqrestore(&xhci->lock, flags);
-		return;
-	}
 	if (!(ep->stop_cmds_pending == 0 && (ep->ep_state & EP_HALT_PENDING))) {
 		xhci_dbg(xhci, "Stop EP timer ran, but no command pending, "
 				"exiting.\n");
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/usb/musb/musbhsdma.h linux-libre-3.2.87-gnu1/drivers/usb/musb/musbhsdma.h
--- linux-libre-3.2.86-gnu1/drivers/usb/musb/musbhsdma.h	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/usb/musb/musbhsdma.h	2017-03-15 22:19:00.000000000 -0400
@@ -161,5 +161,5 @@ struct musb_dma_controller {
 	void __iomem			*base;
 	u8				channel_count;
 	u8				used_channels;
-	u8				irq;
+	int				irq;
 };
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/usb/serial/ch341.c linux-libre-3.2.87-gnu1/drivers/usb/serial/ch341.c
--- linux-libre-3.2.86-gnu1/drivers/usb/serial/ch341.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/usb/serial/ch341.c	2017-03-15 22:19:00.000000000 -0400
@@ -62,13 +62,26 @@
  * the Net/FreeBSD uchcom.c driver by Takanori Watanabe.  Domo arigato.
  */
 
+#define CH341_REQ_READ_VERSION 0x5F
 #define CH341_REQ_WRITE_REG    0x9A
 #define CH341_REQ_READ_REG     0x95
-#define CH341_REG_BREAK1       0x05
-#define CH341_REG_BREAK2       0x18
-#define CH341_NBREAK_BITS_REG1 0x01
-#define CH341_NBREAK_BITS_REG2 0x40
+#define CH341_REQ_SERIAL_INIT  0xA1
+#define CH341_REQ_MODEM_CTRL   0xA4
+
+#define CH341_REG_BREAK        0x05
+#define CH341_REG_LCR          0x18
+#define CH341_NBREAK_BITS      0x01
 
+#define CH341_LCR_ENABLE_RX    0x80
+#define CH341_LCR_ENABLE_TX    0x40
+#define CH341_LCR_MARK_SPACE   0x20
+#define CH341_LCR_PAR_EVEN     0x10
+#define CH341_LCR_ENABLE_PAR   0x08
+#define CH341_LCR_STOP_BITS_2  0x04
+#define CH341_LCR_CS8          0x03
+#define CH341_LCR_CS7          0x02
+#define CH341_LCR_CS6          0x01
+#define CH341_LCR_CS5          0x00
 
 static int debug;
 
@@ -88,6 +101,10 @@ struct ch341_private {
 	u8 multi_status_change; /* status changed multiple since last call */
 };
 
+static void ch341_set_termios(struct tty_struct *tty,
+			      struct usb_serial_port *port,
+			      struct ktermios *old_termios);
+
 static int ch341_control_out(struct usb_device *dev, u8 request,
 			     u16 value, u16 index)
 {
@@ -98,6 +115,8 @@ static int ch341_control_out(struct usb_
 	r = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), request,
 			    USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
 			    value, index, NULL, 0, DEFAULT_TIMEOUT);
+	if (r < 0)
+		dev_err(&dev->dev, "failed to send control message: %d\n", r);
 
 	return r;
 }
@@ -113,13 +132,26 @@ static int ch341_control_in(struct usb_d
 	r = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), request,
 			    USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
 			    value, index, buf, bufsize, DEFAULT_TIMEOUT);
-	return r;
+	if (r < bufsize) {
+		if (r >= 0) {
+			dev_err(&dev->dev,
+				"short control message received (%d < %u)\n",
+				r, bufsize);
+			r = -EIO;
+		}
+
+		dev_err(&dev->dev, "failed to receive control message: %d\n",
+			r);
+		return r;
+	}
+
+	return 0;
 }
 
-static int ch341_set_baudrate(struct usb_device *dev,
-			      struct ch341_private *priv)
+static int ch341_set_baudrate_lcr(struct usb_device *dev,
+				  struct ch341_private *priv, u8 lcr)
 {
-	short a, b;
+	short a;
 	int r;
 	unsigned long factor;
 	short divisor;
@@ -141,11 +173,20 @@ static int ch341_set_baudrate(struct usb
 
 	factor = 0x10000 - factor;
 	a = (factor & 0xff00) | divisor;
-	b = factor & 0xff;
 
-	r = ch341_control_out(dev, 0x9a, 0x1312, a);
-	if (!r)
-		r = ch341_control_out(dev, 0x9a, 0x0f2c, b);
+	/*
+	 * CH341A buffers data until a full endpoint-size packet (32 bytes)
+	 * has been received unless bit 7 is set.
+	 */
+	a |= BIT(7);
+
+	r = ch341_control_out(dev, CH341_REQ_WRITE_REG, 0x1312, a);
+	if (r)
+		return r;
+
+	r = ch341_control_out(dev, CH341_REQ_WRITE_REG, 0x2518, lcr);
+	if (r)
+		return r;
 
 	return r;
 }
@@ -153,14 +194,14 @@ static int ch341_set_baudrate(struct usb
 static int ch341_set_handshake(struct usb_device *dev, u8 control)
 {
 	dbg("ch341_set_handshake(0x%02x)", control);
-	return ch341_control_out(dev, 0xa4, ~control, 0);
+	return ch341_control_out(dev, CH341_REQ_MODEM_CTRL, ~control, 0);
 }
 
 static int ch341_get_status(struct usb_device *dev, struct ch341_private *priv)
 {
+	const unsigned int size = 2;
 	char *buffer;
 	int r;
-	const unsigned size = 8;
 	unsigned long flags;
 
 	dbg("ch341_get_status()");
@@ -169,19 +210,14 @@ static int ch341_get_status(struct usb_d
 	if (!buffer)
 		return -ENOMEM;
 
-	r = ch341_control_in(dev, 0x95, 0x0706, 0, buffer, size);
+	r = ch341_control_in(dev, CH341_REQ_READ_REG, 0x0706, 0, buffer, size);
 	if (r < 0)
 		goto out;
 
-	/* setup the private status if available */
-	if (r == 2) {
-		r = 0;
-		spin_lock_irqsave(&priv->lock, flags);
-		priv->line_status = (~(*buffer)) & CH341_BITS_MODEM_STAT;
-		priv->multi_status_change = 0;
-		spin_unlock_irqrestore(&priv->lock, flags);
-	} else
-		r = -EPROTO;
+	spin_lock_irqsave(&priv->lock, flags);
+	priv->line_status = (~(*buffer)) & CH341_BITS_MODEM_STAT;
+	priv->multi_status_change = 0;
+	spin_unlock_irqrestore(&priv->lock, flags);
 
 out:	kfree(buffer);
 	return r;
@@ -191,9 +227,9 @@ out:	kfree(buffer);
 
 static int ch341_configure(struct usb_device *dev, struct ch341_private *priv)
 {
+	const unsigned int size = 2;
 	char *buffer;
 	int r;
-	const unsigned size = 8;
 
 	dbg("ch341_configure()");
 
@@ -202,24 +238,20 @@ static int ch341_configure(struct usb_de
 		return -ENOMEM;
 
 	/* expect two bytes 0x27 0x00 */
-	r = ch341_control_in(dev, 0x5f, 0, 0, buffer, size);
-	if (r < 0)
-		goto out;
-
-	r = ch341_control_out(dev, 0xa1, 0, 0);
+	r = ch341_control_in(dev, CH341_REQ_READ_VERSION, 0, 0, buffer, size);
 	if (r < 0)
 		goto out;
 
-	r = ch341_set_baudrate(dev, priv);
+	r = ch341_control_out(dev, CH341_REQ_SERIAL_INIT, 0, 0);
 	if (r < 0)
 		goto out;
 
 	/* expect two bytes 0x56 0x00 */
-	r = ch341_control_in(dev, 0x95, 0x2518, 0, buffer, size);
+	r = ch341_control_in(dev, CH341_REQ_READ_REG, 0x2518, 0, buffer, size);
 	if (r < 0)
 		goto out;
 
-	r = ch341_control_out(dev, 0x9a, 0x2518, 0x0050);
+	r = ch341_control_out(dev, CH341_REQ_WRITE_REG, 0x2518, 0x0050);
 	if (r < 0)
 		goto out;
 
@@ -228,11 +260,7 @@ static int ch341_configure(struct usb_de
 	if (r < 0)
 		goto out;
 
-	r = ch341_control_out(dev, 0xa1, 0x501f, 0xd90a);
-	if (r < 0)
-		goto out;
-
-	r = ch341_set_baudrate(dev, priv);
+	r = ch341_set_baudrate_lcr(dev, priv, 0);
 	if (r < 0)
 		goto out;
 
@@ -262,7 +290,6 @@ static int ch341_attach(struct usb_seria
 
 	spin_lock_init(&priv->lock);
 	priv->baud_rate = DEFAULT_BAUD_RATE;
-	priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR;
 
 	r = ch341_configure(serial->dev, priv);
 	if (r < 0)
@@ -318,19 +345,12 @@ static int ch341_open(struct tty_struct
 
 	dbg("ch341_open()");
 
-	priv->baud_rate = DEFAULT_BAUD_RATE;
-
 	r = ch341_configure(serial->dev, priv);
 	if (r)
-		goto out;
-
-	r = ch341_set_handshake(serial->dev, priv->line_control);
-	if (r)
-		goto out;
+		return r;
 
-	r = ch341_set_baudrate(serial->dev, priv);
-	if (r)
-		goto out;
+	if (tty)
+		ch341_set_termios(tty, port, NULL);
 
 	dbg("%s - submitting interrupt urb", __func__);
 	port->interrupt_in_urb->dev = serial->dev;
@@ -338,13 +358,19 @@ static int ch341_open(struct tty_struct
 	if (r) {
 		dev_err(&port->dev, "%s - failed submitting interrupt urb,"
 			" error %d\n", __func__, r);
-		ch341_close(port);
-		return -EPROTO;
+		return r;
 	}
 
 	r = usb_serial_generic_open(tty, port);
+	if (r)
+		goto err_kill_interrupt_urb;
 
-out:	return r;
+	return 0;
+
+err_kill_interrupt_urb:
+	usb_kill_urb(port->interrupt_in_urb);
+
+	return r;
 }
 
 /* Old_termios contains the original termios settings and
@@ -356,25 +382,35 @@ static void ch341_set_termios(struct tty
 	struct ch341_private *priv = usb_get_serial_port_data(port);
 	unsigned baud_rate;
 	unsigned long flags;
+	unsigned char ctrl;
+	int r;
+
+	/* redundant changes may cause the chip to lose bytes */
+	if (old_termios && !tty_termios_hw_change(tty->termios, old_termios))
+		return;
 
 	dbg("ch341_set_termios()");
 
 	baud_rate = tty_get_baud_rate(tty);
 
-	priv->baud_rate = baud_rate;
+	ctrl = CH341_LCR_ENABLE_RX | CH341_LCR_ENABLE_TX | CH341_LCR_CS8;
 
 	if (baud_rate) {
-		spin_lock_irqsave(&priv->lock, flags);
-		priv->line_control |= (CH341_BIT_DTR | CH341_BIT_RTS);
-		spin_unlock_irqrestore(&priv->lock, flags);
-		ch341_set_baudrate(port->serial->dev, priv);
-	} else {
-		spin_lock_irqsave(&priv->lock, flags);
-		priv->line_control &= ~(CH341_BIT_DTR | CH341_BIT_RTS);
-		spin_unlock_irqrestore(&priv->lock, flags);
+		priv->baud_rate = baud_rate;
+
+		r = ch341_set_baudrate_lcr(port->serial->dev, priv, ctrl);
+		if (r < 0 && old_termios) {
+			priv->baud_rate = tty_termios_baud_rate(old_termios);
+			tty_termios_copy_hw(tty->termios, old_termios);
+		}
 	}
 
-	ch341_set_handshake(port->serial->dev, priv->line_control);
+	spin_lock_irqsave(&priv->lock, flags);
+	if (C_BAUD(tty) == B0)
+		priv->line_control &= ~(CH341_BIT_DTR | CH341_BIT_RTS);
+	else if (old_termios && (old_termios->c_cflag & CBAUD) == B0)
+		priv->line_control |= (CH341_BIT_DTR | CH341_BIT_RTS);
+	spin_unlock_irqrestore(&priv->lock, flags);
 
 	/* Unimplemented:
 	 * (cflag & CSIZE) : data bits [5, 8]
@@ -386,7 +422,7 @@ static void ch341_set_termios(struct tty
 static void ch341_break_ctl(struct tty_struct *tty, int break_state)
 {
 	const uint16_t ch341_break_reg =
-		CH341_REG_BREAK1 | ((uint16_t) CH341_REG_BREAK2 << 8);
+			((uint16_t) CH341_REG_LCR << 8) | CH341_REG_BREAK;
 	struct usb_serial_port *port = tty->driver_data;
 	int r;
 	uint16_t reg_contents;
@@ -411,12 +447,12 @@ static void ch341_break_ctl(struct tty_s
 			__func__, break_reg[0], break_reg[1]);
 	if (break_state != 0) {
 		dbg("%s - Enter break state requested", __func__);
-		break_reg[0] &= ~CH341_NBREAK_BITS_REG1;
-		break_reg[1] &= ~CH341_NBREAK_BITS_REG2;
+		break_reg[0] &= ~CH341_NBREAK_BITS;
+		break_reg[1] &= ~CH341_LCR_ENABLE_TX;
 	} else {
 		dbg("%s - Leave break state requested", __func__);
-		break_reg[0] |= CH341_NBREAK_BITS_REG1;
-		break_reg[1] |= CH341_NBREAK_BITS_REG2;
+		break_reg[0] |= CH341_NBREAK_BITS;
+		break_reg[1] |= CH341_LCR_ENABLE_TX;
 	}
 	dbg("%s - New ch341 break register contents - reg1: %x, reg2: %x",
 			__func__, break_reg[0], break_reg[1]);
@@ -605,18 +641,24 @@ static int ch341_tiocmget(struct tty_str
 static int ch341_reset_resume(struct usb_interface *intf)
 {
 	struct usb_device *dev = interface_to_usbdev(intf);
-	struct usb_serial *serial = NULL;
-	struct ch341_private *priv;
-
-	serial = usb_get_intfdata(intf);
-	priv = usb_get_serial_port_data(serial->port[0]);
+	struct usb_serial *serial = usb_get_intfdata(intf);
+	struct usb_serial_port *port = serial->port[0];
+	struct ch341_private *priv = usb_get_serial_port_data(port);
+	int ret;
 
 	/*reconfigure ch341 serial port after bus-reset*/
 	ch341_configure(dev, priv);
 
-	usb_serial_resume(intf);
+	if (port->port.flags & ASYNC_INITIALIZED) {
+		ret = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO);
+		if (ret) {
+			dev_err(&port->dev, "failed to submit interrupt urb: %d\n",
+				ret);
+			return ret;
+		}
+	}
 
-	return 0;
+	return usb_serial_generic_resume(serial);
 }
 
 static struct usb_driver ch341_driver = {
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/usb/serial/cyberjack.c linux-libre-3.2.87-gnu1/drivers/usb/serial/cyberjack.c
--- linux-libre-3.2.86-gnu1/drivers/usb/serial/cyberjack.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/usb/serial/cyberjack.c	2017-03-15 22:19:00.000000000 -0400
@@ -122,6 +122,9 @@ static int cyberjack_startup(struct usb_
 
 	dbg("%s", __func__);
 
+	if (serial->num_bulk_out < serial->num_ports)
+		return -ENODEV;
+
 	/* allocate the private data structure */
 	priv = kmalloc(sizeof(struct cyberjack_private), GFP_KERNEL);
 	if (!priv)
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/usb/serial/garmin_gps.c linux-libre-3.2.87-gnu1/drivers/usb/serial/garmin_gps.c
--- linux-libre-3.2.86-gnu1/drivers/usb/serial/garmin_gps.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/usb/serial/garmin_gps.c	2017-03-15 22:19:00.000000000 -0400
@@ -1075,6 +1075,7 @@ static int garmin_write_bulk(struct usb_
 		   "%s - usb_submit_urb(write bulk) failed with status = %d\n",
 				__func__, status);
 		count = status;
+		kfree(buffer);
 	}
 
 	/* we are done with this urb, so let the host driver
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/usb/serial/io_edgeport.c linux-libre-3.2.87-gnu1/drivers/usb/serial/io_edgeport.c
--- linux-libre-3.2.86-gnu1/drivers/usb/serial/io_edgeport.c	2017-02-27 03:32:34.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/usb/serial/io_edgeport.c	2017-03-16 12:13:37.000000000 -0400
@@ -2936,6 +2936,11 @@ static int edge_startup(struct usb_seria
 					EDGE_COMPATIBILITY_MASK1,
 					EDGE_COMPATIBILITY_MASK2 };
 
+	if (serial->num_bulk_in < 1 || serial->num_interrupt_in < 1) {
+		dev_err(&serial->interface->dev, "missing endpoints\n");
+		return -ENODEV;
+	}
+
 	dev = serial->dev;
 
 	/* create our private serial structure */
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/usb/serial/io_ti.c linux-libre-3.2.87-gnu1/drivers/usb/serial/io_ti.c
--- linux-libre-3.2.86-gnu1/drivers/usb/serial/io_ti.c	2017-02-27 03:32:40.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/usb/serial/io_ti.c	2017-03-16 12:13:43.000000000 -0400
@@ -1500,7 +1500,7 @@ stayinbootmode:
 	dbg("%s - STAYING IN BOOT MODE", __func__);
 	serial->product_info.TiMode = TI_MODE_BOOT;
 
-	return 0;
+	return 1;
 }
 
 
@@ -2642,6 +2642,13 @@ static int edge_startup(struct usb_seria
 
 	dev = serial->dev;
 
+	/* Make sure we have the required endpoints when in download mode. */
+	if (serial->interface->cur_altsetting->desc.bNumEndpoints > 1) {
+		if (serial->num_bulk_in < serial->num_ports ||
+				serial->num_bulk_out < serial->num_ports)
+			return -ENODEV;
+	}
+
 	/* create our private serial structure */
 	edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL);
 	if (edge_serial == NULL) {
@@ -2653,11 +2660,14 @@ static int edge_startup(struct usb_seria
 	usb_set_serial_data(serial, edge_serial);
 
 	status = download_fw(edge_serial);
-	if (status) {
+	if (status < 0) {
 		kfree(edge_serial);
 		return status;
 	}
 
+	if (status > 0)
+		return 1;	/* bind but do not register any ports */
+
 	/* set up our port private structures */
 	for (i = 0; i < serial->num_ports; ++i) {
 		edge_port = kzalloc(sizeof(struct edgeport_port), GFP_KERNEL);
@@ -2708,6 +2718,8 @@ static void edge_release(struct usb_seri
 
 	for (i = 0; i < serial->num_ports; ++i) {
 		edge_port = usb_get_serial_port_data(serial->port[i]);
+		if (!edge_port)
+			continue;
 		kfifo_free(&edge_port->write_fifo);
 		kfree(edge_port);
 	}
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/usb/serial/iuu_phoenix.c linux-libre-3.2.87-gnu1/drivers/usb/serial/iuu_phoenix.c
--- linux-libre-3.2.86-gnu1/drivers/usb/serial/iuu_phoenix.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/usb/serial/iuu_phoenix.c	2017-03-15 22:19:00.000000000 -0400
@@ -112,7 +112,12 @@ static int iuu_alloc_buf(struct iuu_priv
 
 static int iuu_startup(struct usb_serial *serial)
 {
+	unsigned char num_ports = serial->num_ports;
 	struct iuu_private *priv;
+
+	if (serial->num_bulk_in < num_ports || serial->num_bulk_out < num_ports)
+		return -ENODEV;
+
 	priv = kzalloc(sizeof(struct iuu_private), GFP_KERNEL);
 	dbg("%s- priv allocation success", __func__);
 	if (!priv)
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/usb/serial/keyspan_pda.c linux-libre-3.2.87-gnu1/drivers/usb/serial/keyspan_pda.c
--- linux-libre-3.2.86-gnu1/drivers/usb/serial/keyspan_pda.c	2017-02-27 03:32:22.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/usb/serial/keyspan_pda.c	2017-03-16 12:13:25.000000000 -0400
@@ -806,9 +806,15 @@ MODULE_FIRMWARE("keyspan_pda/xircom_pgs.
 
 static int keyspan_pda_startup(struct usb_serial *serial)
 {
-
+	unsigned char num_ports = serial->num_ports;
 	struct keyspan_pda_private *priv;
 
+	if (serial->num_bulk_out < num_ports ||
+			serial->num_interrupt_in < num_ports) {
+		dev_err(&serial->interface->dev, "missing endpoints\n");
+		return -ENODEV;
+	}
+
 	/* allocate the private data structures for all ports. Well, for all
 	   one ports. */
 
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/usb/serial/kl5kusb105.c linux-libre-3.2.87-gnu1/drivers/usb/serial/kl5kusb105.c
--- linux-libre-3.2.86-gnu1/drivers/usb/serial/kl5kusb105.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/usb/serial/kl5kusb105.c	2017-03-15 22:19:00.000000000 -0400
@@ -338,7 +338,7 @@ static int  klsi_105_open(struct tty_str
 	rc = usb_serial_generic_open(tty, port);
 	if (rc) {
 		retval = rc;
-		goto exit;
+		goto err_free_cfg;
 	}
 
 	rc = usb_control_msg(port->serial->dev,
@@ -353,21 +353,38 @@ static int  klsi_105_open(struct tty_str
 	if (rc < 0) {
 		dev_err(&port->dev, "Enabling read failed (error = %d)\n", rc);
 		retval = rc;
+		goto err_generic_close;
 	} else
 		dbg("%s - enabled reading", __func__);
 
 	rc = klsi_105_get_line_state(port, &line_state);
-	if (rc >= 0) {
-		spin_lock_irqsave(&priv->lock, flags);
-		priv->line_state = line_state;
-		spin_unlock_irqrestore(&priv->lock, flags);
-		dbg("%s - read line state 0x%lx", __func__, line_state);
-		retval = 0;
-	} else
+	if (rc < 0) {
 		retval = rc;
+		goto err_disable_read;
+	}
 
-exit:
+	spin_lock_irqsave(&priv->lock, flags);
+	priv->line_state = line_state;
+	spin_unlock_irqrestore(&priv->lock, flags);
+	dev_dbg(&port->dev, "%s - read line state 0x%lx\n", __func__,
+			line_state);
+
+	return 0;
+
+err_disable_read:
+	usb_control_msg(port->serial->dev,
+			     usb_sndctrlpipe(port->serial->dev, 0),
+			     KL5KUSB105A_SIO_CONFIGURE,
+			     USB_TYPE_VENDOR | USB_DIR_OUT,
+			     KL5KUSB105A_SIO_CONFIGURE_READ_OFF,
+			     0, /* index */
+			     NULL, 0,
+			     KLSI_TIMEOUT);
+err_generic_close:
+	usb_serial_generic_close(port);
+err_free_cfg:
 	kfree(cfg);
+
 	return retval;
 }
 
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/usb/serial/kobil_sct.c linux-libre-3.2.87-gnu1/drivers/usb/serial/kobil_sct.c
--- linux-libre-3.2.86-gnu1/drivers/usb/serial/kobil_sct.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/usb/serial/kobil_sct.c	2017-03-15 22:19:00.000000000 -0400
@@ -150,6 +150,11 @@ static int kobil_startup(struct usb_seri
 	struct usb_host_interface *altsetting;
 	struct usb_host_endpoint *endpoint;
 
+	if (serial->num_interrupt_out < serial->num_ports) {
+		dev_err(&serial->interface->dev, "missing interrupt-out endpoint\n");
+		return -ENODEV;
+	}
+
 	priv = kmalloc(sizeof(struct kobil_private), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/usb/serial/mos7720.c linux-libre-3.2.87-gnu1/drivers/usb/serial/mos7720.c
--- linux-libre-3.2.86-gnu1/drivers/usb/serial/mos7720.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/usb/serial/mos7720.c	2017-03-15 22:19:00.000000000 -0400
@@ -73,8 +73,6 @@ struct moschip_port {
 
 static int debug;
 
-static struct usb_serial_driver moschip7720_2port_driver;
-
 #define USB_VENDOR_ID_MOSCHIP		0x9710
 #define MOSCHIP_DEVICE_ID_7720		0x7720
 #define MOSCHIP_DEVICE_ID_7715		0x7715
@@ -1001,25 +999,6 @@ static void mos7720_bulk_out_data_callba
 	tty_kref_put(tty);
 }
 
-/*
- * mos77xx_probe
- *	this function installs the appropriate read interrupt endpoint callback
- *	depending on whether the device is a 7720 or 7715, thus avoiding costly
- *	run-time checks in the high-frequency callback routine itself.
- */
-static int mos77xx_probe(struct usb_serial *serial,
-			 const struct usb_device_id *id)
-{
-	if (id->idProduct == MOSCHIP_DEVICE_ID_7715)
-		moschip7720_2port_driver.read_int_callback =
-			mos7715_interrupt_callback;
-	else
-		moschip7720_2port_driver.read_int_callback =
-			mos7720_interrupt_callback;
-
-	return 0;
-}
-
 static int mos77xx_calc_num_ports(struct usb_serial *serial)
 {
 	u16 product = le16_to_cpu(serial->dev->descriptor.idProduct);
@@ -2079,6 +2058,11 @@ static int mos7720_startup(struct usb_se
 		return -ENODEV;
 	}
 
+	if (serial->num_bulk_in < 2 || serial->num_bulk_out < 2) {
+		dev_err(&serial->interface->dev, "missing bulk endpoints\n");
+		return -ENODEV;
+	}
+
 	product = le16_to_cpu(serial->dev->descriptor.idProduct);
 	dev = serial->dev;
 
@@ -2103,6 +2087,12 @@ static int mos7720_startup(struct usb_se
 			tmp->interrupt_in_endpointAddress;
 		serial->port[1]->interrupt_in_urb = NULL;
 		serial->port[1]->interrupt_in_buffer = NULL;
+
+		if (serial->port[0]->interrupt_in_urb) {
+			struct urb *urb = serial->port[0]->interrupt_in_urb;
+
+			urb->complete = mos7715_interrupt_callback;
+		}
 	}
 
 
@@ -2132,13 +2122,6 @@ static int mos7720_startup(struct usb_se
 	usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
 			(__u8)0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5000);
 
-	/* start the interrupt urb */
-	ret_val = usb_submit_urb(serial->port[0]->interrupt_in_urb, GFP_KERNEL);
-	if (ret_val)
-		dev_err(&dev->dev,
-			"%s - Error %d submitting control urb\n",
-			__func__, ret_val);
-
 #ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT
 	if (product == MOSCHIP_DEVICE_ID_7715) {
 		ret_val = mos7715_parport_init(serial);
@@ -2146,6 +2129,13 @@ static int mos7720_startup(struct usb_se
 			return ret_val;
 	}
 #endif
+	/* start the interrupt urb */
+	ret_val = usb_submit_urb(serial->port[0]->interrupt_in_urb, GFP_KERNEL);
+	if (ret_val) {
+		dev_err(&dev->dev, "failed to submit interrupt urb: %d\n",
+			ret_val);
+	}
+
 	/* LSR For Port 1 */
 	read_mos_reg(serial, 0, LSR, &data);
 	dbg("LSR:%x", data);
@@ -2157,6 +2147,8 @@ static void mos7720_release(struct usb_s
 {
 	int i;
 
+	usb_kill_urb(serial->port[0]->interrupt_in_urb);
+
 #ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT
 	/* close the parallel port */
 
@@ -2221,7 +2213,6 @@ static struct usb_serial_driver moschip7
 	.close			= mos7720_close,
 	.throttle		= mos7720_throttle,
 	.unthrottle		= mos7720_unthrottle,
-	.probe			= mos77xx_probe,
 	.attach			= mos7720_startup,
 	.release		= mos7720_release,
 	.ioctl			= mos7720_ioctl,
@@ -2234,7 +2225,7 @@ static struct usb_serial_driver moschip7
 	.chars_in_buffer	= mos7720_chars_in_buffer,
 	.break_ctl		= mos7720_break,
 	.read_bulk_callback	= mos7720_bulk_in_callback,
-	.read_int_callback	= NULL  /* dynamically assigned in probe() */
+	.read_int_callback	= mos7720_interrupt_callback,
 };
 
 static int __init moschip7720_init(void)
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/usb/serial/mos7840.c linux-libre-3.2.87-gnu1/drivers/usb/serial/mos7840.c
--- linux-libre-3.2.86-gnu1/drivers/usb/serial/mos7840.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/usb/serial/mos7840.c	2017-03-15 22:19:00.000000000 -0400
@@ -1071,9 +1071,7 @@ static int mos7840_open(struct tty_struc
 				serial,
 				serial->port[0]->interrupt_in_urb->interval);
 
-			/* start interrupt read for mos7840               *
-			 * will continue as long as mos7840 is connected  */
-
+			/* start interrupt read for mos7840 */
 			response =
 			    usb_submit_urb(serial->port[0]->interrupt_in_urb,
 					   GFP_KERNEL);
@@ -2386,6 +2384,12 @@ static int mos7840_startup(struct usb_se
 		return -1;
 	}
 
+	if (serial->num_bulk_in < serial->num_ports ||
+			serial->num_bulk_out < serial->num_ports) {
+		dev_err(&serial->interface->dev, "missing endpoints\n");
+		return -ENODEV;
+	}
+
 	dev = serial->dev;
 
 	dbg("%s", "Entering...");
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/usb/serial/omninet.c linux-libre-3.2.87-gnu1/drivers/usb/serial/omninet.c
--- linux-libre-3.2.86-gnu1/drivers/usb/serial/omninet.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/usb/serial/omninet.c	2017-03-15 22:19:00.000000000 -0400
@@ -152,6 +152,12 @@ static int omninet_attach(struct usb_ser
 	struct omninet_data *od;
 	struct usb_serial_port *port = serial->port[0];
 
+	/* The second bulk-out endpoint is used for writing. */
+	if (serial->num_bulk_out < 2) {
+		dev_err(&serial->interface->dev, "missing endpoints\n");
+		return -ENODEV;
+	}
+
 	od = kmalloc(sizeof(struct omninet_data), GFP_KERNEL);
 	if (!od) {
 		dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n",
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/usb/serial/option.c linux-libre-3.2.87-gnu1/drivers/usb/serial/option.c
--- linux-libre-3.2.86-gnu1/drivers/usb/serial/option.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/usb/serial/option.c	2017-03-15 22:19:00.000000000 -0400
@@ -269,6 +269,8 @@ static void option_instat_callback(struc
 #define TELIT_PRODUCT_CC864_SINGLE		0x1006
 #define TELIT_PRODUCT_DE910_DUAL		0x1010
 #define TELIT_PRODUCT_UE910_V2			0x1012
+#define TELIT_PRODUCT_LE922_USBCFG1		0x1040
+#define TELIT_PRODUCT_LE922_USBCFG2		0x1041
 #define TELIT_PRODUCT_LE922_USBCFG0		0x1042
 #define TELIT_PRODUCT_LE922_USBCFG3		0x1043
 #define TELIT_PRODUCT_LE920			0x1200
@@ -1196,6 +1198,10 @@ static const struct usb_device_id option
 	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UE910_V2) },
 	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG0),
 		.driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg0 },
+	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG1),
+		.driver_info = (kernel_ulong_t)&telit_le910_blacklist },
+	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG2),
+		.driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg3 },
 	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG3),
 		.driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg3 },
 	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910),
@@ -1957,6 +1963,7 @@ static const struct usb_device_id option
 	{ USB_DEVICE_AND_INTERFACE_INFO(WETELECOM_VENDOR_ID, WETELECOM_PRODUCT_WMD200, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(WETELECOM_VENDOR_ID, WETELECOM_PRODUCT_6802, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(WETELECOM_VENDOR_ID, WETELECOM_PRODUCT_WMD300, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(0x03f0, 0x421d, 0xff, 0xff, 0xff) }, /* HP lt2523 (Novatel E371) */
 	{ } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/usb/serial/oti6858.c linux-libre-3.2.87-gnu1/drivers/usb/serial/oti6858.c
--- linux-libre-3.2.86-gnu1/drivers/usb/serial/oti6858.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/usb/serial/oti6858.c	2017-03-15 22:19:00.000000000 -0400
@@ -347,9 +347,17 @@ static void send_data(struct work_struct
 static int oti6858_startup(struct usb_serial *serial)
 {
 	struct usb_serial_port *port = serial->port[0];
+	unsigned char num_ports = serial->num_ports;
 	struct oti6858_private *priv;
 	int i;
 
+	if (serial->num_bulk_in < num_ports ||
+			serial->num_bulk_out < num_ports ||
+			serial->num_interrupt_in < num_ports) {
+		dev_err(&serial->interface->dev, "missing endpoints\n");
+		return -ENODEV;
+	}
+
 	for (i = 0; i < serial->num_ports; ++i) {
 		priv = kzalloc(sizeof(struct oti6858_private), GFP_KERNEL);
 		if (!priv)
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/usb/serial/pl2303.c linux-libre-3.2.87-gnu1/drivers/usb/serial/pl2303.c
--- linux-libre-3.2.86-gnu1/drivers/usb/serial/pl2303.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/usb/serial/pl2303.c	2017-03-15 22:19:00.000000000 -0400
@@ -55,6 +55,7 @@ static const struct usb_device_id id_tab
 	{ USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) },
 	{ USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) },
 	{ USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) },
+	{ USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID2) },
 	{ USB_DEVICE(ATEN_VENDOR_ID2, ATEN_PRODUCT_ID) },
 	{ USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID) },
 	{ USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID_UCSGT) },
@@ -185,10 +186,18 @@ static int pl2303_vendor_write(__u16 val
 static int pl2303_startup(struct usb_serial *serial)
 {
 	struct pl2303_private *priv;
+	unsigned char num_ports = serial->num_ports;
 	enum pl2303_type type = type_0;
 	unsigned char *buf;
 	int i;
 
+	if (serial->num_bulk_in < num_ports ||
+			serial->num_bulk_out < num_ports ||
+			serial->num_interrupt_in < num_ports) {
+		dev_err(&serial->interface->dev, "missing endpoints\n");
+		return -ENODEV;
+	}
+
 	buf = kmalloc(10, GFP_KERNEL);
 	if (buf == NULL)
 		return -ENOMEM;
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/usb/serial/pl2303.h linux-libre-3.2.87-gnu1/drivers/usb/serial/pl2303.h
--- linux-libre-3.2.86-gnu1/drivers/usb/serial/pl2303.h	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/usb/serial/pl2303.h	2017-03-15 22:19:00.000000000 -0400
@@ -27,6 +27,7 @@
 #define ATEN_VENDOR_ID		0x0557
 #define ATEN_VENDOR_ID2		0x0547
 #define ATEN_PRODUCT_ID		0x2008
+#define ATEN_PRODUCT_ID2	0x2118
 
 #define IODATA_VENDOR_ID	0x04bb
 #define IODATA_PRODUCT_ID	0x0a03
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/usb/serial/spcp8x5.c linux-libre-3.2.87-gnu1/drivers/usb/serial/spcp8x5.c
--- linux-libre-3.2.86-gnu1/drivers/usb/serial/spcp8x5.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/usb/serial/spcp8x5.c	2017-03-15 22:19:00.000000000 -0400
@@ -176,6 +176,13 @@ static int spcp8x5_startup(struct usb_se
 	int i;
 	enum spcp8x5_type type = SPCP825_007_TYPE;
 	u16 product = le16_to_cpu(serial->dev->descriptor.idProduct);
+	unsigned char num_ports = serial->num_ports;
+
+	if (serial->num_bulk_in < num_ports ||
+			serial->num_bulk_out < num_ports) {
+		dev_err(&serial->interface->dev, "missing endpoints\n");
+		return -ENODEV;
+	}
 
 	if (product == 0x0201)
 		type = SPCP825_007_TYPE;
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/drivers/usb/serial/ti_usb_3410_5052.c linux-libre-3.2.87-gnu1/drivers/usb/serial/ti_usb_3410_5052.c
--- linux-libre-3.2.86-gnu1/drivers/usb/serial/ti_usb_3410_5052.c	2017-02-27 03:32:43.000000000 -0500
+++ linux-libre-3.2.87-gnu1/drivers/usb/serial/ti_usb_3410_5052.c	2017-03-16 12:13:46.000000000 -0400
@@ -432,6 +432,13 @@ static int ti_startup(struct usb_serial
 		goto free_tdev;
 	}
 
+	if (serial->num_bulk_in < serial->num_ports ||
+			serial->num_bulk_out < serial->num_ports) {
+		dev_err(&serial->interface->dev, "missing endpoints\n");
+		status = -ENODEV;
+		goto free_tdev;
+	}
+
 	/* set up port structures */
 	for (i = 0; i < serial->num_ports; ++i) {
 		tport = kzalloc(sizeof(struct ti_port), GFP_KERNEL);
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/fs/block_dev.c linux-libre-3.2.87-gnu1/fs/block_dev.c
--- linux-libre-3.2.86-gnu1/fs/block_dev.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/fs/block_dev.c	2017-03-15 22:19:00.000000000 -0400
@@ -687,7 +687,7 @@ static bool bd_may_claim(struct block_de
 		return true;	 /* already a holder */
 	else if (bdev->bd_holder != NULL)
 		return false; 	 /* held by someone else */
-	else if (bdev->bd_contains == bdev)
+	else if (whole == bdev)
 		return true;  	 /* is a whole device which isn't held */
 
 	else if (whole->bd_holder == bd_may_claim)
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/fs/btrfs/ioctl.c linux-libre-3.2.87-gnu1/fs/btrfs/ioctl.c
--- linux-libre-3.2.86-gnu1/fs/btrfs/ioctl.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/fs/btrfs/ioctl.c	2017-03-15 22:19:00.000000000 -0400
@@ -3276,6 +3276,10 @@ long btrfs_ioctl(struct file *file, unsi
 #ifdef CONFIG_COMPAT
 long btrfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
+	/*
+	 * These all access 32-bit values anyway so no further
+	 * handling is necessary.
+	 */
 	switch (cmd) {
 	case FS_IOC32_GETFLAGS:
 		cmd = FS_IOC_GETFLAGS;
@@ -3286,8 +3290,6 @@ long btrfs_compat_ioctl(struct file *fil
 	case FS_IOC32_GETVERSION:
 		cmd = FS_IOC_GETVERSION;
 		break;
-	default:
-		return -ENOIOCTLCMD;
 	}
 
 	return btrfs_ioctl(file, cmd, (unsigned long) compat_ptr(arg));
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/fs/btrfs/tree-log.c linux-libre-3.2.87-gnu1/fs/btrfs/tree-log.c
--- linux-libre-3.2.86-gnu1/fs/btrfs/tree-log.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/fs/btrfs/tree-log.c	2017-03-15 22:19:00.000000000 -0400
@@ -1415,12 +1415,11 @@ static noinline int find_dir_range(struc
 next:
 	/* check the next slot in the tree to see if it is a valid item */
 	nritems = btrfs_header_nritems(path->nodes[0]);
+	path->slots[0]++;
 	if (path->slots[0] >= nritems) {
 		ret = btrfs_next_leaf(root, path);
 		if (ret)
 			goto out;
-	} else {
-		path->slots[0]++;
 	}
 
 	btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/fs/ceph/mds_client.c linux-libre-3.2.87-gnu1/fs/ceph/mds_client.c
--- linux-libre-3.2.86-gnu1/fs/ceph/mds_client.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/fs/ceph/mds_client.c	2017-03-15 22:19:00.000000000 -0400
@@ -238,7 +238,9 @@ static int parse_reply_info_extra(void *
 				  struct ceph_mds_reply_info_parsed *info,
 				  int features)
 {
-	if (info->head->op == CEPH_MDS_OP_GETFILELOCK)
+	u32 op = le32_to_cpu(info->head->op);
+
+	if (op == CEPH_MDS_OP_GETFILELOCK)
 		return parse_reply_info_filelock(p, end, info, features);
 	else
 		return parse_reply_info_dir(p, end, info, features);
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/fs/ext4/inode.c linux-libre-3.2.87-gnu1/fs/ext4/inode.c
--- linux-libre-3.2.86-gnu1/fs/ext4/inode.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/fs/ext4/inode.c	2017-03-15 22:19:00.000000000 -0400
@@ -3829,6 +3829,7 @@ struct inode *ext4_iget(struct super_blo
 	struct inode *inode;
 	journal_t *journal = EXT4_SB(sb)->s_journal;
 	long ret;
+	loff_t size;
 	int block;
 
 	inode = iget_locked(sb, ino);
@@ -3880,6 +3881,11 @@ struct inode *ext4_iget(struct super_blo
 		ei->i_file_acl |=
 			((__u64)le16_to_cpu(raw_inode->i_file_acl_high)) << 32;
 	inode->i_size = ext4_isize(raw_inode);
+	if ((size = i_size_read(inode)) < 0) {
+		EXT4_ERROR_INODE(inode, "bad i_size value: %lld", size);
+		ret = -EIO;
+		goto bad_inode;
+	}
 	ei->i_disksize = inode->i_size;
 #ifdef CONFIG_QUOTA
 	ei->i_reserved_quota = 0;
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/fs/ext4/mballoc.c linux-libre-3.2.87-gnu1/fs/ext4/mballoc.c
--- linux-libre-3.2.86-gnu1/fs/ext4/mballoc.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/fs/ext4/mballoc.c	2017-03-15 22:19:00.000000000 -0400
@@ -652,7 +652,7 @@ static void ext4_mb_mark_free_simple(str
 	ext4_grpblk_t min;
 	ext4_grpblk_t max;
 	ext4_grpblk_t chunk;
-	unsigned short border;
+	unsigned int border;
 
 	BUG_ON(len > EXT4_CLUSTERS_PER_GROUP(sb));
 
@@ -2134,7 +2134,7 @@ static int ext4_mb_seq_groups_show(struc
 	struct ext4_buddy e4b;
 	struct sg {
 		struct ext4_group_info info;
-		ext4_grpblk_t counters[16];
+		ext4_grpblk_t counters[EXT4_MAX_BLOCK_LOG_SIZE + 2];
 	} sg;
 
 	group--;
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/fs/ext4/super.c linux-libre-3.2.87-gnu1/fs/ext4/super.c
--- linux-libre-3.2.86-gnu1/fs/ext4/super.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/fs/ext4/super.c	2017-03-15 22:19:00.000000000 -0400
@@ -3180,10 +3180,15 @@ static int count_overhead(struct super_b
 			ext4_set_bit(s++, buf);
 			count++;
 		}
-		for (j = ext4_bg_num_gdb(sb, grp); j > 0; j--) {
-			ext4_set_bit(EXT4_B2C(sbi, s++), buf);
-			count++;
+		j = ext4_bg_num_gdb(sb, grp);
+		if (s + j > EXT4_BLOCKS_PER_GROUP(sb)) {
+			ext4_error(sb, "Invalid number of block group "
+				   "descriptor blocks: %d", j);
+			j = EXT4_BLOCKS_PER_GROUP(sb) - s;
 		}
+		count += j;
+		for (; j > 0; j--)
+			ext4_set_bit(EXT4_B2C(sbi, s++), buf);
 	}
 	if (!count)
 		return 0;
@@ -3240,7 +3245,7 @@ static int ext4_fill_super(struct super_
 	char *orig_data = kstrdup(data, GFP_KERNEL);
 	struct buffer_head *bh;
 	struct ext4_super_block *es = NULL;
-	struct ext4_sb_info *sbi;
+	struct ext4_sb_info *sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
 	ext4_fsblk_t block;
 	ext4_fsblk_t sb_block = get_sb_block(&data);
 	ext4_fsblk_t logical_sb_block;
@@ -3260,16 +3265,14 @@ static int ext4_fill_super(struct super_
 	unsigned int journal_ioprio = DEFAULT_JOURNAL_IOPRIO;
 	ext4_group_t first_not_zeroed;
 
-	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
-	if (!sbi)
-		goto out_free_orig;
+	if ((data && !orig_data) || !sbi)
+		goto out_free_base;
 
 	sbi->s_blockgroup_lock =
 		kzalloc(sizeof(struct blockgroup_lock), GFP_KERNEL);
-	if (!sbi->s_blockgroup_lock) {
-		kfree(sbi);
-		goto out_free_orig;
-	}
+	if (!sbi->s_blockgroup_lock)
+		goto out_free_base;
+
 	sb->s_fs_info = sbi;
 	sbi->s_mount_opt = 0;
 	sbi->s_resuid = EXT4_DEF_RESUID;
@@ -3378,11 +3381,19 @@ static int ext4_fill_super(struct super_
 	 */
 	sbi->s_li_wait_mult = EXT4_DEF_LI_WAIT_MULT;
 
-	if (!parse_options((char *) sbi->s_es->s_mount_opts, sb,
-			   &journal_devnum, &journal_ioprio, NULL, 0)) {
-		ext4_msg(sb, KERN_WARNING,
-			 "failed to parse options in superblock: %s",
-			 sbi->s_es->s_mount_opts);
+	if (sbi->s_es->s_mount_opts[0]) {
+		char *s_mount_opts = kstrndup(sbi->s_es->s_mount_opts,
+					      sizeof(sbi->s_es->s_mount_opts),
+					      GFP_KERNEL);
+		if (!s_mount_opts)
+			goto failed_mount;
+		if (!parse_options(s_mount_opts, sb, &journal_devnum,
+				   &journal_ioprio, NULL, 0)) {
+			ext4_msg(sb, KERN_WARNING,
+				 "failed to parse options in superblock: %s",
+				 s_mount_opts);
+		}
+		kfree(s_mount_opts);
 	}
 	if (!parse_options((char *) data, sb, &journal_devnum,
 			   &journal_ioprio, NULL, 0))
@@ -3535,12 +3546,16 @@ static int ext4_fill_super(struct super_
 
 	sbi->s_blocks_per_group = le32_to_cpu(es->s_blocks_per_group);
 	sbi->s_inodes_per_group = le32_to_cpu(es->s_inodes_per_group);
-	if (EXT4_INODE_SIZE(sb) == 0 || EXT4_INODES_PER_GROUP(sb) == 0)
-		goto cantfind_ext4;
 
 	sbi->s_inodes_per_block = blocksize / EXT4_INODE_SIZE(sb);
 	if (sbi->s_inodes_per_block == 0)
 		goto cantfind_ext4;
+	if (sbi->s_inodes_per_group < sbi->s_inodes_per_block ||
+	    sbi->s_inodes_per_group > blocksize * 8) {
+		ext4_msg(sb, KERN_ERR, "invalid inodes per group: %lu\n",
+			 sbi->s_blocks_per_group);
+		goto failed_mount;
+	}
 	sbi->s_itb_per_group = sbi->s_inodes_per_group /
 					sbi->s_inodes_per_block;
 	sbi->s_desc_per_block = blocksize / EXT4_DESC_SIZE(sb);
@@ -3619,13 +3634,6 @@ static int ext4_fill_super(struct super_
 	}
 	sbi->s_cluster_ratio = clustersize / blocksize;
 
-	if (sbi->s_inodes_per_group > blocksize * 8) {
-		ext4_msg(sb, KERN_ERR,
-		       "#inodes per group too big: %lu",
-		       sbi->s_inodes_per_group);
-		goto failed_mount;
-	}
-
 	/*
 	 * Test whether we have more sectors than will fit in sector_t,
 	 * and whether the max offset is addressable by the page cache.
@@ -3978,7 +3986,9 @@ no_journal:
 		descr = "out journal";
 
 	ext4_msg(sb, KERN_INFO, "mounted filesystem with%s. "
-		 "Opts: %s%s%s", descr, sbi->s_es->s_mount_opts,
+		 "Opts: %.*s%s%s", descr,
+		 (int) sizeof(sbi->s_es->s_mount_opts),
+		 sbi->s_es->s_mount_opts,
 		 *sbi->s_es->s_mount_opts ? "; " : "", orig_data);
 
 	if (es->s_error_count)
@@ -4036,8 +4046,8 @@ failed_mount:
 out_fail:
 	sb->s_fs_info = NULL;
 	kfree(sbi->s_blockgroup_lock);
+out_free_base:
 	kfree(sbi);
-out_free_orig:
 	kfree(orig_data);
 	return ret;
 }
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/fs/nfs/file.c linux-libre-3.2.87-gnu1/fs/nfs/file.c
--- linux-libre-3.2.86-gnu1/fs/nfs/file.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/fs/nfs/file.c	2017-03-15 22:19:00.000000000 -0400
@@ -397,7 +397,7 @@ static int nfs_write_end(struct file *fi
 	 */
 	if (!PageUptodate(page)) {
 		unsigned pglen = nfs_page_length(page);
-		unsigned end = offset + len;
+		unsigned end = offset + copied;
 
 		if (pglen == 0) {
 			zero_user_segments(page, 0, offset,
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/fs/notify/inode_mark.c linux-libre-3.2.87-gnu1/fs/notify/inode_mark.c
--- linux-libre-3.2.86-gnu1/fs/notify/inode_mark.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/fs/notify/inode_mark.c	2017-03-15 22:19:00.000000000 -0400
@@ -243,12 +243,10 @@ out:
  */
 void fsnotify_unmount_inodes(struct list_head *list)
 {
-	struct inode *inode, *next_i, *need_iput = NULL;
+	struct inode *inode, *iput_inode = NULL;
 
 	spin_lock(&inode_sb_list_lock);
-	list_for_each_entry_safe(inode, next_i, list, i_sb_list) {
-		struct inode *need_iput_tmp;
-
+	list_for_each_entry(inode, list, i_sb_list) {
 		/*
 		 * We cannot __iget() an inode in state I_FREEING,
 		 * I_WILL_FREE, or I_NEW which is fine because by that point
@@ -271,50 +269,24 @@ void fsnotify_unmount_inodes(struct list
 			continue;
 		}
 
-		need_iput_tmp = need_iput;
-		need_iput = NULL;
-
-		/* In case fsnotify_inode_delete() drops a reference. */
-		if (inode != need_iput_tmp)
-			__iget(inode);
-		else
-			need_iput_tmp = NULL;
+		__iget(inode);
 		spin_unlock(&inode->i_lock);
-
-		/* In case the dropping of a reference would nuke next_i. */
-		while (&next_i->i_sb_list != list) {
-			spin_lock(&next_i->i_lock);
-			if (!(next_i->i_state & (I_FREEING | I_WILL_FREE)) &&
-						atomic_read(&next_i->i_count)) {
-				__iget(next_i);
-				need_iput = next_i;
-				spin_unlock(&next_i->i_lock);
-				break;
-			}
-			spin_unlock(&next_i->i_lock);
-			next_i = list_entry(next_i->i_sb_list.next,
-						struct inode, i_sb_list);
-		}
-
-		/*
-		 * We can safely drop inode_sb_list_lock here because either
-		 * we actually hold references on both inode and next_i or
-		 * end of list.  Also no new inodes will be added since the
-		 * umount has begun.
-		 */
 		spin_unlock(&inode_sb_list_lock);
 
-		if (need_iput_tmp)
-			iput(need_iput_tmp);
+		if (iput_inode)
+			iput(iput_inode);
 
 		/* for each watch, send FS_UNMOUNT and then remove it */
 		fsnotify(inode, FS_UNMOUNT, inode, FSNOTIFY_EVENT_INODE, NULL, 0);
 
 		fsnotify_inode_delete(inode);
 
-		iput(inode);
+		iput_inode = inode;
 
 		spin_lock(&inode_sb_list_lock);
 	}
 	spin_unlock(&inode_sb_list_lock);
+
+	if (iput_inode)
+		iput(iput_inode);
 }
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/fs/ocfs2/dlmglue.c linux-libre-3.2.87-gnu1/fs/ocfs2/dlmglue.c
--- linux-libre-3.2.86-gnu1/fs/ocfs2/dlmglue.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/fs/ocfs2/dlmglue.c	2017-03-15 22:19:00.000000000 -0400
@@ -3270,6 +3270,16 @@ static int ocfs2_downconvert_lock(struct
 	mlog(ML_BASTS, "lockres %s, level %d => %d\n", lockres->l_name,
 	     lockres->l_level, new_level);
 
+	/*
+	 * On DLM_LKF_VALBLK, fsdlm behaves differently with o2cb. It always
+	 * expects DLM_LKF_VALBLK being set if the LKB has LVB, so that
+	 * we can recover correctly from node failure. Otherwise, we may get
+	 * invalid LVB in LKB, but without DLM_SBF_VALNOTVALID being set.
+	 */
+	if (!ocfs2_is_o2cb_active() &&
+	    lockres->l_ops->flags & LOCK_TYPE_USES_LVB)
+		lvb = 1;
+
 	if (lvb)
 		dlm_flags |= DLM_LKF_VALBLK;
 
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/fs/ocfs2/stackglue.c linux-libre-3.2.87-gnu1/fs/ocfs2/stackglue.c
--- linux-libre-3.2.86-gnu1/fs/ocfs2/stackglue.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/fs/ocfs2/stackglue.c	2017-03-15 22:19:00.000000000 -0400
@@ -48,6 +48,12 @@ static char ocfs2_hb_ctl_path[OCFS2_MAX_
  */
 static struct ocfs2_stack_plugin *active_stack;
 
+inline int ocfs2_is_o2cb_active(void)
+{
+	return !strcmp(active_stack->sp_name, OCFS2_STACK_PLUGIN_O2CB);
+}
+EXPORT_SYMBOL_GPL(ocfs2_is_o2cb_active);
+
 static struct ocfs2_stack_plugin *ocfs2_stack_lookup(const char *name)
 {
 	struct ocfs2_stack_plugin *p;
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/fs/ocfs2/stackglue.h linux-libre-3.2.87-gnu1/fs/ocfs2/stackglue.h
--- linux-libre-3.2.86-gnu1/fs/ocfs2/stackglue.h	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/fs/ocfs2/stackglue.h	2017-03-15 22:19:00.000000000 -0400
@@ -289,4 +289,7 @@ void ocfs2_stack_glue_set_max_proto_vers
 int ocfs2_stack_glue_register(struct ocfs2_stack_plugin *plugin);
 void ocfs2_stack_glue_unregister(struct ocfs2_stack_plugin *plugin);
 
+/* In ocfs2_downconvert_lock(), we need to know which stack we are using */
+int ocfs2_is_o2cb_active(void);
+
 #endif  /* STACKGLUE_H */
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/fs/splice.c linux-libre-3.2.87-gnu1/fs/splice.c
--- linux-libre-3.2.86-gnu1/fs/splice.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/fs/splice.c	2017-03-15 22:19:00.000000000 -0400
@@ -214,6 +214,7 @@ ssize_t splice_to_pipe(struct pipe_inode
 			buf->len = spd->partial[page_nr].len;
 			buf->private = spd->partial[page_nr].private;
 			buf->ops = spd->ops;
+			buf->flags = 0;
 			if (spd->flags & SPLICE_F_GIFT)
 				buf->flags |= PIPE_BUF_FLAG_GIFT;
 
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/fs/ubifs/tnc.c linux-libre-3.2.87-gnu1/fs/ubifs/tnc.c
--- linux-libre-3.2.86-gnu1/fs/ubifs/tnc.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/fs/ubifs/tnc.c	2017-03-15 22:19:00.000000000 -0400
@@ -34,6 +34,11 @@
 #include <linux/slab.h>
 #include "ubifs.h"
 
+static int try_read_node(const struct ubifs_info *c, void *buf, int type,
+			 int len, int lnum, int offs);
+static int fallible_read_node(struct ubifs_info *c, const union ubifs_key *key,
+			      struct ubifs_zbranch *zbr, void *node);
+
 /*
  * Returned codes of 'matches_name()' and 'fallible_matches_name()' functions.
  * @NAME_LESS: name corresponding to the first argument is less than second
@@ -420,7 +425,19 @@ static int tnc_read_node_nm(struct ubifs
 		return 0;
 	}
 
-	err = ubifs_tnc_read_node(c, zbr, node);
+	if (c->replaying) {
+		err = fallible_read_node(c, &zbr->key, zbr, node);
+		/*
+		 * When the node was not found, return -ENOENT, 0 otherwise.
+		 * Negative return codes stay as-is.
+		 */
+		if (err == 0)
+			err = -ENOENT;
+		else if (err == 1)
+			err = 0;
+	} else {
+		err = ubifs_tnc_read_node(c, zbr, node);
+	}
 	if (err)
 		return err;
 
@@ -2785,7 +2802,11 @@ struct ubifs_dent_node *ubifs_tnc_next_e
 	if (nm->name) {
 		if (err) {
 			/* Handle collisions */
-			err = resolve_collision(c, key, &znode, &n, nm);
+			if (c->replaying)
+				err = fallible_resolve_collision(c, key, &znode, &n,
+							 nm, 0);
+			else
+				err = resolve_collision(c, key, &znode, &n, nm);
 			dbg_tnc("rc returned %d, znode %p, n %d",
 				err, znode, n);
 			if (unlikely(err < 0))
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/fs/xfs/xfs_dfrag.c linux-libre-3.2.87-gnu1/fs/xfs/xfs_dfrag.c
--- linux-libre-3.2.86-gnu1/fs/xfs/xfs_dfrag.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/fs/xfs/xfs_dfrag.c	2017-03-15 22:19:00.000000000 -0400
@@ -210,6 +210,7 @@ xfs_swap_extents(
 	int		error = 0;
 	int		aforkblks = 0;
 	int		taforkblks = 0;
+	xfs_extnum_t	nextents;
 	__uint64_t	tmp;
 
 	tempifp = kmem_alloc(sizeof(xfs_ifork_t), KM_MAYFAIL);
@@ -394,7 +395,8 @@ xfs_swap_extents(
 		 * pointer.  Otherwise it's already NULL or
 		 * pointing to the extent.
 		 */
-		if (ip->i_d.di_nextents <= XFS_INLINE_EXTS) {
+		nextents = ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
+		if (nextents <= XFS_INLINE_EXTS) {
 			ifp->if_u1.if_extents =
 				ifp->if_u2.if_inline_ext;
 		}
@@ -413,7 +415,8 @@ xfs_swap_extents(
 		 * pointer.  Otherwise it's already NULL or
 		 * pointing to the extent.
 		 */
-		if (tip->i_d.di_nextents <= XFS_INLINE_EXTS) {
+		nextents = tip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
+		if (nextents <= XFS_INLINE_EXTS) {
 			tifp->if_u1.if_extents =
 				tifp->if_u2.if_inline_ext;
 		}
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/include/linux/can/core.h linux-libre-3.2.87-gnu1/include/linux/can/core.h
--- linux-libre-3.2.86-gnu1/include/linux/can/core.h	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/include/linux/can/core.h	2017-03-15 22:19:00.000000000 -0400
@@ -45,10 +45,9 @@ struct can_proto {
 extern int  can_proto_register(const struct can_proto *cp);
 extern void can_proto_unregister(const struct can_proto *cp);
 
-extern int  can_rx_register(struct net_device *dev, canid_t can_id,
-			    canid_t mask,
-			    void (*func)(struct sk_buff *, void *),
-			    void *data, char *ident);
+int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask,
+		    void (*func)(struct sk_buff *, void *),
+		    void *data, char *ident, struct sock *sk);
 
 extern void can_rx_unregister(struct net_device *dev, canid_t can_id,
 			      canid_t mask,
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/include/linux/cpu.h linux-libre-3.2.87-gnu1/include/linux/cpu.h
--- linux-libre-3.2.86-gnu1/include/linux/cpu.h	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/include/linux/cpu.h	2017-03-15 22:19:00.000000000 -0400
@@ -112,22 +112,16 @@ enum {
 		{ .notifier_call = fn, .priority = pri };	\
 	register_cpu_notifier(&fn##_nb);			\
 }
-#else /* #if defined(CONFIG_HOTPLUG_CPU) || !defined(MODULE) */
-#define cpu_notifier(fn, pri)	do { (void)(fn); } while (0)
-#endif /* #else #if defined(CONFIG_HOTPLUG_CPU) || !defined(MODULE) */
-#ifdef CONFIG_HOTPLUG_CPU
 extern int register_cpu_notifier(struct notifier_block *nb);
 extern void unregister_cpu_notifier(struct notifier_block *nb);
-#else
 
-#ifndef MODULE
-extern int register_cpu_notifier(struct notifier_block *nb);
-#else
+#else /* #if defined(CONFIG_HOTPLUG_CPU) || !defined(MODULE) */
+#define cpu_notifier(fn, pri)	do { (void)(fn); } while (0)
+
 static inline int register_cpu_notifier(struct notifier_block *nb)
 {
 	return 0;
 }
-#endif
 
 static inline void unregister_cpu_notifier(struct notifier_block *nb)
 {
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/include/linux/list.h linux-libre-3.2.87-gnu1/include/linux/list.h
--- linux-libre-3.2.86-gnu1/include/linux/list.h	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/include/linux/list.h	2017-03-15 22:19:00.000000000 -0400
@@ -362,6 +362,17 @@ static inline void list_splice_tail_init
 	list_entry((ptr)->next, type, member)
 
 /**
+ * list_first_entry_or_null - get the first element from a list
+ * @ptr:	the list head to take the element from.
+ * @type:	the type of the struct this is embedded in.
+ * @member:	the name of the list_struct within the struct.
+ *
+ * Note that if the list is empty, it returns NULL.
+ */
+#define list_first_entry_or_null(ptr, type, member) \
+	(!list_empty(ptr) ? list_first_entry(ptr, type, member) : NULL)
+
+/**
  * list_for_each	-	iterate over a list
  * @pos:	the &struct list_head to use as a loop cursor.
  * @head:	the head for your list.
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/include/linux/netdevice.h linux-libre-3.2.87-gnu1/include/linux/netdevice.h
--- linux-libre-3.2.86-gnu1/include/linux/netdevice.h	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/include/linux/netdevice.h	2017-03-15 22:19:00.000000000 -0400
@@ -1676,14 +1676,19 @@ static inline int skb_gro_header_hard(st
 	return NAPI_GRO_CB(skb)->frag0_len < hlen;
 }
 
+static inline void skb_gro_frag0_invalidate(struct sk_buff *skb)
+{
+	NAPI_GRO_CB(skb)->frag0 = NULL;
+	NAPI_GRO_CB(skb)->frag0_len = 0;
+}
+
 static inline void *skb_gro_header_slow(struct sk_buff *skb, unsigned int hlen,
 					unsigned int offset)
 {
 	if (!pskb_may_pull(skb, hlen))
 		return NULL;
 
-	NAPI_GRO_CB(skb)->frag0 = NULL;
-	NAPI_GRO_CB(skb)->frag0_len = 0;
+	skb_gro_frag0_invalidate(skb);
 	return skb->data + offset;
 }
 
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/include/net/cipso_ipv4.h linux-libre-3.2.87-gnu1/include/net/cipso_ipv4.h
--- linux-libre-3.2.86-gnu1/include/net/cipso_ipv4.h	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/include/net/cipso_ipv4.h	2017-03-15 22:19:00.000000000 -0400
@@ -303,6 +303,10 @@ static inline int cipso_v4_validate(cons
 	}
 
 	for (opt_iter = 6; opt_iter < opt_len;) {
+		if (opt_iter + 1 == opt_len) {
+			err_offset = opt_iter;
+			goto out;
+		}
 		tag_len = opt[opt_iter + 1];
 		if ((tag_len == 0) || (opt[opt_iter + 1] > (opt_len - opt_iter))) {
 			err_offset = opt_iter + 1;
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/include/net/sock.h linux-libre-3.2.87-gnu1/include/net/sock.h
--- linux-libre-3.2.86-gnu1/include/net/sock.h	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/include/net/sock.h	2017-03-15 22:19:00.000000000 -0400
@@ -961,7 +961,7 @@ static inline struct inode *SOCK_INODE(s
  * Functions for memory accounting
  */
 extern int __sk_mem_schedule(struct sock *sk, int size, int kind);
-extern void __sk_mem_reclaim(struct sock *sk);
+void __sk_mem_reclaim(struct sock *sk, int amount);
 
 #define SK_MEM_QUANTUM ((int)PAGE_SIZE)
 #define SK_MEM_QUANTUM_SHIFT ilog2(SK_MEM_QUANTUM)
@@ -1000,7 +1000,7 @@ static inline void sk_mem_reclaim(struct
 	if (!sk_has_account(sk))
 		return;
 	if (sk->sk_forward_alloc >= SK_MEM_QUANTUM)
-		__sk_mem_reclaim(sk);
+		__sk_mem_reclaim(sk, sk->sk_forward_alloc);
 }
 
 static inline void sk_mem_reclaim_partial(struct sock *sk)
@@ -1008,7 +1008,7 @@ static inline void sk_mem_reclaim_partia
 	if (!sk_has_account(sk))
 		return;
 	if (sk->sk_forward_alloc > SK_MEM_QUANTUM)
-		__sk_mem_reclaim(sk);
+		__sk_mem_reclaim(sk, sk->sk_forward_alloc - 1);
 }
 
 static inline void sk_mem_charge(struct sock *sk, int size)
@@ -1023,6 +1023,16 @@ static inline void sk_mem_uncharge(struc
 	if (!sk_has_account(sk))
 		return;
 	sk->sk_forward_alloc += size;
+
+	/* Avoid a possible overflow.
+	 * TCP send queues can make this happen, if sk_mem_reclaim()
+	 * is not called and more than 2 GBytes are released at once.
+	 *
+	 * If we reach 2 MBytes, reclaim 1 MBytes right now, there is
+	 * no need to hold that much forward allocation anyway.
+	 */
+	if (unlikely(sk->sk_forward_alloc >= 1 << 21))
+		__sk_mem_reclaim(sk, 1 << 20);
 }
 
 static inline void sk_wmem_free_skb(struct sock *sk, struct sk_buff *skb)
@@ -1117,6 +1127,7 @@ extern struct sk_buff		*sock_rmalloc(str
 					      gfp_t priority);
 extern void			sock_wfree(struct sk_buff *skb);
 extern void			sock_rfree(struct sk_buff *skb);
+void sock_efree(struct sk_buff *skb);
 
 extern int			sock_setsockopt(struct socket *sock, int level,
 						int op, char __user *optval,
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/ipc/shm.c linux-libre-3.2.87-gnu1/ipc/shm.c
--- linux-libre-3.2.86-gnu1/ipc/shm.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/ipc/shm.c	2017-03-15 22:19:00.000000000 -0400
@@ -963,8 +963,13 @@ long do_shmat(int shmid, char __user *sh
 		goto out;
 	else if ((addr = (ulong)shmaddr)) {
 		if (addr & (SHMLBA-1)) {
-			if (shmflg & SHM_RND)
-				addr &= ~(SHMLBA-1);	   /* round down */
+			/*
+			 * Round down to the nearest multiple of shmlba.
+			 * For sane do_mmap_pgoff() parameters, avoid
+			 * round downs that trigger nil-page and MAP_FIXED.
+			 */
+			if ((shmflg & SHM_RND) && addr >= SHMLBA)
+				addr &= ~(SHMLBA - 1);
 			else
 #ifndef __ARCH_FORCE_SHMLBA
 				if (addr & ~PAGE_MASK)
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/kernel/cpu.c linux-libre-3.2.87-gnu1/kernel/cpu.c
--- linux-libre-3.2.86-gnu1/kernel/cpu.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/kernel/cpu.c	2017-03-15 22:19:00.000000000 -0400
@@ -176,12 +176,6 @@ static int cpu_notify(unsigned long val,
 	return __cpu_notify(val, v, -1, NULL);
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
-
-static void cpu_notify_nofail(unsigned long val, void *v)
-{
-	BUG_ON(cpu_notify(val, v));
-}
 EXPORT_SYMBOL(register_cpu_notifier);
 
 void __ref unregister_cpu_notifier(struct notifier_block *nb)
@@ -192,6 +186,13 @@ void __ref unregister_cpu_notifier(struc
 }
 EXPORT_SYMBOL(unregister_cpu_notifier);
 
+#ifdef CONFIG_HOTPLUG_CPU
+
+static void cpu_notify_nofail(unsigned long val, void *v)
+{
+	BUG_ON(cpu_notify(val, v));
+}
+
 static inline void check_for_tasks(int cpu)
 {
 	struct task_struct *p;
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/kernel/futex.c linux-libre-3.2.87-gnu1/kernel/futex.c
--- linux-libre-3.2.86-gnu1/kernel/futex.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/kernel/futex.c	2017-03-15 22:19:00.000000000 -0400
@@ -2904,4 +2904,4 @@ static int __init futex_init(void)
 
 	return 0;
 }
-__initcall(futex_init);
+core_initcall(futex_init);
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/kernel/sysctl.c linux-libre-3.2.87-gnu1/kernel/sysctl.c
--- linux-libre-3.2.86-gnu1/kernel/sysctl.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/kernel/sysctl.c	2017-03-15 22:19:00.000000000 -0400
@@ -2554,6 +2554,7 @@ static int __do_proc_doulongvec_minmax(v
 				break;
 			if (neg)
 				continue;
+			val = convmul * val / convdiv;
 			if ((min && val < *min) || (max && val > *max))
 				continue;
 			*i = val;
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/lib/vsprintf.c linux-libre-3.2.87-gnu1/lib/vsprintf.c
--- linux-libre-3.2.86-gnu1/lib/vsprintf.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/lib/vsprintf.c	2017-03-15 22:19:00.000000000 -0400
@@ -1177,7 +1177,7 @@ int vsnprintf(char *buf, size_t size, co
 
 	/* Reject out-of-range values early.  Large positive sizes are
 	   used for unknown buffer sizes. */
-	if (WARN_ON_ONCE((int) size < 0))
+	if (WARN_ON_ONCE(size > INT_MAX))
 		return 0;
 
 	str = buf;
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/Makefile linux-libre-3.2.87-gnu1/Makefile
--- linux-libre-3.2.86-gnu1/Makefile	2017-02-27 03:18:47.000000000 -0500
+++ linux-libre-3.2.87-gnu1/Makefile	2017-03-16 11:55:11.000000000 -0400
@@ -1,6 +1,6 @@
 VERSION = 3
 PATCHLEVEL = 2
-SUBLEVEL = 86
+SUBLEVEL = 87
 EXTRAVERSION =-gnu1
 NAME = Saber-toothed Squirrel
 
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/mm/filemap.c linux-libre-3.2.87-gnu1/mm/filemap.c
--- linux-libre-3.2.86-gnu1/mm/filemap.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/mm/filemap.c	2017-03-15 22:19:00.000000000 -0400
@@ -1117,6 +1117,11 @@ static void do_generic_file_read(struct
 
 		cond_resched();
 find_page:
+		if (fatal_signal_pending(current)) {
+			error = -EINTR;
+			goto out;
+		}
+
 		page = find_get_page(mapping, index);
 		if (!page) {
 			page_cache_sync_readahead(mapping,
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/mm/huge_memory.c linux-libre-3.2.87-gnu1/mm/huge_memory.c
--- linux-libre-3.2.86-gnu1/mm/huge_memory.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/mm/huge_memory.c	2017-03-15 22:19:00.000000000 -0400
@@ -964,6 +964,18 @@ out:
 	return ret;
 }
 
+/*
+ * FOLL_FORCE can write to even unwritable pmd's, but only
+ * after we've gone through a COW cycle and they are dirty.
+ */
+static inline bool can_follow_write_pmd(pmd_t pmd, struct page *page,
+					unsigned int flags)
+{
+	return pmd_write(pmd) ||
+		((flags & FOLL_FORCE) && (flags & FOLL_COW) &&
+		 page && PageAnon(page));
+}
+
 struct page *follow_trans_huge_pmd(struct mm_struct *mm,
 				   unsigned long addr,
 				   pmd_t *pmd,
@@ -973,11 +985,12 @@ struct page *follow_trans_huge_pmd(struc
 
 	assert_spin_locked(&mm->page_table_lock);
 
-	if (flags & FOLL_WRITE && !pmd_write(*pmd))
-		goto out;
-
 	page = pmd_page(*pmd);
 	VM_BUG_ON(!PageHead(page));
+
+	if (flags & FOLL_WRITE && !can_follow_write_pmd(*pmd, page, flags))
+		goto out;
+
 	if (flags & FOLL_TOUCH) {
 		pmd_t _pmd;
 		/*
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/bridge/br_ioctl.c linux-libre-3.2.87-gnu1/net/bridge/br_ioctl.c
--- linux-libre-3.2.86-gnu1/net/bridge/br_ioctl.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/bridge/br_ioctl.c	2017-03-15 22:19:00.000000000 -0400
@@ -21,18 +21,19 @@
 #include <asm/uaccess.h>
 #include "br_private.h"
 
-/* called with RTNL */
 static int get_bridge_ifindices(struct net *net, int *indices, int num)
 {
 	struct net_device *dev;
 	int i = 0;
 
-	for_each_netdev(net, dev) {
+	rcu_read_lock();
+	for_each_netdev_rcu(net, dev) {
 		if (i >= num)
 			break;
 		if (dev->priv_flags & IFF_EBRIDGE)
 			indices[i++] = dev->ifindex;
 	}
+	rcu_read_unlock();
 
 	return i;
 }
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/can/af_can.c linux-libre-3.2.87-gnu1/net/can/af_can.c
--- linux-libre-3.2.86-gnu1/net/can/af_can.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/can/af_can.c	2017-03-15 22:19:00.000000000 -0400
@@ -403,6 +403,7 @@ static struct hlist_head *find_rcv_list(
  * @func: callback function on filter match
  * @data: returned parameter for callback function
  * @ident: string for calling module indentification
+ * @sk: socket pointer (might be NULL)
  *
  * Description:
  *  Invokes the callback function with the received sk_buff and the given
@@ -426,7 +427,7 @@ static struct hlist_head *find_rcv_list(
  */
 int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask,
 		    void (*func)(struct sk_buff *, void *), void *data,
-		    char *ident)
+		    char *ident, struct sock *sk)
 {
 	struct receiver *r;
 	struct hlist_head *rl;
@@ -454,6 +455,7 @@ int can_rx_register(struct net_device *d
 		r->func    = func;
 		r->data    = data;
 		r->ident   = ident;
+		r->sk      = sk;
 
 		hlist_add_head_rcu(&r->list, rl);
 		d->entries++;
@@ -478,8 +480,11 @@ EXPORT_SYMBOL(can_rx_register);
 static void can_rx_delete_receiver(struct rcu_head *rp)
 {
 	struct receiver *r = container_of(rp, struct receiver, rcu);
+	struct sock *sk = r->sk;
 
 	kmem_cache_free(rcv_cache, r);
+	if (sk)
+		sock_put(sk);
 }
 
 /**
@@ -558,8 +563,11 @@ void can_rx_unregister(struct net_device
 	spin_unlock(&can_rcvlists_lock);
 
 	/* schedule the receiver item for deletion */
-	if (r)
+	if (r) {
+		if (r->sk)
+			sock_hold(r->sk);
 		call_rcu(&r->rcu, can_rx_delete_receiver);
+	}
 }
 EXPORT_SYMBOL(can_rx_unregister);
 
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/can/af_can.h linux-libre-3.2.87-gnu1/net/can/af_can.h
--- linux-libre-3.2.86-gnu1/net/can/af_can.h	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/can/af_can.h	2017-03-15 22:19:00.000000000 -0400
@@ -50,13 +50,14 @@
 
 struct receiver {
 	struct hlist_node list;
-	struct rcu_head rcu;
 	canid_t can_id;
 	canid_t mask;
 	unsigned long matches;
 	void (*func)(struct sk_buff *, void *);
 	void *data;
 	char *ident;
+	struct sock *sk;
+	struct rcu_head rcu;
 };
 
 enum { RX_ERR, RX_ALL, RX_FIL, RX_INV, RX_EFF, RX_MAX };
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/can/bcm.c linux-libre-3.2.87-gnu1/net/can/bcm.c
--- linux-libre-3.2.86-gnu1/net/can/bcm.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/can/bcm.c	2017-03-15 22:19:00.000000000 -0400
@@ -702,14 +702,23 @@ static struct bcm_op *bcm_find_op(struct
 
 static void bcm_remove_op(struct bcm_op *op)
 {
-	hrtimer_cancel(&op->timer);
-	hrtimer_cancel(&op->thrtimer);
-
-	if (op->tsklet.func)
-		tasklet_kill(&op->tsklet);
+	if (op->tsklet.func) {
+		while (test_bit(TASKLET_STATE_SCHED, &op->tsklet.state) ||
+		       test_bit(TASKLET_STATE_RUN, &op->tsklet.state) ||
+		       hrtimer_active(&op->timer)) {
+			hrtimer_cancel(&op->timer);
+			tasklet_kill(&op->tsklet);
+		}
+	}
 
-	if (op->thrtsklet.func)
-		tasklet_kill(&op->thrtsklet);
+	if (op->thrtsklet.func) {
+		while (test_bit(TASKLET_STATE_SCHED, &op->thrtsklet.state) ||
+		       test_bit(TASKLET_STATE_RUN, &op->thrtsklet.state) ||
+		       hrtimer_active(&op->thrtimer)) {
+			hrtimer_cancel(&op->thrtimer);
+			tasklet_kill(&op->thrtsklet);
+		}
+	}
 
 	if ((op->frames) && (op->frames != &op->sframe))
 		kfree(op->frames);
@@ -1165,7 +1174,7 @@ static int bcm_rx_setup(struct bcm_msg_h
 				err = can_rx_register(dev, op->can_id,
 						      REGMASK(op->can_id),
 						      bcm_rx_handler, op,
-						      "bcm");
+						      "bcm", sk);
 
 				op->rx_reg_dev = dev;
 				dev_put(dev);
@@ -1174,7 +1183,7 @@ static int bcm_rx_setup(struct bcm_msg_h
 		} else
 			err = can_rx_register(NULL, op->can_id,
 					      REGMASK(op->can_id),
-					      bcm_rx_handler, op, "bcm");
+					      bcm_rx_handler, op, "bcm", sk);
 		if (err) {
 			/* this bcm rx op is broken -> remove it */
 			list_del(&op->list);
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/can/gw.c linux-libre-3.2.87-gnu1/net/can/gw.c
--- linux-libre-3.2.86-gnu1/net/can/gw.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/can/gw.c	2017-03-15 22:19:00.000000000 -0400
@@ -405,7 +405,7 @@ static inline int cgw_register_filter(st
 {
 	return can_rx_register(gwj->src.dev, gwj->ccgw.filter.can_id,
 			       gwj->ccgw.filter.can_mask, can_can_gw_rcv,
-			       gwj, "gw");
+			       gwj, "gw", NULL);
 }
 
 static inline void cgw_unregister_filter(struct cgw_job *gwj)
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/can/raw.c linux-libre-3.2.87-gnu1/net/can/raw.c
--- linux-libre-3.2.86-gnu1/net/can/raw.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/can/raw.c	2017-03-15 22:19:00.000000000 -0400
@@ -158,7 +158,7 @@ static int raw_enable_filters(struct net
 	for (i = 0; i < count; i++) {
 		err = can_rx_register(dev, filter[i].can_id,
 				      filter[i].can_mask,
-				      raw_rcv, sk, "raw");
+				      raw_rcv, sk, "raw", sk);
 		if (err) {
 			/* clean up successfully registered filters */
 			while (--i >= 0)
@@ -179,7 +179,7 @@ static int raw_enable_errfilter(struct n
 
 	if (err_mask)
 		err = can_rx_register(dev, 0, err_mask | CAN_ERR_FLAG,
-				      raw_rcv, sk, "raw");
+				      raw_rcv, sk, "raw", sk);
 
 	return err;
 }
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/ceph/messenger.c linux-libre-3.2.87-gnu1/net/ceph/messenger.c
--- linux-libre-3.2.86-gnu1/net/ceph/messenger.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/ceph/messenger.c	2017-03-15 22:19:00.000000000 -0400
@@ -1350,6 +1350,19 @@ static int process_connect(struct ceph_c
 
 	dout("process_connect on %p tag %d\n", con, (int)con->in_tag);
 
+	if (con->auth_reply_buf) {
+		/*
+		 * Any connection that defines ->get_authorizer()
+		 * should also define ->verify_authorizer_reply().
+		 * See get_connect_authorizer().
+		 */
+		ret = con->ops->verify_authorizer_reply(con, 0);
+		if (ret < 0) {
+			con->error_msg = "bad authorize reply";
+			return ret;
+		}
+	}
+
 	switch (con->in_reply.tag) {
 	case CEPH_MSGR_TAG_FEATURES:
 		pr_err("%s%lld %s feature set mismatch,"
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/core/dev.c linux-libre-3.2.87-gnu1/net/core/dev.c
--- linux-libre-3.2.86-gnu1/net/core/dev.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/core/dev.c	2017-03-15 22:19:00.000000000 -0400
@@ -1918,7 +1918,7 @@ int skb_checksum_help(struct sk_buff *sk
 			goto out;
 	}
 
-	*(__sum16 *)(skb->data + offset) = csum_fold(csum);
+	*(__sum16 *)(skb->data + offset) = csum_fold(csum) ?: CSUM_MANGLED_0;
 out_set_summed:
 	skb->ip_summed = CHECKSUM_NONE;
 out:
@@ -3627,7 +3627,9 @@ void skb_gro_reset_offset(struct sk_buff
 	    !PageHighMem(skb_frag_page(&skb_shinfo(skb)->frags[0]))) {
 		NAPI_GRO_CB(skb)->frag0 =
 			skb_frag_address(&skb_shinfo(skb)->frags[0]);
-		NAPI_GRO_CB(skb)->frag0_len = skb_frag_size(&skb_shinfo(skb)->frags[0]);
+		NAPI_GRO_CB(skb)->frag0_len = min_t(unsigned int,
+						    skb_frag_size(&skb_shinfo(skb)->frags[0]),
+						    skb->end - skb->tail);
 	}
 }
 EXPORT_SYMBOL(skb_gro_reset_offset);
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/core/drop_monitor.c linux-libre-3.2.87-gnu1/net/core/drop_monitor.c
--- linux-libre-3.2.86-gnu1/net/core/drop_monitor.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/core/drop_monitor.c	2017-03-15 22:19:00.000000000 -0400
@@ -77,6 +77,7 @@ static struct sk_buff *reset_per_cpu_dat
 	struct nlattr *nla;
 	struct sk_buff *skb;
 	unsigned long flags;
+	void *msg_header;
 
 	al = sizeof(struct net_dm_alert_msg);
 	al += dm_hit_limit * sizeof(struct net_dm_drop_point);
@@ -84,21 +85,41 @@ static struct sk_buff *reset_per_cpu_dat
 
 	skb = genlmsg_new(al, GFP_KERNEL);
 
-	if (skb) {
-		genlmsg_put(skb, 0, 0, &net_drop_monitor_family,
-				0, NET_DM_CMD_ALERT);
-		nla = nla_reserve(skb, NLA_UNSPEC,
-				  sizeof(struct net_dm_alert_msg));
-		msg = nla_data(nla);
-		memset(msg, 0, al);
-	} else {
-		mod_timer(&data->send_timer, jiffies + HZ / 10);
+	if (!skb)
+		goto err;
+
+	msg_header = genlmsg_put(skb, 0, 0, &net_drop_monitor_family,
+				 0, NET_DM_CMD_ALERT);
+	if (!msg_header) {
+		nlmsg_free(skb);
+		skb = NULL;
+		goto err;
 	}
+	nla = nla_reserve(skb, NLA_UNSPEC,
+			  sizeof(struct net_dm_alert_msg));
+	if (!nla) {
+		nlmsg_free(skb);
+		skb = NULL;
+		goto err;
+	}
+	msg = nla_data(nla);
+	memset(msg, 0, al);
+	goto out;
 
+err:
+	mod_timer(&data->send_timer, jiffies + HZ / 10);
+out:
 	spin_lock_irqsave(&data->lock, flags);
 	swap(data->skb, skb);
 	spin_unlock_irqrestore(&data->lock, flags);
 
+	if (skb) {
+		struct nlmsghdr *nlh = (struct nlmsghdr *)skb->data;
+		struct genlmsghdr *gnlh = (struct genlmsghdr *)nlmsg_data(nlh);
+
+		genlmsg_end(skb, genlmsg_data(gnlh));
+	}
+
 	return skb;
 }
 
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/core/sock.c linux-libre-3.2.87-gnu1/net/core/sock.c
--- linux-libre-3.2.86-gnu1/net/core/sock.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/core/sock.c	2017-03-15 22:19:00.000000000 -0400
@@ -1259,6 +1259,7 @@ struct sock *sk_clone(const struct sock
 		}
 
 		newsk->sk_err	   = 0;
+		newsk->sk_err_soft = 0;
 		newsk->sk_priority = 0;
 		/*
 		 * Before updating sk_refcnt, we must commit prior changes to memory
@@ -1369,6 +1370,11 @@ void sock_rfree(struct sk_buff *skb)
 }
 EXPORT_SYMBOL(sock_rfree);
 
+void sock_efree(struct sk_buff *skb)
+{
+	sock_put(skb->sk);
+}
+EXPORT_SYMBOL(sock_efree);
 
 int sock_i_uid(struct sock *sk)
 {
@@ -1745,14 +1751,15 @@ EXPORT_SYMBOL(__sk_mem_schedule);
 /**
  *	__sk_reclaim - reclaim memory_allocated
  *	@sk: socket
+ *	@amount: number of bytes (rounded down to a SK_MEM_QUANTUM multiple)
  */
-void __sk_mem_reclaim(struct sock *sk)
+void __sk_mem_reclaim(struct sock *sk, int amount)
 {
 	struct proto *prot = sk->sk_prot;
 
-	atomic_long_sub(sk->sk_forward_alloc >> SK_MEM_QUANTUM_SHIFT,
-		   prot->memory_allocated);
-	sk->sk_forward_alloc &= SK_MEM_QUANTUM - 1;
+	amount >>= SK_MEM_QUANTUM_SHIFT;
+	atomic_long_sub(amount, prot->memory_allocated);
+	sk->sk_forward_alloc -= amount << SK_MEM_QUANTUM_SHIFT;
 
 	if (prot->memory_pressure && *prot->memory_pressure &&
 	    (atomic_long_read(prot->memory_allocated) < prot->sysctl_mem[0]))
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/dccp/ipv4.c linux-libre-3.2.87-gnu1/net/dccp/ipv4.c
--- linux-libre-3.2.86-gnu1/net/dccp/ipv4.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/dccp/ipv4.c	2017-03-15 22:19:00.000000000 -0400
@@ -211,7 +211,7 @@ static void dccp_v4_err(struct sk_buff *
 {
 	const struct iphdr *iph = (struct iphdr *)skb->data;
 	const u8 offset = iph->ihl << 2;
-	const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + offset);
+	const struct dccp_hdr *dh;
 	struct dccp_sock *dp;
 	struct inet_sock *inet;
 	const int type = icmp_hdr(skb)->type;
@@ -221,11 +221,13 @@ static void dccp_v4_err(struct sk_buff *
 	int err;
 	struct net *net = dev_net(skb->dev);
 
-	if (skb->len < offset + sizeof(*dh) ||
-	    skb->len < offset + __dccp_basic_hdr_len(dh)) {
-		ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS);
-		return;
-	}
+	/* Only need dccph_dport & dccph_sport which are the first
+	 * 4 bytes in dccp header.
+	 * Our caller (icmp_socket_deliver()) already pulled 8 bytes for us.
+	 */
+	BUILD_BUG_ON(offsetof(struct dccp_hdr, dccph_sport) + sizeof(dh->dccph_sport) > 8);
+	BUILD_BUG_ON(offsetof(struct dccp_hdr, dccph_dport) + sizeof(dh->dccph_dport) > 8);
+	dh = (struct dccp_hdr *)(skb->data + offset);
 
 	sk = inet_lookup(net, &dccp_hashinfo,
 			iph->daddr, dh->dccph_dport,
@@ -728,6 +730,7 @@ int dccp_invalid_packet(struct sk_buff *
 {
 	const struct dccp_hdr *dh;
 	unsigned int cscov;
+	u8 dccph_doff;
 
 	if (skb->pkt_type != PACKET_HOST)
 		return 1;
@@ -749,18 +752,19 @@ int dccp_invalid_packet(struct sk_buff *
 	/*
 	 * If P.Data Offset is too small for packet type, drop packet and return
 	 */
-	if (dh->dccph_doff < dccp_hdr_len(skb) / sizeof(u32)) {
-		DCCP_WARN("P.Data Offset(%u) too small\n", dh->dccph_doff);
+	dccph_doff = dh->dccph_doff;
+	if (dccph_doff < dccp_hdr_len(skb) / sizeof(u32)) {
+		DCCP_WARN("P.Data Offset(%u) too small\n", dccph_doff);
 		return 1;
 	}
 	/*
 	 * If P.Data Offset is too too large for packet, drop packet and return
 	 */
-	if (!pskb_may_pull(skb, dh->dccph_doff * sizeof(u32))) {
-		DCCP_WARN("P.Data Offset(%u) too large\n", dh->dccph_doff);
+	if (!pskb_may_pull(skb, dccph_doff * sizeof(u32))) {
+		DCCP_WARN("P.Data Offset(%u) too large\n", dccph_doff);
 		return 1;
 	}
-
+	dh = dccp_hdr(skb);
 	/*
 	 * If P.type is not Data, Ack, or DataAck and P.X == 0 (the packet
 	 * has short sequence numbers), drop packet and return
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/dccp/ipv6.c linux-libre-3.2.87-gnu1/net/dccp/ipv6.c
--- linux-libre-3.2.86-gnu1/net/dccp/ipv6.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/dccp/ipv6.c	2017-03-15 22:19:00.000000000 -0400
@@ -83,7 +83,7 @@ static void dccp_v6_err(struct sk_buff *
 			u8 type, u8 code, int offset, __be32 info)
 {
 	const struct ipv6hdr *hdr = (const struct ipv6hdr *)skb->data;
-	const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + offset);
+	const struct dccp_hdr *dh;
 	struct dccp_sock *dp;
 	struct ipv6_pinfo *np;
 	struct sock *sk;
@@ -91,12 +91,13 @@ static void dccp_v6_err(struct sk_buff *
 	__u64 seq;
 	struct net *net = dev_net(skb->dev);
 
-	if (skb->len < offset + sizeof(*dh) ||
-	    skb->len < offset + __dccp_basic_hdr_len(dh)) {
-		ICMP6_INC_STATS_BH(net, __in6_dev_get(skb->dev),
-				   ICMP6_MIB_INERRORS);
-		return;
-	}
+	/* Only need dccph_dport & dccph_sport which are the first
+	 * 4 bytes in dccp header.
+	 * Our caller (icmpv6_notify()) already pulled 8 bytes for us.
+	 */
+	BUILD_BUG_ON(offsetof(struct dccp_hdr, dccph_sport) + sizeof(dh->dccph_sport) > 8);
+	BUILD_BUG_ON(offsetof(struct dccp_hdr, dccph_dport) + sizeof(dh->dccph_dport) > 8);
+	dh = (struct dccp_hdr *)(skb->data + offset);
 
 	sk = inet6_lookup(net, &dccp_hashinfo,
 			&hdr->daddr, dh->dccph_dport,
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/dccp/proto.c linux-libre-3.2.87-gnu1/net/dccp/proto.c
--- linux-libre-3.2.86-gnu1/net/dccp/proto.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/dccp/proto.c	2017-03-15 22:19:00.000000000 -0400
@@ -1012,6 +1012,10 @@ void dccp_close(struct sock *sk, long ti
 		__kfree_skb(skb);
 	}
 
+	/* If socket has been already reset kill it. */
+	if (sk->sk_state == DCCP_CLOSED)
+		goto adjudge_to_death;
+
 	if (data_was_unread) {
 		/* Unread data was tossed, send an appropriate Reset Code */
 		DCCP_WARN("ABORT with %u bytes unread\n", data_was_unread);
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/decnet/dn_route.c linux-libre-3.2.87-gnu1/net/decnet/dn_route.c
--- linux-libre-3.2.86-gnu1/net/decnet/dn_route.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/decnet/dn_route.c	2017-03-15 22:19:00.000000000 -0400
@@ -998,10 +998,13 @@ source_ok:
 	if (!fld.daddr) {
 		fld.daddr = fld.saddr;
 
-		err = -EADDRNOTAVAIL;
 		if (dev_out)
 			dev_put(dev_out);
+		err = -EINVAL;
 		dev_out = init_net.loopback_dev;
+		if (!dev_out->dn_ptr)
+			goto out;
+		err = -EADDRNOTAVAIL;
 		dev_hold(dev_out);
 		if (!fld.daddr) {
 			fld.daddr =
@@ -1074,6 +1077,8 @@ source_ok:
 		if (dev_out == NULL)
 			goto out;
 		dn_db = rcu_dereference_raw(dev_out->dn_ptr);
+		if (!dn_db)
+			goto e_inval;
 		/* Possible improvement - check all devices for local addr */
 		if (dn_dev_islocal(dev_out, fld.daddr)) {
 			dev_put(dev_out);
@@ -1115,6 +1120,8 @@ select_source:
 			dev_put(dev_out);
 		dev_out = init_net.loopback_dev;
 		dev_hold(dev_out);
+		if (!dev_out->dn_ptr)
+			goto e_inval;
 		fld.flowidn_oif = dev_out->ifindex;
 		if (res.fi)
 			dn_fib_info_put(res.fi);
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/ipv4/cipso_ipv4.c linux-libre-3.2.87-gnu1/net/ipv4/cipso_ipv4.c
--- linux-libre-3.2.86-gnu1/net/ipv4/cipso_ipv4.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/ipv4/cipso_ipv4.c	2017-03-15 22:19:00.000000000 -0400
@@ -1649,6 +1649,10 @@ int cipso_v4_validate(const struct sk_bu
 				goto validate_return_locked;
 			}
 
+		if (opt_iter + 1 == opt_len) {
+			err_offset = opt_iter;
+			goto validate_return_locked;
+		}
 		tag_len = tag[1];
 		if (tag_len > (opt_len - opt_iter)) {
 			err_offset = opt_iter + 1;
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/ipv4/igmp.c linux-libre-3.2.87-gnu1/net/ipv4/igmp.c
--- linux-libre-3.2.86-gnu1/net/ipv4/igmp.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/ipv4/igmp.c	2017-03-15 22:19:00.000000000 -0400
@@ -140,7 +140,7 @@
 	  time_before(jiffies, (in_dev)->mr_v2_seen)))
 
 static void igmpv3_add_delrec(struct in_device *in_dev, struct ip_mc_list *im);
-static void igmpv3_del_delrec(struct in_device *in_dev, __be32 multiaddr);
+static void igmpv3_del_delrec(struct in_device *in_dev, struct ip_mc_list *im);
 static void igmpv3_clear_delrec(struct in_device *in_dev);
 static int sf_setstate(struct ip_mc_list *pmc);
 static void sf_markstate(struct ip_mc_list *pmc);
@@ -197,9 +197,14 @@ static void igmp_start_timer(struct ip_m
 static void igmp_gq_start_timer(struct in_device *in_dev)
 {
 	int tv = net_random() % in_dev->mr_maxdelay;
+	unsigned long exp = jiffies + tv + 2;
+
+	if (in_dev->mr_gq_running &&
+	    time_after_eq(exp, (in_dev->mr_gq_timer).expires))
+		return;
 
 	in_dev->mr_gq_running = 1;
-	if (!mod_timer(&in_dev->mr_gq_timer, jiffies+tv+2))
+	if (!mod_timer(&in_dev->mr_gq_timer, exp))
 		in_dev_hold(in_dev);
 }
 
@@ -1077,10 +1082,14 @@ static void igmpv3_add_delrec(struct in_
 	spin_unlock_bh(&in_dev->mc_tomb_lock);
 }
 
-static void igmpv3_del_delrec(struct in_device *in_dev, __be32 multiaddr)
+/*
+ * restore ip_mc_list deleted records
+ */
+static void igmpv3_del_delrec(struct in_device *in_dev, struct ip_mc_list *im)
 {
 	struct ip_mc_list *pmc, *pmc_prev;
-	struct ip_sf_list *psf, *psf_next;
+	struct ip_sf_list *psf;
+	__be32 multiaddr = im->multiaddr;
 
 	spin_lock_bh(&in_dev->mc_tomb_lock);
 	pmc_prev = NULL;
@@ -1096,16 +1105,27 @@ static void igmpv3_del_delrec(struct in_
 			in_dev->mc_tomb = pmc->next;
 	}
 	spin_unlock_bh(&in_dev->mc_tomb_lock);
+
+	spin_lock_bh(&im->lock);
 	if (pmc) {
-		for (psf=pmc->tomb; psf; psf=psf_next) {
-			psf_next = psf->sf_next;
-			kfree(psf);
+		im->interface = pmc->interface;
+		im->crcount = in_dev->mr_qrv ?: IGMP_Unsolicited_Report_Count;
+		im->sfmode = pmc->sfmode;
+		if (pmc->sfmode == MCAST_INCLUDE) {
+			im->tomb = pmc->tomb;
+			im->sources = pmc->sources;
+			for (psf = im->sources; psf; psf = psf->sf_next)
+				psf->sf_crcount = im->crcount;
 		}
 		in_dev_put(pmc->interface);
 		kfree(pmc);
 	}
+	spin_unlock_bh(&im->lock);
 }
 
+/*
+ * flush ip_mc_list deleted records
+ */
 static void igmpv3_clear_delrec(struct in_device *in_dev)
 {
 	struct ip_mc_list *pmc, *nextpmc;
@@ -1250,7 +1270,7 @@ void ip_mc_inc_group(struct in_device *i
 	rcu_assign_pointer(in_dev->mc_list, im);
 
 #ifdef CONFIG_IP_MULTICAST
-	igmpv3_del_delrec(in_dev, im->multiaddr);
+	igmpv3_del_delrec(in_dev, im);
 #endif
 	igmp_group_added(im);
 	if (!in_dev->dead)
@@ -1340,8 +1360,12 @@ void ip_mc_remap(struct in_device *in_de
 
 	ASSERT_RTNL();
 
-	for_each_pmc_rtnl(in_dev, pmc)
+	for_each_pmc_rtnl(in_dev, pmc) {
+#ifdef CONFIG_IP_MULTICAST
+		igmpv3_del_delrec(in_dev, pmc);
+#endif
 		igmp_group_added(pmc);
+	}
 }
 
 /* Device going down */
@@ -1362,7 +1386,6 @@ void ip_mc_down(struct in_device *in_dev
 	in_dev->mr_gq_running = 0;
 	if (del_timer(&in_dev->mr_gq_timer))
 		__in_dev_put(in_dev);
-	igmpv3_clear_delrec(in_dev);
 #endif
 
 	ip_mc_dec_group(in_dev, IGMP_ALL_HOSTS);
@@ -1397,8 +1420,12 @@ void ip_mc_up(struct in_device *in_dev)
 
 	ip_mc_inc_group(in_dev, IGMP_ALL_HOSTS);
 
-	for_each_pmc_rtnl(in_dev, pmc)
+	for_each_pmc_rtnl(in_dev, pmc) {
+#ifdef CONFIG_IP_MULTICAST
+		igmpv3_del_delrec(in_dev, pmc);
+#endif
 		igmp_group_added(pmc);
+	}
 }
 
 /*
@@ -1413,13 +1440,13 @@ void ip_mc_destroy_dev(struct in_device
 
 	/* Deactivate timers */
 	ip_mc_down(in_dev);
+#ifdef CONFIG_IP_MULTICAST
+	igmpv3_clear_delrec(in_dev);
+#endif
 
 	while ((i = rtnl_dereference(in_dev->mc_list)) != NULL) {
 		in_dev->mc_list = i->next_rcu;
 		in_dev->mc_count--;
-
-		/* We've dropped the groups in ip_mc_down already */
-		ip_mc_clear_src(i);
 		ip_ma_put(i);
 	}
 }
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/ipv4/ipmr.c linux-libre-3.2.87-gnu1/net/ipv4/ipmr.c
--- linux-libre-3.2.86-gnu1/net/ipv4/ipmr.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/ipv4/ipmr.c	2017-03-15 22:19:00.000000000 -0400
@@ -830,8 +830,10 @@ static struct mfc_cache *ipmr_cache_allo
 {
 	struct mfc_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL);
 
-	if (c)
+	if (c) {
+		c->mfc_un.res.last_assert = jiffies - MFC_ASSERT_THRESH - 1;
 		c->mfc_un.res.minvif = MAXVIFS;
+	}
 	return c;
 }
 
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/ipv4/ping.c linux-libre-3.2.87-gnu1/net/ipv4/ping.c
--- linux-libre-3.2.86-gnu1/net/ipv4/ping.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/ipv4/ping.c	2017-03-15 22:19:00.000000000 -0400
@@ -452,6 +452,8 @@ static int ping_push_pending_frames(stru
 {
 	struct sk_buff *skb = skb_peek(&sk->sk_write_queue);
 
+	if (!skb)
+		return 0;
 	pfh->wcheck = csum_partial((char *)&pfh->icmph,
 		sizeof(struct icmphdr), pfh->wcheck);
 	pfh->icmph.checksum = csum_fold(pfh->wcheck);
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/ipv4/route.c linux-libre-3.2.87-gnu1/net/ipv4/route.c
--- linux-libre-3.2.86-gnu1/net/ipv4/route.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/ipv4/route.c	2017-03-15 22:19:00.000000000 -0400
@@ -2604,6 +2604,18 @@ static struct rtable *__mkroute_output(c
 		 */
 		if (fi && res->prefixlen < 4)
 			fi = NULL;
+	} else if ((type == RTN_LOCAL) && (orig_oif != 0) &&
+		   (orig_oif != dev_out->ifindex)) {
+		/* For local routes that require a particular output interface
+		 * we do not want to cache the result.  Caching the result
+		 * causes incorrect behaviour when there are multiple source
+		 * addresses on the interface, the end result being that if the
+		 * intended recipient is waiting on that interface for the
+		 * packet he won't receive it because it will be delivered on
+		 * the loopback interface and the IP_PKTINFO ipi_ifindex will
+		 * be set to the loopback interface as well.
+		 */
+		fi = NULL;
 	}
 
 	rth = rt_dst_alloc(dev_out,
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/ipv4/tcp_output.c linux-libre-3.2.87-gnu1/net/ipv4/tcp_output.c
--- linux-libre-3.2.86-gnu1/net/ipv4/tcp_output.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/ipv4/tcp_output.c	2017-03-15 22:19:00.000000000 -0400
@@ -1680,12 +1680,14 @@ static int tcp_mtu_probe(struct sock *sk
 	len = 0;
 	tcp_for_write_queue_from_safe(skb, next, sk) {
 		copy = min_t(int, skb->len, probe_size - len);
-		if (nskb->ip_summed)
+		if (nskb->ip_summed) {
 			skb_copy_bits(skb, 0, skb_put(nskb, copy), copy);
-		else
-			nskb->csum = skb_copy_and_csum_bits(skb, 0,
-							    skb_put(nskb, copy),
-							    copy, nskb->csum);
+		} else {
+			__wsum csum = skb_copy_and_csum_bits(skb, 0,
+							     skb_put(nskb, copy),
+							     copy, 0);
+			nskb->csum = csum_block_add(nskb->csum, csum, len);
+		}
 
 		if (skb->len <= copy) {
 			/* We've eaten all the data from this skb.
@@ -1921,9 +1923,11 @@ u32 __tcp_select_window(struct sock *sk)
 	int full_space = min_t(int, tp->window_clamp, tcp_full_space(sk));
 	int window;
 
-	if (mss > full_space)
+	if (unlikely(mss > full_space)) {
 		mss = full_space;
-
+		if (mss <= 0)
+			return 0;
+	}
 	if (free_space < (full_space >> 1)) {
 		icsk->icsk_ack.quick = 0;
 
@@ -2097,7 +2101,8 @@ int tcp_retransmit_skb(struct sock *sk,
 	 * copying overhead: fragmentation, tunneling, mangling etc.
 	 */
 	if (atomic_read(&sk->sk_wmem_alloc) >
-	    min(sk->sk_wmem_queued + (sk->sk_wmem_queued >> 2), sk->sk_sndbuf))
+	    min_t(u32, sk->sk_wmem_queued + (sk->sk_wmem_queued >> 2),
+		  sk->sk_sndbuf))
 		return -EAGAIN;
 
 	if (before(TCP_SKB_CB(skb)->seq, tp->snd_una)) {
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/ipv6/addrconf.c linux-libre-3.2.87-gnu1/net/ipv6/addrconf.c
--- linux-libre-3.2.86-gnu1/net/ipv6/addrconf.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/ipv6/addrconf.c	2017-03-15 22:19:00.000000000 -0400
@@ -4355,8 +4355,7 @@ static void addrconf_disable_change(stru
 	struct net_device *dev;
 	struct inet6_dev *idev;
 
-	rcu_read_lock();
-	for_each_netdev_rcu(net, dev) {
+	for_each_netdev(net, dev) {
 		idev = __in6_dev_get(dev);
 		if (idev) {
 			int changed = (!idev->cnf.disable_ipv6) ^ (!newf);
@@ -4365,7 +4364,6 @@ static void addrconf_disable_change(stru
 				dev_disable_change(idev);
 		}
 	}
-	rcu_read_unlock();
 }
 
 static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int old)
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/ipv6/af_inet6.c linux-libre-3.2.87-gnu1/net/ipv6/af_inet6.c
--- linux-libre-3.2.86-gnu1/net/ipv6/af_inet6.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/ipv6/af_inet6.c	2017-03-15 22:19:00.000000000 -0400
@@ -879,6 +879,7 @@ static struct sk_buff **ipv6_gro_receive
 	ops = rcu_dereference(inet6_protos[proto]);
 	if (!ops || !ops->gro_receive) {
 		__pskb_pull(skb, skb_gro_offset(skb));
+		skb_gro_frag0_invalidate(skb);
 		proto = ipv6_gso_pull_exthdrs(skb, proto);
 		skb_gro_pull(skb, -skb_transport_offset(skb));
 		skb_reset_transport_header(skb);
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/ipv6/ip6mr.c linux-libre-3.2.87-gnu1/net/ipv6/ip6mr.c
--- linux-libre-3.2.86-gnu1/net/ipv6/ip6mr.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/ipv6/ip6mr.c	2017-03-15 22:19:00.000000000 -0400
@@ -1022,6 +1022,7 @@ static struct mfc6_cache *ip6mr_cache_al
 	struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL);
 	if (c == NULL)
 		return NULL;
+	c->mfc_un.res.last_assert = jiffies - MFC_ASSERT_THRESH - 1;
 	c->mfc_un.res.minvif = MAXMIFS;
 	return c;
 }
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/ipv6/ip6_tunnel.c linux-libre-3.2.87-gnu1/net/ipv6/ip6_tunnel.c
--- linux-libre-3.2.86-gnu1/net/ipv6/ip6_tunnel.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/ipv6/ip6_tunnel.c	2017-03-15 22:19:00.000000000 -0400
@@ -372,18 +372,19 @@ ip6_tnl_dev_uninit(struct net_device *de
 static __u16
 parse_tlv_tnl_enc_lim(struct sk_buff *skb, __u8 * raw)
 {
-	const struct ipv6hdr *ipv6h = (const struct ipv6hdr *) raw;
-	__u8 nexthdr = ipv6h->nexthdr;
-	__u16 off = sizeof (*ipv6h);
+	const struct ipv6hdr *ipv6h = (const struct ipv6hdr *)raw;
+	unsigned int nhoff = raw - skb->data;
+	unsigned int off = nhoff + sizeof(*ipv6h);
+	u8 next, nexthdr = ipv6h->nexthdr;
 
 	while (ipv6_ext_hdr(nexthdr) && nexthdr != NEXTHDR_NONE) {
-		__u16 optlen = 0;
 		struct ipv6_opt_hdr *hdr;
-		if (raw + off + sizeof (*hdr) > skb->data &&
-		    !pskb_may_pull(skb, raw - skb->data + off + sizeof (*hdr)))
+		u16 optlen;
+
+		if (!pskb_may_pull(skb, off + sizeof(*hdr)))
 			break;
 
-		hdr = (struct ipv6_opt_hdr *) (raw + off);
+		hdr = (struct ipv6_opt_hdr *)(skb->data + off);
 		if (nexthdr == NEXTHDR_FRAGMENT) {
 			struct frag_hdr *frag_hdr = (struct frag_hdr *) hdr;
 			if (frag_hdr->frag_off)
@@ -394,20 +395,29 @@ parse_tlv_tnl_enc_lim(struct sk_buff *sk
 		} else {
 			optlen = ipv6_optlen(hdr);
 		}
+		/* cache hdr->nexthdr, since pskb_may_pull() might
+		 * invalidate hdr
+		 */
+		next = hdr->nexthdr;
 		if (nexthdr == NEXTHDR_DEST) {
-			__u16 i = off + 2;
+			u16 i = 2;
+
+			/* Remember : hdr is no longer valid at this point. */
+			if (!pskb_may_pull(skb, off + optlen))
+				break;
+
 			while (1) {
 				struct ipv6_tlv_tnl_enc_lim *tel;
 
 				/* No more room for encapsulation limit */
-				if (i + sizeof (*tel) > off + optlen)
+				if (i + sizeof(*tel) > optlen)
 					break;
 
-				tel = (struct ipv6_tlv_tnl_enc_lim *) &raw[i];
+				tel = (struct ipv6_tlv_tnl_enc_lim *)(skb->data + off + i);
 				/* return index of option if found and valid */
 				if (tel->type == IPV6_TLV_TNL_ENCAP_LIMIT &&
 				    tel->length == 1)
-					return i;
+					return i + off - nhoff;
 				/* else jump to next option */
 				if (tel->type)
 					i += tel->length + 2;
@@ -415,7 +425,7 @@ parse_tlv_tnl_enc_lim(struct sk_buff *sk
 					i++;
 			}
 		}
-		nexthdr = hdr->nexthdr;
+		nexthdr = next;
 		off += optlen;
 	}
 	return 0;
@@ -894,13 +904,22 @@ static int ip6_tnl_xmit2(struct sk_buff
 	struct ipv6_tel_txoption opt;
 	struct dst_entry *dst = NULL, *ndst = NULL;
 	struct net_device *tdev;
+	bool use_cache = false;
 	int mtu;
 	unsigned int max_headroom = sizeof(struct ipv6hdr);
 	u8 proto;
 	int err = -1;
 	int pkt_len;
 
-	if (!fl6->flowi6_mark)
+	if (!(t->parms.flags &
+		     (IP6_TNL_F_USE_ORIG_TCLASS | IP6_TNL_F_USE_ORIG_FWMARK))) {
+		/* enable the cache only only if the routing decision does
+		 * not depend on the current inner header value
+		 */
+		use_cache = true;
+	}
+
+	if (use_cache)
 		dst = ip6_tnl_dst_check(t);
 	if (!dst) {
 		ndst = ip6_route_output(net, NULL, fl6);
@@ -959,7 +978,7 @@ static int ip6_tnl_xmit2(struct sk_buff
 		skb = new_skb;
 	}
 	skb_dst_drop(skb);
-	if (fl6->flowi6_mark) {
+	if (!use_cache) {
 		skb_dst_set(skb, dst);
 		ndst = NULL;
 	} else {
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/ipv6/mcast.c linux-libre-3.2.87-gnu1/net/ipv6/mcast.c
--- linux-libre-3.2.86-gnu1/net/ipv6/mcast.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/ipv6/mcast.c	2017-03-15 22:19:00.000000000 -0400
@@ -92,7 +92,7 @@ static void mld_gq_timer_expire(unsigned
 static void mld_ifc_timer_expire(unsigned long data);
 static void mld_ifc_event(struct inet6_dev *idev);
 static void mld_add_delrec(struct inet6_dev *idev, struct ifmcaddr6 *pmc);
-static void mld_del_delrec(struct inet6_dev *idev, const struct in6_addr *addr);
+static void mld_del_delrec(struct inet6_dev *idev, struct ifmcaddr6 *pmc);
 static void mld_clear_delrec(struct inet6_dev *idev);
 static int sf_setstate(struct ifmcaddr6 *pmc);
 static void sf_markstate(struct ifmcaddr6 *pmc);
@@ -691,9 +691,9 @@ static void igmp6_group_dropped(struct i
 			dev_mc_del(dev, buf);
 	}
 
-	if (mc->mca_flags & MAF_NOREPORT)
-		goto done;
 	spin_unlock_bh(&mc->mca_lock);
+	if (mc->mca_flags & MAF_NOREPORT)
+		return;
 
 	if (!mc->idev->dead)
 		igmp6_leave_group(mc);
@@ -701,8 +701,6 @@ static void igmp6_group_dropped(struct i
 	spin_lock_bh(&mc->mca_lock);
 	if (del_timer(&mc->mca_timer))
 		atomic_dec(&mc->mca_refcnt);
-done:
-	ip6_mc_clear_src(mc);
 	spin_unlock_bh(&mc->mca_lock);
 }
 
@@ -747,10 +745,11 @@ static void mld_add_delrec(struct inet6_
 	spin_unlock_bh(&idev->mc_lock);
 }
 
-static void mld_del_delrec(struct inet6_dev *idev, const struct in6_addr *pmca)
+static void mld_del_delrec(struct inet6_dev *idev, struct ifmcaddr6 *im)
 {
 	struct ifmcaddr6 *pmc, *pmc_prev;
-	struct ip6_sf_list *psf, *psf_next;
+	struct ip6_sf_list *psf;
+	struct in6_addr *pmca = &im->mca_addr;
 
 	spin_lock_bh(&idev->mc_lock);
 	pmc_prev = NULL;
@@ -767,14 +766,21 @@ static void mld_del_delrec(struct inet6_
 	}
 	spin_unlock_bh(&idev->mc_lock);
 
+	spin_lock_bh(&im->mca_lock);
 	if (pmc) {
-		for (psf=pmc->mca_tomb; psf; psf=psf_next) {
-			psf_next = psf->sf_next;
-			kfree(psf);
+		im->idev = pmc->idev;
+		im->mca_crcount = idev->mc_qrv;
+		im->mca_sfmode = pmc->mca_sfmode;
+		if (pmc->mca_sfmode == MCAST_INCLUDE) {
+			im->mca_tomb = pmc->mca_tomb;
+			im->mca_sources = pmc->mca_sources;
+			for (psf = im->mca_sources; psf; psf = psf->sf_next)
+				psf->sf_crcount = im->mca_crcount;
 		}
 		in6_dev_put(pmc->idev);
 		kfree(pmc);
 	}
+	spin_unlock_bh(&im->mca_lock);
 }
 
 static void mld_clear_delrec(struct inet6_dev *idev)
@@ -877,7 +883,7 @@ int ipv6_dev_mc_inc(struct net_device *d
 	idev->mc_list = mc;
 	write_unlock_bh(&idev->lock);
 
-	mld_del_delrec(idev, &mc->mca_addr);
+	mld_del_delrec(idev, mc);
 	igmp6_group_added(mc);
 	ma_put(mc);
 	return 0;
@@ -898,6 +904,7 @@ int __ipv6_dev_mc_dec(struct inet6_dev *
 				write_unlock_bh(&idev->lock);
 
 				igmp6_group_dropped(ma);
+				ip6_mc_clear_src(ma);
 
 				ma_put(ma);
 				return 0;
@@ -2231,18 +2238,20 @@ void ipv6_mc_down(struct inet6_dev *idev
 	/* Withdraw multicast list */
 
 	read_lock_bh(&idev->lock);
+
+	for (i = idev->mc_list; i; i=i->next)
+		igmp6_group_dropped(i);
+
+	/* Should stop timer after group drop. or we will
+	 * start timer again in mld_ifc_event()
+	 */
 	idev->mc_ifc_count = 0;
 	if (del_timer(&idev->mc_ifc_timer))
 		__in6_dev_put(idev);
 	idev->mc_gq_running = 0;
 	if (del_timer(&idev->mc_gq_timer))
 		__in6_dev_put(idev);
-
-	for (i = idev->mc_list; i; i=i->next)
-		igmp6_group_dropped(i);
 	read_unlock_bh(&idev->lock);
-
-	mld_clear_delrec(idev);
 }
 
 
@@ -2255,8 +2264,10 @@ void ipv6_mc_up(struct inet6_dev *idev)
 	/* Install multicast list, except for all-nodes (already installed) */
 
 	read_lock_bh(&idev->lock);
-	for (i = idev->mc_list; i; i=i->next)
+	for (i = idev->mc_list; i; i = i->next) {
+		mld_del_delrec(idev, i);
 		igmp6_group_added(i);
+	}
 	read_unlock_bh(&idev->lock);
 }
 
@@ -2289,6 +2300,7 @@ void ipv6_mc_destroy_dev(struct inet6_de
 
 	/* Deactivate timers */
 	ipv6_mc_down(idev);
+	mld_clear_delrec(idev);
 
 	/* Delete all-nodes address. */
 	/* We cannot call ipv6_dev_mc_dec() directly, our caller in
@@ -2303,11 +2315,9 @@ void ipv6_mc_destroy_dev(struct inet6_de
 	write_lock_bh(&idev->lock);
 	while ((i = idev->mc_list) != NULL) {
 		idev->mc_list = i->next;
-		write_unlock_bh(&idev->lock);
 
-		igmp6_group_dropped(i);
+		write_unlock_bh(&idev->lock);
 		ma_put(i);
-
 		write_lock_bh(&idev->lock);
 	}
 	write_unlock_bh(&idev->lock);
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/ipv6/raw.c linux-libre-3.2.87-gnu1/net/ipv6/raw.c
--- linux-libre-3.2.86-gnu1/net/ipv6/raw.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/ipv6/raw.c	2017-03-15 22:19:00.000000000 -0400
@@ -576,8 +576,11 @@ static int rawv6_push_pending_frames(str
 	}
 
 	offset += skb_transport_offset(skb);
-	if (skb_copy_bits(skb, offset, &csum, 2))
-		BUG();
+	err = skb_copy_bits(skb, offset, &csum, 2);
+	if (err < 0) {
+		ip6_flush_pending_frames(sk);
+		goto out;
+	}
 
 	/* in case cksum was not initialized */
 	if (unlikely(csum))
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/irda/irqueue.c linux-libre-3.2.87-gnu1/net/irda/irqueue.c
--- linux-libre-3.2.86-gnu1/net/irda/irqueue.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/irda/irqueue.c	2017-03-15 22:19:00.000000000 -0400
@@ -385,9 +385,6 @@ EXPORT_SYMBOL(hashbin_new);
  *    for deallocating this structure if it's complex. If not the user can
  *    just supply kfree, which should take care of the job.
  */
-#ifdef CONFIG_LOCKDEP
-static int hashbin_lock_depth = 0;
-#endif
 int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func)
 {
 	irda_queue_t* queue;
@@ -398,22 +395,27 @@ int hashbin_delete( hashbin_t* hashbin,
 	IRDA_ASSERT(hashbin->magic == HB_MAGIC, return -1;);
 
 	/* Synchronize */
-	if ( hashbin->hb_type & HB_LOCK ) {
-		spin_lock_irqsave_nested(&hashbin->hb_spinlock, flags,
-					 hashbin_lock_depth++);
-	}
+	if (hashbin->hb_type & HB_LOCK)
+		spin_lock_irqsave(&hashbin->hb_spinlock, flags);
 
 	/*
 	 *  Free the entries in the hashbin, TODO: use hashbin_clear when
 	 *  it has been shown to work
 	 */
 	for (i = 0; i < HASHBIN_SIZE; i ++ ) {
-		queue = dequeue_first((irda_queue_t**) &hashbin->hb_queue[i]);
-		while (queue ) {
-			if (free_func)
-				(*free_func)(queue);
-			queue = dequeue_first(
-				(irda_queue_t**) &hashbin->hb_queue[i]);
+		while (1) {
+			queue = dequeue_first((irda_queue_t**) &hashbin->hb_queue[i]);
+
+			if (!queue)
+				break;
+
+			if (free_func) {
+				if (hashbin->hb_type & HB_LOCK)
+					spin_unlock_irqrestore(&hashbin->hb_spinlock, flags);
+				free_func(queue);
+				if (hashbin->hb_type & HB_LOCK)
+					spin_lock_irqsave(&hashbin->hb_spinlock, flags);
+			}
 		}
 	}
 
@@ -422,12 +424,8 @@ int hashbin_delete( hashbin_t* hashbin,
 	hashbin->magic = ~HB_MAGIC;
 
 	/* Release lock */
-	if ( hashbin->hb_type & HB_LOCK) {
+	if (hashbin->hb_type & HB_LOCK)
 		spin_unlock_irqrestore(&hashbin->hb_spinlock, flags);
-#ifdef CONFIG_LOCKDEP
-		hashbin_lock_depth--;
-#endif
-	}
 
 	/*
 	 *  Free the hashbin structure
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/l2tp/l2tp_core.h linux-libre-3.2.87-gnu1/net/l2tp/l2tp_core.h
--- linux-libre-3.2.86-gnu1/net/l2tp/l2tp_core.h	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/l2tp/l2tp_core.h	2017-03-15 22:19:00.000000000 -0400
@@ -240,6 +240,7 @@ extern int l2tp_xmit_skb(struct l2tp_ses
 
 extern int l2tp_nl_register_ops(enum l2tp_pwtype pw_type, const struct l2tp_nl_cmd_ops *ops);
 extern void l2tp_nl_unregister_ops(enum l2tp_pwtype pw_type);
+int l2tp_ioctl(struct sock *sk, int cmd, unsigned long arg);
 
 /* Session reference counts. Incremented when code obtains a reference
  * to a session.
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/l2tp/l2tp_ip.c linux-libre-3.2.87-gnu1/net/l2tp/l2tp_ip.c
--- linux-libre-3.2.86-gnu1/net/l2tp/l2tp_ip.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/l2tp/l2tp_ip.c	2017-03-15 22:19:00.000000000 -0400
@@ -9,6 +9,7 @@
  *	2 of the License, or (at your option) any later version.
  */
 
+#include <asm/ioctls.h>
 #include <linux/icmp.h>
 #include <linux/module.h>
 #include <linux/skbuff.h>
@@ -612,6 +613,30 @@ out:
 	return copied;
 }
 
+int l2tp_ioctl(struct sock *sk, int cmd, unsigned long arg)
+{
+	struct sk_buff *skb;
+	int amount;
+
+	switch (cmd) {
+	case SIOCOUTQ:
+		amount = sk_wmem_alloc_get(sk);
+		break;
+	case SIOCINQ:
+		spin_lock_bh(&sk->sk_receive_queue.lock);
+		skb = skb_peek(&sk->sk_receive_queue);
+		amount = skb ? skb->len : 0;
+		spin_unlock_bh(&sk->sk_receive_queue.lock);
+		break;
+
+	default:
+		return -ENOIOCTLCMD;
+	}
+
+	return put_user(amount, (int __user *)arg);
+}
+EXPORT_SYMBOL(l2tp_ioctl);
+
 static struct proto l2tp_ip_prot = {
 	.name		   = "L2TP/IP",
 	.owner		   = THIS_MODULE,
@@ -620,7 +645,7 @@ static struct proto l2tp_ip_prot = {
 	.bind		   = l2tp_ip_bind,
 	.connect	   = l2tp_ip_connect,
 	.disconnect	   = l2tp_ip_disconnect,
-	.ioctl		   = udp_ioctl,
+	.ioctl		   = l2tp_ioctl,
 	.destroy	   = l2tp_ip_destroy_sock,
 	.setsockopt	   = ip_setsockopt,
 	.getsockopt	   = ip_getsockopt,
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/llc/llc_conn.c linux-libre-3.2.87-gnu1/net/llc/llc_conn.c
--- linux-libre-3.2.86-gnu1/net/llc/llc_conn.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/llc/llc_conn.c	2017-03-15 22:19:00.000000000 -0400
@@ -821,7 +821,10 @@ void llc_conn_handler(struct llc_sap *sa
 		 * another trick required to cope with how the PROCOM state
 		 * machine works. -acme
 		 */
+		skb_orphan(skb);
+		sock_hold(sk);
 		skb->sk = sk;
+		skb->destructor = sock_efree;
 	}
 	if (!sock_owned_by_user(sk))
 		llc_conn_rcv(sk, skb);
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/llc/llc_sap.c linux-libre-3.2.87-gnu1/net/llc/llc_sap.c
--- linux-libre-3.2.86-gnu1/net/llc/llc_sap.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/llc/llc_sap.c	2017-03-15 22:19:00.000000000 -0400
@@ -294,7 +294,10 @@ static void llc_sap_rcv(struct llc_sap *
 
 	ev->type   = LLC_SAP_EV_TYPE_PDU;
 	ev->reason = 0;
+	skb_orphan(skb);
+	sock_hold(sk);
 	skb->sk = sk;
+	skb->destructor = sock_efree;
 	llc_sap_state_process(sap, skb);
 }
 
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/mac80211/mesh.c linux-libre-3.2.87-gnu1/net/mac80211/mesh.c
--- linux-libre-3.2.86-gnu1/net/mac80211/mesh.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/mac80211/mesh.c	2017-03-15 22:19:00.000000000 -0400
@@ -280,7 +280,7 @@ mesh_add_vendor_ies(struct sk_buff *skb,
 	/* fast-forward to vendor IEs */
 	offset = ieee80211_ie_split_vendor(ifmsh->ie, ifmsh->ie_len, 0);
 
-	if (offset) {
+	if (offset < ifmsh->ie_len) {
 		len = ifmsh->ie_len - offset;
 		data = ifmsh->ie + offset;
 		if (skb_tailroom(skb) < len)
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/packet/af_packet.c linux-libre-3.2.87-gnu1/net/packet/af_packet.c
--- linux-libre-3.2.86-gnu1/net/packet/af_packet.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/packet/af_packet.c	2017-03-15 22:19:00.000000000 -0400
@@ -1242,6 +1242,8 @@ static void __fanout_link(struct sock *s
 	f->arr[f->num_members] = sk;
 	smp_wmb();
 	f->num_members++;
+	if (f->num_members == 1)
+		dev_add_pack(&f->prot_hook);
 	spin_unlock(&f->lock);
 }
 
@@ -1258,6 +1260,8 @@ static void __fanout_unlink(struct sock
 	BUG_ON(i >= f->num_members);
 	f->arr[i] = f->arr[f->num_members - 1];
 	f->num_members--;
+	if (f->num_members == 0)
+		__dev_remove_pack(&f->prot_hook);
 	spin_unlock(&f->lock);
 }
 
@@ -1286,13 +1290,16 @@ static int fanout_add(struct sock *sk, u
 		return -EINVAL;
 	}
 
+	mutex_lock(&fanout_mutex);
+
+	err = -EINVAL;
 	if (!po->running)
-		return -EINVAL;
+		goto out;
 
+	err = -EALREADY;
 	if (po->fanout)
-		return -EALREADY;
+		goto out;
 
-	mutex_lock(&fanout_mutex);
 	match = NULL;
 	list_for_each_entry(f, &fanout_list, list) {
 		if (f->id == id &&
@@ -1322,7 +1329,6 @@ static int fanout_add(struct sock *sk, u
 		match->prot_hook.func = packet_rcv_fanout;
 		match->prot_hook.af_packet_priv = match;
 		match->prot_hook.id_match = match_fanout_group;
-		dev_add_pack(&match->prot_hook);
 		list_add(&match->list, &fanout_list);
 	}
 	err = -EINVAL;
@@ -1343,24 +1349,29 @@ out:
 	return err;
 }
 
-static void fanout_release(struct sock *sk)
+/* If pkt_sk(sk)->fanout->sk_ref is zero, this function removes
+ * pkt_sk(sk)->fanout from fanout_list and returns pkt_sk(sk)->fanout.
+ * It is the responsibility of the caller to call fanout_release_data() and
+ * free the returned packet_fanout (after synchronize_net())
+ */
+static struct packet_fanout *fanout_release(struct sock *sk)
 {
 	struct packet_sock *po = pkt_sk(sk);
 	struct packet_fanout *f;
 
+	mutex_lock(&fanout_mutex);
 	f = po->fanout;
-	if (!f)
-		return;
-
-	po->fanout = NULL;
+	if (f) {
+		po->fanout = NULL;
 
-	mutex_lock(&fanout_mutex);
-	if (atomic_dec_and_test(&f->sk_ref)) {
-		list_del(&f->list);
-		dev_remove_pack(&f->prot_hook);
-		kfree(f);
+		if (atomic_dec_and_test(&f->sk_ref))
+			list_del(&f->list);
+		else
+			f = NULL;
 	}
 	mutex_unlock(&fanout_mutex);
+
+	return f;
 }
 
 static const struct proto_ops packet_ops;
@@ -2383,6 +2394,7 @@ static int packet_release(struct socket
 {
 	struct sock *sk = sock->sk;
 	struct packet_sock *po;
+	struct packet_fanout *f;
 	struct net *net;
 	union tpacket_req_u req_u;
 
@@ -2417,9 +2429,12 @@ static int packet_release(struct socket
 		packet_set_ring(sk, &req_u, 1, 1);
 	}
 
-	fanout_release(sk);
+	f = fanout_release(sk);
 
 	synchronize_net();
+
+	kfree(f);
+
 	/*
 	 *	Now the socket is dead. No more input will appear.
 	 */
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/sched/act_pedit.c linux-libre-3.2.87-gnu1/net/sched/act_pedit.c
--- linux-libre-3.2.86-gnu1/net/sched/act_pedit.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/sched/act_pedit.c	2017-03-15 22:19:00.000000000 -0400
@@ -120,6 +120,17 @@ static int tcf_pedit_cleanup(struct tc_a
 	return 0;
 }
 
+static bool offset_valid(struct sk_buff *skb, int offset)
+{
+	if (offset > 0 && offset > skb->len)
+		return false;
+
+	if  (offset < 0 && -offset > skb_headroom(skb))
+		return false;
+
+	return true;
+}
+
 static int tcf_pedit(struct sk_buff *skb, const struct tc_action *a,
 		     struct tcf_result *res)
 {
@@ -147,6 +158,11 @@ static int tcf_pedit(struct sk_buff *skb
 			if (tkey->offmask) {
 				char *d, _d;
 
+				if (!offset_valid(skb, off + tkey->at)) {
+					pr_info("tc filter pedit 'at' offset %d out of bounds\n",
+						off + tkey->at);
+					goto bad;
+				}
 				d = skb_header_pointer(skb, off + tkey->at, 1,
 						       &_d);
 				if (!d)
@@ -159,10 +175,10 @@ static int tcf_pedit(struct sk_buff *skb
 					" offset must be on 32 bit boundaries\n");
 				goto bad;
 			}
-			if (offset > 0 && offset > skb->len) {
-				pr_info("tc filter pedit"
-					" offset %d can't exceed pkt length %d\n",
-				       offset, skb->len);
+
+			if (!offset_valid(skb, off + offset)) {
+				pr_info("tc filter pedit offset %d out of bounds\n",
+					offset);
 				goto bad;
 			}
 
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/sched/cls_api.c linux-libre-3.2.87-gnu1/net/sched/cls_api.c
--- linux-libre-3.2.86-gnu1/net/sched/cls_api.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/sched/cls_api.c	2017-03-15 22:19:00.000000000 -0400
@@ -137,9 +137,11 @@ static int tc_ctl_tfilter(struct sk_buff
 	unsigned long cl;
 	unsigned long fh;
 	int err;
-	int tp_created = 0;
+	int tp_created;
 
 replay:
+	tp_created = 0;
+
 	t = NLMSG_DATA(n);
 	protocol = TC_H_MIN(t->tcm_info);
 	prio = TC_H_MAJ(t->tcm_info);
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/sched/em_meta.c linux-libre-3.2.87-gnu1/net/sched/em_meta.c
--- linux-libre-3.2.86-gnu1/net/sched/em_meta.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/sched/em_meta.c	2017-03-15 22:19:00.000000000 -0400
@@ -176,11 +176,12 @@ META_COLLECTOR(int_vlan_tag)
 {
 	unsigned short tag;
 
-	tag = vlan_tx_tag_get(skb);
-	if (!tag && __vlan_get_tag(skb, &tag))
-		*err = -1;
-	else
+	if (vlan_tx_tag_present(skb))
+		dst->value = vlan_tx_tag_get(skb);
+	else if (!__vlan_get_tag(skb, &tag))
 		dst->value = tag;
+	else
+		*err = -1;
 }
 
 
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/sched/sch_dsmark.c linux-libre-3.2.87-gnu1/net/sched/sch_dsmark.c
--- linux-libre-3.2.86-gnu1/net/sched/sch_dsmark.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/sched/sch_dsmark.c	2017-03-15 22:19:00.000000000 -0400
@@ -260,6 +260,7 @@ static int dsmark_enqueue(struct sk_buff
 		return err;
 	}
 
+	sch->qstats.backlog += qdisc_pkt_len(skb);
 	sch->q.qlen++;
 
 	return NET_XMIT_SUCCESS;
@@ -283,6 +284,7 @@ static struct sk_buff *dsmark_dequeue(st
 		return NULL;
 
 	qdisc_bstats_update(sch, skb);
+	sch->qstats.backlog -= qdisc_pkt_len(skb);
 	sch->q.qlen--;
 
 	index = skb->tc_index & (p->indices - 1);
@@ -398,6 +400,7 @@ static void dsmark_reset(struct Qdisc *s
 
 	pr_debug("dsmark_reset(sch %p,[qdisc %p])\n", sch, p);
 	qdisc_reset(p->q);
+	sch->qstats.backlog = 0;
 	sch->q.qlen = 0;
 }
 
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/sched/sch_htb.c linux-libre-3.2.87-gnu1/net/sched/sch_htb.c
--- linux-libre-3.2.86-gnu1/net/sched/sch_htb.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/sched/sch_htb.c	2017-03-15 22:19:00.000000000 -0400
@@ -580,6 +580,7 @@ static int htb_enqueue(struct sk_buff *s
 		htb_activate(q, cl);
 	}
 
+	sch->qstats.backlog += qdisc_pkt_len(skb);
 	sch->q.qlen++;
 	return NET_XMIT_SUCCESS;
 }
@@ -867,6 +868,7 @@ static struct sk_buff *htb_dequeue(struc
 ok:
 		qdisc_bstats_update(sch, skb);
 		qdisc_unthrottled(sch);
+		sch->qstats.backlog -= qdisc_pkt_len(skb);
 		sch->q.qlen--;
 		return skb;
 	}
@@ -927,6 +929,7 @@ static unsigned int htb_drop(struct Qdis
 			unsigned int len;
 			if (cl->un.leaf.q->ops->drop &&
 			    (len = cl->un.leaf.q->ops->drop(cl->un.leaf.q))) {
+				sch->qstats.backlog -= len;
 				sch->q.qlen--;
 				if (!cl->un.leaf.q->q.qlen)
 					htb_deactivate(q, cl);
@@ -957,12 +960,12 @@ static void htb_reset(struct Qdisc *sch)
 			}
 			cl->prio_activity = 0;
 			cl->cmode = HTB_CAN_SEND;
-
 		}
 	}
 	qdisc_watchdog_cancel(&q->watchdog);
 	__skb_queue_purge(&q->direct_queue);
 	sch->q.qlen = 0;
+	sch->qstats.backlog = 0;
 	memset(q->row, 0, sizeof(q->row));
 	memset(q->row_mask, 0, sizeof(q->row_mask));
 	memset(q->wait_pq, 0, sizeof(q->wait_pq));
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/sctp/socket.c linux-libre-3.2.87-gnu1/net/sctp/socket.c
--- linux-libre-3.2.86-gnu1/net/sctp/socket.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/sctp/socket.c	2017-03-15 22:19:00.000000000 -0400
@@ -1223,9 +1223,12 @@ static int __sctp_connect(struct sock* s
 
 	timeo = sock_sndtimeo(sk, f_flags & O_NONBLOCK);
 
-	err = sctp_wait_for_connect(asoc, &timeo);
-	if ((err == 0 || err == -EINPROGRESS) && assoc_id)
+	if (assoc_id)
 		*assoc_id = asoc->assoc_id;
+	err = sctp_wait_for_connect(asoc, &timeo);
+	/* Note: the asoc may be freed after the return of
+	 * sctp_wait_for_connect.
+	 */
 
 	/* Don't free association on exit. */
 	asoc = NULL;
@@ -4193,7 +4196,7 @@ static int sctp_getsockopt_disable_fragm
 static int sctp_getsockopt_events(struct sock *sk, int len, char __user *optval,
 				  int __user *optlen)
 {
-	if (len <= 0)
+	if (len == 0)
 		return -EINVAL;
 	if (len > sizeof(struct sctp_event_subscribe))
 		len = sizeof(struct sctp_event_subscribe);
@@ -4239,6 +4242,12 @@ SCTP_STATIC int sctp_do_peeloff(struct s
 	struct sctp_af *af;
 	int err = 0;
 
+	/* If there is a thread waiting on more sndbuf space for
+	 * sending on this asoc, it cannot be peeled.
+	 */
+	if (waitqueue_active(&asoc->wait))
+		return -EBUSY;
+
 	/* An association cannot be branched off from an already peeled-off
 	 * socket, nor is this supported for tcp style sockets.
 	 */
@@ -5586,6 +5595,9 @@ SCTP_STATIC int sctp_getsockopt(struct s
 	if (get_user(len, optlen))
 		return -EFAULT;
 
+	if (len < 0)
+		return -EINVAL;
+
 	sctp_lock_sock(sk);
 
 	switch (optname) {
@@ -6486,7 +6498,6 @@ static int sctp_wait_for_sndbuf(struct s
 		 */
 		sctp_release_sock(sk);
 		current_timeo = schedule_timeout(current_timeo);
-		BUG_ON(sk != asoc->base.sk);
 		sctp_lock_sock(sk);
 
 		*timeo_p = current_timeo;
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/socket.c linux-libre-3.2.87-gnu1/net/socket.c
--- linux-libre-3.2.86-gnu1/net/socket.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/socket.c	2017-03-15 22:19:00.000000000 -0400
@@ -1898,7 +1898,7 @@ static int copy_msghdr_from_user(struct
 
 static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
 			  struct msghdr *msg_sys, unsigned flags,
-			  struct used_address *used_address)
+			  struct used_address *used_address, int *residue)
 {
 	struct compat_msghdr __user *msg_compat =
 	    (struct compat_msghdr __user *)msg;
@@ -2004,6 +2004,8 @@ static int ___sys_sendmsg(struct socket
 			memcpy(&used_address->name, msg_sys->msg_name,
 			       used_address->name_len);
 	}
+	if (residue && err >= 0)
+		*residue = total_len - err;
 
 out_freectl:
 	if (ctl_buf != ctl)
@@ -2029,7 +2031,7 @@ long __sys_sendmsg(int fd, struct msghdr
 	if (!sock)
 		goto out;
 
-	err = ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL);
+	err = ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL, NULL);
 
 	fput_light(sock->file, fput_needed);
 out:
@@ -2056,6 +2058,7 @@ int __sys_sendmmsg(int fd, struct mmsghd
 	struct compat_mmsghdr __user *compat_entry;
 	struct msghdr msg_sys;
 	struct used_address used_address;
+	int residue;
 
 	if (vlen > UIO_MAXIOV)
 		vlen = UIO_MAXIOV;
@@ -2074,7 +2077,8 @@ int __sys_sendmmsg(int fd, struct mmsghd
 	while (datagrams < vlen) {
 		if (MSG_CMSG_COMPAT & flags) {
 			err = ___sys_sendmsg(sock, (struct msghdr __user *)compat_entry,
-					     &msg_sys, flags, &used_address);
+					     &msg_sys, flags, &used_address,
+					     &residue);
 			if (err < 0)
 				break;
 			err = __put_user(err, &compat_entry->msg_len);
@@ -2082,7 +2086,8 @@ int __sys_sendmmsg(int fd, struct mmsghd
 		} else {
 			err = ___sys_sendmsg(sock,
 					     (struct msghdr __user *)entry,
-					     &msg_sys, flags, &used_address);
+					     &msg_sys, flags, &used_address,
+					     &residue);
 			if (err < 0)
 				break;
 			err = put_user(err, &entry->msg_len);
@@ -2092,6 +2097,8 @@ int __sys_sendmmsg(int fd, struct mmsghd
 		if (err)
 			break;
 		++datagrams;
+		if (residue)
+			break;
 	}
 
 	fput_light(sock->file, fput_needed);
@@ -2262,8 +2269,10 @@ int __sys_recvmmsg(int fd, struct mmsghd
 		return err;
 
 	err = sock_error(sock->sk);
-	if (err)
+	if (err) {
+		datagrams = err;
 		goto out_put;
+	}
 
 	entry = mmsg;
 	compat_entry = (struct compat_mmsghdr __user *)mmsg;
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/net/sunrpc/auth_gss/svcauth_gss.c linux-libre-3.2.87-gnu1/net/sunrpc/auth_gss/svcauth_gss.c
--- linux-libre-3.2.86-gnu1/net/sunrpc/auth_gss/svcauth_gss.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/net/sunrpc/auth_gss/svcauth_gss.c	2017-03-15 22:19:00.000000000 -0400
@@ -1151,7 +1151,7 @@ svcauth_gss_accept(struct svc_rqst *rqst
 	case RPC_GSS_PROC_DESTROY:
 		if (gss_write_verf(rqstp, rsci->mechctx, gc->gc_seq))
 			goto auth_err;
-		rsci->h.expiry_time = get_seconds();
+		rsci->h.expiry_time = seconds_since_boot();
 		set_bit(CACHE_NEGATIVE, &rsci->h.flags);
 		if (resv->iov_len + 4 > PAGE_SIZE)
 			goto drop;
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/scripts/kconfig/nconf.gui.c linux-libre-3.2.87-gnu1/scripts/kconfig/nconf.gui.c
--- linux-libre-3.2.86-gnu1/scripts/kconfig/nconf.gui.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/scripts/kconfig/nconf.gui.c	2017-03-15 22:19:00.000000000 -0400
@@ -364,12 +364,14 @@ int dialog_inputbox(WINDOW *main_window,
 	WINDOW *prompt_win;
 	WINDOW *form_win;
 	PANEL *panel;
-	int i, x, y;
+	int i, x, y, lines, columns, win_lines, win_cols;
 	int res = -1;
 	int cursor_position = strlen(init);
 	int cursor_form_win;
 	char *result = *resultp;
 
+	getmaxyx(stdscr, lines, columns);
+
 	if (strlen(init)+1 > *result_len) {
 		*result_len = strlen(init)+1;
 		*resultp = result = realloc(result, *result_len);
@@ -386,14 +388,19 @@ int dialog_inputbox(WINDOW *main_window,
 	if (title)
 		prompt_width = max(prompt_width, strlen(title));
 
+	win_lines = min(prompt_lines+6, lines-2);
+	win_cols = min(prompt_width+7, columns-2);
+	prompt_lines = max(win_lines-6, 0);
+	prompt_width = max(win_cols-7, 0);
+
 	/* place dialog in middle of screen */
-	y = (LINES-(prompt_lines+4))/2;
-	x = (COLS-(prompt_width+4))/2;
+	y = (lines-win_lines)/2;
+	x = (columns-win_cols)/2;
 
 	strncpy(result, init, *result_len);
 
 	/* create the windows */
-	win = newwin(prompt_lines+6, prompt_width+7, y, x);
+	win = newwin(win_lines, win_cols, y, x);
 	prompt_win = derwin(win, prompt_lines+1, prompt_width, 2, 2);
 	form_win = derwin(win, 1, prompt_width, prompt_lines+3, 2);
 	keypad(form_win, TRUE);
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/sound/core/seq/seq_memory.c linux-libre-3.2.87-gnu1/sound/core/seq/seq_memory.c
--- linux-libre-3.2.86-gnu1/sound/core/seq/seq_memory.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/sound/core/seq/seq_memory.c	2017-03-15 22:19:00.000000000 -0400
@@ -421,7 +421,6 @@ int snd_seq_pool_done(struct snd_seq_poo
 {
 	unsigned long flags;
 	struct snd_seq_event_cell *ptr;
-	int max_count = 5 * HZ;
 
 	if (snd_BUG_ON(!pool))
 		return -EINVAL;
@@ -434,14 +433,8 @@ int snd_seq_pool_done(struct snd_seq_poo
 	if (waitqueue_active(&pool->output_sleep))
 		wake_up(&pool->output_sleep);
 
-	while (atomic_read(&pool->counter) > 0) {
-		if (max_count == 0) {
-			snd_printk(KERN_WARNING "snd_seq_pool_done timeout: %d cells remain\n", atomic_read(&pool->counter));
-			break;
-		}
+	while (atomic_read(&pool->counter) > 0)
 		schedule_timeout_uninterruptible(1);
-		max_count--;
-	}
 	
 	/* release all resources */
 	spin_lock_irqsave(&pool->lock, flags);
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/sound/core/seq/seq_queue.c linux-libre-3.2.87-gnu1/sound/core/seq/seq_queue.c
--- linux-libre-3.2.86-gnu1/sound/core/seq/seq_queue.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/sound/core/seq/seq_queue.c	2017-03-15 22:19:00.000000000 -0400
@@ -183,6 +183,8 @@ void __exit snd_seq_queues_delete(void)
 	}
 }
 
+static void queue_use(struct snd_seq_queue *queue, int client, int use);
+
 /* allocate a new queue -
  * return queue index value or negative value for error
  */
@@ -194,11 +196,11 @@ int snd_seq_queue_alloc(int client, int
 	if (q == NULL)
 		return -ENOMEM;
 	q->info_flags = info_flags;
+	queue_use(q, client, 1);
 	if (queue_list_add(q) < 0) {
 		queue_delete(q);
 		return -ENOMEM;
 	}
-	snd_seq_queue_use(q->queue, client, 1); /* use this queue */
 	return q->queue;
 }
 
@@ -504,19 +506,9 @@ int snd_seq_queue_timer_set_tempo(int qu
 	return result;
 }
 
-
-/* use or unuse this queue -
- * if it is the first client, starts the timer.
- * if it is not longer used by any clients, stop the timer.
- */
-int snd_seq_queue_use(int queueid, int client, int use)
+/* use or unuse this queue */
+static void queue_use(struct snd_seq_queue *queue, int client, int use)
 {
-	struct snd_seq_queue *queue;
-
-	queue = queueptr(queueid);
-	if (queue == NULL)
-		return -EINVAL;
-	mutex_lock(&queue->timer_mutex);
 	if (use) {
 		if (!test_and_set_bit(client, queue->clients_bitmap))
 			queue->clients++;
@@ -531,6 +523,21 @@ int snd_seq_queue_use(int queueid, int c
 	} else {
 		snd_seq_timer_close(queue);
 	}
+}
+
+/* use or unuse this queue -
+ * if it is the first client, starts the timer.
+ * if it is not longer used by any clients, stop the timer.
+ */
+int snd_seq_queue_use(int queueid, int client, int use)
+{
+	struct snd_seq_queue *queue;
+
+	queue = queueptr(queueid);
+	if (queue == NULL)
+		return -EINVAL;
+	mutex_lock(&queue->timer_mutex);
+	queue_use(queue, client, use);
 	mutex_unlock(&queue->timer_mutex);
 	queuefree(queue);
 	return 0;
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/sound/usb/card.c linux-libre-3.2.87-gnu1/sound/usb/card.c
--- linux-libre-3.2.86-gnu1/sound/usb/card.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/sound/usb/card.c	2017-03-15 22:19:00.000000000 -0400
@@ -207,7 +207,6 @@ static int snd_usb_create_stream(struct
 	if (! snd_usb_parse_audio_interface(chip, interface)) {
 		usb_set_interface(dev, interface, 0); /* reset the current interface */
 		usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1L);
-		return -EINVAL;
 	}
 
 	return 0;
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/sound/usb/mixer.c linux-libre-3.2.87-gnu1/sound/usb/mixer.c
--- linux-libre-3.2.86-gnu1/sound/usb/mixer.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/sound/usb/mixer.c	2017-03-15 22:19:00.000000000 -0400
@@ -841,9 +841,10 @@ static void volume_control_quirks(struct
 	case USB_ID(0x046d, 0x0826): /* HD Webcam c525 */
 	case USB_ID(0x046d, 0x08ca): /* Logitech Quickcam Fusion */
 	case USB_ID(0x046d, 0x0991):
+	case USB_ID(0x046d, 0x09a2): /* QuickCam Communicate Deluxe/S7500 */
 	/* Most audio usb devices lie about volume resolution.
 	 * Most Logitech webcams have res = 384.
-	 * Proboly there is some logitech magic behind this number --fishor
+	 * Probably there is some logitech magic behind this number --fishor
 	 */
 		if (!strcmp(kctl->id.name, "Mic Capture Volume")) {
 			snd_printk(KERN_INFO
diff -druNp --no-dereference linux-libre-3.2.86-gnu1/tools/perf/util/trace-event-scripting.c linux-libre-3.2.87-gnu1/tools/perf/util/trace-event-scripting.c
--- linux-libre-3.2.86-gnu1/tools/perf/util/trace-event-scripting.c	2017-02-26 15:01:33.000000000 -0500
+++ linux-libre-3.2.87-gnu1/tools/perf/util/trace-event-scripting.c	2017-03-15 22:19:00.000000000 -0400
@@ -88,7 +88,8 @@ static void register_python_scripting(st
 	if (err)
 		die("error registering py script extension");
 
-	scripting_context = malloc(sizeof(struct scripting_context));
+	if (scripting_context == NULL)
+		scripting_context = malloc(sizeof(*scripting_context));
 }
 
 #ifdef NO_LIBPYTHON
@@ -149,7 +150,8 @@ static void register_perl_scripting(stru
 	if (err)
 		die("error registering pl script extension");
 
-	scripting_context = malloc(sizeof(struct scripting_context));
+	if (scripting_context == NULL)
+		scripting_context = malloc(sizeof(*scripting_context));
 }
 
 #ifdef NO_LIBPERL
