diff -druNp --no-dereference linux-libre-3.2.99-gnu1/arch/m32r/kernel/ptrace.c linux-libre-3.2.100-gnu1/arch/m32r/kernel/ptrace.c
--- linux-libre-3.2.99-gnu1/arch/m32r/kernel/ptrace.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/arch/m32r/kernel/ptrace.c	2018-03-03 10:57:56.000000000 -0500
@@ -592,17 +592,16 @@ void user_enable_single_step(struct task
 
 	if (access_process_vm(child, pc&~3, &insn, sizeof(insn), 0)
 	    != sizeof(insn))
-		return -EIO;
+		return;
 
 	compute_next_pc(insn, pc, &next_pc, child);
 	if (next_pc & 0x80000000)
-		return -EIO;
+		return;
 
 	if (embed_debug_trap(child, next_pc))
-		return -EIO;
+		return;
 
 	invalidate_cache();
-	return 0;
 }
 
 void user_disable_single_step(struct task_struct *child)
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/arch/s390/include/asm/system.h linux-libre-3.2.100-gnu1/arch/s390/include/asm/system.h
--- linux-libre-3.2.99-gnu1/arch/s390/include/asm/system.h	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/arch/s390/include/asm/system.h	2018-03-03 10:57:56.000000000 -0500
@@ -89,17 +89,13 @@ static inline void restore_access_regs(u
 	asm volatile("lam 0,15,%0" : : "Q" (*acrs));
 }
 
-#define switch_to(prev,next,last) do {					\
-	if (prev->mm) {							\
-		save_fp_regs(&prev->thread.fp_regs);			\
-		save_access_regs(&prev->thread.acrs[0]);		\
-	}								\
-	if (next->mm) {							\
-		restore_fp_regs(&next->thread.fp_regs);			\
-		restore_access_regs(&next->thread.acrs[0]);		\
-		update_per_regs(next);					\
-	}								\
-	prev = __switch_to(prev,next);					\
+#define switch_to(prev, next, last) do {				\
+	save_fp_regs(&prev->thread.fp_regs);				\
+	save_access_regs(&prev->thread.acrs[0]);			\
+	restore_fp_regs(&next->thread.fp_regs);				\
+	restore_access_regs(&next->thread.acrs[0]);			\
+	update_per_regs(next);						\
+	prev = __switch_to(prev, next);					\
 } while (0)
 
 extern void account_vtime(struct task_struct *, struct task_struct *);
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/arch/s390/kernel/compat_linux.c linux-libre-3.2.100-gnu1/arch/s390/kernel/compat_linux.c
--- linux-libre-3.2.99-gnu1/arch/s390/kernel/compat_linux.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/arch/s390/kernel/compat_linux.c	2018-03-03 10:57:56.000000000 -0500
@@ -242,6 +242,7 @@ asmlinkage long sys32_setgroups16(int gi
 		return retval;
 	}
 
+	groups_sort(group_info);
 	retval = set_current_groups(group_info);
 	put_group_info(group_info);
 
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/arch/sh/boards/mach-se/770x/setup.c linux-libre-3.2.100-gnu1/arch/sh/boards/mach-se/770x/setup.c
--- linux-libre-3.2.99-gnu1/arch/sh/boards/mach-se/770x/setup.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/arch/sh/boards/mach-se/770x/setup.c	2018-03-03 10:57:56.000000000 -0500
@@ -8,6 +8,7 @@
  */
 #include <linux/init.h>
 #include <linux/platform_device.h>
+#include <linux/sh_eth.h>
 #include <mach-se/mach/se.h>
 #include <mach-se/mach/mrshpc.h>
 #include <asm/machvec.h>
@@ -114,13 +115,23 @@ static struct platform_device heartbeat_
 #if defined(CONFIG_CPU_SUBTYPE_SH7710) ||\
 	defined(CONFIG_CPU_SUBTYPE_SH7712)
 /* SH771X Ethernet driver */
+static struct sh_eth_plat_data sh_eth_plat = {
+	.phy = PHY_ID,
+	.phy_interface = PHY_INTERFACE_MODE_MII,
+};
+
 static struct resource sh_eth0_resources[] = {
 	[0] = {
 		.start = SH_ETH0_BASE,
-		.end = SH_ETH0_BASE + 0x1B8,
+		.end = SH_ETH0_BASE + 0x1B8 - 1,
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
+		.start = SH_TSU_BASE,
+		.end = SH_TSU_BASE + 0x200 - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[2] = {
 		.start = SH_ETH0_IRQ,
 		.end = SH_ETH0_IRQ,
 		.flags = IORESOURCE_IRQ,
@@ -131,7 +142,7 @@ static struct platform_device sh_eth0_de
 	.name = "sh-eth",
 	.id	= 0,
 	.dev = {
-		.platform_data = PHY_ID,
+		.platform_data = &sh_eth_plat,
 	},
 	.num_resources = ARRAY_SIZE(sh_eth0_resources),
 	.resource = sh_eth0_resources,
@@ -140,10 +151,15 @@ static struct platform_device sh_eth0_de
 static struct resource sh_eth1_resources[] = {
 	[0] = {
 		.start = SH_ETH1_BASE,
-		.end = SH_ETH1_BASE + 0x1B8,
+		.end = SH_ETH1_BASE + 0x1B8 - 1,
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
+		.start = SH_TSU_BASE,
+		.end = SH_TSU_BASE + 0x200 - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[2] = {
 		.start = SH_ETH1_IRQ,
 		.end = SH_ETH1_IRQ,
 		.flags = IORESOURCE_IRQ,
@@ -154,7 +170,7 @@ static struct platform_device sh_eth1_de
 	.name = "sh-eth",
 	.id	= 1,
 	.dev = {
-		.platform_data = PHY_ID,
+		.platform_data = &sh_eth_plat,
 	},
 	.num_resources = ARRAY_SIZE(sh_eth1_resources),
 	.resource = sh_eth1_resources,
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/arch/sh/include/mach-se/mach/se.h linux-libre-3.2.100-gnu1/arch/sh/include/mach-se/mach/se.h
--- linux-libre-3.2.99-gnu1/arch/sh/include/mach-se/mach/se.h	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/arch/sh/include/mach-se/mach/se.h	2018-03-03 10:57:56.000000000 -0500
@@ -98,6 +98,7 @@
 /* Base address */
 #define SH_ETH0_BASE 0xA7000000
 #define SH_ETH1_BASE 0xA7000400
+#define SH_TSU_BASE  0xA7000800
 /* PHY ID */
 #if defined(CONFIG_CPU_SUBTYPE_SH7710)
 # define PHY_ID 0x00
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/arch/x86/include/asm/kvm_host.h linux-libre-3.2.100-gnu1/arch/x86/include/asm/kvm_host.h
--- linux-libre-3.2.99-gnu1/arch/x86/include/asm/kvm_host.h	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/arch/x86/include/asm/kvm_host.h	2018-03-03 10:57:56.000000000 -0500
@@ -694,13 +694,15 @@ enum emulation_result {
 #define EMULTYPE_NO_DECODE	    (1 << 0)
 #define EMULTYPE_TRAP_UD	    (1 << 1)
 #define EMULTYPE_SKIP		    (1 << 2)
+#define EMULTYPE_NO_REEXECUTE	    (1 << 4)
 int x86_emulate_instruction(struct kvm_vcpu *vcpu, unsigned long cr2,
 			    int emulation_type, void *insn, int insn_len);
 
 static inline int emulate_instruction(struct kvm_vcpu *vcpu,
 			int emulation_type)
 {
-	return x86_emulate_instruction(vcpu, 0, emulation_type, NULL, 0);
+	return x86_emulate_instruction(vcpu, 0,
+			emulation_type | EMULTYPE_NO_REEXECUTE, NULL, 0);
 }
 
 void kvm_enable_efer_bits(u64);
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/arch/x86/include/asm/traps.h linux-libre-3.2.100-gnu1/arch/x86/include/asm/traps.h
--- linux-libre-3.2.99-gnu1/arch/x86/include/asm/traps.h	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/arch/x86/include/asm/traps.h	2018-03-03 10:57:56.000000000 -0500
@@ -69,6 +69,7 @@ dotraplinkage void do_simd_coprocessor_e
 #ifdef CONFIG_X86_32
 dotraplinkage void do_iret_error(struct pt_regs *, long);
 #endif
+void do_mce(struct pt_regs *, long);
 
 static inline int get_si_code(unsigned long condition)
 {
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/arch/x86/kernel/cpu/mcheck/mce.c linux-libre-3.2.100-gnu1/arch/x86/kernel/cpu/mcheck/mce.c
--- linux-libre-3.2.99-gnu1/arch/x86/kernel/cpu/mcheck/mce.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/arch/x86/kernel/cpu/mcheck/mce.c	2018-03-03 10:57:56.000000000 -0500
@@ -1407,6 +1407,11 @@ static void unexpected_machine_check(str
 void (*machine_check_vector)(struct pt_regs *, long error_code) =
 						unexpected_machine_check;
 
+void do_mce(struct pt_regs *regs, long error_code)
+{
+	machine_check_vector(regs, error_code);
+}
+
 /*
  * Called for each booted CPU to set up machine checks.
  * Must be called with preempt off:
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/arch/x86/kernel/entry_64.S linux-libre-3.2.100-gnu1/arch/x86/kernel/entry_64.S
--- linux-libre-3.2.99-gnu1/arch/x86/kernel/entry_64.S	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/arch/x86/kernel/entry_64.S	2018-03-03 10:57:56.000000000 -0500
@@ -1399,7 +1399,7 @@ errorentry page_fault do_page_fault
 errorentry async_page_fault do_async_page_fault
 #endif
 #ifdef CONFIG_X86_MCE
-paranoidzeroentry machine_check *machine_check_vector(%rip)
+paranoidzeroentry machine_check do_mce
 #endif
 
 	/*
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/arch/x86/kvm/lapic.c linux-libre-3.2.100-gnu1/arch/x86/kvm/lapic.c
--- linux-libre-3.2.99-gnu1/arch/x86/kvm/lapic.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/arch/x86/kvm/lapic.c	2018-03-03 10:57:56.000000000 -0500
@@ -1022,7 +1022,7 @@ void kvm_lapic_set_base(struct kvm_vcpu
 	vcpu->arch.apic_base = value;
 	if (apic_x2apic_mode(apic)) {
 		u32 id = kvm_apic_id(apic);
-		u32 ldr = ((id & ~0xf) << 16) | (1 << (id & 0xf));
+		u32 ldr = ((id >> 4) << 16) | (1 << (id & 0xf));
 		apic_set_reg(apic, APIC_LDR, ldr);
 	}
 	apic->base_address = apic->vcpu->arch.apic_base &
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/arch/x86/kvm/vmx.c linux-libre-3.2.100-gnu1/arch/x86/kvm/vmx.c
--- linux-libre-3.2.99-gnu1/arch/x86/kvm/vmx.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/arch/x86/kvm/vmx.c	2018-03-03 10:57:56.000000000 -0500
@@ -573,8 +573,18 @@ static const int max_vmcs_field = ARRAY_
 
 static inline short vmcs_field_to_offset(unsigned long field)
 {
-	if (field >= max_vmcs_field || vmcs_field_to_offset_table[field] == 0)
+	if (field >= max_vmcs_field)
+		return -1;
+
+	/*
+	 * FIXME: Mitigation for CVE-2017-5753.  To be replaced with a
+	 * generic mechanism.
+	 */
+	asm("lfence");
+
+	if (vmcs_field_to_offset_table[field] == 0)
 		return -1;
+
 	return vmcs_field_to_offset_table[field];
 }
 
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/arch/x86/kvm/x86.c linux-libre-3.2.100-gnu1/arch/x86/kvm/x86.c
--- linux-libre-3.2.99-gnu1/arch/x86/kvm/x86.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/arch/x86/kvm/x86.c	2018-03-03 10:57:56.000000000 -0500
@@ -4888,10 +4888,14 @@ static int handle_emulation_failure(stru
 	return r;
 }
 
-static bool reexecute_instruction(struct kvm_vcpu *vcpu, gva_t gva)
+static bool reexecute_instruction(struct kvm_vcpu *vcpu, gva_t gva,
+				  int emulation_type)
 {
 	gpa_t gpa;
 
+	if (emulation_type & EMULTYPE_NO_REEXECUTE)
+		return false;
+
 	if (tdp_enabled)
 		return false;
 
@@ -4942,7 +4946,7 @@ int x86_emulate_instruction(struct kvm_v
 		if (r != EMULATION_OK)  {
 			if (emulation_type & EMULTYPE_TRAP_UD)
 				return EMULATE_FAIL;
-			if (reexecute_instruction(vcpu, cr2))
+			if (reexecute_instruction(vcpu, cr2, emulation_type))
 				return EMULATE_DONE;
 			if (emulation_type & EMULTYPE_SKIP)
 				return EMULATE_FAIL;
@@ -4969,7 +4973,7 @@ restart:
 		return EMULATE_DONE;
 
 	if (r == EMULATION_FAILED) {
-		if (reexecute_instruction(vcpu, cr2))
+		if (reexecute_instruction(vcpu, cr2, emulation_type))
 			return EMULATE_DONE;
 
 		return handle_emulation_failure(vcpu);
@@ -6073,7 +6077,7 @@ int kvm_arch_vcpu_ioctl_set_regs(struct
 #endif
 
 	kvm_rip_write(vcpu, regs->rip);
-	kvm_set_rflags(vcpu, regs->rflags);
+	kvm_set_rflags(vcpu, regs->rflags | 0x2 /*X86_EFLAGS_FIXED*/);
 
 	vcpu->arch.exception.pending = false;
 
@@ -6168,6 +6172,29 @@ int kvm_task_switch(struct kvm_vcpu *vcp
 }
 EXPORT_SYMBOL_GPL(kvm_task_switch);
 
+int kvm_valid_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
+{
+	if ((sregs->efer & EFER_LME) && (sregs->cr0 & X86_CR0_PG)) {
+		/*
+		 * When EFER.LME and CR0.PG are set, the processor is in
+		 * 64-bit mode (though maybe in a 32-bit code segment).
+		 * CR4.PAE and EFER.LMA must be set.
+		 */
+		if (!(sregs->cr4 & X86_CR4_PAE)
+		    || !(sregs->efer & EFER_LMA))
+			return -EINVAL;
+	} else {
+		/*
+		 * Not in 64-bit mode: EFER.LMA is clear and the code
+		 * segment cannot be 64-bit.
+		 */
+		if (sregs->efer & EFER_LMA || sregs->cs.l)
+			return -EINVAL;
+	}
+
+	return 0;
+}
+
 int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
 				  struct kvm_sregs *sregs)
 {
@@ -6178,6 +6205,9 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct
 	if (!guest_cpuid_has_xsave(vcpu) && (sregs->cr4 & X86_CR4_OSXSAVE))
 		return -EINVAL;
 
+	if (kvm_valid_sregs(vcpu, sregs))
+		return -EINVAL;
+
 	dt.size = sregs->idt.limit;
 	dt.address = sregs->idt.base;
 	kvm_x86_ops->set_idt(vcpu, &dt);
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/crypto/algapi.c linux-libre-3.2.100-gnu1/crypto/algapi.c
--- linux-libre-3.2.99-gnu1/crypto/algapi.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/crypto/algapi.c	2018-03-03 10:57:56.000000000 -0500
@@ -163,6 +163,18 @@ void crypto_remove_spawns(struct crypto_
 
 			spawn->alg = NULL;
 			spawns = &inst->alg.cra_users;
+
+			/*
+			 * We may encounter an unregistered instance here, since
+			 * an instance's spawns are set up prior to the instance
+			 * being registered.  An unregistered instance will have
+			 * NULL ->cra_users.next, since ->cra_users isn't
+			 * properly initialized until registration.  But an
+			 * unregistered instance cannot have any users, so treat
+			 * it the same as ->cra_users being empty.
+			 */
+			if (spawns->next == NULL)
+				break;
 		}
 	} while ((spawns = crypto_more_spawns(alg, &stack, &top,
 					      &secondary_spawns)));
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/acpi/apei/erst.c linux-libre-3.2.100-gnu1/drivers/acpi/apei/erst.c
--- linux-libre-3.2.99-gnu1/drivers/acpi/apei/erst.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/acpi/apei/erst.c	2018-03-03 10:57:56.000000000 -0500
@@ -1019,7 +1019,7 @@ skip:
 	/* The record may be cleared by others, try read next record */
 	if (len == -ENOENT)
 		goto skip;
-	else if (len < sizeof(*rcd)) {
+	else if (len < 0 || len < sizeof(*rcd)) {
 		rc = -EIO;
 		goto out;
 	}
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/acpi/sbshc.c linux-libre-3.2.100-gnu1/drivers/acpi/sbshc.c
--- linux-libre-3.2.99-gnu1/drivers/acpi/sbshc.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/acpi/sbshc.c	2018-03-03 10:57:56.000000000 -0500
@@ -288,8 +288,8 @@ static int acpi_smbus_hc_add(struct acpi
 	device->driver_data = hc;
 
 	acpi_ec_add_query_handler(hc->ec, hc->query_bit, NULL, smbus_alarm, hc);
-	printk(KERN_INFO PREFIX "SBS HC: EC = 0x%p, offset = 0x%0x, query_bit = 0x%0x\n",
-		hc->ec, hc->offset, hc->query_bit);
+	dev_info(&device->dev, "SBS HC: offset = 0x%0x, query_bit = 0x%0x\n",
+		 hc->offset, hc->query_bit);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/base/isa.c linux-libre-3.2.100-gnu1/drivers/base/isa.c
--- linux-libre-3.2.99-gnu1/drivers/base/isa.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/base/isa.c	2018-03-03 10:57:56.000000000 -0500
@@ -39,7 +39,7 @@ static int isa_bus_probe(struct device *
 {
 	struct isa_driver *isa_driver = dev->platform_data;
 
-	if (isa_driver->probe)
+	if (isa_driver && isa_driver->probe)
 		return isa_driver->probe(dev, to_isa_dev(dev)->id);
 
 	return 0;
@@ -49,7 +49,7 @@ static int isa_bus_remove(struct device
 {
 	struct isa_driver *isa_driver = dev->platform_data;
 
-	if (isa_driver->remove)
+	if (isa_driver && isa_driver->remove)
 		return isa_driver->remove(dev, to_isa_dev(dev)->id);
 
 	return 0;
@@ -59,7 +59,7 @@ static void isa_bus_shutdown(struct devi
 {
 	struct isa_driver *isa_driver = dev->platform_data;
 
-	if (isa_driver->shutdown)
+	if (isa_driver && isa_driver->shutdown)
 		isa_driver->shutdown(dev, to_isa_dev(dev)->id);
 }
 
@@ -67,7 +67,7 @@ static int isa_bus_suspend(struct device
 {
 	struct isa_driver *isa_driver = dev->platform_data;
 
-	if (isa_driver->suspend)
+	if (isa_driver && isa_driver->suspend)
 		return isa_driver->suspend(dev, to_isa_dev(dev)->id, state);
 
 	return 0;
@@ -77,7 +77,7 @@ static int isa_bus_resume(struct device
 {
 	struct isa_driver *isa_driver = dev->platform_data;
 
-	if (isa_driver->resume)
+	if (isa_driver && isa_driver->resume)
 		return isa_driver->resume(dev, to_isa_dev(dev)->id);
 
 	return 0;
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/crypto/n2_core.c linux-libre-3.2.100-gnu1/drivers/crypto/n2_core.c
--- linux-libre-3.2.99-gnu1/drivers/crypto/n2_core.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/crypto/n2_core.c	2018-03-03 10:57:56.000000000 -0500
@@ -1642,6 +1642,7 @@ static int queue_cache_init(void)
 					  CWQ_ENTRY_SIZE, 0, NULL);
 	if (!queue_cache[HV_NCS_QTYPE_CWQ - 1]) {
 		kmem_cache_destroy(queue_cache[HV_NCS_QTYPE_MAU - 1]);
+		queue_cache[HV_NCS_QTYPE_MAU - 1] = NULL;
 		return -ENOMEM;
 	}
 	return 0;
@@ -1651,6 +1652,8 @@ static void queue_cache_destroy(void)
 {
 	kmem_cache_destroy(queue_cache[HV_NCS_QTYPE_MAU - 1]);
 	kmem_cache_destroy(queue_cache[HV_NCS_QTYPE_CWQ - 1]);
+	queue_cache[HV_NCS_QTYPE_MAU - 1] = NULL;
+	queue_cache[HV_NCS_QTYPE_CWQ - 1] = NULL;
 }
 
 static int spu_queue_register(struct spu_queue *p, unsigned long q_type)
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/hwmon/pmbus/pmbus_core.c linux-libre-3.2.100-gnu1/drivers/hwmon/pmbus/pmbus_core.c
--- linux-libre-3.2.99-gnu1/drivers/hwmon/pmbus/pmbus_core.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/hwmon/pmbus/pmbus_core.c	2018-03-03 10:57:56.000000000 -0500
@@ -19,6 +19,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/math64.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/err.h>
@@ -475,8 +476,8 @@ static long pmbus_reg2data_linear(struct
 static long pmbus_reg2data_direct(struct pmbus_data *data,
 				  struct pmbus_sensor *sensor)
 {
-	long val = (s16) sensor->data;
-	long m, b, R;
+	s64 b, val = (s16)sensor->data;
+	s32 m, R;
 
 	m = data->info->m[sensor->class];
 	b = data->info->b[sensor->class];
@@ -504,11 +505,12 @@ static long pmbus_reg2data_direct(struct
 		R--;
 	}
 	while (R < 0) {
-		val = DIV_ROUND_CLOSEST(val, 10);
+		val = div_s64(val + 5LL, 10L);  /* round closest */
 		R++;
 	}
 
-	return (val - b) / m;
+	val = div_s64(val - b, m);
+	return clamp_val(val, LONG_MIN, LONG_MAX);
 }
 
 /*
@@ -620,7 +622,8 @@ static u16 pmbus_data2reg_linear(struct
 static u16 pmbus_data2reg_direct(struct pmbus_data *data,
 				 enum pmbus_sensor_classes class, long val)
 {
-	long m, b, R;
+	s64 b, val64 = val;
+	s32 m, R;
 
 	m = data->info->m[class];
 	b = data->info->b[class];
@@ -637,18 +640,18 @@ static u16 pmbus_data2reg_direct(struct
 		R -= 3;		/* Adjust R and b for data in milli-units */
 		b *= 1000;
 	}
-	val = val * m + b;
+	val64 = val64 * m + b;
 
 	while (R > 0) {
-		val *= 10;
+		val64 *= 10;
 		R--;
 	}
 	while (R < 0) {
-		val = DIV_ROUND_CLOSEST(val, 10);
+		val64 = div_s64(val64 + 5LL, 10L);  /* round closest */
 		R++;
 	}
 
-	return val;
+	return (u16)clamp_val(val64, -32768, 32767);
 }
 
 static u16 pmbus_data2reg_vid(struct pmbus_data *data,
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/i2c/i2c-core.c linux-libre-3.2.100-gnu1/drivers/i2c/i2c-core.c
--- linux-libre-3.2.99-gnu1/drivers/i2c/i2c-core.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/i2c/i2c-core.c	2018-03-03 10:57:56.000000000 -0500
@@ -2009,16 +2009,17 @@ static s32 i2c_smbus_xfer_emulated(struc
 				   the underlying bus driver */
 		break;
 	case I2C_SMBUS_I2C_BLOCK_DATA:
+		if (data->block[0] > I2C_SMBUS_BLOCK_MAX) {
+			dev_err(&adapter->dev, "Invalid block %s size %d\n",
+				read_write == I2C_SMBUS_READ ? "read" : "write",
+				data->block[0]);
+			return -EINVAL;
+		}
+
 		if (read_write == I2C_SMBUS_READ) {
 			msg[1].len = data->block[0];
 		} else {
 			msg[0].len = data->block[0] + 1;
-			if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 1) {
-				dev_err(&adapter->dev,
-					"Invalid block write size %d\n",
-					data->block[0]);
-				return -EINVAL;
-			}
 			for (i = 1; i <= data->block[0]; i++)
 				msgbuf0[i] = data->block[i];
 		}
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/infiniband/hw/cxgb4/cq.c linux-libre-3.2.100-gnu1/drivers/infiniband/hw/cxgb4/cq.c
--- linux-libre-3.2.99-gnu1/drivers/infiniband/hw/cxgb4/cq.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/infiniband/hw/cxgb4/cq.c	2018-03-03 10:57:56.000000000 -0500
@@ -484,10 +484,10 @@ static int poll_cq(struct t4_wq *wq, str
 			ret = -EAGAIN;
 			goto skip_cqe;
 		}
-		if (unlikely((CQE_WRID_MSN(hw_cqe) != (wq->rq.msn)))) {
+		if (unlikely(!CQE_STATUS(hw_cqe) &&
+			     CQE_WRID_MSN(hw_cqe) != wq->rq.msn)) {
 			t4_set_wq_in_error(wq);
-			hw_cqe->header |= htonl(V_CQE_STATUS(T4_ERR_MSN));
-			goto proc_cqe;
+			hw_cqe->header |= cpu_to_be32(V_CQE_STATUS(T4_ERR_MSN));
 		}
 		goto proc_cqe;
 	}
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/input/mouse/elantech.c linux-libre-3.2.100-gnu1/drivers/input/mouse/elantech.c
--- linux-libre-3.2.99-gnu1/drivers/input/mouse/elantech.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/input/mouse/elantech.c	2018-03-03 10:57:56.000000000 -0500
@@ -1284,7 +1284,7 @@ static int elantech_set_properties(struc
 		case 5:
 			etd->hw_version = 3;
 			break;
-		case 6 ... 14:
+		case 6 ... 15:
 			etd->hw_version = 4;
 			break;
 		default:
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/input/mouse/trackpoint.c linux-libre-3.2.100-gnu1/drivers/input/mouse/trackpoint.c
--- linux-libre-3.2.99-gnu1/drivers/input/mouse/trackpoint.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/input/mouse/trackpoint.c	2018-03-03 10:57:56.000000000 -0500
@@ -298,8 +298,11 @@ int trackpoint_detect(struct psmouse *ps
 		return 0;
 
 	if (trackpoint_read(&psmouse->ps2dev, TP_EXT_BTN, &button_info)) {
-		printk(KERN_WARNING "trackpoint.c: failed to get extended button data\n");
-		button_info = 0;
+		printk(KERN_WARNING "trackpoint.c: failed to get extended button data, assuming 3 buttons\n");
+		button_info = 0x33;
+	} else if (!button_info) {
+		printk(KERN_WARNING "trackpoint.c: got 0 in extended button data, assuming 3 buttons\n");
+		button_info = 0x33;
 	}
 
 	psmouse->private = kzalloc(sizeof(struct trackpoint_data), GFP_KERNEL);
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/iommu/intel-iommu.c linux-libre-3.2.100-gnu1/drivers/iommu/intel-iommu.c
--- linux-libre-3.2.99-gnu1/drivers/iommu/intel-iommu.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/iommu/intel-iommu.c	2018-03-03 10:57:56.000000000 -0500
@@ -1783,10 +1783,12 @@ static int __domain_mapping(struct dmar_
 		uint64_t tmp;
 
 		if (!sg_res) {
+			unsigned int pgoff = sg->offset & ~PAGE_MASK;
+
 			sg_res = aligned_nrpages(sg->offset, sg->length);
-			sg->dma_address = ((dma_addr_t)iov_pfn << VTD_PAGE_SHIFT) + sg->offset;
+			sg->dma_address = ((dma_addr_t)iov_pfn << VTD_PAGE_SHIFT) + pgoff;
 			sg->dma_length = sg->length;
-			pteval = page_to_phys(sg_page(sg)) | prot;
+			pteval = (sg_phys(sg) - pgoff) | prot;
 			phys_pfn = pteval >> VTD_PAGE_SHIFT;
 		}
 
@@ -3085,7 +3087,7 @@ static int intel_nontranslate_map_sg(str
 
 	for_each_sg(sglist, sg, nelems, i) {
 		BUG_ON(!sg_page(sg));
-		sg->dma_address = page_to_phys(sg_page(sg)) + sg->offset;
+		sg->dma_address = sg_phys(sg);
 		sg->dma_length = sg->length;
 	}
 	return nelems;
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/md/dm-mpath.c linux-libre-3.2.100-gnu1/drivers/md/dm-mpath.c
--- linux-libre-3.2.99-gnu1/drivers/md/dm-mpath.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/md/dm-mpath.c	2018-03-03 10:57:56.000000000 -0500
@@ -1658,19 +1658,11 @@ static int __init dm_multipath_init(void
 	if (!_mpio_cache)
 		return -ENOMEM;
 
-	r = dm_register_target(&multipath_target);
-	if (r < 0) {
-		DMERR("register failed %d", r);
-		kmem_cache_destroy(_mpio_cache);
-		return -EINVAL;
-	}
-
 	kmultipathd = alloc_workqueue("kmpathd", WQ_MEM_RECLAIM, 0);
 	if (!kmultipathd) {
 		DMERR("failed to create workqueue kmpathd");
-		dm_unregister_target(&multipath_target);
-		kmem_cache_destroy(_mpio_cache);
-		return -ENOMEM;
+		r = -ENOMEM;
+		goto bad_alloc_kmultipathd;
 	}
 
 	/*
@@ -1683,16 +1675,30 @@ static int __init dm_multipath_init(void
 						  WQ_MEM_RECLAIM);
 	if (!kmpath_handlerd) {
 		DMERR("failed to create workqueue kmpath_handlerd");
-		destroy_workqueue(kmultipathd);
-		dm_unregister_target(&multipath_target);
-		kmem_cache_destroy(_mpio_cache);
-		return -ENOMEM;
+		r = -ENOMEM;
+		goto bad_alloc_kmpath_handlerd;
+	}
+
+	r = dm_register_target(&multipath_target);
+	if (r < 0) {
+		DMERR("register failed %d", r);
+		r = -EINVAL;
+		goto bad_register_target;
 	}
 
 	DMINFO("version %u.%u.%u loaded",
 	       multipath_target.version[0], multipath_target.version[1],
 	       multipath_target.version[2]);
 
+	return 0;
+
+bad_register_target:
+	destroy_workqueue(kmpath_handlerd);
+bad_alloc_kmpath_handlerd:
+	destroy_workqueue(kmultipathd);
+bad_alloc_kmultipathd:
+	kmem_cache_destroy(_mpio_cache);
+
 	return r;
 }
 
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/md/dm-snap.c linux-libre-3.2.100-gnu1/drivers/md/dm-snap.c
--- linux-libre-3.2.99-gnu1/drivers/md/dm-snap.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/md/dm-snap.c	2018-03-03 10:57:56.000000000 -0500
@@ -2293,24 +2293,6 @@ static int __init dm_snapshot_init(void)
 		return r;
 	}
 
-	r = dm_register_target(&snapshot_target);
-	if (r < 0) {
-		DMERR("snapshot target register failed %d", r);
-		goto bad_register_snapshot_target;
-	}
-
-	r = dm_register_target(&origin_target);
-	if (r < 0) {
-		DMERR("Origin target register failed %d", r);
-		goto bad_register_origin_target;
-	}
-
-	r = dm_register_target(&merge_target);
-	if (r < 0) {
-		DMERR("Merge target register failed %d", r);
-		goto bad_register_merge_target;
-	}
-
 	r = init_origin_hash();
 	if (r) {
 		DMERR("init_origin_hash failed.");
@@ -2338,8 +2320,32 @@ static int __init dm_snapshot_init(void)
 		goto bad_tracked_chunk_cache;
 	}
 
+	r = dm_register_target(&snapshot_target);
+	if (r < 0) {
+		DMERR("snapshot target register failed %d", r);
+		goto bad_register_snapshot_target;
+	}
+
+	r = dm_register_target(&origin_target);
+	if (r < 0) {
+		DMERR("Origin target register failed %d", r);
+		goto bad_register_origin_target;
+	}
+
+	r = dm_register_target(&merge_target);
+	if (r < 0) {
+		DMERR("Merge target register failed %d", r);
+		goto bad_register_merge_target;
+	}
+
 	return 0;
 
+bad_register_merge_target:
+	dm_unregister_target(&origin_target);
+bad_register_origin_target:
+	dm_unregister_target(&snapshot_target);
+bad_register_snapshot_target:
+	kmem_cache_destroy(tracked_chunk_cache);
 bad_tracked_chunk_cache:
 	kmem_cache_destroy(pending_cache);
 bad_pending_cache:
@@ -2347,12 +2353,6 @@ bad_pending_cache:
 bad_exception_cache:
 	exit_origin_hash();
 bad_origin_hash:
-	dm_unregister_target(&merge_target);
-bad_register_merge_target:
-	dm_unregister_target(&origin_target);
-bad_register_origin_target:
-	dm_unregister_target(&snapshot_target);
-bad_register_snapshot_target:
 	dm_exception_store_exit();
 
 	return r;
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/md/dm-thin-metadata.c linux-libre-3.2.100-gnu1/drivers/md/dm-thin-metadata.c
--- linux-libre-3.2.99-gnu1/drivers/md/dm-thin-metadata.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/md/dm-thin-metadata.c	2018-03-03 10:57:56.000000000 -0500
@@ -80,6 +80,16 @@
 #define THIN_METADATA_CACHE_SIZE 64
 #define SECTOR_TO_BLOCK_SHIFT 3
 
+/*
+ * For btree insert:
+ *  3 for btree insert +
+ *  2 for btree lookup used within space map
+ * For btree remove:
+ *  2 for shadow spine +
+ *  4 for rebalance 3 child node
+ */
+#define THIN_MAX_CONCURRENT_LOCKS 6
+
 /* This should be plenty */
 #define SPACE_MAP_ROOT_SIZE 128
 
@@ -669,13 +679,9 @@ struct dm_pool_metadata *dm_pool_metadat
 		return ERR_PTR(-ENOMEM);
 	}
 
-	/*
-	 * Max hex locks:
-	 *  3 for btree insert +
-	 *  2 for btree lookup used within space map
-	 */
 	bm = dm_block_manager_create(bdev, THIN_METADATA_BLOCK_SIZE,
-				     THIN_METADATA_CACHE_SIZE, 5);
+				     THIN_METADATA_CACHE_SIZE,
+				     THIN_MAX_CONCURRENT_LOCKS);
 	if (!bm) {
 		DMERR("could not create block manager");
 		kfree(pmd);
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/md/persistent-data/dm-btree.c linux-libre-3.2.100-gnu1/drivers/md/persistent-data/dm-btree.c
--- linux-libre-3.2.99-gnu1/drivers/md/persistent-data/dm-btree.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/md/persistent-data/dm-btree.c	2018-03-03 10:57:56.000000000 -0500
@@ -568,23 +568,8 @@ static int btree_split_beneath(struct sh
 	pn->keys[1] = rn->keys[0];
 	memcpy_disk(value_ptr(pn, 1, sizeof(__le64)), &val, sizeof(__le64));
 
-	/*
-	 * rejig the spine.  This is ugly, since it knows too
-	 * much about the spine
-	 */
-	if (s->nodes[0] != new_parent) {
-		unlock_block(s->info, s->nodes[0]);
-		s->nodes[0] = new_parent;
-	}
-	if (key < le64_to_cpu(rn->keys[0])) {
-		unlock_block(s->info, right);
-		s->nodes[1] = left;
-	} else {
-		unlock_block(s->info, left);
-		s->nodes[1] = right;
-	}
-	s->count = 2;
-
+	unlock_block(s->info, left);
+	unlock_block(s->info, right);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/media/dvb/dvb-usb/dibusb-common.c linux-libre-3.2.100-gnu1/drivers/media/dvb/dvb-usb/dibusb-common.c
--- linux-libre-3.2.99-gnu1/drivers/media/dvb/dvb-usb/dibusb-common.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/media/dvb/dvb-usb/dibusb-common.c	2018-03-03 10:57:56.000000000 -0500
@@ -169,8 +169,20 @@ EXPORT_SYMBOL(dibusb_i2c_algo);
 
 int dibusb_read_eeprom_byte(struct dvb_usb_device *d, u8 offs, u8 *val)
 {
-	u8 wbuf[1] = { offs };
-	return dibusb_i2c_msg(d, 0x50, wbuf, 1, val, 1);
+	u8 *buf;
+	int rc;
+
+	buf = kmalloc(2, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	buf[0] = offs;
+
+	rc = dibusb_i2c_msg(d, 0x50, &buf[0], 1, &buf[1], 1);
+	*val = buf[1];
+	kfree(buf);
+
+	return rc;
 }
 EXPORT_SYMBOL(dibusb_read_eeprom_byte);
 
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/media/video/Makefile linux-libre-3.2.100-gnu1/drivers/media/video/Makefile
--- linux-libre-3.2.99-gnu1/drivers/media/video/Makefile	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/media/video/Makefile	2018-03-03 10:57:56.000000000 -0500
@@ -13,12 +13,13 @@ omap2cam-objs	:=	omap24xxcam.o omap24xxc
 videodev-objs	:=	v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o \
 			v4l2-event.o v4l2-ctrls.o v4l2-subdev.o
 
+ifeq ($(CONFIG_COMPAT),y)
+  videodev-objs += v4l2-compat-ioctl32.o
+endif
+
 # V4L2 core modules
 
 obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-int-device.o
-ifeq ($(CONFIG_COMPAT),y)
-  obj-$(CONFIG_VIDEO_DEV) += v4l2-compat-ioctl32.o
-endif
 
 obj-$(CONFIG_VIDEO_V4L2_COMMON) += v4l2-common.o
 
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/media/video/v4l2-compat-ioctl32.c linux-libre-3.2.100-gnu1/drivers/media/video/v4l2-compat-ioctl32.c
--- linux-libre-3.2.99-gnu1/drivers/media/video/v4l2-compat-ioctl32.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/media/video/v4l2-compat-ioctl32.c	2018-03-03 10:57:56.000000000 -0500
@@ -17,9 +17,20 @@
 #include <linux/videodev2.h>
 #include <linux/module.h>
 #include <media/v4l2-ioctl.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-ctrls.h>
 
 #ifdef CONFIG_COMPAT
 
+/* Use the same argument order as copy_in_user */
+#define assign_in_user(to, from)					\
+({									\
+	typeof(*from) __assign_tmp;					\
+									\
+	get_user(__assign_tmp, from) || put_user(__assign_tmp, to);	\
+})
+
 static long native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	long ret = -ENOIOCTLCMD;
@@ -33,117 +44,88 @@ static long native_ioctl(struct file *fi
 
 struct v4l2_clip32 {
 	struct v4l2_rect        c;
-	compat_caddr_t 		next;
+	compat_caddr_t		next;
 };
 
 struct v4l2_window32 {
 	struct v4l2_rect        w;
-	enum v4l2_field  	field;
+	__u32			field;	/* enum v4l2_field */
 	__u32			chromakey;
 	compat_caddr_t		clips; /* actually struct v4l2_clip32 * */
 	__u32			clipcount;
 	compat_caddr_t		bitmap;
+	__u8                    global_alpha;
 };
 
-static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up)
-{
-	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) ||
-		copy_from_user(&kp->w, &up->w, sizeof(up->w)) ||
-		get_user(kp->field, &up->field) ||
-		get_user(kp->chromakey, &up->chromakey) ||
-		get_user(kp->clipcount, &up->clipcount))
-			return -EFAULT;
-	if (kp->clipcount > 2048)
-		return -EINVAL;
-	if (kp->clipcount) {
-		struct v4l2_clip32 __user *uclips;
-		struct v4l2_clip __user *kclips;
-		int n = kp->clipcount;
-		compat_caddr_t p;
-
-		if (get_user(p, &up->clips))
-			return -EFAULT;
-		uclips = compat_ptr(p);
-		kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip));
-		kp->clips = kclips;
-		while (--n >= 0) {
-			if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c)))
-				return -EFAULT;
-			if (put_user(n ? kclips + 1 : NULL, &kclips->next))
-				return -EFAULT;
-			uclips += 1;
-			kclips += 1;
-		}
-	} else
-		kp->clips = NULL;
-	return 0;
-}
-
-static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up)
+static int get_v4l2_window32(struct v4l2_window __user *kp,
+			     struct v4l2_window32 __user *up,
+			     void __user *aux_buf, u32 aux_space)
 {
-	if (copy_to_user(&up->w, &kp->w, sizeof(kp->w)) ||
-		put_user(kp->field, &up->field) ||
-		put_user(kp->chromakey, &up->chromakey) ||
-		put_user(kp->clipcount, &up->clipcount))
-			return -EFAULT;
-	return 0;
-}
+	struct v4l2_clip32 __user *uclips;
+	struct v4l2_clip __user *kclips;
+	compat_caddr_t p;
+	u32 clipcount;
 
-static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up)
-{
-	if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format)))
+	if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+	    copy_in_user(&kp->w, &up->w, sizeof(up->w)) ||
+	    assign_in_user(&kp->field, &up->field) ||
+	    assign_in_user(&kp->chromakey, &up->chromakey) ||
+	    assign_in_user(&kp->global_alpha, &up->global_alpha) ||
+	    get_user(clipcount, &up->clipcount) ||
+	    put_user(clipcount, &kp->clipcount))
 		return -EFAULT;
-	return 0;
-}
+	if (clipcount > 2048)
+		return -EINVAL;
+	if (!clipcount)
+		return put_user(NULL, &kp->clips);
 
-static inline int get_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
-				struct v4l2_pix_format_mplane __user *up)
-{
-	if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format_mplane)))
+	if (get_user(p, &up->clips))
 		return -EFAULT;
-	return 0;
-}
-
-static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up)
-{
-	if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format)))
+	uclips = compat_ptr(p);
+	if (aux_space < clipcount * sizeof(*kclips))
 		return -EFAULT;
-	return 0;
-}
-
-static inline int put_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
-				struct v4l2_pix_format_mplane __user *up)
-{
-	if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format_mplane)))
+	kclips = aux_buf;
+	if (put_user(kclips, &kp->clips))
 		return -EFAULT;
-	return 0;
-}
 
-static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up)
-{
-	if (copy_from_user(kp, up, sizeof(struct v4l2_vbi_format)))
-		return -EFAULT;
+	while (clipcount--) {
+		if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c)))
+			return -EFAULT;
+		if (put_user(clipcount ? kclips + 1 : NULL, &kclips->next))
+			return -EFAULT;
+		uclips++;
+		kclips++;
+	}
 	return 0;
 }
 
-static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up)
+static int put_v4l2_window32(struct v4l2_window __user *kp,
+			     struct v4l2_window32 __user *up)
 {
-	if (copy_to_user(up, kp, sizeof(struct v4l2_vbi_format)))
-		return -EFAULT;
-	return 0;
-}
+	struct v4l2_clip __user *kclips = kp->clips;
+	struct v4l2_clip32 __user *uclips;
+	compat_caddr_t p;
+	u32 clipcount;
 
-static inline int get_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format *kp, struct v4l2_sliced_vbi_format __user *up)
-{
-	if (copy_from_user(kp, up, sizeof(struct v4l2_sliced_vbi_format)))
+	if (copy_in_user(&up->w, &kp->w, sizeof(kp->w)) ||
+	    assign_in_user(&up->field, &kp->field) ||
+	    assign_in_user(&up->chromakey, &kp->chromakey) ||
+	    assign_in_user(&up->global_alpha, &kp->global_alpha) ||
+	    get_user(clipcount, &kp->clipcount) ||
+	    put_user(clipcount, &up->clipcount))
 		return -EFAULT;
-	return 0;
-}
+	if (!clipcount)
+		return 0;
 
-static inline int put_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format *kp, struct v4l2_sliced_vbi_format __user *up)
-{
-	if (copy_to_user(up, kp, sizeof(struct v4l2_sliced_vbi_format)))
+	if (get_user(p, &up->clips))
 		return -EFAULT;
+	uclips = compat_ptr(p);
+	while (clipcount--) {
+		if (copy_in_user(&uclips->c, &kclips->c, sizeof(uclips->c)))
+			return -EFAULT;
+		uclips++;
+		kclips++;
+	}
 	return 0;
 }
 
@@ -176,128 +158,185 @@ struct v4l2_create_buffers32 {
 	__u32			reserved[8];
 };
 
-static int __get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
+static int __bufsize_v4l2_format(struct v4l2_format32 __user *up, u32 *size)
 {
-	if (get_user(kp->type, &up->type))
+	u32 type;
+
+	if (get_user(type, &up->type))
 		return -EFAULT;
 
-	switch (kp->type) {
+	switch (type) {
+	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: {
+		u32 clipcount;
+
+		if (get_user(clipcount, &up->fmt.win.clipcount))
+			return -EFAULT;
+		if (clipcount > 2048)
+			return -EINVAL;
+		*size = clipcount * sizeof(struct v4l2_clip);
+		return 0;
+	}
+	default:
+		*size = 0;
+		return 0;
+	}
+}
+
+static int bufsize_v4l2_format(struct v4l2_format32 __user *up, u32 *size)
+{
+	if (!access_ok(VERIFY_READ, up, sizeof(*up)))
+		return -EFAULT;
+	return __bufsize_v4l2_format(up, size);
+}
+
+static int __get_v4l2_format32(struct v4l2_format __user *kp,
+			       struct v4l2_format32 __user *up,
+			       void __user *aux_buf, u32 aux_space)
+{
+	u32 type;
+
+	if (get_user(type, &up->type) || put_user(type, &kp->type))
+		return -EFAULT;
+
+	switch (type) {
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-		return get_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix);
+		return copy_in_user(&kp->fmt.pix, &up->fmt.pix,
+				    sizeof(kp->fmt.pix)) ? -EFAULT : 0;
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
-		return get_v4l2_pix_format_mplane(&kp->fmt.pix_mp,
-						  &up->fmt.pix_mp);
+		return copy_in_user(&kp->fmt.pix_mp, &up->fmt.pix_mp,
+				    sizeof(kp->fmt.pix_mp)) ? -EFAULT : 0;
 	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
-		return get_v4l2_window32(&kp->fmt.win, &up->fmt.win);
+		return get_v4l2_window32(&kp->fmt.win, &up->fmt.win,
+					 aux_buf, aux_space);
 	case V4L2_BUF_TYPE_VBI_CAPTURE:
 	case V4L2_BUF_TYPE_VBI_OUTPUT:
-		return get_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi);
+		return copy_in_user(&kp->fmt.vbi, &up->fmt.vbi,
+				    sizeof(kp->fmt.vbi)) ? -EFAULT : 0;
 	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
 	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
-		return get_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced);
-	case V4L2_BUF_TYPE_PRIVATE:
-		if (copy_from_user(kp, up, sizeof(kp->fmt.raw_data)))
-			return -EFAULT;
-		return 0;
+		return copy_in_user(&kp->fmt.sliced, &up->fmt.sliced,
+				    sizeof(kp->fmt.sliced)) ? -EFAULT : 0;
 	default:
-		printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
-								kp->type);
 		return -EINVAL;
 	}
 }
 
-static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
+static int get_v4l2_format32(struct v4l2_format __user *kp,
+			     struct v4l2_format32 __user *up,
+			     void __user *aux_buf, u32 aux_space)
 {
-	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)))
+	if (!access_ok(VERIFY_READ, up, sizeof(*up)))
 		return -EFAULT;
-	return __get_v4l2_format32(kp, up);
+	return __get_v4l2_format32(kp, up, aux_buf, aux_space);
 }
 
-static int get_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up)
+static int bufsize_v4l2_create(struct v4l2_create_buffers32 __user *up,
+			       u32 *size)
 {
-	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_create_buffers32)) ||
-	    copy_from_user(kp, up, offsetof(struct v4l2_create_buffers32, format)))
+	if (!access_ok(VERIFY_READ, up, sizeof(*up)))
 		return -EFAULT;
-	return __get_v4l2_format32(&kp->format, &up->format);
+	return __bufsize_v4l2_format(&up->format, size);
 }
 
-static int __put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
+static int get_v4l2_create32(struct v4l2_create_buffers __user *kp,
+			     struct v4l2_create_buffers32 __user *up,
+			     void __user *aux_buf, u32 aux_space)
 {
-	switch (kp->type) {
+	if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+	    copy_in_user(kp, up,
+			 offsetof(struct v4l2_create_buffers32, format)))
+		return -EFAULT;
+	return __get_v4l2_format32(&kp->format, &up->format,
+				   aux_buf, aux_space);
+}
+
+static int __put_v4l2_format32(struct v4l2_format __user *kp,
+			       struct v4l2_format32 __user *up)
+{
+	u32 type;
+
+	if (get_user(type, &kp->type))
+		return -EFAULT;
+
+	switch (type) {
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-		return put_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix);
+		return copy_in_user(&up->fmt.pix, &kp->fmt.pix,
+				    sizeof(kp->fmt.pix)) ? -EFAULT : 0;
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
-		return put_v4l2_pix_format_mplane(&kp->fmt.pix_mp,
-						  &up->fmt.pix_mp);
+		return copy_in_user(&up->fmt.pix_mp, &kp->fmt.pix_mp,
+				    sizeof(kp->fmt.pix_mp)) ? -EFAULT : 0;
 	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
 		return put_v4l2_window32(&kp->fmt.win, &up->fmt.win);
 	case V4L2_BUF_TYPE_VBI_CAPTURE:
 	case V4L2_BUF_TYPE_VBI_OUTPUT:
-		return put_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi);
+		return copy_in_user(&up->fmt.vbi, &kp->fmt.vbi,
+				    sizeof(kp->fmt.vbi)) ? -EFAULT : 0;
 	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
 	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
-		return put_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced);
-	case V4L2_BUF_TYPE_PRIVATE:
-		if (copy_to_user(up, kp, sizeof(up->fmt.raw_data)))
-			return -EFAULT;
-		return 0;
+		return copy_in_user(&up->fmt.sliced, &kp->fmt.sliced,
+				    sizeof(kp->fmt.sliced)) ? -EFAULT : 0;
 	default:
-		printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
-								kp->type);
 		return -EINVAL;
 	}
 }
 
-static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
+static int put_v4l2_format32(struct v4l2_format __user *kp,
+			     struct v4l2_format32 __user *up)
 {
-	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)) ||
-		put_user(kp->type, &up->type))
+	if (!access_ok(VERIFY_WRITE, up, sizeof(*up)))
 		return -EFAULT;
 	return __put_v4l2_format32(kp, up);
 }
 
-static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up)
+static int put_v4l2_create32(struct v4l2_create_buffers __user *kp,
+			     struct v4l2_create_buffers32 __user *up)
 {
-	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_create_buffers32)) ||
-	    copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, format.fmt)))
-			return -EFAULT;
+	if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
+	    copy_in_user(up, kp,
+			 offsetof(struct v4l2_create_buffers32, format)) ||
+	    copy_in_user(up->reserved, kp->reserved, sizeof(kp->reserved)))
+		return -EFAULT;
 	return __put_v4l2_format32(&kp->format, &up->format);
 }
 
 struct v4l2_standard32 {
 	__u32		     index;
-	__u32		     id[2]; /* __u64 would get the alignment wrong */
+	compat_u64	     id;
 	__u8		     name[24];
 	struct v4l2_fract    frameperiod; /* Frames, not fields */
 	__u32		     framelines;
 	__u32		     reserved[4];
 };
 
-static int get_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up)
+static int get_v4l2_standard32(struct v4l2_standard __user *kp,
+			       struct v4l2_standard32 __user *up)
 {
 	/* other fields are not set by the user, nor used by the driver */
-	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) ||
-		get_user(kp->index, &up->index))
+	if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+	    assign_in_user(&kp->index, &up->index))
 		return -EFAULT;
 	return 0;
 }
 
-static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up)
+static int put_v4l2_standard32(struct v4l2_standard __user *kp,
+			       struct v4l2_standard32 __user *up)
 {
-	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) ||
-		put_user(kp->index, &up->index) ||
-		copy_to_user(up->id, &kp->id, sizeof(__u64)) ||
-		copy_to_user(up->name, kp->name, 24) ||
-		copy_to_user(&up->frameperiod, &kp->frameperiod, sizeof(kp->frameperiod)) ||
-		put_user(kp->framelines, &up->framelines) ||
-		copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32)))
-			return -EFAULT;
+	if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
+	    assign_in_user(&up->index, &kp->index) ||
+	    assign_in_user(&up->id, &kp->id) ||
+	    copy_in_user(up->name, kp->name, sizeof(up->name)) ||
+	    copy_in_user(&up->frameperiod, &kp->frameperiod,
+			 sizeof(up->frameperiod)) ||
+	    assign_in_user(&up->framelines, &kp->framelines) ||
+	    copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)))
+		return -EFAULT;
 	return 0;
 }
 
@@ -334,191 +373,242 @@ struct v4l2_buffer32 {
 	__u32			reserved;
 };
 
-static int get_v4l2_plane32(struct v4l2_plane *up, struct v4l2_plane32 *up32,
-				enum v4l2_memory memory)
+static int get_v4l2_plane32(struct v4l2_plane __user *up,
+			    struct v4l2_plane32 __user *up32,
+			    enum v4l2_memory memory)
 {
-	void __user *up_pln;
-	compat_long_t p;
+	compat_ulong_t p;
 
 	if (copy_in_user(up, up32, 2 * sizeof(__u32)) ||
-		copy_in_user(&up->data_offset, &up32->data_offset,
-				sizeof(__u32)))
+	    copy_in_user(&up->data_offset, &up32->data_offset,
+			 sizeof(up->data_offset)))
 		return -EFAULT;
 
-	if (memory == V4L2_MEMORY_USERPTR) {
-		if (get_user(p, &up32->m.userptr))
-			return -EFAULT;
-		up_pln = compat_ptr(p);
-		if (put_user((unsigned long)up_pln, &up->m.userptr))
-			return -EFAULT;
-	} else {
+	switch (memory) {
+	case V4L2_MEMORY_MMAP:
+	case V4L2_MEMORY_OVERLAY:
 		if (copy_in_user(&up->m.mem_offset, &up32->m.mem_offset,
-					sizeof(__u32)))
+				 sizeof(up32->m.mem_offset)))
+			return -EFAULT;
+		break;
+	case V4L2_MEMORY_USERPTR:
+		if (get_user(p, &up32->m.userptr) ||
+		    put_user((unsigned long)compat_ptr(p), &up->m.userptr))
 			return -EFAULT;
+		break;
 	}
 
 	return 0;
 }
 
-static int put_v4l2_plane32(struct v4l2_plane *up, struct v4l2_plane32 *up32,
-				enum v4l2_memory memory)
+static int put_v4l2_plane32(struct v4l2_plane __user *up,
+			    struct v4l2_plane32 __user *up32,
+			    enum v4l2_memory memory)
 {
+	unsigned long p;
+
 	if (copy_in_user(up32, up, 2 * sizeof(__u32)) ||
-		copy_in_user(&up32->data_offset, &up->data_offset,
-				sizeof(__u32)))
+	    copy_in_user(&up32->data_offset, &up->data_offset,
+			 sizeof(up->data_offset)))
 		return -EFAULT;
 
-	/* For MMAP, driver might've set up the offset, so copy it back.
-	 * USERPTR stays the same (was userspace-provided), so no copying. */
-	if (memory == V4L2_MEMORY_MMAP)
+	switch (memory) {
+	case V4L2_MEMORY_MMAP:
+	case V4L2_MEMORY_OVERLAY:
 		if (copy_in_user(&up32->m.mem_offset, &up->m.mem_offset,
-					sizeof(__u32)))
+				 sizeof(up->m.mem_offset)))
 			return -EFAULT;
+		break;
+	case V4L2_MEMORY_USERPTR:
+		if (get_user(p, &up->m.userptr) ||
+		    put_user((compat_ulong_t)ptr_to_compat((__force void *)p),
+			     &up32->m.userptr))
+			return -EFAULT;
+		break;
+	}
 
 	return 0;
 }
 
-static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up)
+static int bufsize_v4l2_buffer(struct v4l2_buffer32 __user *up, u32 *size)
+{
+	u32 type;
+	u32 length;
+
+	if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+	    get_user(type, &up->type) ||
+	    get_user(length, &up->length))
+		return -EFAULT;
+
+	if (V4L2_TYPE_IS_MULTIPLANAR(type)) {
+		if (length > VIDEO_MAX_PLANES)
+			return -EINVAL;
+
+		/*
+		 * We don't really care if userspace decides to kill itself
+		 * by passing a very big length value
+		 */
+		*size = length * sizeof(struct v4l2_plane);
+	} else {
+		*size = 0;
+	}
+	return 0;
+}
+
+static int get_v4l2_buffer32(struct v4l2_buffer __user *kp,
+			     struct v4l2_buffer32 __user *up,
+			     void __user *aux_buf, u32 aux_space)
 {
+	u32 type;
+	u32 length;
+	enum v4l2_memory memory;
 	struct v4l2_plane32 __user *uplane32;
 	struct v4l2_plane __user *uplane;
 	compat_caddr_t p;
-	int num_planes;
 	int ret;
 
-	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_buffer32)) ||
-		get_user(kp->index, &up->index) ||
-		get_user(kp->type, &up->type) ||
-		get_user(kp->flags, &up->flags) ||
-		get_user(kp->memory, &up->memory) ||
-		get_user(kp->input, &up->input))
-			return -EFAULT;
+	if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+	    assign_in_user(&kp->index, &up->index) ||
+	    get_user(type, &up->type) ||
+	    put_user(type, &kp->type) ||
+	    assign_in_user(&kp->flags, &up->flags) ||
+	    get_user(memory, &up->memory) ||
+	    put_user(memory, &kp->memory) ||
+	    get_user(length, &up->length) ||
+	    put_user(length, &kp->length))
+		return -EFAULT;
 
-	if (V4L2_TYPE_IS_OUTPUT(kp->type))
-		if (get_user(kp->bytesused, &up->bytesused) ||
-			get_user(kp->field, &up->field) ||
-			get_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
-			get_user(kp->timestamp.tv_usec,
-					&up->timestamp.tv_usec))
+	if (V4L2_TYPE_IS_OUTPUT(type))
+		if (assign_in_user(&kp->bytesused, &up->bytesused) ||
+		    assign_in_user(&kp->field, &up->field) ||
+		    assign_in_user(&kp->timestamp.tv_sec,
+				   &up->timestamp.tv_sec) ||
+		    assign_in_user(&kp->timestamp.tv_usec,
+				   &up->timestamp.tv_usec))
 			return -EFAULT;
 
-	if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) {
-		if (get_user(kp->length, &up->length))
-			return -EFAULT;
+	if (V4L2_TYPE_IS_MULTIPLANAR(type)) {
+		u32 num_planes = length;
 
-		num_planes = kp->length;
 		if (num_planes == 0) {
-			kp->m.planes = NULL;
-			/* num_planes == 0 is legal, e.g. when userspace doesn't
-			 * need planes array on DQBUF*/
-			return 0;
+			/*
+			 * num_planes == 0 is legal, e.g. when userspace doesn't
+			 * need planes array on DQBUF
+			 */
+			return put_user(NULL, &kp->m.planes);
 		}
+		if (num_planes > VIDEO_MAX_PLANES)
+			return -EINVAL;
 
 		if (get_user(p, &up->m.planes))
 			return -EFAULT;
 
 		uplane32 = compat_ptr(p);
 		if (!access_ok(VERIFY_READ, uplane32,
-				num_planes * sizeof(struct v4l2_plane32)))
+			       num_planes * sizeof(*uplane32)))
 			return -EFAULT;
 
-		/* We don't really care if userspace decides to kill itself
-		 * by passing a very big num_planes value */
-		uplane = compat_alloc_user_space(num_planes *
-						sizeof(struct v4l2_plane));
-		kp->m.planes = uplane;
+		/*
+		 * We don't really care if userspace decides to kill itself
+		 * by passing a very big num_planes value
+		 */
+		if (aux_space < num_planes * sizeof(*uplane))
+			return -EFAULT;
 
-		while (--num_planes >= 0) {
-			ret = get_v4l2_plane32(uplane, uplane32, kp->memory);
+		uplane = aux_buf;
+		if (put_user((__force struct v4l2_plane *)uplane,
+			     &kp->m.planes))
+			return -EFAULT;
+
+		while (num_planes--) {
+			ret = get_v4l2_plane32(uplane, uplane32, memory);
 			if (ret)
 				return ret;
-			++uplane;
-			++uplane32;
+			uplane++;
+			uplane32++;
 		}
 	} else {
-		switch (kp->memory) {
+		switch (memory) {
 		case V4L2_MEMORY_MMAP:
-			if (get_user(kp->length, &up->length) ||
-				get_user(kp->m.offset, &up->m.offset))
+		case V4L2_MEMORY_OVERLAY:
+			if (assign_in_user(&kp->m.offset, &up->m.offset))
 				return -EFAULT;
 			break;
-		case V4L2_MEMORY_USERPTR:
-			{
-			compat_long_t tmp;
-
-			if (get_user(kp->length, &up->length) ||
-			    get_user(tmp, &up->m.userptr))
-				return -EFAULT;
+		case V4L2_MEMORY_USERPTR: {
+			compat_ulong_t userptr;
 
-			kp->m.userptr = (unsigned long)compat_ptr(tmp);
-			}
-			break;
-		case V4L2_MEMORY_OVERLAY:
-			if (get_user(kp->m.offset, &up->m.offset))
+			if (get_user(userptr, &up->m.userptr) ||
+			    put_user((unsigned long)compat_ptr(userptr),
+				     &kp->m.userptr))
 				return -EFAULT;
 			break;
 		}
+ 		}
 	}
 
 	return 0;
 }
 
-static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up)
+static int put_v4l2_buffer32(struct v4l2_buffer __user *kp,
+			     struct v4l2_buffer32 __user *up)
 {
+	u32 type;
+	u32 length;
+	enum v4l2_memory memory;
 	struct v4l2_plane32 __user *uplane32;
 	struct v4l2_plane __user *uplane;
 	compat_caddr_t p;
-	int num_planes;
 	int ret;
 
-	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_buffer32)) ||
-		put_user(kp->index, &up->index) ||
-		put_user(kp->type, &up->type) ||
-		put_user(kp->flags, &up->flags) ||
-		put_user(kp->memory, &up->memory) ||
-		put_user(kp->input, &up->input))
-			return -EFAULT;
+	if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
+	    assign_in_user(&up->index, &kp->index) ||
+	    get_user(type, &kp->type) ||
+	    put_user(type, &up->type) ||
+	    assign_in_user(&up->flags, &kp->flags) ||
+	    get_user(memory, &kp->memory) ||
+	    put_user(memory, &up->memory))
+		return -EFAULT;
 
-	if (put_user(kp->bytesused, &up->bytesused) ||
-		put_user(kp->field, &up->field) ||
-		put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
-		put_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec) ||
-		copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)) ||
-		put_user(kp->sequence, &up->sequence) ||
-		put_user(kp->reserved, &up->reserved))
-			return -EFAULT;
+	if (assign_in_user(&up->bytesused, &kp->bytesused) ||
+	    assign_in_user(&up->field, &kp->field) ||
+	    assign_in_user(&up->timestamp.tv_sec, &kp->timestamp.tv_sec) ||
+	    assign_in_user(&up->timestamp.tv_usec, &kp->timestamp.tv_usec) ||
+	    copy_in_user(&up->timecode, &kp->timecode, sizeof(kp->timecode)) ||
+	    assign_in_user(&up->sequence, &kp->sequence) ||
+	    assign_in_user(&up->input, &kp->input) ||
+	    assign_in_user(&up->reserved, &kp->reserved) ||
+	    get_user(length, &kp->length) ||
+	    put_user(length, &up->length))
+		return -EFAULT;
+
+	if (V4L2_TYPE_IS_MULTIPLANAR(type)) {
+		u32 num_planes = length;
 
-	if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) {
-		num_planes = kp->length;
 		if (num_planes == 0)
 			return 0;
 
-		uplane = kp->m.planes;
+		if (get_user(uplane, ((__force struct v4l2_plane __user **)&kp->m.planes)))
+			return -EFAULT;
 		if (get_user(p, &up->m.planes))
 			return -EFAULT;
 		uplane32 = compat_ptr(p);
 
-		while (--num_planes >= 0) {
-			ret = put_v4l2_plane32(uplane, uplane32, kp->memory);
+		while (num_planes--) {
+			ret = put_v4l2_plane32(uplane, uplane32, memory);
 			if (ret)
 				return ret;
 			++uplane;
 			++uplane32;
 		}
 	} else {
-		switch (kp->memory) {
+		switch (memory) {
 		case V4L2_MEMORY_MMAP:
-			if (put_user(kp->length, &up->length) ||
-				put_user(kp->m.offset, &up->m.offset))
+		case V4L2_MEMORY_OVERLAY:
+			if (assign_in_user(&up->m.offset, &kp->m.offset))
 				return -EFAULT;
 			break;
 		case V4L2_MEMORY_USERPTR:
-			if (put_user(kp->length, &up->length) ||
-				put_user(kp->m.userptr, &up->m.userptr))
-				return -EFAULT;
-			break;
-		case V4L2_MEMORY_OVERLAY:
-			if (put_user(kp->m.offset, &up->m.offset))
+			if (assign_in_user(&up->m.userptr, &kp->m.userptr))
 				return -EFAULT;
 			break;
 		}
@@ -530,34 +620,46 @@ static int put_v4l2_buffer32(struct v4l2
 struct v4l2_framebuffer32 {
 	__u32			capability;
 	__u32			flags;
-	compat_caddr_t 		base;
-	struct v4l2_pix_format	fmt;
+	compat_caddr_t		base;
+	struct {
+		__u32		width;
+		__u32		height;
+		__u32		pixelformat;
+		__u32		field;
+		__u32		bytesperline;
+		__u32		sizeimage;
+		__u32		colorspace;
+		__u32		priv;
+	} fmt;
 };
 
-static int get_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up)
+static int get_v4l2_framebuffer32(struct v4l2_framebuffer __user *kp,
+				  struct v4l2_framebuffer32 __user *up)
 {
-	u32 tmp;
+	compat_caddr_t tmp;
 
-	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_framebuffer32)) ||
-		get_user(tmp, &up->base) ||
-		get_user(kp->capability, &up->capability) ||
-		get_user(kp->flags, &up->flags))
-			return -EFAULT;
-	kp->base = compat_ptr(tmp);
-	get_v4l2_pix_format(&kp->fmt, &up->fmt);
+	if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+	    get_user(tmp, &up->base) ||
+	    put_user((__force void *)compat_ptr(tmp), &kp->base) ||
+	    assign_in_user(&kp->capability, &up->capability) ||
+	    assign_in_user(&kp->flags, &up->flags) ||
+	    copy_in_user(&kp->fmt, &up->fmt, sizeof(kp->fmt)))
+		return -EFAULT;
 	return 0;
 }
 
-static int put_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up)
+static int put_v4l2_framebuffer32(struct v4l2_framebuffer __user *kp,
+				  struct v4l2_framebuffer32 __user *up)
 {
-	u32 tmp = (u32)((unsigned long)kp->base);
+	void *base;
 
-	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_framebuffer32)) ||
-		put_user(tmp, &up->base) ||
-		put_user(kp->capability, &up->capability) ||
-		put_user(kp->flags, &up->flags))
-			return -EFAULT;
-	put_v4l2_pix_format(&kp->fmt, &up->fmt);
+	if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
+	    get_user(base, &kp->base) ||
+	    put_user(ptr_to_compat(base), &up->base) ||
+	    assign_in_user(&up->capability, &kp->capability) ||
+	    assign_in_user(&up->flags, &kp->flags) ||
+	    copy_in_user(&up->fmt, &kp->fmt, sizeof(kp->fmt)))
+		return -EFAULT;
 	return 0;
 }
 
@@ -567,33 +669,38 @@ struct v4l2_input32 {
 	__u32	     type;		/*  Type of input */
 	__u32	     audioset;		/*  Associated audios (bitfield) */
 	__u32        tuner;             /*  Associated tuner */
-	v4l2_std_id  std;
+	compat_u64   std;
 	__u32	     status;
-	__u32	     reserved[4];
-} __attribute__ ((packed));
+	__u32	     capabilities;
+	__u32	     reserved[3];
+};
 
-/* The 64-bit v4l2_input struct has extra padding at the end of the struct.
-   Otherwise it is identical to the 32-bit version. */
-static inline int get_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __user *up)
+/*
+ * The 64-bit v4l2_input struct has extra padding at the end of the struct.
+ * Otherwise it is identical to the 32-bit version.
+ */
+static inline int get_v4l2_input32(struct v4l2_input __user *kp,
+				   struct v4l2_input32 __user *up)
 {
-	if (copy_from_user(kp, up, sizeof(struct v4l2_input32)))
+	if (copy_in_user(kp, up, sizeof(*up)))
 		return -EFAULT;
 	return 0;
 }
 
-static inline int put_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __user *up)
+static inline int put_v4l2_input32(struct v4l2_input __user *kp,
+				   struct v4l2_input32 __user *up)
 {
-	if (copy_to_user(up, kp, sizeof(struct v4l2_input32)))
+	if (copy_in_user(up, kp, sizeof(*up)))
 		return -EFAULT;
 	return 0;
 }
 
 struct v4l2_ext_controls32 {
-       __u32 ctrl_class;
-       __u32 count;
-       __u32 error_idx;
-       __u32 reserved[2];
-       compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */
+	__u32 ctrl_class;
+	__u32 count;
+	__u32 error_idx;
+	__u32 reserved[2];
+	compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */
 };
 
 struct v4l2_ext_control32 {
@@ -607,53 +714,88 @@ struct v4l2_ext_control32 {
 	};
 } __attribute__ ((packed));
 
-/* The following function really belong in v4l2-common, but that causes
-   a circular dependency between modules. We need to think about this, but
-   for now this will do. */
-
-/* Return non-zero if this control is a pointer type. Currently only
-   type STRING is a pointer type. */
-static inline int ctrl_is_pointer(u32 id)
+/* Return true if this control is a pointer type. */
+static inline bool ctrl_is_pointer(struct file *file, u32 id)
 {
-	switch (id) {
-	case V4L2_CID_RDS_TX_PS_NAME:
-	case V4L2_CID_RDS_TX_RADIO_TEXT:
-		return 1;
-	default:
-		return 0;
+	struct video_device *vdev = video_devdata(file);
+	struct v4l2_fh *fh = NULL;
+	struct v4l2_ctrl_handler *hdl = NULL;
+
+	if (test_bit(V4L2_FL_USES_V4L2_FH, &vdev->flags))
+		fh = file->private_data;
+
+	if (fh && fh->ctrl_handler)
+		hdl = fh->ctrl_handler;
+	else if (vdev->ctrl_handler)
+		hdl = vdev->ctrl_handler;
+
+	if (hdl) {
+		struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, id);
+
+		return ctrl && ctrl->type == V4L2_CTRL_TYPE_STRING;
 	}
+	return false;
 }
 
-static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up)
+static int bufsize_v4l2_ext_controls(struct v4l2_ext_controls32 __user *up,
+				     u32 *size)
+{
+	u32 count;
+
+	if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+	    get_user(count, &up->count))
+		return -EFAULT;
+	if (count > V4L2_CID_MAX_CTRLS)
+		return -EINVAL;
+	*size = count * sizeof(struct v4l2_ext_control);
+	return 0;
+}
+
+static int get_v4l2_ext_controls32(struct file *file,
+				   struct v4l2_ext_controls __user *kp,
+				   struct v4l2_ext_controls32 __user *up,
+				   void __user *aux_buf, u32 aux_space)
 {
 	struct v4l2_ext_control32 __user *ucontrols;
 	struct v4l2_ext_control __user *kcontrols;
-	int n;
+	u32 count;
+	u32 n;
 	compat_caddr_t p;
 
-	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_ext_controls32)) ||
-		get_user(kp->ctrl_class, &up->ctrl_class) ||
-		get_user(kp->count, &up->count) ||
-		get_user(kp->error_idx, &up->error_idx) ||
-		copy_from_user(kp->reserved, up->reserved, sizeof(kp->reserved)))
-			return -EFAULT;
-	n = kp->count;
-	if (n == 0) {
-		kp->controls = NULL;
-		return 0;
-	}
+	if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+	    assign_in_user(&kp->ctrl_class, &up->ctrl_class) ||
+	    get_user(count, &up->count) ||
+	    put_user(count, &kp->count) ||
+	    assign_in_user(&kp->error_idx, &up->error_idx) ||
+	    copy_in_user(kp->reserved, up->reserved, sizeof(kp->reserved)))
+		return -EFAULT;
+
+	if (count == 0)
+		return put_user(NULL, &kp->controls);
+	if (count > V4L2_CID_MAX_CTRLS)
+		return -EINVAL;
 	if (get_user(p, &up->controls))
 		return -EFAULT;
 	ucontrols = compat_ptr(p);
-	if (!access_ok(VERIFY_READ, ucontrols,
-			n * sizeof(struct v4l2_ext_control32)))
+	if (!access_ok(VERIFY_READ, ucontrols, count * sizeof(*ucontrols)))
 		return -EFAULT;
-	kcontrols = compat_alloc_user_space(n * sizeof(struct v4l2_ext_control));
-	kp->controls = kcontrols;
-	while (--n >= 0) {
+	if (aux_space < count * sizeof(*kcontrols))
+		return -EFAULT;
+	kcontrols = aux_buf;
+	if (put_user((__force struct v4l2_ext_control *)kcontrols,
+		     &kp->controls))
+		return -EFAULT;
+
+	for (n = 0; n < count; n++) {
+		u32 id;
+
 		if (copy_in_user(kcontrols, ucontrols, sizeof(*ucontrols)))
 			return -EFAULT;
-		if (ctrl_is_pointer(kcontrols->id)) {
+
+		if (get_user(id, &kcontrols->id))
+			return -EFAULT;
+
+		if (ctrl_is_pointer(file, id)) {
 			void __user *s;
 
 			if (get_user(p, &ucontrols->string))
@@ -668,39 +810,55 @@ static int get_v4l2_ext_controls32(struc
 	return 0;
 }
 
-static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up)
+static int put_v4l2_ext_controls32(struct file *file,
+				   struct v4l2_ext_controls __user *kp,
+				   struct v4l2_ext_controls32 __user *up)
 {
 	struct v4l2_ext_control32 __user *ucontrols;
-	struct v4l2_ext_control __user *kcontrols = kp->controls;
-	int n = kp->count;
+	struct v4l2_ext_control __user *kcontrols;
+	u32 count;
+	u32 n;
 	compat_caddr_t p;
 
-	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_ext_controls32)) ||
-		put_user(kp->ctrl_class, &up->ctrl_class) ||
-		put_user(kp->count, &up->count) ||
-		put_user(kp->error_idx, &up->error_idx) ||
-		copy_to_user(up->reserved, kp->reserved, sizeof(up->reserved)))
-			return -EFAULT;
-	if (!kp->count)
-		return 0;
+	if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
+	    assign_in_user(&up->ctrl_class, &kp->ctrl_class) ||
+	    get_user(count, &kp->count) ||
+	    put_user(count, &up->count) ||
+	    assign_in_user(&up->error_idx, &kp->error_idx) ||
+	    copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)) ||
+	    get_user(kcontrols, &kp->controls))
+		return -EFAULT;
 
+	if (!count)
+		return 0;
 	if (get_user(p, &up->controls))
 		return -EFAULT;
 	ucontrols = compat_ptr(p);
-	if (!access_ok(VERIFY_WRITE, ucontrols,
-			n * sizeof(struct v4l2_ext_control32)))
+	if (!access_ok(VERIFY_WRITE, ucontrols, count * sizeof(*ucontrols)))
 		return -EFAULT;
 
-	while (--n >= 0) {
-		unsigned size = sizeof(*ucontrols);
+	for (n = 0; n < count; n++) {
+		unsigned int size = sizeof(*ucontrols);
+		u32 id;
 
-		/* Do not modify the pointer when copying a pointer control.
-		   The contents of the pointer was changed, not the pointer
-		   itself. */
-		if (ctrl_is_pointer(kcontrols->id))
+		if (get_user(id, &kcontrols->id) ||
+		    put_user(id, &ucontrols->id) ||
+		    assign_in_user(&ucontrols->size, &kcontrols->size) ||
+		    copy_in_user(&ucontrols->reserved2, &kcontrols->reserved2,
+				 sizeof(ucontrols->reserved2)))
+			return -EFAULT;
+
+		/*
+		 * Do not modify the pointer when copying a pointer control.
+		 * The contents of the pointer was changed, not the pointer
+		 * itself.
+		 */
+		if (ctrl_is_pointer(file, id))
 			size -= sizeof(ucontrols->value64);
+
 		if (copy_in_user(ucontrols, kcontrols, size))
 			return -EFAULT;
+
 		ucontrols++;
 		kcontrols++;
 	}
@@ -710,6 +868,7 @@ static int put_v4l2_ext_controls32(struc
 struct v4l2_event32 {
 	__u32				type;
 	union {
+		compat_s64		value64;
 		__u8			data[64];
 	} u;
 	__u32				pending;
@@ -719,17 +878,19 @@ struct v4l2_event32 {
 	__u32				reserved[8];
 };
 
-static int put_v4l2_event32(struct v4l2_event *kp, struct v4l2_event32 __user *up)
+static int put_v4l2_event32(struct v4l2_event __user *kp,
+			    struct v4l2_event32 __user *up)
 {
-	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_event32)) ||
-		put_user(kp->type, &up->type) ||
-		copy_to_user(&up->u, &kp->u, sizeof(kp->u)) ||
-		put_user(kp->pending, &up->pending) ||
-		put_user(kp->sequence, &up->sequence) ||
-		put_compat_timespec(&kp->timestamp, &up->timestamp) ||
-		put_user(kp->id, &up->id) ||
-		copy_to_user(up->reserved, kp->reserved, 8 * sizeof(__u32)))
-			return -EFAULT;
+	if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
+	    assign_in_user(&up->type, &kp->type) ||
+	    copy_in_user(&up->u, &kp->u, sizeof(kp->u)) ||
+	    assign_in_user(&up->pending, &kp->pending) ||
+	    assign_in_user(&up->sequence, &kp->sequence) ||
+	    assign_in_user(&up->timestamp.tv_sec, &kp->timestamp.tv_sec) ||
+	    assign_in_user(&up->timestamp.tv_nsec, &kp->timestamp.tv_nsec) ||
+	    assign_in_user(&up->id, &kp->id) ||
+	    copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)))
+		return -EFAULT;
 	return 0;
 }
 
@@ -742,7 +903,7 @@ static int put_v4l2_event32(struct v4l2_
 #define VIDIOC_DQBUF32		_IOWR('V', 17, struct v4l2_buffer32)
 #define VIDIOC_ENUMSTD32	_IOWR('V', 25, struct v4l2_standard32)
 #define VIDIOC_ENUMINPUT32	_IOWR('V', 26, struct v4l2_input32)
-#define VIDIOC_TRY_FMT32      	_IOWR('V', 64, struct v4l2_format32)
+#define VIDIOC_TRY_FMT32	_IOWR('V', 64, struct v4l2_format32)
 #define VIDIOC_G_EXT_CTRLS32    _IOWR('V', 71, struct v4l2_ext_controls32)
 #define VIDIOC_S_EXT_CTRLS32    _IOWR('V', 72, struct v4l2_ext_controls32)
 #define VIDIOC_TRY_EXT_CTRLS32  _IOWR('V', 73, struct v4l2_ext_controls32)
@@ -758,21 +919,23 @@ static int put_v4l2_event32(struct v4l2_
 #define VIDIOC_G_OUTPUT32	_IOR ('V', 46, s32)
 #define VIDIOC_S_OUTPUT32	_IOWR('V', 47, s32)
 
+static int alloc_userspace(unsigned int size, u32 aux_space,
+			   void __user **up_native)
+{
+	*up_native = compat_alloc_user_space(size + aux_space);
+	if (!*up_native)
+		return -ENOMEM;
+	if (clear_user(*up_native, size))
+		return -EFAULT;
+	return 0;
+}
+
 static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-	union {
-		struct v4l2_format v2f;
-		struct v4l2_buffer v2b;
-		struct v4l2_framebuffer v2fb;
-		struct v4l2_input v2i;
-		struct v4l2_standard v2s;
-		struct v4l2_ext_controls v2ecs;
-		struct v4l2_event v2ev;
-		struct v4l2_create_buffers v2crt;
-		unsigned long vx;
-		int vi;
-	} karg;
 	void __user *up = compat_ptr(arg);
+	void __user *up_native = NULL;
+	void __user *aux_buf;
+	u32 aux_space;
 	int compatible_arg = 1;
 	long err = 0;
 
@@ -809,24 +972,44 @@ static long do_video_ioctl(struct file *
 	case VIDIOC_STREAMOFF:
 	case VIDIOC_S_INPUT:
 	case VIDIOC_S_OUTPUT:
-		err = get_user(karg.vi, (s32 __user *)up);
+		err = alloc_userspace(sizeof(unsigned int), 0, &up_native);
+		if (!err && assign_in_user((unsigned int __user *)up_native,
+					   (compat_uint_t __user *)up))
+			err = -EFAULT;
 		compatible_arg = 0;
 		break;
 
 	case VIDIOC_G_INPUT:
 	case VIDIOC_G_OUTPUT:
+		err = alloc_userspace(sizeof(unsigned int), 0, &up_native);
 		compatible_arg = 0;
 		break;
 
 	case VIDIOC_G_FMT:
 	case VIDIOC_S_FMT:
 	case VIDIOC_TRY_FMT:
-		err = get_v4l2_format32(&karg.v2f, up);
+		err = bufsize_v4l2_format(up, &aux_space);
+		if (!err)
+			err = alloc_userspace(sizeof(struct v4l2_format),
+					      aux_space, &up_native);
+		if (!err) {
+			aux_buf = up_native + sizeof(struct v4l2_format);
+			err = get_v4l2_format32(up_native, up,
+						aux_buf, aux_space);
+		}
 		compatible_arg = 0;
 		break;
 
 	case VIDIOC_CREATE_BUFS:
-		err = get_v4l2_create32(&karg.v2crt, up);
+		err = bufsize_v4l2_create(up, &aux_space);
+		if (!err)
+			err = alloc_userspace(sizeof(struct v4l2_create_buffers),
+					      aux_space, &up_native);
+		if (!err) {
+			aux_buf = up_native + sizeof(struct v4l2_create_buffers);
+			err = get_v4l2_create32(up_native, up,
+						aux_buf, aux_space);
+		}
 		compatible_arg = 0;
 		break;
 
@@ -834,36 +1017,63 @@ static long do_video_ioctl(struct file *
 	case VIDIOC_QUERYBUF:
 	case VIDIOC_QBUF:
 	case VIDIOC_DQBUF:
-		err = get_v4l2_buffer32(&karg.v2b, up);
+		err = bufsize_v4l2_buffer(up, &aux_space);
+		if (!err)
+			err = alloc_userspace(sizeof(struct v4l2_buffer),
+					      aux_space, &up_native);
+		if (!err) {
+			aux_buf = up_native + sizeof(struct v4l2_buffer);
+			err = get_v4l2_buffer32(up_native, up,
+						aux_buf, aux_space);
+		}
 		compatible_arg = 0;
 		break;
 
 	case VIDIOC_S_FBUF:
-		err = get_v4l2_framebuffer32(&karg.v2fb, up);
+		err = alloc_userspace(sizeof(struct v4l2_framebuffer), 0,
+				      &up_native);
+		if (!err)
+			err = get_v4l2_framebuffer32(up_native, up);
 		compatible_arg = 0;
 		break;
 
 	case VIDIOC_G_FBUF:
+		err = alloc_userspace(sizeof(struct v4l2_framebuffer), 0,
+				      &up_native);
 		compatible_arg = 0;
 		break;
 
 	case VIDIOC_ENUMSTD:
-		err = get_v4l2_standard32(&karg.v2s, up);
+		err = alloc_userspace(sizeof(struct v4l2_standard), 0,
+				      &up_native);
+		if (!err)
+			err = get_v4l2_standard32(up_native, up);
 		compatible_arg = 0;
 		break;
 
 	case VIDIOC_ENUMINPUT:
-		err = get_v4l2_input32(&karg.v2i, up);
+		err = alloc_userspace(sizeof(struct v4l2_input), 0, &up_native);
+		if (!err)
+			err = get_v4l2_input32(up_native, up);
 		compatible_arg = 0;
 		break;
 
 	case VIDIOC_G_EXT_CTRLS:
 	case VIDIOC_S_EXT_CTRLS:
 	case VIDIOC_TRY_EXT_CTRLS:
-		err = get_v4l2_ext_controls32(&karg.v2ecs, up);
+		err = bufsize_v4l2_ext_controls(up, &aux_space);
+		if (!err)
+			err = alloc_userspace(sizeof(struct v4l2_ext_controls),
+					      aux_space, &up_native);
+		if (!err) {
+			aux_buf = up_native + sizeof(struct v4l2_ext_controls);
+			err = get_v4l2_ext_controls32(file, up_native, up,
+						      aux_buf, aux_space);
+		}
 		compatible_arg = 0;
 		break;
 	case VIDIOC_DQEVENT:
+		err = alloc_userspace(sizeof(struct v4l2_event), 0, &up_native);
 		compatible_arg = 0;
 		break;
 	}
@@ -872,22 +1082,22 @@ static long do_video_ioctl(struct file *
 
 	if (compatible_arg)
 		err = native_ioctl(file, cmd, (unsigned long)up);
-	else {
-		mm_segment_t old_fs = get_fs();
+	else
+		err = native_ioctl(file, cmd, (unsigned long)up_native);
 
-		set_fs(KERNEL_DS);
-		err = native_ioctl(file, cmd, (unsigned long)&karg);
-		set_fs(old_fs);
-	}
+	if (err == -ENOTTY)
+		return err;
 
-	/* Special case: even after an error we need to put the
-	   results back for these ioctls since the error_idx will
-	   contain information on which control failed. */
+	/*
+	 * Special case: even after an error we need to put the
+	 * results back for these ioctls since the error_idx will
+	 * contain information on which control failed.
+	 */
 	switch (cmd) {
 	case VIDIOC_G_EXT_CTRLS:
 	case VIDIOC_S_EXT_CTRLS:
 	case VIDIOC_TRY_EXT_CTRLS:
-		if (put_v4l2_ext_controls32(&karg.v2ecs, up))
+		if (put_v4l2_ext_controls32(file, up_native, up))
 			err = -EFAULT;
 		break;
 	}
@@ -899,39 +1109,42 @@ static long do_video_ioctl(struct file *
 	case VIDIOC_S_OUTPUT:
 	case VIDIOC_G_INPUT:
 	case VIDIOC_G_OUTPUT:
-		err = put_user(((s32)karg.vi), (s32 __user *)up);
+		if (assign_in_user((compat_uint_t __user *)up,
+				   ((unsigned int __user *)up_native)))
+			err = -EFAULT;
 		break;
 
 	case VIDIOC_G_FBUF:
-		err = put_v4l2_framebuffer32(&karg.v2fb, up);
+		err = put_v4l2_framebuffer32(up_native, up);
 		break;
 
 	case VIDIOC_DQEVENT:
-		err = put_v4l2_event32(&karg.v2ev, up);
+		err = put_v4l2_event32(up_native, up);
 		break;
 
 	case VIDIOC_G_FMT:
 	case VIDIOC_S_FMT:
 	case VIDIOC_TRY_FMT:
-		err = put_v4l2_format32(&karg.v2f, up);
+		err = put_v4l2_format32(up_native, up);
 		break;
 
 	case VIDIOC_CREATE_BUFS:
-		err = put_v4l2_create32(&karg.v2crt, up);
+		err = put_v4l2_create32(up_native, up);
 		break;
 
+	case VIDIOC_PREPARE_BUF:
 	case VIDIOC_QUERYBUF:
 	case VIDIOC_QBUF:
 	case VIDIOC_DQBUF:
-		err = put_v4l2_buffer32(&karg.v2b, up);
+		err = put_v4l2_buffer32(up_native, up);
 		break;
 
 	case VIDIOC_ENUMSTD:
-		err = put_v4l2_standard32(&karg.v2s, up);
+		err = put_v4l2_standard32(up_native, up);
 		break;
 
 	case VIDIOC_ENUMINPUT:
-		err = put_v4l2_input32(&karg.v2i, up);
+		err = put_v4l2_input32(up_native, up);
 		break;
 	}
 	return err;
@@ -1026,8 +1239,8 @@ long v4l2_compat_ioctl32(struct file *fi
 
 	default:
 		printk(KERN_WARNING "compat_ioctl32: "
-			"unknown ioctl '%c', dir=%d, #%d (0x%08x)\n",
-			_IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), cmd);
+		       "unknown ioctl '%c', dir=%d, #%d (0x%08x)\n",
+		       _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), cmd);
 		break;
 	}
 	return ret;
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/media/video/v4l2-ioctl.c linux-libre-3.2.100-gnu1/drivers/media/video/v4l2-ioctl.c
--- linux-libre-3.2.99-gnu1/drivers/media/video/v4l2-ioctl.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/media/video/v4l2-ioctl.c	2018-03-03 10:57:56.000000000 -0500
@@ -2308,8 +2308,10 @@ video_usercopy(struct file *file, unsign
 
 	/* Handles IOCTL */
 	err = func(file, cmd, parg);
-	if (err == -ENOIOCTLCMD)
-		err = -EINVAL;
+	if (err == -ENOTTY || err == -ENOIOCTLCMD) {
+		err = -ENOTTY;
+		goto out;
+	}
 
 	if (has_array_args) {
 		*kernel_ptr = user_ptr;
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/misc/eeprom/at24.c linux-libre-3.2.100-gnu1/drivers/misc/eeprom/at24.c
--- linux-libre-3.2.99-gnu1/drivers/misc/eeprom/at24.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/misc/eeprom/at24.c	2018-03-03 10:57:56.000000000 -0500
@@ -274,6 +274,9 @@ static ssize_t at24_read(struct at24_dat
 	if (unlikely(!count))
 		return count;
 
+	if (off + count > at24->chip.byte_len)
+		return -EINVAL;
+
 	/*
 	 * Read data from chip, protecting against concurrent updates
 	 * from this host, but not from other I2C masters.
@@ -396,6 +399,9 @@ static ssize_t at24_write(struct at24_da
 	if (unlikely(!count))
 		return count;
 
+	if (off + count > at24->chip.byte_len)
+		return -EINVAL;
+
 	/*
 	 * Write data to chip, protecting against concurrent updates
 	 * from this host, but not from other I2C masters.
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/mmc/host/s3cmci.c linux-libre-3.2.100-gnu1/drivers/mmc/host/s3cmci.c
--- linux-libre-3.2.99-gnu1/drivers/mmc/host/s3cmci.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/mmc/host/s3cmci.c	2018-03-03 10:57:56.000000000 -0500
@@ -1460,7 +1460,9 @@ static const struct file_operations s3cm
 struct s3cmci_reg {
 	unsigned short	addr;
 	unsigned char	*name;
-} debug_regs[] = {
+};
+
+static const struct s3cmci_reg debug_regs[] = {
 	DBG_REG(CON),
 	DBG_REG(PRE),
 	DBG_REG(CMDARG),
@@ -1482,7 +1484,7 @@ struct s3cmci_reg {
 static int s3cmci_regs_show(struct seq_file *seq, void *v)
 {
 	struct s3cmci_host *host = seq->private;
-	struct s3cmci_reg *rptr = debug_regs;
+	const struct s3cmci_reg *rptr = debug_regs;
 
 	for (; rptr->name; rptr++)
 		seq_printf(seq, "SDI%s\t=0x%08x\n", rptr->name,
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/net/can/ti_hecc.c linux-libre-3.2.100-gnu1/drivers/net/can/ti_hecc.c
--- linux-libre-3.2.99-gnu1/drivers/net/can/ti_hecc.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/net/can/ti_hecc.c	2018-03-03 10:57:56.000000000 -0500
@@ -651,6 +651,9 @@ static int ti_hecc_rx_poll(struct napi_s
 		mbx_mask = hecc_read(priv, HECC_CANMIM);
 		mbx_mask |= HECC_TX_MBOX_MASK;
 		hecc_write(priv, HECC_CANMIM, mbx_mask);
+	} else {
+		/* repoll is done only if whole budget is used */
+		num_pkts = quota;
 	}
 
 	return num_pkts;
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/net/can/usb/ems_usb.c linux-libre-3.2.100-gnu1/drivers/net/can/usb/ems_usb.c
--- linux-libre-3.2.99-gnu1/drivers/net/can/usb/ems_usb.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/net/can/usb/ems_usb.c	2018-03-03 10:57:56.000000000 -0500
@@ -292,6 +292,8 @@ static void ems_usb_read_interrupt_callb
 
 	case -ECONNRESET: /* unlink */
 	case -ENOENT:
+	case -EPIPE:
+	case -EPROTO:
 	case -ESHUTDOWN:
 		return;
 
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/net/can/usb/esd_usb2.c linux-libre-3.2.100-gnu1/drivers/net/can/usb/esd_usb2.c
--- linux-libre-3.2.99-gnu1/drivers/net/can/usb/esd_usb2.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/net/can/usb/esd_usb2.c	2018-03-03 10:57:56.000000000 -0500
@@ -393,6 +393,8 @@ static void esd_usb2_read_bulk_callback(
 		break;
 
 	case -ENOENT:
+	case -EPIPE:
+	case -EPROTO:
 	case -ESHUTDOWN:
 		return;
 
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/net/ethernet/freescale/fs_enet/fs_enet.h linux-libre-3.2.100-gnu1/drivers/net/ethernet/freescale/fs_enet/fs_enet.h
--- linux-libre-3.2.99-gnu1/drivers/net/ethernet/freescale/fs_enet/fs_enet.h	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/net/ethernet/freescale/fs_enet/fs_enet.h	2018-03-03 10:57:56.000000000 -0500
@@ -124,6 +124,7 @@ struct fs_enet_private {
 	spinlock_t lock;	/* during all ops except TX pckt processing */
 	spinlock_t tx_lock;	/* during fs_start_xmit and fs_tx         */
 	struct fs_platform_info *fpi;
+	struct work_struct timeout_work;
 	const struct fs_ops *ops;
 	int rx_ring, tx_ring;
 	dma_addr_t ring_mem_addr;
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c linux-libre-3.2.100-gnu1/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
--- linux-libre-3.2.99-gnu1/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c	2018-03-03 10:57:56.000000000 -0500
@@ -706,9 +706,11 @@ static int fs_enet_start_xmit(struct sk_
 	return NETDEV_TX_OK;
 }
 
-static void fs_timeout(struct net_device *dev)
+static void fs_timeout_work(struct work_struct *work)
 {
-	struct fs_enet_private *fep = netdev_priv(dev);
+	struct fs_enet_private *fep = container_of(work, struct fs_enet_private,
+						   timeout_work);
+	struct net_device *dev = fep->ndev;
 	unsigned long flags;
 	int wake = 0;
 
@@ -720,7 +722,6 @@ static void fs_timeout(struct net_device
 		phy_stop(fep->phydev);
 		(*fep->ops->stop)(dev);
 		(*fep->ops->restart)(dev);
-		phy_start(fep->phydev);
 	}
 
 	phy_start(fep->phydev);
@@ -731,6 +732,13 @@ static void fs_timeout(struct net_device
 		netif_wake_queue(dev);
 }
 
+static void fs_timeout(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+
+	schedule_work(&fep->timeout_work);
+}
+
 /*-----------------------------------------------------------------------------
  *  generic link-change handler - should be sufficient for most cases
  *-----------------------------------------------------------------------------*/
@@ -857,6 +865,7 @@ static int fs_enet_close(struct net_devi
 	netif_carrier_off(dev);
 	if (fep->fpi->use_napi)
 		napi_disable(&fep->napi);
+	cancel_work_sync(&fep->timeout_work);
 	phy_stop(fep->phydev);
 
 	spin_lock_irqsave(&fep->lock, flags);
@@ -1080,6 +1089,7 @@ static int __devinit fs_enet_probe(struc
 
 	ndev->netdev_ops = &fs_enet_netdev_ops;
 	ndev->watchdog_timeo = 2 * HZ;
+	INIT_WORK(&fep->timeout_work, fs_timeout_work);
 	if (fpi->use_napi)
 		netif_napi_add(ndev, &fep->napi, fs_enet_rx_napi,
 		               fpi->napi_weight);
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/net/ethernet/intel/e1000e/ich8lan.c linux-libre-3.2.100-gnu1/drivers/net/ethernet/intel/e1000e/ich8lan.c
--- linux-libre-3.2.99-gnu1/drivers/net/ethernet/intel/e1000e/ich8lan.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/net/ethernet/intel/e1000e/ich8lan.c	2018-03-03 10:57:56.000000000 -0500
@@ -657,6 +657,9 @@ out:
  *  Checks to see of the link status of the hardware has changed.  If a
  *  change in link status has been detected, then we read the PHY registers
  *  to get the current speed/duplex if link exists.
+ *
+ *  Returns a negative error code (-E1000_ERR_*) or 0 (link down) or 1 (link
+ *  up).
  **/
 static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
 {
@@ -672,7 +675,7 @@ static s32 e1000_check_for_copper_link_i
 	 * Change or Rx Sequence Error interrupt.
 	 */
 	if (!mac->get_link_status) {
-		ret_val = 0;
+		ret_val = 1;
 		goto out;
 	}
 
@@ -761,9 +764,12 @@ static s32 e1000_check_for_copper_link_i
 	 * different link partner.
 	 */
 	ret_val = e1000e_config_fc_after_link_up(hw);
-	if (ret_val)
+	if (ret_val) {
 		e_dbg("Error configuring flow control\n");
+		return ret_val;
+	}
 
+	ret_val = 1;
 out:
 	return ret_val;
 }
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/net/ethernet/intel/e1000e/lib.c linux-libre-3.2.100-gnu1/drivers/net/ethernet/intel/e1000e/lib.c
--- linux-libre-3.2.99-gnu1/drivers/net/ethernet/intel/e1000e/lib.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/net/ethernet/intel/e1000e/lib.c	2018-03-03 10:57:56.000000000 -0500
@@ -435,6 +435,9 @@ void e1000e_clear_hw_cntrs_base(struct e
  *  Checks to see of the link status of the hardware has changed.  If a
  *  change in link status has been detected, then we read the PHY registers
  *  to get the current speed/duplex if link exists.
+ *
+ *  Returns a negative error code (-E1000_ERR_*) or 0 (link down) or 1 (link
+ *  up).
  **/
 s32 e1000e_check_for_copper_link(struct e1000_hw *hw)
 {
@@ -449,7 +452,7 @@ s32 e1000e_check_for_copper_link(struct
 	 * Change or Rx Sequence Error interrupt.
 	 */
 	if (!mac->get_link_status)
-		return 0;
+		return 1;
 
 	/*
 	 * First we want to see if the MII Status Register reports
@@ -494,10 +497,12 @@ s32 e1000e_check_for_copper_link(struct
 	 * different link partner.
 	 */
 	ret_val = e1000e_config_fc_after_link_up(hw);
-	if (ret_val)
+	if (ret_val) {
 		e_dbg("Error configuring flow control\n");
+		return ret_val;
+	}
 
-	return ret_val;
+	return 1;
 }
 
 /**
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/net/ethernet/intel/e1000e/netdev.c linux-libre-3.2.100-gnu1/drivers/net/ethernet/intel/e1000e/netdev.c
--- linux-libre-3.2.99-gnu1/drivers/net/ethernet/intel/e1000e/netdev.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/net/ethernet/intel/e1000e/netdev.c	2018-03-03 10:57:56.000000000 -0500
@@ -4222,7 +4222,7 @@ static bool e1000e_has_link(struct e1000
 	case e1000_media_type_copper:
 		if (hw->mac.get_link_status) {
 			ret_val = hw->mac.ops.check_for_link(hw);
-			link_active = !hw->mac.get_link_status;
+			link_active = ret_val > 0;
 		} else {
 			link_active = 1;
 		}
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/net/phy/marvell.c linux-libre-3.2.100-gnu1/drivers/net/phy/marvell.c
--- linux-libre-3.2.99-gnu1/drivers/net/phy/marvell.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/net/phy/marvell.c	2018-03-03 10:57:56.000000000 -0500
@@ -808,7 +808,7 @@ static struct phy_driver marvell_drivers
 		.features = PHY_GBIT_FEATURES,
 		.flags = PHY_HAS_INTERRUPT,
 		.config_init = &m88e1145_config_init,
-		.config_aneg = &marvell_config_aneg,
+		.config_aneg = &m88e1101_config_aneg,
 		.read_status = &genphy_read_status,
 		.ack_interrupt = &marvell_ack_interrupt,
 		.config_intr = &marvell_config_intr,
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/net/ppp/pppoe.c linux-libre-3.2.100-gnu1/drivers/net/ppp/pppoe.c
--- linux-libre-3.2.99-gnu1/drivers/net/ppp/pppoe.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/net/ppp/pppoe.c	2018-03-03 10:57:56.000000000 -0500
@@ -838,6 +838,7 @@ static int pppoe_sendmsg(struct kiocb *i
 	struct pppoe_hdr *ph;
 	struct net_device *dev;
 	char *start;
+	int hlen;
 
 	lock_sock(sk);
 	if (sock_flag(sk, SOCK_DEAD) || !(sk->sk_state & PPPOX_CONNECTED)) {
@@ -856,16 +857,16 @@ static int pppoe_sendmsg(struct kiocb *i
 	if (total_len > (dev->mtu + dev->hard_header_len))
 		goto end;
 
-
-	skb = sock_wmalloc(sk, total_len + dev->hard_header_len + 32,
-			   0, GFP_KERNEL);
+	hlen = LL_RESERVED_SPACE(dev);
+	skb = sock_wmalloc(sk, hlen + sizeof(*ph) + total_len +
+			   dev->needed_tailroom, 0, GFP_KERNEL);
 	if (!skb) {
 		error = -ENOMEM;
 		goto end;
 	}
 
 	/* Reserve space for headers. */
-	skb_reserve(skb, dev->hard_header_len);
+	skb_reserve(skb, hlen);
 	skb_reset_network_header(skb);
 
 	skb->dev = dev;
@@ -926,7 +927,7 @@ static int __pppoe_xmit(struct sock *sk,
 	/* Copy the data if there is no space for the header or if it's
 	 * read-only.
 	 */
-	if (skb_cow_head(skb, sizeof(*ph) + dev->hard_header_len))
+	if (skb_cow_head(skb, LL_RESERVED_SPACE(dev) + sizeof(*ph)))
 		goto abort;
 
 	__skb_push(skb, sizeof(*ph));
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/of/fdt.c linux-libre-3.2.100-gnu1/drivers/of/fdt.c
--- linux-libre-3.2.99-gnu1/drivers/of/fdt.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/of/fdt.c	2018-03-03 10:57:56.000000000 -0500
@@ -389,7 +389,7 @@ static void __unflatten_device_tree(stru
 	mem = (unsigned long)
 		dt_alloc(size + 4, __alignof__(struct device_node));
 	if (!mem)
-		return NULL;
+		return;
 
 	memset((void *)mem, 0, size);
 
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/parisc/lba_pci.c linux-libre-3.2.100-gnu1/drivers/parisc/lba_pci.c
--- linux-libre-3.2.99-gnu1/drivers/parisc/lba_pci.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/parisc/lba_pci.c	2018-03-03 10:57:56.000000000 -0500
@@ -1603,3 +1603,36 @@ void lba_set_iregs(struct parisc_device
 	iounmap(base_addr);
 }
 
+
+/*
+ * The design of the Diva management card in rp34x0 machines (rp3410, rp3440)
+ * seems rushed, so that many built-in components simply don't work.
+ * The following quirks disable the serial AUX port and the built-in ATI RV100
+ * Radeon 7000 graphics card which both don't have any external connectors and
+ * thus are useless, and even worse, e.g. the AUX port occupies ttyS0 and as
+ * such makes those machines the only PARISC machines on which we can't use
+ * ttyS0 as boot console.
+ */
+static void quirk_diva_ati_card(struct pci_dev *dev)
+{
+	if (dev->subsystem_vendor != PCI_VENDOR_ID_HP ||
+	    dev->subsystem_device != 0x1292)
+		return;
+
+	dev_info(&dev->dev, "Hiding Diva built-in ATI card");
+	dev->device = 0;
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QY,
+	quirk_diva_ati_card);
+
+static void quirk_diva_aux_disable(struct pci_dev *dev)
+{
+	if (dev->subsystem_vendor != PCI_VENDOR_ID_HP ||
+	    dev->subsystem_device != 0x1291)
+		return;
+
+	dev_info(&dev->dev, "Hiding Diva built-in AUX serial device");
+	dev->device = 0;
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA_AUX,
+	quirk_diva_aux_disable);
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/pci/pci-driver.c linux-libre-3.2.100-gnu1/drivers/pci/pci-driver.c
--- linux-libre-3.2.99-gnu1/drivers/pci/pci-driver.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/pci/pci-driver.c	2018-03-03 10:57:56.000000000 -0500
@@ -872,7 +872,12 @@ static int pci_pm_thaw_noirq(struct devi
 	if (pci_has_legacy_pm_support(pci_dev))
 		return pci_legacy_resume_early(dev);
 
-	pci_update_current_state(pci_dev, PCI_D0);
+	/*
+	 * pci_restore_state() requires the device to be in D0 (because of MSI
+	 * restoration among other things), so force it into D0 in case the
+	 * driver's "freeze" callbacks put it into a low-power state directly.
+	 */
+	pci_set_power_state(pci_dev, PCI_D0);
 	pci_restore_state(pci_dev);
 
 	if (drv && drv->pm && drv->pm->thaw_noirq)
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/scsi/libsas/sas_ata.c linux-libre-3.2.100-gnu1/drivers/scsi/libsas/sas_ata.c
--- linux-libre-3.2.99-gnu1/drivers/scsi/libsas/sas_ata.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/scsi/libsas/sas_ata.c	2018-03-03 10:57:56.000000000 -0500
@@ -121,10 +121,6 @@ static void sas_ata_task_done(struct sas
 			if (unlikely(link->eh_info.err_mask))
 				qc->flags |= ATA_QCFLAG_FAILED;
 		}
-
-		dev->sata_dev.sstatus = resp->sstatus;
-		dev->sata_dev.serror = resp->serror;
-		dev->sata_dev.scontrol = resp->scontrol;
 	} else {
 		ac = sas_to_ata_err(stat);
 		if (ac) {
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/scsi/scsi_lib.c linux-libre-3.2.100-gnu1/drivers/scsi/scsi_lib.c
--- linux-libre-3.2.99-gnu1/drivers/scsi/scsi_lib.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/scsi/scsi_lib.c	2018-03-03 10:57:56.000000000 -0500
@@ -1688,11 +1688,13 @@ struct request_queue *__scsi_alloc_queue
 		q->limits.cluster = 0;
 
 	/*
-	 * set a reasonable default alignment on word boundaries: the
-	 * host and device may alter it using
-	 * blk_queue_update_dma_alignment() later.
+	 * Set a reasonable default alignment:  The larger of 32-byte (dword),
+	 * which is a common minimum for HBAs, and the minimum DMA alignment,
+	 * which is set by the platform.
+	 *
+	 * Devices that require a bigger alignment can increase it later.
 	 */
-	blk_queue_dma_alignment(q, 0x03);
+	blk_queue_dma_alignment(q, max(4, dma_get_cache_alignment()) - 1);
 
 	return q;
 }
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/staging/usbip/stub_dev.c linux-libre-3.2.100-gnu1/drivers/staging/usbip/stub_dev.c
--- linux-libre-3.2.99-gnu1/drivers/staging/usbip/stub_dev.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/staging/usbip/stub_dev.c	2018-03-03 10:57:56.000000000 -0500
@@ -186,8 +186,7 @@ static void stub_shutdown_connection(str
 	 * step 1?
 	 */
 	if (ud->tcp_socket) {
-		dev_dbg(&sdev->udev->dev, "shutdown tcp_socket %p\n",
-			ud->tcp_socket);
+		dev_dbg(&sdev->udev->dev, "shutdown sockfd %d\n", ud->sockfd);
 		kernel_sock_shutdown(ud->tcp_socket, SHUT_RDWR);
 	}
 
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/staging/usbip/stub_main.c linux-libre-3.2.100-gnu1/drivers/staging/usbip/stub_main.c
--- linux-libre-3.2.99-gnu1/drivers/staging/usbip/stub_main.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/staging/usbip/stub_main.c	2018-03-03 10:57:56.000000000 -0500
@@ -227,11 +227,12 @@ void stub_device_cleanup_urbs(struct stu
 	struct stub_priv *priv;
 	struct urb *urb;
 
-	dev_dbg(&sdev->udev->dev, "free sdev %p\n", sdev);
+	dev_dbg(&sdev->udev->dev, "Stub device cleaning up urbs\n");
 
 	while ((priv = stub_priv_pop(sdev))) {
 		urb = priv->urb;
-		dev_dbg(&sdev->udev->dev, "free urb %p\n", urb);
+		dev_dbg(&sdev->udev->dev, "free urb seqnum %lu\n",
+			priv->seqnum);
 		usb_kill_urb(urb);
 
 		kmem_cache_free(stub_priv_cache, priv);
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/staging/usbip/stub_rx.c linux-libre-3.2.100-gnu1/drivers/staging/usbip/stub_rx.c
--- linux-libre-3.2.99-gnu1/drivers/staging/usbip/stub_rx.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/staging/usbip/stub_rx.c	2018-03-03 10:57:56.000000000 -0500
@@ -239,9 +239,6 @@ static int stub_recv_cmd_unlink(struct s
 		if (priv->seqnum == pdu->u.cmd_unlink.seqnum) {
 			int ret;
 
-			dev_info(&priv->urb->dev->dev, "unlink urb %p\n",
-				 priv->urb);
-
 			/*
 			 * This matched urb is not completed yet (i.e., be in
 			 * flight in usb hcd hardware/driver). Now we are
@@ -280,8 +277,8 @@ static int stub_recv_cmd_unlink(struct s
 			ret = usb_unlink_urb(priv->urb);
 			if (ret != -EINPROGRESS)
 				dev_err(&priv->urb->dev->dev,
-					"failed to unlink a urb %p, ret %d\n",
-					priv->urb, ret);
+					"failed to unlink a urb # %lu, ret %d\n",
+					priv->seqnum, ret);
 			return 0;
 		}
 	}
@@ -586,7 +583,7 @@ static void stub_rx_pdu(struct usbip_dev
 	memset(&pdu, 0, sizeof(pdu));
 
 	/* 1. receive a pdu header */
-	ret = usbip_xmit(0, ud->tcp_socket, (char *) &pdu, sizeof(pdu), 0);
+	ret = usbip_recv(ud->tcp_socket, &pdu, sizeof(pdu));
 	if (ret != sizeof(pdu)) {
 		dev_err(dev, "recv a header, %d\n", ret);
 		usbip_event_add(ud, SDEV_EVENT_ERROR_TCP);
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/staging/usbip/stub_tx.c linux-libre-3.2.100-gnu1/drivers/staging/usbip/stub_tx.c
--- linux-libre-3.2.99-gnu1/drivers/staging/usbip/stub_tx.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/staging/usbip/stub_tx.c	2018-03-03 10:57:56.000000000 -0500
@@ -201,8 +201,8 @@ static int stub_send_ret_submit(struct s
 
 		/* 1. setup usbip_header */
 		setup_ret_submit_pdu(&pdu_header, urb);
-		usbip_dbg_stub_tx("setup txdata seqnum: %d urb: %p\n",
-				  pdu_header.base.seqnum, urb);
+		usbip_dbg_stub_tx("setup txdata seqnum: %d\n",
+				  pdu_header.base.seqnum);
 		/*usbip_dump_header(pdu_header);*/
 		usbip_header_correct_endian(&pdu_header, 1);
 
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/staging/usbip/usbip_common.c linux-libre-3.2.100-gnu1/drivers/staging/usbip/usbip_common.c
--- linux-libre-3.2.99-gnu1/drivers/staging/usbip/usbip_common.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/staging/usbip/usbip_common.c	2018-03-03 10:57:56.000000000 -0500
@@ -115,7 +115,7 @@ static void usbip_dump_usb_device(struct
 		break;
 	}
 
-	pr_debug("tt %p, ttport %d\n", udev->tt, udev->ttport);
+	pr_debug("tt hub ttport %d\n", udev->ttport);
 
 	dev_dbg(dev, "                    ");
 	for (i = 0; i < 16; i++)
@@ -148,11 +148,8 @@ static void usbip_dump_usb_device(struct
 	}
 	pr_debug("\n");
 
-	dev_dbg(dev, "parent %p, bus %p\n", udev->parent, udev->bus);
-
-	dev_dbg(dev, "descriptor %p, config %p, actconfig %p, "
-		"rawdescriptors %p\n", &udev->descriptor, udev->config,
-		udev->actconfig, udev->rawdescriptors);
+	dev_dbg(dev, "parent %s, bus %s\n", dev_name(&udev->parent->dev),
+		udev->bus->bus_name);
 
 	dev_dbg(dev, "have_langid %d, string_langid %d\n",
 		udev->have_langid, udev->string_langid);
@@ -261,9 +258,6 @@ void usbip_dump_urb(struct urb *urb)
 
 	dev = &urb->dev->dev;
 
-	dev_dbg(dev, "   urb                   :%p\n", urb);
-	dev_dbg(dev, "   dev                   :%p\n", urb->dev);
-
 	usbip_dump_usb_device(urb->dev);
 
 	dev_dbg(dev, "   pipe                  :%08x ", urb->pipe);
@@ -272,11 +266,9 @@ void usbip_dump_urb(struct urb *urb)
 
 	dev_dbg(dev, "   status                :%d\n", urb->status);
 	dev_dbg(dev, "   transfer_flags        :%08X\n", urb->transfer_flags);
-	dev_dbg(dev, "   transfer_buffer       :%p\n", urb->transfer_buffer);
 	dev_dbg(dev, "   transfer_buffer_length:%d\n",
 						urb->transfer_buffer_length);
 	dev_dbg(dev, "   actual_length         :%d\n", urb->actual_length);
-	dev_dbg(dev, "   setup_packet          :%p\n", urb->setup_packet);
 
 	if (urb->setup_packet && usb_pipetype(urb->pipe) == PIPE_CONTROL)
 		usbip_dump_usb_ctrlrequest(
@@ -286,8 +278,6 @@ void usbip_dump_urb(struct urb *urb)
 	dev_dbg(dev, "   number_of_packets     :%d\n", urb->number_of_packets);
 	dev_dbg(dev, "   interval              :%d\n", urb->interval);
 	dev_dbg(dev, "   error_count           :%d\n", urb->error_count);
-	dev_dbg(dev, "   context               :%p\n", urb->context);
-	dev_dbg(dev, "   complete              :%p\n", urb->complete);
 }
 EXPORT_SYMBOL_GPL(usbip_dump_urb);
 
@@ -334,9 +324,8 @@ void usbip_dump_header(struct usbip_head
 }
 EXPORT_SYMBOL_GPL(usbip_dump_header);
 
-/* Send/receive messages over TCP/IP. I refer drivers/block/nbd.c */
-int usbip_xmit(int send, struct socket *sock, char *buf, int size,
-	       int msg_flags)
+/* Receive data over TCP/IP. */
+int usbip_recv(struct socket *sock, void *buf, int size)
 {
 	int result;
 	struct msghdr msg;
@@ -347,26 +336,10 @@ int usbip_xmit(int send, struct socket *
 	char *bp = buf;
 	int osize = size;
 
-	usbip_dbg_xmit("enter\n");
-
-	if (!sock || !buf || !size) {
-		pr_err("invalid arg, sock %p buff %p size %d\n", sock, buf,
-		       size);
+	if (!sock || !buf || !size)
 		return -EINVAL;
-	}
 
-	if (usbip_dbg_flag_xmit) {
-		if (send) {
-			if (!in_interrupt())
-				pr_debug("%-10s:", current->comm);
-			else
-				pr_debug("interrupt  :");
-
-			pr_debug("sending... , sock %p, buf %p, size %d, "
-				 "msg_flags %d\n", sock, buf, size, msg_flags);
-			usbip_dump_buffer(buf, size);
-		}
-	}
+	usbip_dbg_xmit("enter\n");
 
 	do {
 		sock->sk->sk_allocation = GFP_NOIO;
@@ -377,42 +350,27 @@ int usbip_xmit(int send, struct socket *
 		msg.msg_control = NULL;
 		msg.msg_controllen = 0;
 		msg.msg_namelen    = 0;
-		msg.msg_flags      = msg_flags | MSG_NOSIGNAL;
-
-		if (send)
-			result = kernel_sendmsg(sock, &msg, &iov, 1, size);
-		else
-			result = kernel_recvmsg(sock, &msg, &iov, 1, size,
-						MSG_WAITALL);
+		msg.msg_flags      = MSG_NOSIGNAL;
 
-		if (result <= 0) {
-			pr_debug("%s sock %p buf %p size %u ret %d total %d\n",
-				 send ? "send" : "receive", sock, buf, size,
-				 result, total);
+		result = kernel_recvmsg(sock, &msg, &iov, 1, size, MSG_WAITALL);
+		if (result <= 0)
 			goto err;
-		}
 
 		size -= result;
 		buf += result;
 		total += result;
-
 	} while (size > 0);
 
 	if (usbip_dbg_flag_xmit) {
-		if (!send) {
-			if (!in_interrupt())
-				pr_debug("%-10s:", current->comm);
-			else
-				pr_debug("interrupt  :");
-
-			pr_debug("receiving....\n");
-			usbip_dump_buffer(bp, osize);
-			pr_debug("received, osize %d ret %d size %d total %d\n",
-				 osize, result, size, total);
-		}
+		if (!in_interrupt())
+			pr_debug("%-10s:", current->comm);
+		else
+			pr_debug("interrupt  :");
 
-		if (send)
-			pr_debug("send, total %d\n", total);
+		pr_debug("receiving....\n");
+		usbip_dump_buffer(bp, osize);
+		pr_debug("received, osize %d ret %d size %d total %d\n",
+			osize, result, size, total);
 	}
 
 	return total;
@@ -420,7 +378,7 @@ int usbip_xmit(int send, struct socket *
 err:
 	return result;
 }
-EXPORT_SYMBOL_GPL(usbip_xmit);
+EXPORT_SYMBOL_GPL(usbip_recv);
 
 struct socket *sockfd_to_socket(unsigned int sockfd)
 {
@@ -712,7 +670,7 @@ int usbip_recv_iso(struct usbip_device *
 	if (!buff)
 		return -ENOMEM;
 
-	ret = usbip_xmit(0, ud->tcp_socket, buff, size, 0);
+	ret = usbip_recv(ud->tcp_socket, buff, size);
 	if (ret != size) {
 		dev_err(&urb->dev->dev, "recv iso_frame_descriptor, %d\n",
 			ret);
@@ -831,8 +789,7 @@ int usbip_recv_xbuff(struct usbip_device
 		}
 	}
 
-	ret = usbip_xmit(0, ud->tcp_socket, (char *)urb->transfer_buffer,
-			 size, 0);
+	ret = usbip_recv(ud->tcp_socket, urb->transfer_buffer, size);
 	if (ret != size) {
 		dev_err(&urb->dev->dev, "recv xbuf, %d\n", ret);
 		if (ud->side == USBIP_STUB) {
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/staging/usbip/usbip_common.h linux-libre-3.2.100-gnu1/drivers/staging/usbip/usbip_common.h
--- linux-libre-3.2.99-gnu1/drivers/staging/usbip/usbip_common.h	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/staging/usbip/usbip_common.h	2018-03-03 10:57:56.000000000 -0500
@@ -306,8 +306,7 @@ void setreuse(struct socket *);
 void usbip_dump_urb(struct urb *purb);
 void usbip_dump_header(struct usbip_header *pdu);
 
-int usbip_xmit(int send, struct socket *sock, char *buf, int size,
-	       int msg_flags);
+int usbip_recv(struct socket *sock, void *buf, int size);
 struct socket *sockfd_to_socket(unsigned int sockfd);
 
 void usbip_pack_pdu(struct usbip_header *pdu, struct urb *urb, int cmd,
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/staging/usbip/userspace/src/utils.c linux-libre-3.2.100-gnu1/drivers/staging/usbip/userspace/src/utils.c
--- linux-libre-3.2.99-gnu1/drivers/staging/usbip/userspace/src/utils.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/staging/usbip/userspace/src/utils.c	2018-03-03 10:57:56.000000000 -0500
@@ -34,6 +34,7 @@ int modify_match_busid(char *busid, int
 	char match_busid_attr_path[SYSFS_PATH_MAX];
 	struct sysfs_attribute *match_busid_attr;
 	int rc, ret = 0;
+	int cmd_size;
 
 	if (strnlen(busid, SYSFS_BUS_ID_SIZE) > SYSFS_BUS_ID_SIZE - 1) {
 		dbg("busid is too long");
@@ -58,13 +59,15 @@ int modify_match_busid(char *busid, int
 	}
 
 	if (add)
-		snprintf(buff, SYSFS_BUS_ID_SIZE + 4, "add %s", busid);
+		cmd_size = snprintf(buff, SYSFS_BUS_ID_SIZE + 4, "add %s",
+				    busid);
 	else
-		snprintf(buff, SYSFS_BUS_ID_SIZE + 4, "del %s", busid);
+		cmd_size = snprintf(buff, SYSFS_BUS_ID_SIZE + 4, "del %s",
+				    busid);
 
 	dbg("write \"%s\" to %s", buff, match_busid_attr->path);
 
-	rc = sysfs_write_attribute(match_busid_attr, buff, sizeof(buff));
+	rc = sysfs_write_attribute(match_busid_attr, buff, cmd_size);
 	if (rc < 0) {
 		dbg("failed to write match_busid: %s", strerror(errno));
 		ret = -1;
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/staging/usbip/vhci_hcd.c linux-libre-3.2.100-gnu1/drivers/staging/usbip/vhci_hcd.c
--- linux-libre-3.2.99-gnu1/drivers/staging/usbip/vhci_hcd.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/staging/usbip/vhci_hcd.c	2018-03-03 10:57:56.000000000 -0500
@@ -516,9 +516,6 @@ static int vhci_urb_enqueue(struct usb_h
 	unsigned long flags;
 	struct vhci_device *vdev;
 
-	usbip_dbg_vhci_hc("enter, usb_hcd %p urb %p mem_flags %d\n",
-			  hcd, urb, mem_flags);
-
 	/* patch to usb_sg_init() is in 2.5.60 */
 	BUG_ON(!urb->transfer_buffer && urb->transfer_buffer_length);
 
@@ -677,8 +674,6 @@ static int vhci_urb_dequeue(struct usb_h
 	struct vhci_priv *priv;
 	struct vhci_device *vdev;
 
-	pr_info("dequeue a urb %p\n", urb);
-
 	spin_lock_irqsave(&the_controller->lock, flags);
 
 	priv = urb->hcpriv;
@@ -707,7 +702,6 @@ static int vhci_urb_dequeue(struct usb_h
 
 		spin_lock_irqsave(&vdev->priv_lock, flags2);
 
-		pr_info("device %p seems to be disconnected\n", vdev);
 		list_del(&priv->list);
 		kfree(priv);
 		urb->hcpriv = NULL;
@@ -719,8 +713,6 @@ static int vhci_urb_dequeue(struct usb_h
 		 * vhci_rx will receive RET_UNLINK and give back the URB.
 		 * Otherwise, we give back it here.
 		 */
-		pr_info("gives back urb %p\n", urb);
-
 		usb_hcd_unlink_urb_from_ep(hcd, urb);
 
 		spin_unlock_irqrestore(&the_controller->lock, flags);
@@ -751,8 +743,6 @@ static int vhci_urb_dequeue(struct usb_h
 
 		unlink->unlink_seqnum = priv->seqnum;
 
-		pr_info("device %p seems to be still connected\n", vdev);
-
 		/* send cmd_unlink and try to cancel the pending URB in the
 		 * peer */
 		list_add_tail(&unlink->list, &vdev->unlink_tx);
@@ -821,7 +811,7 @@ static void vhci_shutdown_connection(str
 
 	/* need this? see stub_dev.c */
 	if (ud->tcp_socket) {
-		pr_debug("shutdown tcp_socket %p\n", ud->tcp_socket);
+		pr_debug("shutdown tcp_socket %d\n", ud->sockfd);
 		kernel_sock_shutdown(ud->tcp_socket, SHUT_RDWR);
 	}
 
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/staging/usbip/vhci_rx.c linux-libre-3.2.100-gnu1/drivers/staging/usbip/vhci_rx.c
--- linux-libre-3.2.99-gnu1/drivers/staging/usbip/vhci_rx.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/staging/usbip/vhci_rx.c	2018-03-03 10:57:56.000000000 -0500
@@ -35,21 +35,19 @@ struct urb *pickup_urb_and_free_priv(str
 			urb = priv->urb;
 			status = urb->status;
 
-			usbip_dbg_vhci_rx("find urb %p vurb %p seqnum %u\n",
-					  urb, priv, seqnum);
+			usbip_dbg_vhci_rx("find urb seqnum %u\n", seqnum);
 
 			/* TODO: fix logic here to improve indent situtation */
 			if (status != -EINPROGRESS) {
 				if (status == -ENOENT ||
 				    status == -ECONNRESET)
-					dev_info(&urb->dev->dev,
-						 "urb %p was unlinked "
-						 "%ssynchronuously.\n", urb,
-						 status == -ENOENT ? "" : "a");
+					dev_dbg(&urb->dev->dev,
+						"urb seq# %u was unlinked %ssynchronuously\n",
+						seqnum, status == -ENOENT ? "" : "a");
 				else
-					dev_info(&urb->dev->dev,
-						 "urb %p may be in a error, "
-						 "status %d\n", urb, status);
+					dev_dbg(&urb->dev->dev,
+						"urb seq# %u may be in a error, status %d\n",
+						seqnum, status);
 			}
 
 			list_del(&priv->list);
@@ -75,8 +73,8 @@ static void vhci_recv_ret_submit(struct
 	spin_unlock(&vdev->priv_lock);
 
 	if (!urb) {
-		pr_err("cannot find a urb of seqnum %u\n", pdu->base.seqnum);
-		pr_info("max seqnum %d\n",
+		pr_err("cannot find a urb of seqnum %u max seqnum %d\n",
+			pdu->base.seqnum,
 			atomic_read(&the_controller->seqnum));
 		usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
 		return;
@@ -99,7 +97,7 @@ static void vhci_recv_ret_submit(struct
 	if (usbip_dbg_flag_vhci_rx)
 		usbip_dump_urb(urb);
 
-	usbip_dbg_vhci_rx("now giveback urb %p\n", urb);
+	usbip_dbg_vhci_rx("now giveback urb %u\n", pdu->base.seqnum);
 
 	spin_lock_irqsave(&the_controller->lock, flags);
 	usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb);
@@ -165,7 +163,7 @@ static void vhci_recv_ret_unlink(struct
 		pr_info("the urb (seqnum %d) was already given backed\n",
 			pdu->base.seqnum);
 	} else {
-		usbip_dbg_vhci_rx("now giveback urb %p\n", urb);
+		usbip_dbg_vhci_rx("now giveback urb %d\n", pdu->base.seqnum);
 
 		/* If unlink is succeed, status is -ECONNRESET */
 		urb->status = pdu->u.ret_unlink.status;
@@ -205,7 +203,7 @@ static void vhci_rx_pdu(struct usbip_dev
 	memset(&pdu, 0, sizeof(pdu));
 
 	/* 1. receive a pdu header */
-	ret = usbip_xmit(0, ud->tcp_socket, (char *) &pdu, sizeof(pdu), 0);
+	ret = usbip_recv(ud->tcp_socket, &pdu, sizeof(pdu));
 	if (ret < 0) {
 		if (ret == -ECONNRESET)
 			pr_info("connection reset by peer\n");
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/staging/usbip/vhci_tx.c linux-libre-3.2.100-gnu1/drivers/staging/usbip/vhci_tx.c
--- linux-libre-3.2.99-gnu1/drivers/staging/usbip/vhci_tx.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/staging/usbip/vhci_tx.c	2018-03-03 10:57:56.000000000 -0500
@@ -83,7 +83,8 @@ static int vhci_send_cmd_submit(struct v
 		memset(&msg, 0, sizeof(msg));
 		memset(&iov, 0, sizeof(iov));
 
-		usbip_dbg_vhci_tx("setup txdata urb %p\n", urb);
+		usbip_dbg_vhci_tx("setup txdata urb seqnum %lu\n",
+				  priv->seqnum);
 
 		/* 1. setup usbip_header */
 		setup_cmd_submit_pdu(&pdu_header, urb);
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/tty/n_tty.c linux-libre-3.2.100-gnu1/drivers/tty/n_tty.c
--- linux-libre-3.2.99-gnu1/drivers/tty/n_tty.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/tty/n_tty.c	2018-03-03 10:57:56.000000000 -0500
@@ -1459,7 +1459,7 @@ static void n_tty_set_termios(struct tty
 	BUG_ON(!tty);
 
 	if (old)
-		canon_change = (old->c_lflag ^ tty->termios->c_lflag) & ICANON;
+		canon_change = (old->c_lflag ^ tty->termios->c_lflag) & (ICANON | EXTPROC);
 	if (canon_change) {
 		memset(&tty->read_flags, 0, sizeof tty->read_flags);
 		tty->canon_head = tty->read_tail;
@@ -2096,7 +2096,7 @@ static int n_tty_ioctl(struct tty_struct
 	case TIOCINQ:
 		/* FIXME: Locking */
 		retval = tty->read_cnt;
-		if (L_ICANON(tty))
+		if (L_ICANON(tty) && !L_EXTPROC(tty))
 			retval = inq_canon(tty);
 		return put_user(retval, (unsigned int __user *) arg);
 	default:
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/tty/serial/8250_pci.c linux-libre-3.2.100-gnu1/drivers/tty/serial/8250_pci.c
--- linux-libre-3.2.99-gnu1/drivers/tty/serial/8250_pci.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/tty/serial/8250_pci.c	2018-03-03 10:57:56.000000000 -0500
@@ -4175,6 +4175,9 @@ static struct pci_device_id serial_pci_t
 	{ PCI_DEVICE(0x1601, 0x0800), .driver_data = pbn_b0_4_1250000 },
 	{ PCI_DEVICE(0x1601, 0xa801), .driver_data = pbn_b0_4_1250000 },
 
+	/* Amazon PCI serial device */
+	{ PCI_DEVICE(0x1d0f, 0x8250), .driver_data = pbn_b0_1_115200 },
+
 	/*
 	 * These entries match devices with class COMMUNICATION_SERIAL,
 	 * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/usb/core/config.c linux-libre-3.2.100-gnu1/drivers/usb/core/config.c
--- linux-libre-3.2.99-gnu1/drivers/usb/core/config.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/usb/core/config.c	2018-03-03 10:57:56.000000000 -0500
@@ -878,6 +878,13 @@ void usb_release_bos_descriptor(struct u
 	}
 }
 
+static const __u8 bos_desc_len[256] = {
+	[USB_CAP_TYPE_WIRELESS_USB] = USB_DT_USB_WIRELESS_CAP_SIZE,
+	[USB_CAP_TYPE_EXT]          = USB_DT_USB_EXT_CAP_SIZE,
+	[USB_SS_CAP_TYPE]           = USB_DT_USB_SS_CAP_SIZE,
+	[CONTAINER_ID_TYPE]         = USB_DT_USB_SS_CONTN_ID_SIZE,
+};
+
 /* Get BOS descriptor set */
 int usb_get_bos_descriptor(struct usb_device *dev)
 {
@@ -886,6 +893,7 @@ int usb_get_bos_descriptor(struct usb_de
 	struct usb_dev_cap_header *cap;
 	unsigned char *buffer;
 	int length, total_len, num, i;
+	__u8 cap_type;
 	int ret;
 
 	bos = kzalloc(sizeof(struct usb_bos_descriptor), GFP_KERNEL);
@@ -938,7 +946,13 @@ int usb_get_bos_descriptor(struct usb_de
 			dev->bos->desc->bNumDeviceCaps = i;
 			break;
 		}
+		cap_type = cap->bDevCapabilityType;
 		length = cap->bLength;
+		if (bos_desc_len[cap_type] && length < bos_desc_len[cap_type]) {
+			dev->bos->desc->bNumDeviceCaps = i;
+			break;
+		}
+
 		total_len -= length;
 
 		if (cap->bDescriptorType != USB_DT_DEVICE_CAPABILITY) {
@@ -946,7 +960,7 @@ int usb_get_bos_descriptor(struct usb_de
 			continue;
 		}
 
-		switch (cap->bDevCapabilityType) {
+		switch (cap_type) {
 		case USB_CAP_TYPE_WIRELESS_USB:
 			/* Wireless USB cap descriptor is handled by wusb */
 			break;
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/usb/core/devio.c linux-libre-3.2.100-gnu1/drivers/usb/core/devio.c
--- linux-libre-3.2.99-gnu1/drivers/usb/core/devio.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/usb/core/devio.c	2018-03-03 10:57:56.000000000 -0500
@@ -1093,14 +1093,18 @@ static int proc_do_submiturb(struct dev_
 	unsigned int u, totlen, isofrmlen;
 	int ret, ifnum = -1;
 	int is_in;
-
-	if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP |
-				USBDEVFS_URB_SHORT_NOT_OK |
+	unsigned long mask =	USBDEVFS_URB_SHORT_NOT_OK |
 				USBDEVFS_URB_BULK_CONTINUATION |
 				USBDEVFS_URB_NO_FSBR |
 				USBDEVFS_URB_ZERO_PACKET |
-				USBDEVFS_URB_NO_INTERRUPT))
-		return -EINVAL;
+				USBDEVFS_URB_NO_INTERRUPT;
+	/* USBDEVFS_URB_ISO_ASAP is a special case */
+	if (uurb->type == USBDEVFS_URB_TYPE_ISO)
+		mask |= USBDEVFS_URB_ISO_ASAP;
+
+	if (uurb->flags & ~mask)
+			return -EINVAL;
+
 	if (uurb->buffer_length > 0 && !uurb->buffer)
 		return -EINVAL;
 	if (!(uurb->type == USBDEVFS_URB_TYPE_CONTROL &&
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/usb/core/quirks.c linux-libre-3.2.100-gnu1/drivers/usb/core/quirks.c
--- linux-libre-3.2.99-gnu1/drivers/usb/core/quirks.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/usb/core/quirks.c	2018-03-03 10:57:56.000000000 -0500
@@ -53,10 +53,11 @@ static const struct usb_device_id usb_qu
 	/* Microsoft LifeCam-VX700 v2.0 */
 	{ USB_DEVICE(0x045e, 0x0770), .driver_info = USB_QUIRK_RESET_RESUME },
 
-	/* Logitech HD Pro Webcams C920, C920-C and C930e */
+	/* Logitech HD Pro Webcams C920, C920-C, C925e and C930e */
 	{ USB_DEVICE(0x046d, 0x082d), .driver_info = USB_QUIRK_DELAY_INIT },
 	{ USB_DEVICE(0x046d, 0x0841), .driver_info = USB_QUIRK_DELAY_INIT },
 	{ USB_DEVICE(0x046d, 0x0843), .driver_info = USB_QUIRK_DELAY_INIT },
+	{ USB_DEVICE(0x046d, 0x085b), .driver_info = USB_QUIRK_DELAY_INIT },
 
 	/* Logitech ConferenceCam CC3000e */
 	{ USB_DEVICE(0x046d, 0x0847), .driver_info = USB_QUIRK_DELAY_INIT },
@@ -128,6 +129,9 @@ static const struct usb_device_id usb_qu
 	/* appletouch */
 	{ USB_DEVICE(0x05ac, 0x021a), .driver_info = USB_QUIRK_RESET_RESUME },
 
+	/* ELSA MicroLink 56K */
+	{ USB_DEVICE(0x05cc, 0x2267), .driver_info = USB_QUIRK_RESET_RESUME },
+
 	/* Avision AV600U */
 	{ USB_DEVICE(0x0638, 0x0a13), .driver_info =
 	  USB_QUIRK_STRING_FETCH_255 },
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/usb/host/ehci-dbg.c linux-libre-3.2.100-gnu1/drivers/usb/host/ehci-dbg.c
--- linux-libre-3.2.99-gnu1/drivers/usb/host/ehci-dbg.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/usb/host/ehci-dbg.c	2018-03-03 10:57:56.000000000 -0500
@@ -785,7 +785,7 @@ static ssize_t fill_registers_buffer(str
 			default:		/* unknown */
 				break;
 			}
-			temp = (cap >> 8) & 0xff;
+			offset = (cap >> 8) & 0xff;
 		}
 	}
 #endif
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/usb/host/xhci-mem.c linux-libre-3.2.100-gnu1/drivers/usb/host/xhci-mem.c
--- linux-libre-3.2.99-gnu1/drivers/usb/host/xhci-mem.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/usb/host/xhci-mem.c	2018-03-03 10:57:56.000000000 -0500
@@ -873,10 +873,9 @@ int xhci_alloc_virt_device(struct xhci_h
 		return 0;
 	}
 
-	xhci->devs[slot_id] = kzalloc(sizeof(*xhci->devs[slot_id]), flags);
-	if (!xhci->devs[slot_id])
+	dev = kzalloc(sizeof(*dev), flags);
+	if (!dev)
 		return 0;
-	dev = xhci->devs[slot_id];
 
 	/* Allocate the (output) device context that will be used in the HC. */
 	dev->out_ctx = xhci_alloc_container_ctx(xhci, XHCI_CTX_TYPE_DEVICE, flags);
@@ -925,9 +924,19 @@ int xhci_alloc_virt_device(struct xhci_h
 		 &xhci->dcbaa->dev_context_ptrs[slot_id],
 		 le64_to_cpu(xhci->dcbaa->dev_context_ptrs[slot_id]));
 
+	xhci->devs[slot_id] = dev;
+
 	return 1;
 fail:
-	xhci_free_virt_device(xhci, slot_id);
+
+	if (dev->eps[0].ring)
+		xhci_ring_free(xhci, dev->eps[0].ring);
+	if (dev->in_ctx)
+		xhci_free_container_ctx(xhci, dev->in_ctx);
+	if (dev->out_ctx)
+		xhci_free_container_ctx(xhci, dev->out_ctx);
+	kfree(dev);
+
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/usb/host/xhci-ring.c linux-libre-3.2.100-gnu1/drivers/usb/host/xhci-ring.c
--- linux-libre-3.2.99-gnu1/drivers/usb/host/xhci-ring.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/usb/host/xhci-ring.c	2018-03-03 10:57:56.000000000 -0500
@@ -2396,12 +2396,16 @@ static int handle_tx_event(struct xhci_h
 		 */
 		if (list_empty(&ep_ring->td_list)) {
 			/*
-			 * A stopped endpoint may generate an extra completion
-			 * event if the device was suspended.  Don't print
-			 * warnings.
+			 * Don't print wanings if it's due to a stopped endpoint
+			 * generating an extra completion event if the device
+			 * was suspended. Or, a event for the last TRB of a
+			 * short TD we already got a short event for.
+			 * The short TD is already removed from the TD list.
 			 */
+
 			if (!(trb_comp_code == COMP_STOP ||
-						trb_comp_code == COMP_STOP_INVAL)) {
+			      trb_comp_code == COMP_STOP_INVAL ||
+			      ep_ring->last_td_was_short)) {
 				xhci_warn(xhci, "WARN Event TRB for slot %d ep %d with no TDs queued?\n",
 						TRB_TO_SLOT_ID(le32_to_cpu(event->flags)),
 						ep_index);
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/usb/mon/mon_bin.c linux-libre-3.2.100-gnu1/drivers/usb/mon/mon_bin.c
--- linux-libre-3.2.99-gnu1/drivers/usb/mon/mon_bin.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/usb/mon/mon_bin.c	2018-03-03 10:57:56.000000000 -0500
@@ -1000,7 +1000,9 @@ static long mon_bin_ioctl(struct file *f
 		break;
 
 	case MON_IOCQ_RING_SIZE:
+		mutex_lock(&rp->fetch_lock);
 		ret = rp->b_size;
+		mutex_unlock(&rp->fetch_lock);
 		break;
 
 	case MON_IOCT_RING_SIZE:
@@ -1227,12 +1229,16 @@ static int mon_bin_vma_fault(struct vm_a
 	unsigned long offset, chunk_idx;
 	struct page *pageptr;
 
+	mutex_lock(&rp->fetch_lock);
 	offset = vmf->pgoff << PAGE_SHIFT;
-	if (offset >= rp->b_size)
+	if (offset >= rp->b_size) {
+		mutex_unlock(&rp->fetch_lock);
 		return VM_FAULT_SIGBUS;
+	}
 	chunk_idx = offset / CHUNK_SIZE;
 	pageptr = rp->b_vec[chunk_idx].pg;
 	get_page(pageptr);
+	mutex_unlock(&rp->fetch_lock);
 	vmf->page = pageptr;
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/usb/serial/cp210x.c linux-libre-3.2.100-gnu1/drivers/usb/serial/cp210x.c
--- linux-libre-3.2.99-gnu1/drivers/usb/serial/cp210x.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/usb/serial/cp210x.c	2018-03-03 10:57:56.000000000 -0500
@@ -126,6 +126,7 @@ static const struct usb_device_id id_tab
 	{ USB_DEVICE(0x10C4, 0x8470) }, /* Juniper Networks BX Series System Console */
 	{ USB_DEVICE(0x10C4, 0x8477) }, /* Balluff RFID */
 	{ USB_DEVICE(0x10C4, 0x84B6) }, /* Starizona Hyperion */
+	{ USB_DEVICE(0x10C4, 0x85A7) }, /* LifeScan OneTouch Verio IQ */
 	{ USB_DEVICE(0x10C4, 0x85EA) }, /* AC-Services IBUS-IF */
 	{ USB_DEVICE(0x10C4, 0x85EB) }, /* AC-Services CIS-IBUS */
 	{ USB_DEVICE(0x10C4, 0x85F8) }, /* Virtenio Preon32 */
@@ -176,6 +177,7 @@ static const struct usb_device_id id_tab
 	{ USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */
 	{ USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
 	{ USB_DEVICE(0x18EF, 0xE025) }, /* ELV Marble Sound Board 1 */
+	{ USB_DEVICE(0x18EF, 0xE030) }, /* ELV ALC 8xxx Battery Charger */
 	{ USB_DEVICE(0x18EF, 0xE032) }, /* ELV TFD500 Data Logger */
 	{ USB_DEVICE(0x1901, 0x0190) }, /* GE B850 CP2105 Recorder interface */
 	{ USB_DEVICE(0x1901, 0x0193) }, /* GE B650 CP2104 PMC interface */
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/usb/serial/ftdi_sio.c linux-libre-3.2.100-gnu1/drivers/usb/serial/ftdi_sio.c
--- linux-libre-3.2.99-gnu1/drivers/usb/serial/ftdi_sio.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/usb/serial/ftdi_sio.c	2018-03-03 10:57:56.000000000 -0500
@@ -1037,6 +1037,7 @@ static struct usb_device_id id_table_com
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
 	{ USB_DEVICE(CYPRESS_VID, CYPRESS_WICED_BT_USB_PID) },
 	{ USB_DEVICE(CYPRESS_VID, CYPRESS_WICED_WL_USB_PID) },
+	{ USB_DEVICE(AIRBUS_DS_VID, AIRBUS_DS_P8GR) },
 	{ },					/* Optional parameter entry */
 	{ }					/* Terminating entry */
 };
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/usb/serial/ftdi_sio_ids.h linux-libre-3.2.100-gnu1/drivers/usb/serial/ftdi_sio_ids.h
--- linux-libre-3.2.99-gnu1/drivers/usb/serial/ftdi_sio_ids.h	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/usb/serial/ftdi_sio_ids.h	2018-03-03 10:57:56.000000000 -0500
@@ -899,6 +899,12 @@
 #define ICPDAS_I7563U_PID		0x0105
 
 /*
+ * Airbus Defence and Space
+ */
+#define AIRBUS_DS_VID			0x1e8e  /* Vendor ID */
+#define AIRBUS_DS_P8GR			0x6001  /* Tetra P8GR */
+
+/*
  * RT Systems programming cables for various ham radios
  */
 #define RTSYSTEMS_VID		0x2100	/* Vendor ID */
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/usb/serial/option.c linux-libre-3.2.100-gnu1/drivers/usb/serial/option.c
--- linux-libre-3.2.99-gnu1/drivers/usb/serial/option.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/usb/serial/option.c	2018-03-03 10:57:56.000000000 -0500
@@ -237,11 +237,14 @@ static void option_instat_callback(struc
 /* These Quectel products use Qualcomm's vendor ID */
 #define QUECTEL_PRODUCT_UC20			0x9003
 #define QUECTEL_PRODUCT_UC15			0x9090
+/* These Yuga products use Qualcomm's vendor ID */
+#define YUGA_PRODUCT_CLM920_NC5			0x9625
 
 #define QUECTEL_VENDOR_ID			0x2c7c
 /* These Quectel products use Quectel's vendor ID */
 #define QUECTEL_PRODUCT_EC21			0x0121
 #define QUECTEL_PRODUCT_EC25			0x0125
+#define QUECTEL_PRODUCT_BG96			0x0296
 
 #define CMOTECH_VENDOR_ID			0x16d8
 #define CMOTECH_PRODUCT_6001			0x6001
@@ -656,6 +659,10 @@ static const struct option_blacklist_inf
 	.reserved = BIT(1) | BIT(2) | BIT(3),
 };
 
+static const struct option_blacklist_info yuga_clm920_nc5_blacklist = {
+	.reserved = BIT(1) | BIT(4),
+};
+
 static const struct usb_device_id option_ids[] = {
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
@@ -1160,11 +1167,16 @@ static const struct usb_device_id option
 	{ USB_DEVICE(QUALCOMM_VENDOR_ID, QUECTEL_PRODUCT_UC15)},
 	{ USB_DEVICE(QUALCOMM_VENDOR_ID, QUECTEL_PRODUCT_UC20),
 	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+	/* Yuga products use Qualcomm vendor ID */
+	{ USB_DEVICE(QUALCOMM_VENDOR_ID, YUGA_PRODUCT_CLM920_NC5),
+	  .driver_info = (kernel_ulong_t)&yuga_clm920_nc5_blacklist },
 	/* Quectel products using Quectel vendor ID */
 	{ USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC21),
 	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
 	{ USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC25),
 	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+	{ USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96),
+	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
 	{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) },
 	{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) },
 	{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6003),
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/drivers/usb/storage/unusual_devs.h linux-libre-3.2.100-gnu1/drivers/usb/storage/unusual_devs.h
--- linux-libre-3.2.99-gnu1/drivers/usb/storage/unusual_devs.h	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/drivers/usb/storage/unusual_devs.h	2018-03-03 10:57:56.000000000 -0500
@@ -1961,6 +1961,13 @@ UNUSUAL_DEV(  0x152d, 0x0567, 0x0114, 0x
 		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_BROKEN_FUA ),
 
+/* Reported by David Kozub <zub@linux.fjfi.cvut.cz> */
+UNUSUAL_DEV(0x152d, 0x0578, 0x0000, 0x9999,
+		"JMicron",
+		"JMS567",
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+		US_FL_BROKEN_FUA),
+
 /* Reported by Alexandre Oliva <oliva@lsd.ic.unicamp.br>
  * JMicron responds to USN and several other SCSI ioctls with a
  * residue that causes subsequent I/O requests to fail.  */
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/fs/btrfs/extent-tree.c linux-libre-3.2.100-gnu1/fs/btrfs/extent-tree.c
--- linux-libre-3.2.99-gnu1/fs/btrfs/extent-tree.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/fs/btrfs/extent-tree.c	2018-03-03 10:57:56.000000000 -0500
@@ -2759,13 +2759,6 @@ again:
 		goto again;
 	}
 
-	/* We've already setup this transaction, go ahead and exit */
-	if (block_group->cache_generation == trans->transid &&
-	    i_size_read(inode)) {
-		dcs = BTRFS_DC_SETUP;
-		goto out_put;
-	}
-
 	/*
 	 * We want to set the generation to 0, that way if anything goes wrong
 	 * from here on out we know not to trust this cache when we load up next
@@ -2775,6 +2768,13 @@ again:
 	ret = btrfs_update_inode(trans, root, inode);
 	WARN_ON(ret);
 
+	/* We've already setup this transaction, go ahead and exit */
+	if (block_group->cache_generation == trans->transid &&
+	    i_size_read(inode)) {
+		dcs = BTRFS_DC_SETUP;
+		goto out_put;
+	}
+
 	if (i_size_read(inode) > 0) {
 		ret = btrfs_truncate_free_space_cache(root, trans, path,
 						      inode);
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/fs/btrfs/ioctl.c linux-libre-3.2.100-gnu1/fs/btrfs/ioctl.c
--- linux-libre-3.2.99-gnu1/fs/btrfs/ioctl.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/fs/btrfs/ioctl.c	2018-03-03 10:57:56.000000000 -0500
@@ -1751,7 +1751,7 @@ static noinline int btrfs_search_path_in
 	if (!path)
 		return -ENOMEM;
 
-	ptr = &name[BTRFS_INO_LOOKUP_PATH_MAX];
+	ptr = &name[BTRFS_INO_LOOKUP_PATH_MAX - 1];
 
 	key.objectid = tree_id;
 	key.type = BTRFS_ROOT_ITEM_KEY;
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/fs/ext4/namei.c linux-libre-3.2.100-gnu1/fs/ext4/namei.c
--- linux-libre-3.2.99-gnu1/fs/ext4/namei.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/fs/ext4/namei.c	2018-03-03 10:57:56.000000000 -0500
@@ -892,6 +892,10 @@ static struct buffer_head * ext4_find_en
 			       "falling back\n"));
 	}
 	nblocks = dir->i_size >> EXT4_BLOCK_SIZE_BITS(sb);
+	if (!nblocks) {
+		ret = NULL;
+		goto cleanup_and_exit;
+	}
 	start = EXT4_I(dir)->i_dir_start_lookup;
 	if (start >= nblocks)
 		start = 0;
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/fs/nfsd/auth.c linux-libre-3.2.100-gnu1/fs/nfsd/auth.c
--- linux-libre-3.2.99-gnu1/fs/nfsd/auth.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/fs/nfsd/auth.c	2018-03-03 10:57:56.000000000 -0500
@@ -61,6 +61,9 @@ int nfsd_setuser(struct svc_rqst *rqstp,
 			else
 				GROUP_AT(gi, i) = GROUP_AT(rqgi, i);
 		}
+
+		/* Each thread allocates its own gi, no race */
+		groups_sort(gi);
 	} else {
 		gi = get_group_info(rqgi);
 	}
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/include/asm-generic/dma-mapping-broken.h linux-libre-3.2.100-gnu1/include/asm-generic/dma-mapping-broken.h
--- linux-libre-3.2.99-gnu1/include/asm-generic/dma-mapping-broken.h	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/include/asm-generic/dma-mapping-broken.h	2018-03-03 10:57:56.000000000 -0500
@@ -69,9 +69,6 @@ dma_supported(struct device *dev, u64 ma
 extern int
 dma_set_mask(struct device *dev, u64 mask);
 
-extern int
-dma_get_cache_alignment(void);
-
 extern void
 dma_cache_sync(struct device *dev, void *vaddr, size_t size,
 	       enum dma_data_direction direction);
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/include/linux/cred.h linux-libre-3.2.100-gnu1/include/linux/cred.h
--- linux-libre-3.2.99-gnu1/include/linux/cred.h	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/include/linux/cred.h	2018-03-03 10:57:56.000000000 -0500
@@ -67,6 +67,7 @@ extern void groups_free(struct group_inf
 extern int set_current_groups(struct group_info *);
 extern int set_groups(struct cred *, struct group_info *);
 extern int groups_search(const struct group_info *, gid_t);
+extern void groups_sort(struct group_info *);
 
 /* access the groups "array" with this macro */
 #define GROUP_AT(gi, i) \
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/include/linux/dma-mapping.h linux-libre-3.2.100-gnu1/include/linux/dma-mapping.h
--- linux-libre-3.2.99-gnu1/include/linux/dma-mapping.h	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/include/linux/dma-mapping.h	2018-03-03 10:57:56.000000000 -0500
@@ -130,7 +130,6 @@ static inline void *dma_zalloc_coherent(
 	return ret;
 }
 
-#ifdef CONFIG_HAS_DMA
 static inline int dma_get_cache_alignment(void)
 {
 #ifdef ARCH_DMA_MINALIGN
@@ -138,7 +137,6 @@ static inline int dma_get_cache_alignmen
 #endif
 	return 1;
 }
-#endif
 
 /* flags for the coherent memory api */
 #define	DMA_MEMORY_MAP			0x01
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/include/linux/fscache.h linux-libre-3.2.100-gnu1/include/linux/fscache.h
--- linux-libre-3.2.99-gnu1/include/linux/fscache.h	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/include/linux/fscache.h	2018-03-03 10:57:56.000000000 -0500
@@ -642,7 +642,7 @@ bool fscache_maybe_release_page(struct f
 {
 	if (fscache_cookie_valid(cookie) && PageFsCache(page))
 		return __fscache_maybe_release_page(cookie, page, gfp);
-	return false;
+	return true;
 }
 
 /**
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/include/linux/stddef.h linux-libre-3.2.100-gnu1/include/linux/stddef.h
--- linux-libre-3.2.99-gnu1/include/linux/stddef.h	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/include/linux/stddef.h	2018-03-03 10:57:56.000000000 -0500
@@ -23,6 +23,16 @@ enum {
 #else
 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
 #endif
+
+/**
+ * offsetofend(TYPE, MEMBER)
+ *
+ * @TYPE: The type of the structure
+ * @MEMBER: The member within the structure to get the end offset of
+ */
+#define offsetofend(TYPE, MEMBER) \
+	(offsetof(TYPE, MEMBER)	+ sizeof(((TYPE *)0)->MEMBER))
+
 #endif /* __KERNEL__ */
 
 #endif
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/include/linux/usb/ch9.h linux-libre-3.2.100-gnu1/include/linux/usb/ch9.h
--- linux-libre-3.2.99-gnu1/include/linux/usb/ch9.h	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/include/linux/usb/ch9.h	2018-03-03 10:57:56.000000000 -0500
@@ -800,6 +800,8 @@ struct usb_wireless_cap_descriptor {	/*
 	__u8  bReserved;
 } __attribute__((packed));
 
+#define USB_DT_USB_WIRELESS_CAP_SIZE	11
+
 /* USB 2.0 Extension descriptor */
 #define	USB_CAP_TYPE_EXT		2
 
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/include/net/red.h linux-libre-3.2.100-gnu1/include/net/red.h
--- linux-libre-3.2.99-gnu1/include/net/red.h	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/include/net/red.h	2018-03-03 10:57:56.000000000 -0500
@@ -124,6 +124,17 @@ static inline u32 red_rmask(u8 Plog)
 	return Plog < 32 ? ((1 << Plog) - 1) : ~0UL;
 }
 
+static inline bool red_check_params(u32 qth_min, u32 qth_max, u8 Wlog)
+{
+	if (fls(qth_min) + Wlog > 32)
+		return false;
+	if (fls(qth_max) + Wlog > 32)
+		return false;
+	if (qth_max < qth_min)
+		return false;
+	return true;
+}
+
 static inline void red_set_parms(struct red_parms *p,
 				 u32 qth_min, u32 qth_max, u8 Wlog, u8 Plog,
 				 u8 Scell_log, u8 *stab)
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/include/net/xfrm.h linux-libre-3.2.100-gnu1/include/net/xfrm.h
--- linux-libre-3.2.99-gnu1/include/net/xfrm.h	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/include/net/xfrm.h	2018-03-03 10:57:56.000000000 -0500
@@ -1439,6 +1439,7 @@ extern int xfrm_prepare_input(struct xfr
 extern int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi,
 		      int encap_type);
 extern int xfrm_input_resume(struct sk_buff *skb, int nexthdr);
+int xfrm_trans_queue(struct sk_buff *skb, int (*finish)(struct sk_buff *));
 extern int xfrm_output_resume(struct sk_buff *skb, int err);
 extern int xfrm_output(struct sk_buff *skb);
 extern int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb);
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/include/scsi/libsas.h linux-libre-3.2.100-gnu1/include/scsi/libsas.h
--- linux-libre-3.2.99-gnu1/include/scsi/libsas.h	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/include/scsi/libsas.h	2018-03-03 10:57:56.000000000 -0500
@@ -163,7 +163,6 @@ enum ata_command_set {
 
 struct sata_device {
         enum   ata_command_set command_set;
-        struct smp_resp        rps_resp; /* report_phy_sata_resp */
         __le16 *identify_device;
         __le16 *identify_packet_device;
 
@@ -172,10 +171,8 @@ struct sata_device {
 
 	struct ata_port *ap;
 	struct ata_host ata_host;
+	struct smp_resp rps_resp ____cacheline_aligned; /* report_phy_sata_resp */
 	u8     fis[ATA_RESP_FIS_SIZE];
-	u32 sstatus;
-	u32 serror;
-	u32 scontrol;
 };
 
 /* ---------- Domain device ---------- */
@@ -492,10 +489,6 @@ enum exec_status {
 struct ata_task_resp {
 	u16  frame_len;
 	u8   ending_fis[ATA_RESP_FIS_SIZE];	  /* dev to host or data-in */
-	u32  sstatus;
-	u32  serror;
-	u32  scontrol;
-	u32  sactive;
 };
 
 #define SAS_STATUS_BUF_SIZE 96
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/kernel/debug/kdb/kdb_io.c linux-libre-3.2.100-gnu1/kernel/debug/kdb/kdb_io.c
--- linux-libre-3.2.99-gnu1/kernel/debug/kdb/kdb_io.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/kernel/debug/kdb/kdb_io.c	2018-03-03 10:57:56.000000000 -0500
@@ -349,7 +349,7 @@ poll_again:
 			}
 			kdb_printf("\n");
 			for (i = 0; i < count; i++) {
-				if (kallsyms_symbol_next(p_tmp, i) < 0)
+				if (WARN_ON(!kallsyms_symbol_next(p_tmp, i)))
 					break;
 				kdb_printf("%s ", p_tmp);
 				*(p_tmp + len) = '\0';
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/kernel/futex.c linux-libre-3.2.100-gnu1/kernel/futex.c
--- linux-libre-3.2.99-gnu1/kernel/futex.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/kernel/futex.c	2018-03-03 10:57:56.000000000 -0500
@@ -1376,6 +1376,9 @@ static int futex_requeue(u32 __user *uad
 	struct plist_head *head1;
 	struct futex_q *this, *next;
 
+	if (nr_wake < 0 || nr_requeue < 0)
+		return -EINVAL;
+
 	if (requeue_pi) {
 		/*
 		 * Requeue PI only works on two distinct uaddrs. This
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/kernel/groups.c linux-libre-3.2.100-gnu1/kernel/groups.c
--- linux-libre-3.2.99-gnu1/kernel/groups.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/kernel/groups.c	2018-03-03 10:57:56.000000000 -0500
@@ -103,7 +103,7 @@ static int groups_from_user(struct group
 }
 
 /* a simple Shell sort */
-static void groups_sort(struct group_info *group_info)
+void groups_sort(struct group_info *group_info)
 {
 	int base, max, stride;
 	int gidsetsize = group_info->ngroups;
@@ -130,6 +130,7 @@ static void groups_sort(struct group_inf
 		stride /= 3;
 	}
 }
+EXPORT_SYMBOL(groups_sort);
 
 /* a simple bsearch */
 int groups_search(const struct group_info *group_info, gid_t grp)
@@ -164,7 +165,6 @@ int groups_search(const struct group_inf
 int set_groups(struct cred *new, struct group_info *group_info)
 {
 	put_group_info(new->group_info);
-	groups_sort(group_info);
 	get_group_info(group_info);
 	new->group_info = group_info;
 	return 0;
@@ -247,6 +247,7 @@ SYSCALL_DEFINE2(setgroups, int, gidsetsi
 		return retval;
 	}
 
+	groups_sort(group_info);
 	retval = set_current_groups(group_info);
 	put_group_info(group_info);
 
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/kernel/hrtimer.c linux-libre-3.2.100-gnu1/kernel/hrtimer.c
--- linux-libre-3.2.99-gnu1/kernel/hrtimer.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/kernel/hrtimer.c	2018-03-03 10:57:56.000000000 -0500
@@ -657,6 +657,7 @@ static int hrtimer_reprogram(struct hrti
 static inline void hrtimer_init_hres(struct hrtimer_cpu_base *base)
 {
 	base->expires_next.tv64 = KTIME_MAX;
+	base->hang_detected = 0;
 	base->hres_active = 0;
 }
 
@@ -1702,6 +1703,7 @@ static void __cpuinit init_hrtimers_cpu(
 		timerqueue_init_head(&cpu_base->clock_base[i].active);
 	}
 
+	cpu_base->active_bases = 0;
 	hrtimer_init_hres(cpu_base);
 }
 
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/kernel/posix-timers.c linux-libre-3.2.100-gnu1/kernel/posix-timers.c
--- linux-libre-3.2.99-gnu1/kernel/posix-timers.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/kernel/posix-timers.c	2018-03-03 10:57:56.000000000 -0500
@@ -440,17 +440,22 @@ static struct pid *good_sigevent(sigeven
 {
 	struct task_struct *rtn = current->group_leader;
 
-	if ((event->sigev_notify & SIGEV_THREAD_ID ) &&
-		(!(rtn = find_task_by_vpid(event->sigev_notify_thread_id)) ||
-		 !same_thread_group(rtn, current) ||
-		 (event->sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_SIGNAL))
-		return NULL;
-
-	if (((event->sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) &&
-	    ((event->sigev_signo <= 0) || (event->sigev_signo > SIGRTMAX)))
+	switch (event->sigev_notify) {
+	case SIGEV_SIGNAL | SIGEV_THREAD_ID:
+		rtn = find_task_by_vpid(event->sigev_notify_thread_id);
+		if (!rtn || !same_thread_group(rtn, current))
+			return NULL;
+		/* FALLTHRU */
+	case SIGEV_SIGNAL:
+	case SIGEV_THREAD:
+		if (event->sigev_signo <= 0 || event->sigev_signo > SIGRTMAX)
+			return NULL;
+		/* FALLTHRU */
+	case SIGEV_NONE:
+		return task_pid(rtn);
+	default:
 		return NULL;
-
-	return task_pid(rtn);
+	}
 }
 
 void posix_timers_register_clock(const clockid_t clock_id,
@@ -683,16 +688,17 @@ common_timer_get(struct k_itimer *timr,
 {
 	ktime_t now, remaining, iv;
 	struct hrtimer *timer = &timr->it.real.timer;
+	bool sig_none;
 
 	memset(cur_setting, 0, sizeof(struct itimerspec));
 
+	sig_none = timr->it_sigev_notify == SIGEV_NONE;
 	iv = timr->it.real.interval;
 
 	/* interval timer ? */
 	if (iv.tv64)
 		cur_setting->it_interval = ktime_to_timespec(iv);
-	else if (!hrtimer_active(timer) &&
-		 (timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE)
+	else if (!hrtimer_active(timer) && !sig_none)
 		return;
 
 	now = timer->base->get_time();
@@ -702,8 +708,7 @@ common_timer_get(struct k_itimer *timr,
 	 * timer move the expiry time forward by intervals, so
 	 * expiry is > now.
 	 */
-	if (iv.tv64 && (timr->it_requeue_pending & REQUEUE_PENDING ||
-	    (timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE))
+	if (iv.tv64 && (timr->it_requeue_pending & REQUEUE_PENDING || sig_none))
 		timr->it_overrun += (unsigned int) hrtimer_forward(timer, now, iv);
 
 	remaining = __hrtimer_expires_remaining_adjusted(timer, now);
@@ -713,7 +718,7 @@ common_timer_get(struct k_itimer *timr,
 		 * A single shot SIGEV_NONE timer must return 0, when
 		 * it is expired !
 		 */
-		if ((timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE)
+		if (!sig_none)
 			cur_setting->it_value.tv_nsec = 1;
 	} else
 		cur_setting->it_value = ktime_to_timespec(remaining);
@@ -811,7 +816,7 @@ common_timer_set(struct k_itimer *timr,
 	timr->it.real.interval = timespec_to_ktime(new_setting->it_interval);
 
 	/* SIGEV_NONE timers are not queued ! See common_timer_get */
-	if (((timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) {
+	if (timr->it_sigev_notify == SIGEV_NONE) {
 		/* Setup correct expiry time for relative timers */
 		if (mode == HRTIMER_MODE_REL) {
 			hrtimer_add_expires(timer, timer->base->get_time());
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/kernel/trace/ring_buffer.c linux-libre-3.2.100-gnu1/kernel/trace/ring_buffer.c
--- linux-libre-3.2.99-gnu1/kernel/trace/ring_buffer.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/kernel/trace/ring_buffer.c	2018-03-03 10:57:56.000000000 -0500
@@ -360,6 +360,8 @@ EXPORT_SYMBOL_GPL(ring_buffer_event_data
 /* Missed count stored at end */
 #define RB_MISSED_STORED	(1 << 30)
 
+#define RB_MISSED_FLAGS		(RB_MISSED_EVENTS|RB_MISSED_STORED)
+
 struct buffer_data_page {
 	u64		 time_stamp;	/* page time stamp */
 	local_t		 commit;	/* write committed index */
@@ -411,7 +413,9 @@ static void rb_init_page(struct buffer_d
  */
 size_t ring_buffer_page_len(void *page)
 {
-	return local_read(&((struct buffer_data_page *)page)->commit)
+	struct buffer_data_page *bpage = page;
+
+	return (local_read(&bpage->commit) & ~RB_MISSED_FLAGS)
 		+ BUF_PAGE_HDR_SIZE;
 }
 
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/kernel/uid16.c linux-libre-3.2.100-gnu1/kernel/uid16.c
--- linux-libre-3.2.99-gnu1/kernel/uid16.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/kernel/uid16.c	2018-03-03 10:57:56.000000000 -0500
@@ -203,6 +203,7 @@ SYSCALL_DEFINE2(setgroups16, int, gidset
 		return retval;
 	}
 
+	groups_sort(group_info);
 	retval = set_current_groups(group_info);
 	put_group_info(group_info);
 
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/Makefile linux-libre-3.2.100-gnu1/Makefile
--- linux-libre-3.2.99-gnu1/Makefile	2018-02-14 18:47:47.000000000 -0500
+++ linux-libre-3.2.100-gnu1/Makefile	2018-03-04 23:10:48.000000000 -0500
@@ -1,8 +1,8 @@
 VERSION = 3
 PATCHLEVEL = 2
-SUBLEVEL = 99
+SUBLEVEL = 100
 EXTRAVERSION =-gnu1
-NAME = Saber-toothed Squirrel
+NAME = Sleepy Otter
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
@@ -631,6 +631,9 @@ KBUILD_CFLAGS += $(call cc-disable-warni
 # disable invalid "can't wrap" optimizations for signed / pointers
 KBUILD_CFLAGS	+= $(call cc-option,-fno-strict-overflow)
 
+# Make sure -fstack-check isn't enabled (like gentoo apparently did)
+KBUILD_CFLAGS  += $(call cc-option,-fno-stack-check,)
+
 # conserve stack if available
 KBUILD_CFLAGS   += $(call cc-option,-fconserve-stack)
 
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/mm/mprotect.c linux-libre-3.2.100-gnu1/mm/mprotect.c
--- linux-libre-3.2.99-gnu1/mm/mprotect.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/mm/mprotect.c	2018-03-03 10:57:56.000000000 -0500
@@ -92,13 +92,15 @@ static inline void change_pmd_range(stru
 			if (next - addr != HPAGE_PMD_SIZE)
 				split_huge_page_pmd(vma->vm_mm, pmd);
 			else if (change_huge_pmd(vma, pmd, addr, newprot))
-				continue;
+				goto next;
 			/* fall through */
 		}
 		if (pmd_none_or_clear_bad(pmd))
-			continue;
+			goto next;
 		change_pte_range(vma->vm_mm, pmd, addr, next, newprot,
 				 dirty_accountable);
+next:
+		cond_resched();
 	} while (pmd++, addr = next, addr != end);
 }
 
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/net/8021q/vlan.c linux-libre-3.2.100-gnu1/net/8021q/vlan.c
--- linux-libre-3.2.99-gnu1/net/8021q/vlan.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/net/8021q/vlan.c	2018-03-03 10:57:56.000000000 -0500
@@ -132,11 +132,7 @@ void unregister_vlan_dev(struct net_devi
 		call_rcu(&grp->rcu, vlan_rcu_free);
 	}
 
-	/* Take it out of our own structures, but be sure to interlock with
-	 * HW accelerating devices or SW vlan input packet processing if
-	 * VLAN is not 0 (leave it there for 802.1p).
-	 */
-	if (vlan_id && (real_dev->features & NETIF_F_HW_VLAN_FILTER))
+	if (real_dev->features & NETIF_F_HW_VLAN_FILTER)
 		ops->ndo_vlan_rx_kill_vid(real_dev, vlan_id);
 
 	/* Get rid of the vlan's reference to real_dev */
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/net/batman-adv/bat_iv_ogm.c linux-libre-3.2.100-gnu1/net/batman-adv/bat_iv_ogm.c
--- linux-libre-3.2.99-gnu1/net/batman-adv/bat_iv_ogm.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/net/batman-adv/bat_iv_ogm.c	2018-03-03 10:57:56.000000000 -0500
@@ -760,10 +760,10 @@ static int bat_ogm_calc_tq(struct orig_n
 	orig_node->last_valid = jiffies;
 
 	/* find packet count of corresponding one hop neighbor */
-	spin_lock_bh(&orig_node->ogm_cnt_lock);
+	spin_lock_bh(&orig_neigh_node->ogm_cnt_lock);
 	orig_eq_count = orig_neigh_node->bcast_own_sum[if_incoming->if_num];
 	neigh_rq_count = neigh_node->real_packet_count;
-	spin_unlock_bh(&orig_node->ogm_cnt_lock);
+	spin_unlock_bh(&orig_neigh_node->ogm_cnt_lock);
 
 	/* pay attention to not get a value bigger than 100 % */
 	total_count = (orig_eq_count > neigh_rq_count ?
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/net/bridge/br_netlink.c linux-libre-3.2.100-gnu1/net/bridge/br_netlink.c
--- linux-libre-3.2.99-gnu1/net/bridge/br_netlink.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/net/bridge/br_netlink.c	2018-03-03 10:57:56.000000000 -0500
@@ -215,6 +215,11 @@ static int br_dev_newlink(struct net *sr
 			  struct nlattr *tb[], struct nlattr *data[])
 {
 	struct net_bridge *br = netdev_priv(dev);
+	int err;
+
+	err = register_netdevice(dev);
+	if (err)
+		return err;
 
 	if (tb[IFLA_ADDRESS]) {
 		spin_lock_bh(&br->lock);
@@ -222,7 +227,7 @@ static int br_dev_newlink(struct net *sr
 		spin_unlock_bh(&br->lock);
 	}
 
-	return register_netdevice(dev);
+	return 0;
 }
 
 struct rtnl_link_ops br_link_ops __read_mostly = {
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/net/can/af_can.c linux-libre-3.2.100-gnu1/net/can/af_can.c
--- linux-libre-3.2.99-gnu1/net/can/af_can.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/net/can/af_can.c	2018-03-03 10:57:56.000000000 -0500
@@ -653,13 +653,13 @@ static int can_rcv(struct sk_buff *skb,
 	if (!net_eq(dev_net(dev), &init_net))
 		goto drop;
 
-	if (WARN_ONCE(dev->type != ARPHRD_CAN ||
-		      skb->len != sizeof(struct can_frame) ||
-		      cf->can_dlc > 8,
-		      "PF_CAN: dropped non conform skbuf: "
-		      "dev type %d, len %d, can_dlc %d\n",
-		      dev->type, skb->len, cf->can_dlc))
+	if (unlikely(dev->type != ARPHRD_CAN ||
+		     skb->len != sizeof(struct can_frame) ||
+		     cf->can_dlc > 8)) {
+		pr_warn_once("PF_CAN: dropped non conform CAN skbuf: dev type %d, len %d, can_dlc %d\n",
+			     dev->type, skb->len, cf->can_dlc);
 		goto drop;
+	}
 
 	/* update statistics */
 	can_stats.rx_frames++;
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/net/dccp/ccids/ccid2.c linux-libre-3.2.100-gnu1/net/dccp/ccids/ccid2.c
--- linux-libre-3.2.99-gnu1/net/dccp/ccids/ccid2.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/net/dccp/ccids/ccid2.c	2018-03-03 10:57:56.000000000 -0500
@@ -140,6 +140,9 @@ static void ccid2_hc_tx_rto_expire(unsig
 
 	ccid2_pr_debug("RTO_EXPIRE\n");
 
+	if (sk->sk_state == DCCP_CLOSED)
+		goto out;
+
 	/* back-off timer */
 	hc->tx_rto <<= 1;
 	if (hc->tx_rto > DCCP_RTO_MAX)
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/net/ipv4/esp4.c linux-libre-3.2.100-gnu1/net/ipv4/esp4.c
--- linux-libre-3.2.99-gnu1/net/ipv4/esp4.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/net/ipv4/esp4.c	2018-03-03 10:57:56.000000000 -0500
@@ -658,6 +658,7 @@ static int esp_init_state(struct xfrm_st
 
 		switch (encap->encap_type) {
 		default:
+			err = -EINVAL;
 			goto error;
 		case UDP_ENCAP_ESPINUDP:
 			x->props.header_len += sizeof(struct udphdr);
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/net/ipv4/igmp.c linux-libre-3.2.100-gnu1/net/ipv4/igmp.c
--- linux-libre-3.2.99-gnu1/net/ipv4/igmp.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/net/ipv4/igmp.c	2018-03-03 10:57:56.000000000 -0500
@@ -89,6 +89,7 @@
 #include <linux/if_arp.h>
 #include <linux/rtnetlink.h>
 #include <linux/times.h>
+#include <linux/byteorder/generic.h>
 
 #include <net/net_namespace.h>
 #include <net/arp.h>
@@ -299,6 +300,23 @@ igmp_scount(struct ip_mc_list *pmc, int
 	return scount;
 }
 
+/* source address selection per RFC 3376 section 4.2.13 */
+static __be32 igmpv3_get_srcaddr(struct net_device *dev,
+				 const struct flowi4 *fl4)
+{
+	struct in_device *in_dev = __in_dev_get_rcu(dev);
+
+	if (!in_dev)
+		return htonl(INADDR_ANY);
+
+	for_ifa(in_dev) {
+		if (fl4->saddr == ifa->ifa_local)
+			return fl4->saddr;
+	} endfor_ifa(in_dev);
+
+	return htonl(INADDR_ANY);
+}
+
 static struct sk_buff *igmpv3_newpack(struct net_device *dev, unsigned int mtu)
 {
 	struct sk_buff *skb;
@@ -345,7 +363,7 @@ static struct sk_buff *igmpv3_newpack(st
 	pip->frag_off = htons(IP_DF);
 	pip->ttl      = 1;
 	pip->daddr    = fl4.daddr;
-	pip->saddr    = fl4.saddr;
+	pip->saddr    = igmpv3_get_srcaddr(dev, &fl4);
 	pip->protocol = IPPROTO_IGMP;
 	pip->tot_len  = 0;	/* filled in later */
 	ip_select_ident(skb, NULL);
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/net/ipv4/raw.c linux-libre-3.2.100-gnu1/net/ipv4/raw.c
--- linux-libre-3.2.99-gnu1/net/ipv4/raw.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/net/ipv4/raw.c	2018-03-03 10:57:56.000000000 -0500
@@ -78,6 +78,16 @@
 #include <linux/netfilter.h>
 #include <linux/netfilter_ipv4.h>
 #include <linux/compat.h>
+#include <linux/uio.h>
+
+struct raw_frag_vec {
+	struct iovec *iov;
+	union {
+		struct icmphdr icmph;
+		char c[1];
+	} hdr;
+	int hlen;
+};
 
 static struct raw_hashinfo raw_v4_hashinfo = {
 	.lock = __RW_LOCK_UNLOCKED(raw_v4_hashinfo.lock),
@@ -409,53 +419,57 @@ error:
 	return err;
 }
 
-static int raw_probe_proto_opt(struct flowi4 *fl4, struct msghdr *msg)
+static int raw_probe_proto_opt(struct raw_frag_vec *rfv, struct flowi4 *fl4)
 {
-	struct iovec *iov;
-	u8 __user *type = NULL;
-	u8 __user *code = NULL;
-	int probed = 0;
-	unsigned int i;
+	int err;
 
-	if (!msg->msg_iov)
+	if (fl4->flowi4_proto != IPPROTO_ICMP)
 		return 0;
 
-	for (i = 0; i < msg->msg_iovlen; i++) {
-		iov = &msg->msg_iov[i];
-		if (!iov)
-			continue;
+	/* We only need the first two bytes. */
+	rfv->hlen = 2;
 
-		switch (fl4->flowi4_proto) {
-		case IPPROTO_ICMP:
-			/* check if one-byte field is readable or not. */
-			if (iov->iov_base && iov->iov_len < 1)
-				break;
+	err = memcpy_fromiovec(rfv->hdr.c, rfv->iov, rfv->hlen);
+	if (err)
+		return err;
 
-			if (!type) {
-				type = iov->iov_base;
-				/* check if code field is readable or not. */
-				if (iov->iov_len > 1)
-					code = type + 1;
-			} else if (!code)
-				code = iov->iov_base;
+	fl4->fl4_icmp_type = rfv->hdr.icmph.type;
+	fl4->fl4_icmp_code = rfv->hdr.icmph.code;
 
-			if (type && code) {
-				if (get_user(fl4->fl4_icmp_type, type) ||
-				    get_user(fl4->fl4_icmp_code, code))
-					return -EFAULT;
-				probed = 1;
-			}
-			break;
-		default:
-			probed = 1;
-			break;
-		}
-		if (probed)
-			break;
-	}
 	return 0;
 }
 
+static int raw_getfrag(void *from, char *to, int offset, int len, int odd,
+		       struct sk_buff *skb)
+{
+	struct raw_frag_vec *rfv = from;
+
+	if (offset < rfv->hlen) {
+		int copy = min(rfv->hlen - offset, len);
+
+		if (skb->ip_summed == CHECKSUM_PARTIAL)
+			memcpy(to, rfv->hdr.c + offset, copy);
+		else
+			skb->csum = csum_block_add(
+				skb->csum,
+				csum_partial_copy_nocheck(rfv->hdr.c + offset,
+							  to, copy, 0),
+				odd);
+
+		odd = 0;
+		offset += copy;
+		to += copy;
+		len -= copy;
+
+		if (!len)
+			return 0;
+	}
+
+	offset -= rfv->hlen;
+
+	return ip_generic_getfrag(rfv->iov, to, offset, len, odd, skb);
+}
+
 static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 		       size_t len)
 {
@@ -469,11 +483,19 @@ static int raw_sendmsg(struct kiocb *ioc
 	u8  tos;
 	int err;
 	struct ip_options_data opt_copy;
+	struct raw_frag_vec rfv;
+	int hdrincl;
 
 	err = -EMSGSIZE;
 	if (len > 0xFFFF)
 		goto out;
 
+	/* hdrincl should be READ_ONCE(inet->hdrincl)
+	 * but READ_ONCE() doesn't work with bit fields.
+	 * Doing this indirectly yields the same result.
+	 */
+	hdrincl = inet->hdrincl;
+	hdrincl = ACCESS_ONCE(hdrincl);
 	/*
 	 *	Check the flags.
 	 */
@@ -549,7 +571,7 @@ static int raw_sendmsg(struct kiocb *ioc
 		/* Linux does not mangle headers on raw sockets,
 		 * so that IP options + IP_HDRINCL is non-sense.
 		 */
-		if (inet->hdrincl)
+		if (hdrincl)
 			goto done;
 		if (ipc.opt->opt.srr) {
 			if (!daddr)
@@ -570,12 +592,15 @@ static int raw_sendmsg(struct kiocb *ioc
 
 	flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos,
 			   RT_SCOPE_UNIVERSE,
-			   inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol,
+			   hdrincl ? IPPROTO_RAW : sk->sk_protocol,
 			   inet_sk_flowi_flags(sk) | FLOWI_FLAG_CAN_SLEEP,
 			   daddr, saddr, 0, 0);
 
-	if (!inet->hdrincl) {
-		err = raw_probe_proto_opt(&fl4, msg);
+	if (!hdrincl) {
+		rfv.iov = msg->msg_iov;
+		rfv.hlen = 0;
+
+		err = raw_probe_proto_opt(&rfv, &fl4);
 		if (err)
 			goto done;
 	}
@@ -596,7 +621,7 @@ static int raw_sendmsg(struct kiocb *ioc
 		goto do_confirm;
 back_from_confirm:
 
-	if (inet->hdrincl)
+	if (hdrincl)
 		err = raw_send_hdrinc(sk, &fl4, msg->msg_iov, len,
 				      &rt, msg->msg_flags);
 
@@ -604,8 +629,8 @@ back_from_confirm:
 		if (!ipc.addr)
 			ipc.addr = fl4.daddr;
 		lock_sock(sk);
-		err = ip_append_data(sk, &fl4, ip_generic_getfrag,
-				     msg->msg_iov, len, 0,
+		err = ip_append_data(sk, &fl4, raw_getfrag,
+				     &rfv, len, 0,
 				     &ipc, &rt, msg->msg_flags);
 		if (err)
 			ip_flush_pending_frames(sk);
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/net/ipv4/tcp_ipv4.c linux-libre-3.2.100-gnu1/net/ipv4/tcp_ipv4.c
--- linux-libre-3.2.99-gnu1/net/ipv4/tcp_ipv4.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/net/ipv4/tcp_ipv4.c	2018-03-03 10:57:56.000000000 -0500
@@ -764,7 +764,7 @@ static void tcp_v4_reqsk_send_ack(struct
 			tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd,
 			req->ts_recent,
 			0,
-			tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->daddr),
+			tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->saddr),
 			inet_rsk(req)->no_srccheck ? IP_REPLY_ARG_NOSRCCHECK : 0,
 			ip_hdr(skb)->tos);
 }
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/net/ipv4/xfrm4_input.c linux-libre-3.2.100-gnu1/net/ipv4/xfrm4_input.c
--- linux-libre-3.2.99-gnu1/net/ipv4/xfrm4_input.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/net/ipv4/xfrm4_input.c	2018-03-03 10:57:56.000000000 -0500
@@ -22,6 +22,11 @@ int xfrm4_extract_input(struct xfrm_stat
 	return xfrm4_extract_header(skb);
 }
 
+static int xfrm4_rcv_encap_finish2(struct sk_buff *skb)
+{
+	return dst_input(skb);
+}
+
 static inline int xfrm4_rcv_encap_finish(struct sk_buff *skb)
 {
 	if (skb_dst(skb) == NULL) {
@@ -31,7 +36,11 @@ static inline int xfrm4_rcv_encap_finish
 					 iph->tos, skb->dev))
 			goto drop;
 	}
-	return dst_input(skb);
+
+	if (xfrm_trans_queue(skb, xfrm4_rcv_encap_finish2))
+		goto drop;
+
+	return 0;
 drop:
 	kfree_skb(skb);
 	return NET_RX_DROP;
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/net/ipv6/esp6.c linux-libre-3.2.100-gnu1/net/ipv6/esp6.c
--- linux-libre-3.2.99-gnu1/net/ipv6/esp6.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/net/ipv6/esp6.c	2018-03-03 10:57:56.000000000 -0500
@@ -606,13 +606,12 @@ static int esp6_init_state(struct xfrm_s
 			x->props.header_len += IPV4_BEET_PHMAXLEN +
 				               (sizeof(struct ipv6hdr) - sizeof(struct iphdr));
 		break;
+	default:
 	case XFRM_MODE_TRANSPORT:
 		break;
 	case XFRM_MODE_TUNNEL:
 		x->props.header_len += sizeof(struct ipv6hdr);
 		break;
-	default:
-		goto error;
 	}
 
 	align = ALIGN(crypto_aead_blocksize(aead), 4);
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/net/ipv6/tcp_ipv6.c linux-libre-3.2.100-gnu1/net/ipv6/tcp_ipv6.c
--- linux-libre-3.2.99-gnu1/net/ipv6/tcp_ipv6.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/net/ipv6/tcp_ipv6.c	2018-03-03 10:57:56.000000000 -0500
@@ -1116,7 +1116,7 @@ static void tcp_v6_reqsk_send_ack(struct
 				  struct request_sock *req)
 {
 	tcp_v6_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent,
-			tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr), 0);
+			tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->saddr), 0);
 }
 
 
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/net/ipv6/xfrm6_input.c linux-libre-3.2.100-gnu1/net/ipv6/xfrm6_input.c
--- linux-libre-3.2.99-gnu1/net/ipv6/xfrm6_input.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/net/ipv6/xfrm6_input.c	2018-03-03 10:57:56.000000000 -0500
@@ -29,6 +29,13 @@ int xfrm6_rcv_spi(struct sk_buff *skb, i
 }
 EXPORT_SYMBOL(xfrm6_rcv_spi);
 
+static int xfrm6_transport_finish2(struct sk_buff *skb)
+{
+	if (xfrm_trans_queue(skb, ip6_rcv_finish))
+		__kfree_skb(skb);
+	return -1;
+}
+
 int xfrm6_transport_finish(struct sk_buff *skb, int async)
 {
 	skb_network_header(skb)[IP6CB(skb)->nhoff] =
@@ -43,7 +50,7 @@ int xfrm6_transport_finish(struct sk_buf
 	__skb_push(skb, skb->data - skb_network_header(skb));
 
 	NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING, skb, skb->dev, NULL,
-		ip6_rcv_finish);
+		xfrm6_transport_finish2);
 	return -1;
 }
 
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/net/key/af_key.c linux-libre-3.2.100-gnu1/net/key/af_key.c
--- linux-libre-3.2.99-gnu1/net/key/af_key.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/net/key/af_key.c	2018-03-03 10:57:56.000000000 -0500
@@ -398,6 +398,11 @@ static int verify_address_len(const void
 #endif
 	int len;
 
+	if (sp->sadb_address_len <
+	    DIV_ROUND_UP(sizeof(*sp) + offsetofend(typeof(*addr), sa_family),
+			 sizeof(uint64_t)))
+		return -EINVAL;
+
 	switch (addr->sa_family) {
 	case AF_INET:
 		len = DIV_ROUND_UP(sizeof(*sp) + sizeof(*sin), sizeof(uint64_t));
@@ -508,6 +513,9 @@ static int parse_exthdrs(struct sk_buff
 		uint16_t ext_type;
 		int ext_len;
 
+		if (len < sizeof(*ehdr))
+			return -EINVAL;
+
 		ext_len  = ehdr->sadb_ext_len;
 		ext_len *= sizeof(uint64_t);
 		ext_type = ehdr->sadb_ext_type;
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/net/packet/af_packet.c linux-libre-3.2.100-gnu1/net/packet/af_packet.c
--- linux-libre-3.2.99-gnu1/net/packet/af_packet.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/net/packet/af_packet.c	2018-03-03 10:57:56.000000000 -0500
@@ -2516,6 +2516,10 @@ static int packet_do_bind(struct sock *s
 
 	if (po->running) {
 		rcu_read_unlock();
+		/* prevents packet_notifier() from calling
+		 * register_prot_hook()
+		 */
+		po->num = 0;
 		__unregister_prot_hook(sk, true);
 		rcu_read_lock();
 		dev_curr = po->prot_hook.dev;
@@ -2523,6 +2527,7 @@ static int packet_do_bind(struct sock *s
 			unlisted = !dev_get_by_index_rcu(sock_net(sk),
 							 dev->ifindex);
 	}
+	BUG_ON(po->running);
 	po->num = protocol;
 	po->prot_hook.type = protocol;
 
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/net/rds/rdma.c linux-libre-3.2.100-gnu1/net/rds/rdma.c
--- linux-libre-3.2.99-gnu1/net/rds/rdma.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/net/rds/rdma.c	2018-03-03 10:57:56.000000000 -0500
@@ -184,7 +184,7 @@ static int __rds_rdma_map(struct rds_soc
 	long i;
 	int ret;
 
-	if (rs->rs_bound_addr == 0) {
+	if (rs->rs_bound_addr == 0 || !rs->rs_transport) {
 		ret = -ENOTCONN; /* XXX not a great errno */
 		goto out;
 	}
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/net/sched/sch_choke.c linux-libre-3.2.100-gnu1/net/sched/sch_choke.c
--- linux-libre-3.2.99-gnu1/net/sched/sch_choke.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/net/sched/sch_choke.c	2018-03-03 10:57:56.000000000 -0500
@@ -479,6 +479,9 @@ static int choke_change(struct Qdisc *sc
 
 	ctl = nla_data(tb[TCA_CHOKE_PARMS]);
 
+	if (!red_check_params(ctl->qth_min, ctl->qth_max, ctl->Wlog))
+		return -EINVAL;
+
 	if (ctl->limit > CHOKE_MAX_QUEUE)
 		return -EINVAL;
 
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/net/sched/sch_gred.c linux-libre-3.2.100-gnu1/net/sched/sch_gred.c
--- linux-libre-3.2.99-gnu1/net/sched/sch_gred.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/net/sched/sch_gred.c	2018-03-03 10:57:56.000000000 -0500
@@ -384,6 +384,9 @@ static inline int gred_change_vq(struct
 	struct gred_sched *table = qdisc_priv(sch);
 	struct gred_sched_data *q;
 
+	if (!red_check_params(ctl->qth_min, ctl->qth_max, ctl->Wlog))
+		return -EINVAL;
+
 	if (table->tab[dp] == NULL) {
 		table->tab[dp] = kzalloc(sizeof(*q), GFP_ATOMIC);
 		if (table->tab[dp] == NULL)
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/net/sched/sch_red.c linux-libre-3.2.100-gnu1/net/sched/sch_red.c
--- linux-libre-3.2.99-gnu1/net/sched/sch_red.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/net/sched/sch_red.c	2018-03-03 10:57:56.000000000 -0500
@@ -189,6 +189,8 @@ static int red_change(struct Qdisc *sch,
 		return -EINVAL;
 
 	ctl = nla_data(tb[TCA_RED_PARMS]);
+	if (!red_check_params(ctl->qth_min, ctl->qth_max, ctl->Wlog))
+		return -EINVAL;
 
 	if (ctl->limit > 0) {
 		child = fifo_create_dflt(sch, &bfifo_qdisc_ops, ctl->limit);
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/net/sctp/socket.c linux-libre-3.2.100-gnu1/net/sctp/socket.c
--- linux-libre-3.2.99-gnu1/net/sctp/socket.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/net/sctp/socket.c	2018-03-03 10:57:56.000000000 -0500
@@ -93,7 +93,7 @@
 /* Forward declarations for internal helper functions. */
 static int sctp_writeable(struct sock *sk);
 static void sctp_wfree(struct sk_buff *skb);
-static int sctp_wait_for_sndbuf(struct sctp_association *, long *timeo_p,
+static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p,
 				size_t msg_len);
 static int sctp_wait_for_packet(struct sock * sk, int *err, long *timeo_p);
 static int sctp_wait_for_connect(struct sctp_association *, long *timeo_p);
@@ -314,16 +314,14 @@ static struct sctp_af *sctp_sockaddr_af(
 	if (len < sizeof (struct sockaddr))
 		return NULL;
 
+	if (!opt->pf->af_supported(addr->sa.sa_family, opt))
+		return NULL;
+
 	/* V4 mapped address are really of AF_INET family */
 	if (addr->sa.sa_family == AF_INET6 &&
-	    ipv6_addr_v4mapped(&addr->v6.sin6_addr)) {
-		if (!opt->pf->af_supported(AF_INET, opt))
-			return NULL;
-	} else {
-		/* Does this PF support this AF? */
-		if (!opt->pf->af_supported(addr->sa.sa_family, opt))
-			return NULL;
-	}
+	    ipv6_addr_v4mapped(&addr->v6.sin6_addr) &&
+	    !opt->pf->af_supported(AF_INET, opt))
+		return NULL;
 
 	/* If we get this far, af is valid. */
 	af = sctp_get_af_specific(addr->sa.sa_family);
@@ -1911,6 +1909,7 @@ SCTP_STATIC int sctp_sendmsg(struct kioc
 
 	timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT);
 	if (!sctp_wspace(asoc)) {
+		/* sk can be changed by peel off when waiting for buf. */
 		err = sctp_wait_for_sndbuf(asoc, &timeo, msg_len);
 		if (err)
 			goto out_free;
@@ -4247,12 +4246,6 @@ SCTP_STATIC int sctp_do_peeloff(struct s
 	if (!net_eq(current->nsproxy->net_ns, sock_net(sk)))
 		return -EINVAL;
 
-	/* 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.
 	 */
@@ -6473,9 +6466,9 @@ static int sctp_wait_for_sndbuf(struct s
 				size_t msg_len)
 {
 	struct sock *sk = asoc->base.sk;
-	int err = 0;
 	long current_timeo = *timeo_p;
 	DEFINE_WAIT(wait);
+	int err = 0;
 
 	SCTP_DEBUG_PRINTK("wait_for_sndbuf: asoc=%p, timeo=%ld, msg_len=%zu\n",
 			  asoc, (long)(*timeo_p), msg_len);
@@ -6503,6 +6496,8 @@ static int sctp_wait_for_sndbuf(struct s
 		sctp_release_sock(sk);
 		current_timeo = schedule_timeout(current_timeo);
 		sctp_lock_sock(sk);
+		if (sk != asoc->base.sk)
+			goto do_error;
 
 		*timeo_p = current_timeo;
 	}
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/net/sunrpc/auth_gss/svcauth_gss.c linux-libre-3.2.100-gnu1/net/sunrpc/auth_gss/svcauth_gss.c
--- linux-libre-3.2.99-gnu1/net/sunrpc/auth_gss/svcauth_gss.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/net/sunrpc/auth_gss/svcauth_gss.c	2018-03-03 10:57:56.000000000 -0500
@@ -477,6 +477,7 @@ static int rsc_parse(struct cache_detail
 				goto out;
 			GROUP_AT(rsci.cred.cr_group_info, i) = gid;
 		}
+		groups_sort(rsci.cred.cr_group_info);
 
 		/* mech name */
 		len = qword_get(&mesg, buf, mlen);
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/net/sunrpc/svcauth_unix.c linux-libre-3.2.100-gnu1/net/sunrpc/svcauth_unix.c
--- linux-libre-3.2.99-gnu1/net/sunrpc/svcauth_unix.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/net/sunrpc/svcauth_unix.c	2018-03-03 10:57:56.000000000 -0500
@@ -539,6 +539,7 @@ static int unix_gid_parse(struct cache_d
 		GROUP_AT(ug.gi, i) = gid;
 	}
 
+	groups_sort(ug.gi);
 	ugp = unix_gid_lookup(uid);
 	if (ugp) {
 		struct cache_head *ch;
@@ -806,6 +807,7 @@ svcauth_unix_accept(struct svc_rqst *rqs
 		return SVC_CLOSE;
 	for (i = 0; i < slen; i++)
 		GROUP_AT(cred->cr_group_info, i) = svc_getnl(argv);
+	groups_sort(cred->cr_group_info);
 	if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) {
 		*authp = rpc_autherr_badverf;
 		return SVC_DENIED;
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/net/wireless/core.c linux-libre-3.2.100-gnu1/net/wireless/core.c
--- linux-libre-3.2.99-gnu1/net/wireless/core.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/net/wireless/core.c	2018-03-03 10:57:56.000000000 -0500
@@ -329,6 +329,7 @@ struct wiphy *wiphy_new(const struct cfg
 
 	struct cfg80211_registered_device *rdev;
 	int alloc_size;
+	int rv;
 
 	WARN_ON(ops->add_key && (!ops->del_key || !ops->set_default_key));
 	WARN_ON(ops->auth && (!ops->assoc || !ops->deauth || !ops->disassoc));
@@ -362,7 +363,11 @@ struct wiphy *wiphy_new(const struct cfg
 	mutex_unlock(&cfg80211_mutex);
 
 	/* give it a proper name */
-	dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx);
+	rv = dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx);
+	if (rv < 0) {
+		kfree(rdev);
+		return NULL;
+	}
 
 	mutex_init(&rdev->mtx);
 	mutex_init(&rdev->devlist_mtx);
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/net/wireless/wext-compat.c linux-libre-3.2.100-gnu1/net/wireless/wext-compat.c
--- linux-libre-3.2.99-gnu1/net/wireless/wext-compat.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/net/wireless/wext-compat.c	2018-03-03 10:57:56.000000000 -0500
@@ -1265,8 +1265,7 @@ static int cfg80211_wext_giwrate(struct
 {
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
 	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
-	/* we are under RTNL - globally locked - so can use a static struct */
-	static struct station_info sinfo;
+	struct station_info sinfo = {};
 	u8 addr[ETH_ALEN];
 	int err;
 
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/net/xfrm/xfrm_input.c linux-libre-3.2.100-gnu1/net/xfrm/xfrm_input.c
--- linux-libre-3.2.99-gnu1/net/xfrm/xfrm_input.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/net/xfrm/xfrm_input.c	2018-03-03 10:57:56.000000000 -0500
@@ -7,15 +7,31 @@
  *
  */
 
+#include <linux/bottom_half.h>
+#include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
+#include <linux/percpu.h>
 #include <net/dst.h>
 #include <net/ip.h>
 #include <net/xfrm.h>
 
+struct xfrm_trans_tasklet {
+	struct tasklet_struct tasklet;
+	struct sk_buff_head queue;
+};
+
+struct xfrm_trans_cb {
+	int (*finish)(struct sk_buff *skb);
+};
+
+#define XFRM_TRANS_SKB_CB(__skb) ((struct xfrm_trans_cb *)&((__skb)->cb[0]))
+
 static struct kmem_cache *secpath_cachep __read_mostly;
 
+static DEFINE_PER_CPU(struct xfrm_trans_tasklet, xfrm_trans_tasklet);
+
 void __secpath_destroy(struct sec_path *sp)
 {
 	int i;
@@ -285,10 +301,50 @@ int xfrm_input_resume(struct sk_buff *sk
 }
 EXPORT_SYMBOL(xfrm_input_resume);
 
+static void xfrm_trans_reinject(unsigned long data)
+{
+	struct xfrm_trans_tasklet *trans = (void *)data;
+	struct sk_buff_head queue;
+	struct sk_buff *skb;
+
+	__skb_queue_head_init(&queue);
+	skb_queue_splice_init(&trans->queue, &queue);
+
+	while ((skb = __skb_dequeue(&queue)))
+		XFRM_TRANS_SKB_CB(skb)->finish(skb);
+}
+
+int xfrm_trans_queue(struct sk_buff *skb, int (*finish)(struct sk_buff *))
+{
+	struct xfrm_trans_tasklet *trans;
+
+	trans = this_cpu_ptr(&xfrm_trans_tasklet);
+
+	if (skb_queue_len(&trans->queue) >= netdev_max_backlog)
+		return -ENOBUFS;
+
+	XFRM_TRANS_SKB_CB(skb)->finish = finish;
+	__skb_queue_tail(&trans->queue, skb);
+	tasklet_schedule(&trans->tasklet);
+	return 0;
+}
+EXPORT_SYMBOL(xfrm_trans_queue);
+
 void __init xfrm_input_init(void)
 {
+	int i;
+
 	secpath_cachep = kmem_cache_create("secpath_cache",
 					   sizeof(struct sec_path),
 					   0, SLAB_HWCACHE_ALIGN|SLAB_PANIC,
 					   NULL);
+
+	for_each_possible_cpu(i) {
+		struct xfrm_trans_tasklet *trans;
+
+		trans = &per_cpu(xfrm_trans_tasklet, i);
+		__skb_queue_head_init(&trans->queue);
+		tasklet_init(&trans->tasklet, xfrm_trans_reinject,
+			     (unsigned long)trans);
+	}
 }
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/sound/core/oss/pcm_oss.c linux-libre-3.2.100-gnu1/sound/core/oss/pcm_oss.c
--- linux-libre-3.2.99-gnu1/sound/core/oss/pcm_oss.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/sound/core/oss/pcm_oss.c	2018-03-03 10:57:56.000000000 -0500
@@ -465,7 +465,6 @@ static int snd_pcm_hw_param_near(struct
 		v = snd_pcm_hw_param_last(pcm, params, var, dir);
 	else
 		v = snd_pcm_hw_param_first(pcm, params, var, dir);
-	snd_BUG_ON(v < 0);
 	return v;
 }
 
@@ -1376,8 +1375,11 @@ static ssize_t snd_pcm_oss_write1(struct
 
 	if ((tmp = snd_pcm_oss_make_ready(substream)) < 0)
 		return tmp;
-	mutex_lock(&runtime->oss.params_lock);
 	while (bytes > 0) {
+		if (mutex_lock_interruptible(&runtime->oss.params_lock)) {
+			tmp = -ERESTARTSYS;
+			break;
+		}
 		if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) {
 			tmp = bytes;
 			if (tmp + runtime->oss.buffer_used > runtime->oss.period_bytes)
@@ -1421,14 +1423,18 @@ static ssize_t snd_pcm_oss_write1(struct
 			xfer += tmp;
 			if ((substream->f_flags & O_NONBLOCK) != 0 &&
 			    tmp != runtime->oss.period_bytes)
-				break;
+				tmp = -EAGAIN;
 		}
-	}
-	mutex_unlock(&runtime->oss.params_lock);
-	return xfer;
-
  err:
-	mutex_unlock(&runtime->oss.params_lock);
+		mutex_unlock(&runtime->oss.params_lock);
+		if (tmp < 0)
+			break;
+		if (signal_pending(current)) {
+			tmp = -ERESTARTSYS;
+			break;
+		}
+		tmp = 0;
+	}
 	return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
 }
 
@@ -1476,8 +1482,11 @@ static ssize_t snd_pcm_oss_read1(struct
 
 	if ((tmp = snd_pcm_oss_make_ready(substream)) < 0)
 		return tmp;
-	mutex_lock(&runtime->oss.params_lock);
 	while (bytes > 0) {
+		if (mutex_lock_interruptible(&runtime->oss.params_lock)) {
+			tmp = -ERESTARTSYS;
+			break;
+		}
 		if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) {
 			if (runtime->oss.buffer_used == 0) {
 				tmp = snd_pcm_oss_read2(substream, runtime->oss.buffer, runtime->oss.period_bytes, 1);
@@ -1508,12 +1517,16 @@ static ssize_t snd_pcm_oss_read1(struct
 			bytes -= tmp;
 			xfer += tmp;
 		}
-	}
-	mutex_unlock(&runtime->oss.params_lock);
-	return xfer;
-
  err:
-	mutex_unlock(&runtime->oss.params_lock);
+		mutex_unlock(&runtime->oss.params_lock);
+		if (tmp < 0)
+			break;
+		if (signal_pending(current)) {
+			tmp = -ERESTARTSYS;
+			break;
+		}
+		tmp = 0;
+	}
 	return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
 }
 
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/sound/core/oss/pcm_plugin.c linux-libre-3.2.100-gnu1/sound/core/oss/pcm_plugin.c
--- linux-libre-3.2.99-gnu1/sound/core/oss/pcm_plugin.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/sound/core/oss/pcm_plugin.c	2018-03-03 10:57:56.000000000 -0500
@@ -589,18 +589,26 @@ snd_pcm_sframes_t snd_pcm_plug_write_tra
 	snd_pcm_sframes_t frames = size;
 
 	plugin = snd_pcm_plug_first(plug);
-	while (plugin && frames > 0) {
+	while (plugin) {
+		if (frames <= 0)
+			return frames;
 		if ((next = plugin->next) != NULL) {
 			snd_pcm_sframes_t frames1 = frames;
-			if (plugin->dst_frames)
+			if (plugin->dst_frames) {
 				frames1 = plugin->dst_frames(plugin, frames);
+				if (frames1 <= 0)
+					return frames1;
+			}
 			if ((err = next->client_channels(next, frames1, &dst_channels)) < 0) {
 				return err;
 			}
 			if (err != frames1) {
 				frames = err;
-				if (plugin->src_frames)
+				if (plugin->src_frames) {
 					frames = plugin->src_frames(plugin, frames1);
+					if (frames <= 0)
+						return frames;
+				}
 			}
 		} else
 			dst_channels = NULL;
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/sound/core/pcm.c linux-libre-3.2.100-gnu1/sound/core/pcm.c
--- linux-libre-3.2.99-gnu1/sound/core/pcm.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/sound/core/pcm.c	2018-03-03 10:57:56.000000000 -0500
@@ -145,7 +145,9 @@ static int snd_pcm_control_ioctl(struct
 				err = -ENXIO;
 				goto _error;
 			}
+			mutex_lock(&pcm->open_mutex);
 			err = snd_pcm_info_user(substream, info);
+			mutex_unlock(&pcm->open_mutex);
 		_error:
 			mutex_unlock(&register_mutex);
 			return err;
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/sound/core/pcm_lib.c linux-libre-3.2.100-gnu1/sound/core/pcm_lib.c
--- linux-libre-3.2.99-gnu1/sound/core/pcm_lib.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/sound/core/pcm_lib.c	2018-03-03 10:57:56.000000000 -0500
@@ -590,7 +590,6 @@ static inline unsigned int muldiv32(unsi
 {
 	u_int64_t n = (u_int64_t) a * b;
 	if (c == 0) {
-		snd_BUG_ON(!n);
 		*r = 0;
 		return UINT_MAX;
 	}
@@ -1546,7 +1545,7 @@ int snd_pcm_hw_param_first(struct snd_pc
 		return changed;
 	if (params->rmask) {
 		int err = snd_pcm_hw_refine(pcm, params);
-		if (snd_BUG_ON(err < 0))
+		if (err < 0)
 			return err;
 	}
 	return snd_pcm_hw_param_value(params, var, dir);
@@ -1592,7 +1591,7 @@ int snd_pcm_hw_param_last(struct snd_pcm
 		return changed;
 	if (params->rmask) {
 		int err = snd_pcm_hw_refine(pcm, params);
-		if (snd_BUG_ON(err < 0))
+		if (err < 0)
 			return err;
 	}
 	return snd_pcm_hw_param_value(params, var, dir);
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/sound/core/rawmidi.c linux-libre-3.2.100-gnu1/sound/core/rawmidi.c
--- linux-libre-3.2.99-gnu1/sound/core/rawmidi.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/sound/core/rawmidi.c	2018-03-03 10:57:56.000000000 -0500
@@ -575,15 +575,14 @@ static int snd_rawmidi_info_user(struct
 	return 0;
 }
 
-int snd_rawmidi_info_select(struct snd_card *card, struct snd_rawmidi_info *info)
+static int __snd_rawmidi_info_select(struct snd_card *card,
+				     struct snd_rawmidi_info *info)
 {
 	struct snd_rawmidi *rmidi;
 	struct snd_rawmidi_str *pstr;
 	struct snd_rawmidi_substream *substream;
 
-	mutex_lock(&register_mutex);
 	rmidi = snd_rawmidi_search(card, info->device);
-	mutex_unlock(&register_mutex);
 	if (!rmidi)
 		return -ENXIO;
 	if (info->stream < 0 || info->stream > 1)
@@ -600,6 +599,16 @@ int snd_rawmidi_info_select(struct snd_c
 	return -ENXIO;
 }
 
+int snd_rawmidi_info_select(struct snd_card *card, struct snd_rawmidi_info *info)
+{
+	int ret;
+
+	mutex_lock(&register_mutex);
+	ret = __snd_rawmidi_info_select(card, info);
+	mutex_unlock(&register_mutex);
+	return ret;
+}
+
 static int snd_rawmidi_info_select_user(struct snd_card *card,
 					struct snd_rawmidi_info __user *_info)
 {
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/sound/core/seq/seq_clientmgr.c linux-libre-3.2.100-gnu1/sound/core/seq/seq_clientmgr.c
--- linux-libre-3.2.99-gnu1/sound/core/seq/seq_clientmgr.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/sound/core/seq/seq_clientmgr.c	2018-03-03 10:57:56.000000000 -0500
@@ -2189,7 +2189,6 @@ static int snd_seq_do_ioctl(struct snd_s
 			    void __user *arg)
 {
 	struct seq_ioctl_table *p;
-	int ret;
 
 	switch (cmd) {
 	case SNDRV_SEQ_IOCTL_PVERSION:
@@ -2203,12 +2202,8 @@ static int snd_seq_do_ioctl(struct snd_s
 	if (! arg)
 		return -EFAULT;
 	for (p = ioctl_tables; p->cmd; p++) {
-		if (p->cmd == cmd) {
-			mutex_lock(&client->ioctl_mutex);
-			ret = p->func(client, arg);
-			mutex_unlock(&client->ioctl_mutex);
-			return ret;
-		}
+		if (p->cmd == cmd)
+			return p->func(client, arg);
 	}
 	snd_printd("seq unknown ioctl() 0x%x (type='%c', number=0x%02x)\n",
 		   cmd, _IOC_TYPE(cmd), _IOC_NR(cmd));
@@ -2219,11 +2214,15 @@ static int snd_seq_do_ioctl(struct snd_s
 static long snd_seq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	struct snd_seq_client *client = file->private_data;
+	long ret;
 
 	if (snd_BUG_ON(!client))
 		return -ENXIO;
 		
-	return snd_seq_do_ioctl(client, cmd, (void __user *) arg);
+	mutex_lock(&client->ioctl_mutex);
+	ret = snd_seq_do_ioctl(client, cmd, (void __user *) arg);
+	mutex_unlock(&client->ioctl_mutex);
+	return ret;
 }
 
 #ifdef CONFIG_COMPAT
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/sound/core/seq/seq_timer.c linux-libre-3.2.100-gnu1/sound/core/seq/seq_timer.c
--- linux-libre-3.2.99-gnu1/sound/core/seq/seq_timer.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/sound/core/seq/seq_timer.c	2018-03-03 10:57:56.000000000 -0500
@@ -357,7 +357,7 @@ static int initialize_timer(struct snd_s
 	unsigned long freq;
 
 	t = tmr->timeri->timer;
-	if (snd_BUG_ON(!t))
+	if (!t)
 		return -EINVAL;
 
 	freq = tmr->preferred_resolution;
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/sound/drivers/aloop.c linux-libre-3.2.100-gnu1/sound/drivers/aloop.c
--- linux-libre-3.2.99-gnu1/sound/drivers/aloop.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/sound/drivers/aloop.c	2018-03-03 10:57:56.000000000 -0500
@@ -39,6 +39,7 @@
 #include <sound/core.h>
 #include <sound/control.h>
 #include <sound/pcm.h>
+#include <sound/pcm_params.h>
 #include <sound/info.h>
 #include <sound/initval.h>
 
@@ -307,19 +308,6 @@ static int loopback_trigger(struct snd_p
 	return 0;
 }
 
-static void params_change_substream(struct loopback_pcm *dpcm,
-				    struct snd_pcm_runtime *runtime)
-{
-	struct snd_pcm_runtime *dst_runtime;
-
-	if (dpcm == NULL || dpcm->substream == NULL)
-		return;
-	dst_runtime = dpcm->substream->runtime;
-	if (dst_runtime == NULL)
-		return;
-	dst_runtime->hw = dpcm->cable->hw;
-}
-
 static void params_change(struct snd_pcm_substream *substream)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
@@ -331,10 +319,6 @@ static void params_change(struct snd_pcm
 	cable->hw.rate_max = runtime->rate;
 	cable->hw.channels_min = runtime->channels;
 	cable->hw.channels_max = runtime->channels;
-	params_change_substream(cable->streams[SNDRV_PCM_STREAM_PLAYBACK],
-				runtime);
-	params_change_substream(cable->streams[SNDRV_PCM_STREAM_CAPTURE],
-				runtime);
 }
 
 static int loopback_prepare(struct snd_pcm_substream *substream)
@@ -610,26 +594,29 @@ static unsigned int get_cable_index(stru
 static int rule_format(struct snd_pcm_hw_params *params,
 		       struct snd_pcm_hw_rule *rule)
 {
+	struct loopback_pcm *dpcm = rule->private;
+	struct loopback_cable *cable = dpcm->cable;
+	struct snd_mask m;
 
-	struct snd_pcm_hardware *hw = rule->private;
-	struct snd_mask *maskp = hw_param_mask(params, rule->var);
-
-	maskp->bits[0] &= (u_int32_t)hw->formats;
-	maskp->bits[1] &= (u_int32_t)(hw->formats >> 32);
-	memset(maskp->bits + 2, 0, (SNDRV_MASK_MAX-64) / 8); /* clear rest */
-	if (! maskp->bits[0] && ! maskp->bits[1])
-		return -EINVAL;
-	return 0;
+	snd_mask_none(&m);
+	mutex_lock(&dpcm->loopback->cable_lock);
+	m.bits[0] = (u_int32_t)cable->hw.formats;
+	m.bits[1] = (u_int32_t)(cable->hw.formats >> 32);
+	mutex_unlock(&dpcm->loopback->cable_lock);
+	return snd_mask_refine(hw_param_mask(params, rule->var), &m);
 }
 
 static int rule_rate(struct snd_pcm_hw_params *params,
 		     struct snd_pcm_hw_rule *rule)
 {
-	struct snd_pcm_hardware *hw = rule->private;
+	struct loopback_pcm *dpcm = rule->private;
+	struct loopback_cable *cable = dpcm->cable;
 	struct snd_interval t;
 
-        t.min = hw->rate_min;
-        t.max = hw->rate_max;
+	mutex_lock(&dpcm->loopback->cable_lock);
+	t.min = cable->hw.rate_min;
+	t.max = cable->hw.rate_max;
+	mutex_unlock(&dpcm->loopback->cable_lock);
         t.openmin = t.openmax = 0;
         t.integer = 0;
 	return snd_interval_refine(hw_param_interval(params, rule->var), &t);
@@ -638,22 +625,44 @@ static int rule_rate(struct snd_pcm_hw_p
 static int rule_channels(struct snd_pcm_hw_params *params,
 			 struct snd_pcm_hw_rule *rule)
 {
-	struct snd_pcm_hardware *hw = rule->private;
+	struct loopback_pcm *dpcm = rule->private;
+	struct loopback_cable *cable = dpcm->cable;
 	struct snd_interval t;
 
-        t.min = hw->channels_min;
-        t.max = hw->channels_max;
+	mutex_lock(&dpcm->loopback->cable_lock);
+	t.min = cable->hw.channels_min;
+	t.max = cable->hw.channels_max;
+	mutex_unlock(&dpcm->loopback->cable_lock);
         t.openmin = t.openmax = 0;
         t.integer = 0;
 	return snd_interval_refine(hw_param_interval(params, rule->var), &t);
 }
 
+static void free_cable(struct snd_pcm_substream *substream)
+{
+	struct loopback *loopback = substream->private_data;
+	int dev = get_cable_index(substream);
+	struct loopback_cable *cable;
+
+	cable = loopback->cables[substream->number][dev];
+	if (!cable)
+		return;
+	if (cable->streams[!substream->stream]) {
+		/* other stream is still alive */
+		cable->streams[substream->stream] = NULL;
+	} else {
+		/* free the cable */
+		loopback->cables[substream->number][dev] = NULL;
+		kfree(cable);
+	}
+}
+
 static int loopback_open(struct snd_pcm_substream *substream)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct loopback *loopback = substream->private_data;
 	struct loopback_pcm *dpcm;
-	struct loopback_cable *cable;
+	struct loopback_cable *cable = NULL;
 	int err = 0;
 	int dev = get_cable_index(substream);
 
@@ -673,7 +682,6 @@ static int loopback_open(struct snd_pcm_
 	if (!cable) {
 		cable = kzalloc(sizeof(*cable), GFP_KERNEL);
 		if (!cable) {
-			kfree(dpcm);
 			err = -ENOMEM;
 			goto unlock;
 		}
@@ -691,19 +699,19 @@ static int loopback_open(struct snd_pcm_
 	/* are cached -> they do not reflect the actual state */
 	err = snd_pcm_hw_rule_add(runtime, 0,
 				  SNDRV_PCM_HW_PARAM_FORMAT,
-				  rule_format, &runtime->hw,
+				  rule_format, dpcm,
 				  SNDRV_PCM_HW_PARAM_FORMAT, -1);
 	if (err < 0)
 		goto unlock;
 	err = snd_pcm_hw_rule_add(runtime, 0,
 				  SNDRV_PCM_HW_PARAM_RATE,
-				  rule_rate, &runtime->hw,
+				  rule_rate, dpcm,
 				  SNDRV_PCM_HW_PARAM_RATE, -1);
 	if (err < 0)
 		goto unlock;
 	err = snd_pcm_hw_rule_add(runtime, 0,
 				  SNDRV_PCM_HW_PARAM_CHANNELS,
-				  rule_channels, &runtime->hw,
+				  rule_channels, dpcm,
 				  SNDRV_PCM_HW_PARAM_CHANNELS, -1);
 	if (err < 0)
 		goto unlock;
@@ -715,6 +723,10 @@ static int loopback_open(struct snd_pcm_
 	else
 		runtime->hw = cable->hw;
  unlock:
+	if (err < 0) {
+		free_cable(substream);
+		kfree(dpcm);
+	}
 	mutex_unlock(&loopback->cable_lock);
 	return err;
 }
@@ -723,20 +735,10 @@ static int loopback_close(struct snd_pcm
 {
 	struct loopback *loopback = substream->private_data;
 	struct loopback_pcm *dpcm = substream->runtime->private_data;
-	struct loopback_cable *cable;
-	int dev = get_cable_index(substream);
 
 	loopback_timer_stop(dpcm);
 	mutex_lock(&loopback->cable_lock);
-	cable = loopback->cables[substream->number][dev];
-	if (cable->streams[!substream->stream]) {
-		/* other stream is still alive */
-		cable->streams[substream->stream] = NULL;
-	} else {
-		/* free the cable */
-		loopback->cables[substream->number][dev] = NULL;
-		kfree(cable);
-	}
+	free_cable(substream);
 	mutex_unlock(&loopback->cable_lock);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.2.99-gnu1/sound/usb/mixer.c linux-libre-3.2.100-gnu1/sound/usb/mixer.c
--- linux-libre-3.2.99-gnu1/sound/usb/mixer.c	2018-02-13 13:32:25.000000000 -0500
+++ linux-libre-3.2.100-gnu1/sound/usb/mixer.c	2018-03-03 10:57:56.000000000 -0500
@@ -197,6 +197,10 @@ static void *find_audio_control_unit(str
 static int snd_usb_copy_string_desc(struct mixer_build *state, int index, char *buf, int maxlen)
 {
 	int len = usb_string(state->chip->dev, index, buf, maxlen - 1);
+
+	if (len < 0)
+		return 0;
+
 	buf[len] = 0;
 	return len;
 }
@@ -1919,18 +1923,25 @@ static int parse_audio_selector_unit(str
 	kctl->private_value = (unsigned long)namelist;
 	kctl->private_free = usb_mixer_selector_elem_free;
 
-	nameid = uac_selector_unit_iSelector(desc);
+	/* check the static mapping table at first */
 	len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name));
-	if (len)
-		;
-	else if (nameid)
-		snd_usb_copy_string_desc(state, nameid, kctl->id.name, sizeof(kctl->id.name));
-	else {
-		len = get_term_name(state, &state->oterm,
+	if (!len) {
+		/* no mapping ? */
+		/* if iSelector is given, use it */
+		nameid = uac_selector_unit_iSelector(desc);
+		if (nameid)
+			len = snd_usb_copy_string_desc(state, nameid,
+						       kctl->id.name,
+						       sizeof(kctl->id.name));
+		/* ... or pick up the terminal name at next */
+		if (!len)
+			len = get_term_name(state, &state->oterm,
 				    kctl->id.name, sizeof(kctl->id.name), 0);
-		if (! len)
+		/* ... or use the fixed string "USB" as the last resort */
+		if (!len)
 			strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name));
 
+		/* and add the proper suffix */
 		if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR)
 			append_ctl_name(kctl, " Clock Source");
 		else if ((state->oterm.type & 0xff00) == 0x0100)
