diff -druNp --no-dereference linux-libre-4.4.223-gnu/arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts linux-libre-4.4.224-gnu/arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts
--- linux-libre-4.4.223-gnu/arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts	2020-05-20 02:11:57.000000000 -0400
@@ -81,8 +81,8 @@
 	imx27-phycard-s-rdk {
 		pinctrl_i2c1: i2c1grp {
 			fsl,pins = <
-				MX27_PAD_I2C2_SDA__I2C2_SDA 0x0
-				MX27_PAD_I2C2_SCL__I2C2_SCL 0x0
+				MX27_PAD_I2C_DATA__I2C_DATA 0x0
+				MX27_PAD_I2C_CLK__I2C_CLK 0x0
 			>;
 		};
 
diff -druNp --no-dereference linux-libre-4.4.223-gnu/arch/arm/boot/dts/r8a7740.dtsi linux-libre-4.4.224-gnu/arch/arm/boot/dts/r8a7740.dtsi
--- linux-libre-4.4.223-gnu/arch/arm/boot/dts/r8a7740.dtsi	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/arch/arm/boot/dts/r8a7740.dtsi	2020-05-20 02:11:57.000000000 -0400
@@ -461,7 +461,7 @@
 		cpg_clocks: cpg_clocks@e6150000 {
 			compatible = "renesas,r8a7740-cpg-clocks";
 			reg = <0xe6150000 0x10000>;
-			clocks = <&extal1_clk>, <&extalr_clk>;
+			clocks = <&extal1_clk>, <&extal2_clk>, <&extalr_clk>;
 			#clock-cells = <1>;
 			clock-output-names = "system", "pllc0", "pllc1",
 					     "pllc2", "r",
diff -druNp --no-dereference linux-libre-4.4.223-gnu/arch/x86/entry/entry_32.S linux-libre-4.4.224-gnu/arch/x86/entry/entry_32.S
--- linux-libre-4.4.223-gnu/arch/x86/entry/entry_32.S	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/arch/x86/entry/entry_32.S	2020-05-20 02:11:57.000000000 -0400
@@ -331,7 +331,8 @@ sysenter_past_esp:
 	 * Return back to the vDSO, which will pop ecx and edx.
 	 * Don't bother with DS and ES (they already contain __USER_DS).
 	 */
-	ENABLE_INTERRUPTS_SYSEXIT
+	sti
+	sysexit
 
 .pushsection .fixup, "ax"
 2:	movl	$0, PT_FS(%esp)
@@ -554,11 +555,6 @@ ENTRY(native_iret)
 	iret
 	_ASM_EXTABLE(native_iret, iret_exc)
 END(native_iret)
-
-ENTRY(native_irq_enable_sysexit)
-	sti
-	sysexit
-END(native_irq_enable_sysexit)
 #endif
 
 ENTRY(overflow)
diff -druNp --no-dereference linux-libre-4.4.223-gnu/arch/x86/include/asm/apm.h linux-libre-4.4.224-gnu/arch/x86/include/asm/apm.h
--- linux-libre-4.4.223-gnu/arch/x86/include/asm/apm.h	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/arch/x86/include/asm/apm.h	2020-05-20 02:11:57.000000000 -0400
@@ -6,8 +6,6 @@
 #ifndef _ASM_X86_MACH_DEFAULT_APM_H
 #define _ASM_X86_MACH_DEFAULT_APM_H
 
-#include <asm/nospec-branch.h>
-
 #ifdef APM_ZERO_SEGS
 #	define APM_DO_ZERO_SEGS \
 		"pushl %%ds\n\t" \
@@ -33,7 +31,6 @@ static inline void apm_bios_call_asm(u32
 	 * N.B. We do NOT need a cld after the BIOS call
 	 * because we always save and restore the flags.
 	 */
-	firmware_restrict_branch_speculation_start();
 	__asm__ __volatile__(APM_DO_ZERO_SEGS
 		"pushl %%edi\n\t"
 		"pushl %%ebp\n\t"
@@ -46,7 +43,6 @@ static inline void apm_bios_call_asm(u32
 		  "=S" (*esi)
 		: "a" (func), "b" (ebx_in), "c" (ecx_in)
 		: "memory", "cc");
-	firmware_restrict_branch_speculation_end();
 }
 
 static inline u8 apm_bios_call_simple_asm(u32 func, u32 ebx_in,
@@ -59,7 +55,6 @@ static inline u8 apm_bios_call_simple_as
 	 * N.B. We do NOT need a cld after the BIOS call
 	 * because we always save and restore the flags.
 	 */
-	firmware_restrict_branch_speculation_start();
 	__asm__ __volatile__(APM_DO_ZERO_SEGS
 		"pushl %%edi\n\t"
 		"pushl %%ebp\n\t"
@@ -72,7 +67,6 @@ static inline u8 apm_bios_call_simple_as
 		  "=S" (si)
 		: "a" (func), "b" (ebx_in), "c" (ecx_in)
 		: "memory", "cc");
-	firmware_restrict_branch_speculation_end();
 	return error;
 }
 
diff -druNp --no-dereference linux-libre-4.4.223-gnu/arch/x86/include/asm/paravirt.h linux-libre-4.4.224-gnu/arch/x86/include/asm/paravirt.h
--- linux-libre-4.4.223-gnu/arch/x86/include/asm/paravirt.h	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/arch/x86/include/asm/paravirt.h	2020-05-20 02:11:57.000000000 -0400
@@ -938,13 +938,6 @@ extern void default_banner(void);
 	push %ecx; push %edx;				\
 	call PARA_INDIRECT(pv_cpu_ops+PV_CPU_read_cr0);	\
 	pop %edx; pop %ecx
-
-#define ENABLE_INTERRUPTS_SYSEXIT					\
-	PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_irq_enable_sysexit),	\
-		  CLBR_NONE,						\
-		  jmp PARA_INDIRECT(pv_cpu_ops+PV_CPU_irq_enable_sysexit))
-
-
 #else	/* !CONFIG_X86_32 */
 
 /*
diff -druNp --no-dereference linux-libre-4.4.223-gnu/arch/x86/include/asm/paravirt_types.h linux-libre-4.4.224-gnu/arch/x86/include/asm/paravirt_types.h
--- linux-libre-4.4.223-gnu/arch/x86/include/asm/paravirt_types.h	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/arch/x86/include/asm/paravirt_types.h	2020-05-20 02:11:57.000000000 -0400
@@ -162,15 +162,6 @@ struct pv_cpu_ops {
 
 	u64 (*read_pmc)(int counter);
 
-#ifdef CONFIG_X86_32
-	/*
-	 * Atomically enable interrupts and return to userspace.  This
-	 * is only used in 32-bit kernels.  64-bit kernels use
-	 * usergs_sysret32 instead.
-	 */
-	void (*irq_enable_sysexit)(void);
-#endif
-
 	/*
 	 * Switch to usermode gs and return to 64-bit usermode using
 	 * sysret.  Only used in 64-bit kernels to return to 64-bit
diff -druNp --no-dereference linux-libre-4.4.223-gnu/arch/x86/include/asm/stackprotector.h linux-libre-4.4.224-gnu/arch/x86/include/asm/stackprotector.h
--- linux-libre-4.4.223-gnu/arch/x86/include/asm/stackprotector.h	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/arch/x86/include/asm/stackprotector.h	2020-05-20 02:11:57.000000000 -0400
@@ -54,8 +54,13 @@
 /*
  * Initialize the stackprotector canary value.
  *
- * NOTE: this must only be called from functions that never return,
+ * NOTE: this must only be called from functions that never return
  * and it must always be inlined.
+ *
+ * In addition, it should be called from a compilation unit for which
+ * stack protector is disabled. Alternatively, the caller should not end
+ * with a function call which gets tail-call optimized as that would
+ * lead to checking a modified canary value.
  */
 static __always_inline void boot_init_stack_canary(void)
 {
diff -druNp --no-dereference linux-libre-4.4.223-gnu/arch/x86/kernel/apm_32.c linux-libre-4.4.224-gnu/arch/x86/kernel/apm_32.c
--- linux-libre-4.4.223-gnu/arch/x86/kernel/apm_32.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/arch/x86/kernel/apm_32.c	2020-05-20 02:11:57.000000000 -0400
@@ -239,6 +239,7 @@
 #include <asm/olpc.h>
 #include <asm/paravirt.h>
 #include <asm/reboot.h>
+#include <asm/nospec-branch.h>
 
 #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
 extern int (*console_blank_hook)(int);
@@ -613,11 +614,13 @@ static long __apm_bios_call(void *_call)
 	gdt[0x40 / 8] = bad_bios_desc;
 
 	apm_irq_save(flags);
+	firmware_restrict_branch_speculation_start();
 	APM_DO_SAVE_SEGS;
 	apm_bios_call_asm(call->func, call->ebx, call->ecx,
 			  &call->eax, &call->ebx, &call->ecx, &call->edx,
 			  &call->esi);
 	APM_DO_RESTORE_SEGS;
+	firmware_restrict_branch_speculation_end();
 	apm_irq_restore(flags);
 	gdt[0x40 / 8] = save_desc_40;
 	put_cpu();
@@ -689,10 +692,12 @@ static long __apm_bios_call_simple(void
 	gdt[0x40 / 8] = bad_bios_desc;
 
 	apm_irq_save(flags);
+	firmware_restrict_branch_speculation_start();
 	APM_DO_SAVE_SEGS;
 	error = apm_bios_call_simple_asm(call->func, call->ebx, call->ecx,
 					 &call->eax);
 	APM_DO_RESTORE_SEGS;
+	firmware_restrict_branch_speculation_end();
 	apm_irq_restore(flags);
 	gdt[0x40 / 8] = save_desc_40;
 	put_cpu();
diff -druNp --no-dereference linux-libre-4.4.223-gnu/arch/x86/kernel/asm-offsets.c linux-libre-4.4.224-gnu/arch/x86/kernel/asm-offsets.c
--- linux-libre-4.4.223-gnu/arch/x86/kernel/asm-offsets.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/arch/x86/kernel/asm-offsets.c	2020-05-20 02:11:57.000000000 -0400
@@ -65,9 +65,6 @@ void common(void) {
 	OFFSET(PV_IRQ_irq_disable, pv_irq_ops, irq_disable);
 	OFFSET(PV_IRQ_irq_enable, pv_irq_ops, irq_enable);
 	OFFSET(PV_CPU_iret, pv_cpu_ops, iret);
-#ifdef CONFIG_X86_32
-	OFFSET(PV_CPU_irq_enable_sysexit, pv_cpu_ops, irq_enable_sysexit);
-#endif
 	OFFSET(PV_CPU_read_cr0, pv_cpu_ops, read_cr0);
 	OFFSET(PV_MMU_read_cr2, pv_mmu_ops, read_cr2);
 #endif
diff -druNp --no-dereference linux-libre-4.4.223-gnu/arch/x86/kernel/paravirt.c linux-libre-4.4.224-gnu/arch/x86/kernel/paravirt.c
--- linux-libre-4.4.223-gnu/arch/x86/kernel/paravirt.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/arch/x86/kernel/paravirt.c	2020-05-20 02:11:57.000000000 -0400
@@ -168,9 +168,6 @@ unsigned paravirt_patch_default(u8 type,
 		ret = paravirt_patch_ident_64(insnbuf, len);
 
 	else if (type == PARAVIRT_PATCH(pv_cpu_ops.iret) ||
-#ifdef CONFIG_X86_32
-		 type == PARAVIRT_PATCH(pv_cpu_ops.irq_enable_sysexit) ||
-#endif
 		 type == PARAVIRT_PATCH(pv_cpu_ops.usergs_sysret32) ||
 		 type == PARAVIRT_PATCH(pv_cpu_ops.usergs_sysret64))
 		/* If operation requires a jmp, then jmp */
@@ -226,7 +223,6 @@ static u64 native_steal_clock(int cpu)
 
 /* These are in entry.S */
 extern void native_iret(void);
-extern void native_irq_enable_sysexit(void);
 extern void native_usergs_sysret32(void);
 extern void native_usergs_sysret64(void);
 
@@ -385,9 +381,6 @@ __visible struct pv_cpu_ops pv_cpu_ops =
 
 	.load_sp0 = native_load_sp0,
 
-#if defined(CONFIG_X86_32)
-	.irq_enable_sysexit = native_irq_enable_sysexit,
-#endif
 #ifdef CONFIG_X86_64
 #ifdef CONFIG_IA32_EMULATION
 	.usergs_sysret32 = native_usergs_sysret32,
diff -druNp --no-dereference linux-libre-4.4.223-gnu/arch/x86/kernel/paravirt_patch_32.c linux-libre-4.4.224-gnu/arch/x86/kernel/paravirt_patch_32.c
--- linux-libre-4.4.223-gnu/arch/x86/kernel/paravirt_patch_32.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/arch/x86/kernel/paravirt_patch_32.c	2020-05-20 02:11:57.000000000 -0400
@@ -5,7 +5,6 @@ DEF_NATIVE(pv_irq_ops, irq_enable, "sti"
 DEF_NATIVE(pv_irq_ops, restore_fl, "push %eax; popf");
 DEF_NATIVE(pv_irq_ops, save_fl, "pushf; pop %eax");
 DEF_NATIVE(pv_cpu_ops, iret, "iret");
-DEF_NATIVE(pv_cpu_ops, irq_enable_sysexit, "sti; sysexit");
 DEF_NATIVE(pv_mmu_ops, read_cr2, "mov %cr2, %eax");
 DEF_NATIVE(pv_mmu_ops, write_cr3, "mov %eax, %cr3");
 DEF_NATIVE(pv_mmu_ops, read_cr3, "mov %cr3, %eax");
@@ -46,7 +45,6 @@ unsigned native_patch(u8 type, u16 clobb
 		PATCH_SITE(pv_irq_ops, restore_fl);
 		PATCH_SITE(pv_irq_ops, save_fl);
 		PATCH_SITE(pv_cpu_ops, iret);
-		PATCH_SITE(pv_cpu_ops, irq_enable_sysexit);
 		PATCH_SITE(pv_mmu_ops, read_cr2);
 		PATCH_SITE(pv_mmu_ops, read_cr3);
 		PATCH_SITE(pv_mmu_ops, write_cr3);
diff -druNp --no-dereference linux-libre-4.4.223-gnu/arch/x86/kernel/paravirt_patch_64.c linux-libre-4.4.224-gnu/arch/x86/kernel/paravirt_patch_64.c
--- linux-libre-4.4.223-gnu/arch/x86/kernel/paravirt_patch_64.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/arch/x86/kernel/paravirt_patch_64.c	2020-05-20 02:11:57.000000000 -0400
@@ -12,7 +12,6 @@ DEF_NATIVE(pv_mmu_ops, write_cr3, "movq
 DEF_NATIVE(pv_cpu_ops, clts, "clts");
 DEF_NATIVE(pv_cpu_ops, wbinvd, "wbinvd");
 
-DEF_NATIVE(pv_cpu_ops, irq_enable_sysexit, "swapgs; sti; sysexit");
 DEF_NATIVE(pv_cpu_ops, usergs_sysret64, "swapgs; sysretq");
 DEF_NATIVE(pv_cpu_ops, usergs_sysret32, "swapgs; sysretl");
 DEF_NATIVE(pv_cpu_ops, swapgs, "swapgs");
diff -druNp --no-dereference linux-libre-4.4.223-gnu/arch/x86/kernel/smpboot.c linux-libre-4.4.224-gnu/arch/x86/kernel/smpboot.c
--- linux-libre-4.4.223-gnu/arch/x86/kernel/smpboot.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/arch/x86/kernel/smpboot.c	2020-05-20 02:11:57.000000000 -0400
@@ -243,6 +243,14 @@ static void notrace start_secondary(void
 
 	wmb();
 	cpu_startup_entry(CPUHP_ONLINE);
+
+	/*
+	 * Prevent tail call to cpu_startup_entry() because the stack protector
+	 * guard has been changed a couple of function calls up, in
+	 * boot_init_stack_canary() and must not be checked before tail calling
+	 * another function.
+	 */
+	prevent_tail_call_optimization();
 }
 
 void __init smp_store_boot_cpu_info(void)
diff -druNp --no-dereference linux-libre-4.4.223-gnu/arch/x86/kvm/x86.c linux-libre-4.4.224-gnu/arch/x86/kvm/x86.c
--- linux-libre-4.4.223-gnu/arch/x86/kvm/x86.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/arch/x86/kvm/x86.c	2020-05-20 02:11:57.000000000 -0400
@@ -2941,7 +2941,7 @@ static int kvm_vcpu_ioctl_x86_setup_mce(
 	unsigned bank_num = mcg_cap & 0xff, bank;
 
 	r = -EINVAL;
-	if (!bank_num || bank_num >= KVM_MAX_MCE_BANKS)
+	if (!bank_num || bank_num > KVM_MAX_MCE_BANKS)
 		goto out;
 	if (mcg_cap & ~(KVM_MCE_CAP_SUPPORTED | 0xff | 0xff0000))
 		goto out;
diff -druNp --no-dereference linux-libre-4.4.223-gnu/arch/x86/xen/enlighten.c linux-libre-4.4.224-gnu/arch/x86/xen/enlighten.c
--- linux-libre-4.4.223-gnu/arch/x86/xen/enlighten.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/arch/x86/xen/enlighten.c	2020-05-20 02:11:57.000000000 -0400
@@ -1240,10 +1240,7 @@ static const struct pv_cpu_ops xen_cpu_o
 
 	.iret = xen_iret,
 #ifdef CONFIG_X86_64
-	.usergs_sysret32 = xen_sysret32,
 	.usergs_sysret64 = xen_sysret64,
-#else
-	.irq_enable_sysexit = xen_sysexit,
 #endif
 
 	.load_tr_desc = paravirt_nop,
diff -druNp --no-dereference linux-libre-4.4.223-gnu/arch/x86/xen/smp.c linux-libre-4.4.224-gnu/arch/x86/xen/smp.c
--- linux-libre-4.4.223-gnu/arch/x86/xen/smp.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/arch/x86/xen/smp.c	2020-05-20 02:11:57.000000000 -0400
@@ -116,6 +116,7 @@ asmlinkage __visible void cpu_bringup_an
 #endif
 	cpu_bringup();
 	cpu_startup_entry(CPUHP_ONLINE);
+	prevent_tail_call_optimization();
 }
 
 static void xen_smp_intr_free(unsigned int cpu)
diff -druNp --no-dereference linux-libre-4.4.223-gnu/arch/x86/xen/xen-asm_32.S linux-libre-4.4.224-gnu/arch/x86/xen/xen-asm_32.S
--- linux-libre-4.4.223-gnu/arch/x86/xen/xen-asm_32.S	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/arch/x86/xen/xen-asm_32.S	2020-05-20 02:11:57.000000000 -0400
@@ -35,20 +35,6 @@ check_events:
 	ret
 
 /*
- * We can't use sysexit directly, because we're not running in ring0.
- * But we can easily fake it up using iret.  Assuming xen_sysexit is
- * jumped to with a standard stack frame, we can just strip it back to
- * a standard iret frame and use iret.
- */
-ENTRY(xen_sysexit)
-	movl PT_EAX(%esp), %eax			/* Shouldn't be necessary? */
-	orl $X86_EFLAGS_IF, PT_EFLAGS(%esp)
-	lea PT_EIP(%esp), %esp
-
-	jmp xen_iret
-ENDPROC(xen_sysexit)
-
-/*
  * This is run where a normal iret would be run, with the same stack setup:
  *	8: eflags
  *	4: cs
diff -druNp --no-dereference linux-libre-4.4.223-gnu/arch/x86/xen/xen-ops.h linux-libre-4.4.224-gnu/arch/x86/xen/xen-ops.h
--- linux-libre-4.4.223-gnu/arch/x86/xen/xen-ops.h	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/arch/x86/xen/xen-ops.h	2020-05-20 02:11:57.000000000 -0400
@@ -139,9 +139,6 @@ DECL_ASM(void, xen_restore_fl_direct, un
 
 /* These are not functions, and cannot be called normally */
 __visible void xen_iret(void);
-#ifdef CONFIG_X86_32
-__visible void xen_sysexit(void);
-#endif
 __visible void xen_sysret32(void);
 __visible void xen_sysret64(void);
 __visible void xen_adjust_exception_frame(void);
diff -druNp --no-dereference linux-libre-4.4.223-gnu/block/blk-core.c linux-libre-4.4.224-gnu/block/blk-core.c
--- linux-libre-4.4.223-gnu/block/blk-core.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/block/blk-core.c	2020-05-20 02:11:57.000000000 -0400
@@ -719,6 +719,9 @@ struct request_queue *blk_alloc_queue_no
 
 	kobject_init(&q->kobj, &blk_queue_ktype);
 
+#ifdef CONFIG_BLK_DEV_IO_TRACE
+	mutex_init(&q->blk_trace_mutex);
+#endif
 	mutex_init(&q->sysfs_lock);
 	spin_lock_init(&q->__queue_lock);
 
diff -druNp --no-dereference linux-libre-4.4.223-gnu/block/blk-mq.c linux-libre-4.4.224-gnu/block/blk-mq.c
--- linux-libre-4.4.223-gnu/block/blk-mq.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/block/blk-mq.c	2020-05-20 02:11:57.000000000 -0400
@@ -628,6 +628,22 @@ static void blk_mq_rq_timer(unsigned lon
 	};
 	int i;
 
+	/* A deadlock might occur if a request is stuck requiring a
+	 * timeout at the same time a queue freeze is waiting
+	 * completion, since the timeout code would not be able to
+	 * acquire the queue reference here.
+	 *
+	 * That's why we don't use blk_queue_enter here; instead, we use
+	 * percpu_ref_tryget directly, because we need to be able to
+	 * obtain a reference even in the short window between the queue
+	 * starting to freeze, by dropping the first reference in
+	 * blk_mq_freeze_queue_start, and the moment the last request is
+	 * consumed, marked by the instant q_usage_counter reaches
+	 * zero.
+	 */
+	if (!percpu_ref_tryget(&q->q_usage_counter))
+		return;
+
 	blk_mq_queue_tag_busy_iter(q, blk_mq_check_expired, &data);
 
 	if (data.next_set) {
@@ -642,6 +658,7 @@ static void blk_mq_rq_timer(unsigned lon
 				blk_mq_tag_idle(hctx);
 		}
 	}
+	blk_queue_exit(q);
 }
 
 /*
diff -druNp --no-dereference linux-libre-4.4.223-gnu/block/blk-mq-tag.c linux-libre-4.4.224-gnu/block/blk-mq-tag.c
--- linux-libre-4.4.223-gnu/block/blk-mq-tag.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/block/blk-mq-tag.c	2020-05-20 02:11:57.000000000 -0400
@@ -481,6 +481,11 @@ void blk_mq_queue_tag_busy_iter(struct r
 	struct blk_mq_hw_ctx *hctx;
 	int i;
 
+	/*
+	 * Avoid potential races with things like queue removal.
+	 */
+	if (!percpu_ref_tryget(&q->q_usage_counter))
+		return;
 
 	queue_for_each_hw_ctx(q, hctx, i) {
 		struct blk_mq_tags *tags = hctx->tags;
@@ -497,7 +502,7 @@ void blk_mq_queue_tag_busy_iter(struct r
 		bt_for_each(hctx, &tags->bitmap_tags, tags->nr_reserved_tags, fn, priv,
 		      false);
 	}
-
+	blk_queue_exit(q);
 }
 
 static unsigned int bt_unused_tags(struct blk_mq_bitmap_tags *bt)
diff -druNp --no-dereference linux-libre-4.4.223-gnu/block/blk-timeout.c linux-libre-4.4.224-gnu/block/blk-timeout.c
--- linux-libre-4.4.223-gnu/block/blk-timeout.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/block/blk-timeout.c	2020-05-20 02:11:57.000000000 -0400
@@ -134,6 +134,8 @@ void blk_rq_timed_out_timer(unsigned lon
 	struct request *rq, *tmp;
 	int next_set = 0;
 
+	if (blk_queue_enter(q, GFP_NOWAIT))
+		return;
 	spin_lock_irqsave(q->queue_lock, flags);
 
 	list_for_each_entry_safe(rq, tmp, &q->timeout_list, timeout_list)
@@ -143,6 +145,7 @@ void blk_rq_timed_out_timer(unsigned lon
 		mod_timer(&q->timeout, round_jiffies_up(next));
 
 	spin_unlock_irqrestore(q->queue_lock, flags);
+	blk_queue_exit(q);
 }
 
 /**
diff -druNp --no-dereference linux-libre-4.4.223-gnu/crypto/lrw.c linux-libre-4.4.224-gnu/crypto/lrw.c
--- linux-libre-4.4.223-gnu/crypto/lrw.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/crypto/lrw.c	2020-05-20 02:11:57.000000000 -0400
@@ -377,7 +377,7 @@ out_put_alg:
 	return inst;
 }
 
-static void free(struct crypto_instance *inst)
+static void free_inst(struct crypto_instance *inst)
 {
 	crypto_drop_spawn(crypto_instance_ctx(inst));
 	kfree(inst);
@@ -386,7 +386,7 @@ static void free(struct crypto_instance
 static struct crypto_template crypto_tmpl = {
 	.name = "lrw",
 	.alloc = alloc,
-	.free = free,
+	.free = free_inst,
 	.module = THIS_MODULE,
 };
 
diff -druNp --no-dereference linux-libre-4.4.223-gnu/crypto/xts.c linux-libre-4.4.224-gnu/crypto/xts.c
--- linux-libre-4.4.223-gnu/crypto/xts.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/crypto/xts.c	2020-05-20 02:11:57.000000000 -0400
@@ -334,7 +334,7 @@ out_put_alg:
 	return inst;
 }
 
-static void free(struct crypto_instance *inst)
+static void free_inst(struct crypto_instance *inst)
 {
 	crypto_drop_spawn(crypto_instance_ctx(inst));
 	kfree(inst);
@@ -343,7 +343,7 @@ static void free(struct crypto_instance
 static struct crypto_template crypto_tmpl = {
 	.name = "xts",
 	.alloc = alloc,
-	.free = free,
+	.free = free_inst,
 	.module = THIS_MODULE,
 };
 
diff -druNp --no-dereference linux-libre-4.4.223-gnu/drivers/acpi/video_detect.c linux-libre-4.4.224-gnu/drivers/acpi/video_detect.c
--- linux-libre-4.4.223-gnu/drivers/acpi/video_detect.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/drivers/acpi/video_detect.c	2020-05-20 02:11:57.000000000 -0400
@@ -289,17 +289,6 @@ static const struct dmi_system_id video_
 		DMI_MATCH(DMI_PRODUCT_NAME, "Dell System XPS L702X"),
 		},
 	},
-	{
-	/* https://bugzilla.redhat.com/show_bug.cgi?id=1204476 */
-	/* https://bugs.launchpad.net/ubuntu/+source/linux-lts-trusty/+bug/1416940 */
-	.callback = video_detect_force_native,
-	.ident = "HP Pavilion dv6",
-	.matches = {
-		DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-		DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv6 Notebook PC"),
-		},
-	},
-
 	{ },
 };
 
diff -druNp --no-dereference linux-libre-4.4.223-gnu/drivers/dma/mmp_tdma.c linux-libre-4.4.224-gnu/drivers/dma/mmp_tdma.c
--- linux-libre-4.4.223-gnu/drivers/dma/mmp_tdma.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/drivers/dma/mmp_tdma.c	2020-05-20 02:11:57.000000000 -0400
@@ -364,6 +364,8 @@ static void mmp_tdma_free_descriptor(str
 		gen_pool_free(gpool, (unsigned long)tdmac->desc_arr,
 				size);
 	tdmac->desc_arr = NULL;
+	if (tdmac->status == DMA_ERROR)
+		tdmac->status = DMA_COMPLETE;
 
 	return;
 }
diff -druNp --no-dereference linux-libre-4.4.223-gnu/drivers/dma/pch_dma.c linux-libre-4.4.224-gnu/drivers/dma/pch_dma.c
--- linux-libre-4.4.223-gnu/drivers/dma/pch_dma.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/drivers/dma/pch_dma.c	2020-05-20 02:11:57.000000000 -0400
@@ -877,6 +877,7 @@ static int pch_dma_probe(struct pci_dev
 	}
 
 	pci_set_master(pdev);
+	pd->dma.dev = &pdev->dev;
 
 	err = request_irq(pdev->irq, pd_irq, IRQF_SHARED, DRV_NAME, pd);
 	if (err) {
@@ -892,7 +893,6 @@ static int pch_dma_probe(struct pci_dev
 		goto err_free_irq;
 	}
 
-	pd->dma.dev = &pdev->dev;
 
 	INIT_LIST_HEAD(&pd->dma.channels);
 
diff -druNp --no-dereference linux-libre-4.4.223-gnu/drivers/gpu/drm/qxl/qxl_image.c linux-libre-4.4.224-gnu/drivers/gpu/drm/qxl/qxl_image.c
--- linux-libre-4.4.223-gnu/drivers/gpu/drm/qxl/qxl_image.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/drivers/gpu/drm/qxl/qxl_image.c	2020-05-20 02:11:57.000000000 -0400
@@ -210,7 +210,8 @@ qxl_image_init_helper(struct qxl_device
 		break;
 	default:
 		DRM_ERROR("unsupported image bit depth\n");
-		return -EINVAL; /* TODO: cleanup */
+		qxl_bo_kunmap_atomic_page(qdev, image_bo, ptr);
+		return -EINVAL;
 	}
 	image->u.bitmap.flags = QXL_BITMAP_TOP_DOWN;
 	image->u.bitmap.x = width;
diff -druNp --no-dereference linux-libre-4.4.223-gnu/drivers/infiniband/core/addr.c linux-libre-4.4.224-gnu/drivers/infiniband/core/addr.c
--- linux-libre-4.4.223-gnu/drivers/infiniband/core/addr.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/drivers/infiniband/core/addr.c	2020-05-20 02:11:57.000000000 -0400
@@ -293,9 +293,9 @@ static int addr6_resolve(struct sockaddr
 	fl6.saddr = src_in->sin6_addr;
 	fl6.flowi6_oif = addr->bound_dev_if;
 
-	ret = ipv6_stub->ipv6_dst_lookup(addr->net, NULL, &dst, &fl6);
-	if (ret < 0)
-		goto put;
+	dst = ipv6_stub->ipv6_dst_lookup_flow(addr->net, NULL, &fl6, NULL);
+	if (IS_ERR(dst))
+		return PTR_ERR(dst);
 
 	if (ipv6_addr_any(&fl6.saddr)) {
 		ret = ipv6_dev_get_saddr(addr->net, ip6_dst_idev(dst)->dev,
diff -druNp --no-dereference linux-libre-4.4.223-gnu/drivers/infiniband/hw/mlx4/qp.c linux-libre-4.4.224-gnu/drivers/infiniband/hw/mlx4/qp.c
--- linux-libre-4.4.223-gnu/drivers/infiniband/hw/mlx4/qp.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/drivers/infiniband/hw/mlx4/qp.c	2020-05-20 02:11:57.000000000 -0400
@@ -2156,6 +2156,7 @@ static int build_sriov_qp0_header(struct
 	int send_size;
 	int header_size;
 	int spc;
+	int err;
 	int i;
 
 	if (wr->wr.opcode != IB_WR_SEND)
@@ -2190,7 +2191,9 @@ static int build_sriov_qp0_header(struct
 
 	sqp->ud_header.lrh.virtual_lane    = 0;
 	sqp->ud_header.bth.solicited_event = !!(wr->wr.send_flags & IB_SEND_SOLICITED);
-	ib_get_cached_pkey(ib_dev, sqp->qp.port, 0, &pkey);
+	err = ib_get_cached_pkey(ib_dev, sqp->qp.port, 0, &pkey);
+	if (err)
+		return err;
 	sqp->ud_header.bth.pkey = cpu_to_be16(pkey);
 	if (sqp->qp.mlx4_ib_qp_type == MLX4_IB_QPT_TUN_SMI_OWNER)
 		sqp->ud_header.bth.destination_qpn = cpu_to_be32(wr->remote_qpn);
@@ -2423,9 +2426,14 @@ static int build_mlx_header(struct mlx4_
 	}
 	sqp->ud_header.bth.solicited_event = !!(wr->wr.send_flags & IB_SEND_SOLICITED);
 	if (!sqp->qp.ibqp.qp_num)
-		ib_get_cached_pkey(ib_dev, sqp->qp.port, sqp->pkey_index, &pkey);
+		err = ib_get_cached_pkey(ib_dev, sqp->qp.port, sqp->pkey_index,
+					 &pkey);
 	else
-		ib_get_cached_pkey(ib_dev, sqp->qp.port, wr->pkey_index, &pkey);
+		err = ib_get_cached_pkey(ib_dev, sqp->qp.port, wr->pkey_index,
+					 &pkey);
+	if (err)
+		return err;
+
 	sqp->ud_header.bth.pkey = cpu_to_be16(pkey);
 	sqp->ud_header.bth.destination_qpn = cpu_to_be32(wr->remote_qpn);
 	sqp->ud_header.bth.psn = cpu_to_be32((sqp->send_psn++) & ((1 << 24) - 1));
diff -druNp --no-dereference linux-libre-4.4.223-gnu/drivers/infiniband/ulp/ipoib/ipoib_ib.c linux-libre-4.4.224-gnu/drivers/infiniband/ulp/ipoib/ipoib_ib.c
--- linux-libre-4.4.223-gnu/drivers/infiniband/ulp/ipoib/ipoib_ib.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/drivers/infiniband/ulp/ipoib/ipoib_ib.c	2020-05-20 02:11:57.000000000 -0400
@@ -945,19 +945,6 @@ static inline int update_parent_pkey(str
 		 */
 		priv->dev->broadcast[8] = priv->pkey >> 8;
 		priv->dev->broadcast[9] = priv->pkey & 0xff;
-
-		/*
-		 * Update the broadcast address in the priv->broadcast object,
-		 * in case it already exists, otherwise no one will do that.
-		 */
-		if (priv->broadcast) {
-			spin_lock_irq(&priv->lock);
-			memcpy(priv->broadcast->mcmember.mgid.raw,
-			       priv->dev->broadcast + 4,
-			sizeof(union ib_gid));
-			spin_unlock_irq(&priv->lock);
-		}
-
 		return 0;
 	}
 
diff -druNp --no-dereference linux-libre-4.4.223-gnu/drivers/net/ethernet/cisco/enic/enic_main.c linux-libre-4.4.224-gnu/drivers/net/ethernet/cisco/enic/enic_main.c
--- linux-libre-4.4.223-gnu/drivers/net/ethernet/cisco/enic/enic_main.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/drivers/net/ethernet/cisco/enic/enic_main.c	2020-05-20 02:11:57.000000000 -0400
@@ -1708,7 +1708,7 @@ static int enic_open(struct net_device *
 {
 	struct enic *enic = netdev_priv(netdev);
 	unsigned int i;
-	int err;
+	int err, ret;
 
 	err = enic_request_intr(enic);
 	if (err) {
@@ -1766,10 +1766,9 @@ static int enic_open(struct net_device *
 
 err_out_free_rq:
 	for (i = 0; i < enic->rq_count; i++) {
-		err = vnic_rq_disable(&enic->rq[i]);
-		if (err)
-			return err;
-		vnic_rq_clean(&enic->rq[i], enic_free_rq_buf);
+		ret = vnic_rq_disable(&enic->rq[i]);
+		if (!ret)
+			vnic_rq_clean(&enic->rq[i], enic_free_rq_buf);
 	}
 	enic_dev_notify_unset(enic);
 err_out_free_intr:
diff -druNp --no-dereference linux-libre-4.4.223-gnu/drivers/net/ethernet/intel/i40e/i40e_nvm.c linux-libre-4.4.224-gnu/drivers/net/ethernet/intel/i40e/i40e_nvm.c
--- linux-libre-4.4.223-gnu/drivers/net/ethernet/intel/i40e/i40e_nvm.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/drivers/net/ethernet/intel/i40e/i40e_nvm.c	2020-05-20 02:11:57.000000000 -0400
@@ -266,7 +266,7 @@ static i40e_status i40e_read_nvm_aq(stru
  * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
  * @data: word read from the Shadow RAM
  *
- * Reads one 16 bit word from the Shadow RAM using the GLNVM_SRCTL register.
+ * Reads one 16 bit word from the Shadow RAM using the AdminQ
  **/
 static i40e_status i40e_read_nvm_word_aq(struct i40e_hw *hw, u16 offset,
 					 u16 *data)
@@ -280,27 +280,49 @@ static i40e_status i40e_read_nvm_word_aq
 }
 
 /**
- * i40e_read_nvm_word - Reads Shadow RAM
+ * __i40e_read_nvm_word - Reads nvm word, assumes called does the locking
  * @hw: pointer to the HW structure
  * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
  * @data: word read from the Shadow RAM
  *
- * Reads one 16 bit word from the Shadow RAM using the GLNVM_SRCTL register.
+ * Reads one 16 bit word from the Shadow RAM.
+ *
+ * Do not use this function except in cases where the nvm lock is already
+ * taken via i40e_acquire_nvm().
+ **/
+static i40e_status __i40e_read_nvm_word(struct i40e_hw *hw,
+					u16 offset, u16 *data)
+{
+	i40e_status ret_code = 0;
+
+	if (hw->flags & I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE)
+		ret_code = i40e_read_nvm_word_aq(hw, offset, data);
+	else
+		ret_code = i40e_read_nvm_word_srctl(hw, offset, data);
+	return ret_code;
+}
+
+/**
+ * i40e_read_nvm_word - Reads nvm word and acquire lock if necessary
+ * @hw: pointer to the HW structure
+ * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
+ * @data: word read from the Shadow RAM
+ *
+ * Reads one 16 bit word from the Shadow RAM.
  **/
 i40e_status i40e_read_nvm_word(struct i40e_hw *hw, u16 offset,
 			       u16 *data)
 {
-	enum i40e_status_code ret_code = 0;
+	i40e_status ret_code = 0;
 
 	ret_code = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
-	if (!ret_code) {
-		if (hw->flags & I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE) {
-			ret_code = i40e_read_nvm_word_aq(hw, offset, data);
-		} else {
-			ret_code = i40e_read_nvm_word_srctl(hw, offset, data);
-		}
-		i40e_release_nvm(hw);
-	}
+	if (ret_code)
+		return ret_code;
+
+	ret_code = __i40e_read_nvm_word(hw, offset, data);
+
+	i40e_release_nvm(hw);
+
 	return ret_code;
 }
 
@@ -393,31 +415,25 @@ read_nvm_buffer_aq_exit:
 }
 
 /**
- * i40e_read_nvm_buffer - Reads Shadow RAM buffer
+ * __i40e_read_nvm_buffer - Reads nvm buffer, caller must acquire lock
  * @hw: pointer to the HW structure
  * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF).
  * @words: (in) number of words to read; (out) number of words actually read
  * @data: words read from the Shadow RAM
  *
  * Reads 16 bit words (data buffer) from the SR using the i40e_read_nvm_srrd()
- * method. The buffer read is preceded by the NVM ownership take
- * and followed by the release.
+ * method.
  **/
-i40e_status i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset,
-				 u16 *words, u16 *data)
+static i40e_status __i40e_read_nvm_buffer(struct i40e_hw *hw,
+					  u16 offset, u16 *words,
+					  u16 *data)
 {
-	enum i40e_status_code ret_code = 0;
+	i40e_status ret_code = 0;
 
-	if (hw->flags & I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE) {
-		ret_code = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
-		if (!ret_code) {
-			ret_code = i40e_read_nvm_buffer_aq(hw, offset, words,
-							   data);
-			i40e_release_nvm(hw);
-		}
-	} else {
+	if (hw->flags & I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE)
+		ret_code = i40e_read_nvm_buffer_aq(hw, offset, words, data);
+	else
 		ret_code = i40e_read_nvm_buffer_srctl(hw, offset, words, data);
-	}
 	return ret_code;
 }
 
@@ -499,15 +515,15 @@ static i40e_status i40e_calc_nvm_checksu
 	data = (u16 *)vmem.va;
 
 	/* read pointer to VPD area */
-	ret_code = i40e_read_nvm_word(hw, I40E_SR_VPD_PTR, &vpd_module);
+	ret_code = __i40e_read_nvm_word(hw, I40E_SR_VPD_PTR, &vpd_module);
 	if (ret_code) {
 		ret_code = I40E_ERR_NVM_CHECKSUM;
 		goto i40e_calc_nvm_checksum_exit;
 	}
 
 	/* read pointer to PCIe Alt Auto-load module */
-	ret_code = i40e_read_nvm_word(hw, I40E_SR_PCIE_ALT_AUTO_LOAD_PTR,
-				      &pcie_alt_module);
+	ret_code = __i40e_read_nvm_word(hw, I40E_SR_PCIE_ALT_AUTO_LOAD_PTR,
+					&pcie_alt_module);
 	if (ret_code) {
 		ret_code = I40E_ERR_NVM_CHECKSUM;
 		goto i40e_calc_nvm_checksum_exit;
@@ -521,7 +537,7 @@ static i40e_status i40e_calc_nvm_checksu
 		if ((i % I40E_SR_SECTOR_SIZE_IN_WORDS) == 0) {
 			u16 words = I40E_SR_SECTOR_SIZE_IN_WORDS;
 
-			ret_code = i40e_read_nvm_buffer(hw, i, &words, data);
+			ret_code = __i40e_read_nvm_buffer(hw, i, &words, data);
 			if (ret_code) {
 				ret_code = I40E_ERR_NVM_CHECKSUM;
 				goto i40e_calc_nvm_checksum_exit;
@@ -593,14 +609,19 @@ i40e_status i40e_validate_nvm_checksum(s
 	u16 checksum_sr = 0;
 	u16 checksum_local = 0;
 
+	/* We must acquire the NVM lock in order to correctly synchronize the
+	 * NVM accesses across multiple PFs. Without doing so it is possible
+	 * for one of the PFs to read invalid data potentially indicating that
+	 * the checksum is invalid.
+	 */
+	ret_code = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
+	if (ret_code)
+		return ret_code;
 	ret_code = i40e_calc_nvm_checksum(hw, &checksum_local);
+	__i40e_read_nvm_word(hw, I40E_SR_SW_CHECKSUM_WORD, &checksum_sr);
+	i40e_release_nvm(hw);
 	if (ret_code)
-		goto i40e_validate_nvm_checksum_exit;
-
-	/* Do not use i40e_read_nvm_word() because we do not want to take
-	 * the synchronization semaphores twice here.
-	 */
-	i40e_read_nvm_word(hw, I40E_SR_SW_CHECKSUM_WORD, &checksum_sr);
+		return ret_code;
 
 	/* Verify read checksum from EEPROM is the same as
 	 * calculated checksum
@@ -612,7 +633,6 @@ i40e_status i40e_validate_nvm_checksum(s
 	if (checksum)
 		*checksum = checksum_local;
 
-i40e_validate_nvm_checksum_exit:
 	return ret_code;
 }
 
@@ -958,6 +978,7 @@ retry:
 		break;
 
 	case I40E_NVMUPD_CSUM_CON:
+		/* Assumes the caller has acquired the nvm */
 		status = i40e_update_nvm_checksum(hw);
 		if (status) {
 			*perrno = hw->aq.asq_last_status ?
@@ -971,6 +992,7 @@ retry:
 		break;
 
 	case I40E_NVMUPD_CSUM_LCB:
+		/* Assumes the caller has acquired the nvm */
 		status = i40e_update_nvm_checksum(hw);
 		if (status) {
 			*perrno = hw->aq.asq_last_status ?
diff -druNp --no-dereference linux-libre-4.4.223-gnu/drivers/net/ethernet/intel/i40e/i40e_prototype.h linux-libre-4.4.224-gnu/drivers/net/ethernet/intel/i40e/i40e_prototype.h
--- linux-libre-4.4.223-gnu/drivers/net/ethernet/intel/i40e/i40e_prototype.h	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/drivers/net/ethernet/intel/i40e/i40e_prototype.h	2020-05-20 02:11:57.000000000 -0400
@@ -282,8 +282,6 @@ i40e_status i40e_acquire_nvm(struct i40e
 void i40e_release_nvm(struct i40e_hw *hw);
 i40e_status i40e_read_nvm_word(struct i40e_hw *hw, u16 offset,
 					 u16 *data);
-i40e_status i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset,
-					   u16 *words, u16 *data);
 i40e_status i40e_update_nvm_checksum(struct i40e_hw *hw);
 i40e_status i40e_validate_nvm_checksum(struct i40e_hw *hw,
 						 u16 *checksum);
diff -druNp --no-dereference linux-libre-4.4.223-gnu/drivers/net/ethernet/mellanox/mlx4/main.c linux-libre-4.4.224-gnu/drivers/net/ethernet/mellanox/mlx4/main.c
--- linux-libre-4.4.223-gnu/drivers/net/ethernet/mellanox/mlx4/main.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/drivers/net/ethernet/mellanox/mlx4/main.c	2020-05-20 02:11:57.000000000 -0400
@@ -2295,6 +2295,7 @@ static int mlx4_allocate_default_counter
 
 		if (!err || err == -ENOSPC) {
 			priv->def_counter[port] = idx;
+			err = 0;
 		} else if (err == -ENOENT) {
 			err = 0;
 			continue;
@@ -2344,7 +2345,8 @@ int mlx4_counter_alloc(struct mlx4_dev *
 				   MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
 		if (!err)
 			*idx = get_param_l(&out_param);
-
+		if (WARN_ON(err == -ENOSPC))
+			err = -EINVAL;
 		return err;
 	}
 	return __mlx4_counter_alloc(dev, idx);
diff -druNp --no-dereference linux-libre-4.4.223-gnu/drivers/net/ethernet/mellanox/mlx5/core/main.c linux-libre-4.4.224-gnu/drivers/net/ethernet/mellanox/mlx5/core/main.c
--- linux-libre-4.4.223-gnu/drivers/net/ethernet/mellanox/mlx5/core/main.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/drivers/net/ethernet/mellanox/mlx5/core/main.c	2020-05-20 02:11:57.000000000 -0400
@@ -933,7 +933,7 @@ static int mlx5_load_one(struct mlx5_cor
 	if (err) {
 		dev_err(&dev->pdev->dev, "Firmware over %d MS in pre-initializing state, aborting\n",
 			FW_PRE_INIT_TIMEOUT_MILI);
-		goto out;
+		goto out_err;
 	}
 
 	err = mlx5_cmd_init(dev);
diff -druNp --no-dereference linux-libre-4.4.223-gnu/drivers/net/ethernet/moxa/moxart_ether.c linux-libre-4.4.224-gnu/drivers/net/ethernet/moxa/moxart_ether.c
--- linux-libre-4.4.223-gnu/drivers/net/ethernet/moxa/moxart_ether.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/drivers/net/ethernet/moxa/moxart_ether.c	2020-05-20 02:11:57.000000000 -0400
@@ -541,7 +541,7 @@ static int moxart_remove(struct platform
 	struct net_device *ndev = platform_get_drvdata(pdev);
 
 	unregister_netdev(ndev);
-	free_irq(ndev->irq, ndev);
+	devm_free_irq(&pdev->dev, ndev->irq, ndev);
 	moxart_mac_free_memory(ndev);
 	free_netdev(ndev);
 
diff -druNp --no-dereference linux-libre-4.4.223-gnu/drivers/net/ethernet/natsemi/jazzsonic.c linux-libre-4.4.224-gnu/drivers/net/ethernet/natsemi/jazzsonic.c
--- linux-libre-4.4.223-gnu/drivers/net/ethernet/natsemi/jazzsonic.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/drivers/net/ethernet/natsemi/jazzsonic.c	2020-05-20 02:11:57.000000000 -0400
@@ -247,13 +247,15 @@ static int jazz_sonic_probe(struct platf
 		goto out;
 	err = register_netdev(dev);
 	if (err)
-		goto out1;
+		goto undo_probe1;
 
 	printk("%s: MAC %pM IRQ %d\n", dev->name, dev->dev_addr, dev->irq);
 
 	return 0;
 
-out1:
+undo_probe1:
+	dma_free_coherent(lp->device, SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
+			  lp->descriptors, lp->descriptors_laddr);
 	release_mem_region(dev->base_addr, SONIC_MEM_SIZE);
 out:
 	free_netdev(dev);
diff -druNp --no-dereference linux-libre-4.4.223-gnu/drivers/net/geneve.c linux-libre-4.4.224-gnu/drivers/net/geneve.c
--- linux-libre-4.4.223-gnu/drivers/net/geneve.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/drivers/net/geneve.c	2020-05-20 02:11:57.000000000 -0400
@@ -781,7 +781,9 @@ static struct dst_entry *geneve_get_v6_d
 		fl6->daddr = geneve->remote.sin6.sin6_addr;
 	}
 
-	if (ipv6_stub->ipv6_dst_lookup(geneve->net, gs6->sock->sk, &dst, fl6)) {
+	dst = ipv6_stub->ipv6_dst_lookup_flow(geneve->net, gs6->sock->sk, fl6,
+					      NULL);
+	if (IS_ERR(dst)) {
 		netdev_dbg(dev, "no route to %pI6\n", &fl6->daddr);
 		return ERR_PTR(-ENETUNREACH);
 	}
diff -druNp --no-dereference linux-libre-4.4.223-gnu/drivers/net/phy/dp83640.c linux-libre-4.4.224-gnu/drivers/net/phy/dp83640.c
--- linux-libre-4.4.223-gnu/drivers/net/phy/dp83640.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/drivers/net/phy/dp83640.c	2020-05-20 02:11:57.000000000 -0400
@@ -1107,7 +1107,7 @@ static struct dp83640_clock *dp83640_clo
 		goto out;
 	}
 	dp83640_clock_init(clock, bus);
-	list_add_tail(&phyter_clocks, &clock->list);
+	list_add_tail(&clock->list, &phyter_clocks);
 out:
 	mutex_unlock(&phyter_clocks_lock);
 
diff -druNp --no-dereference linux-libre-4.4.223-gnu/drivers/net/phy/micrel.c linux-libre-4.4.224-gnu/drivers/net/phy/micrel.c
--- linux-libre-4.4.223-gnu/drivers/net/phy/micrel.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/drivers/net/phy/micrel.c	2020-05-20 02:11:57.000000000 -0400
@@ -592,6 +592,21 @@ ksz9021_wr_mmd_phyreg(struct phy_device
 {
 }
 
+static int kszphy_resume(struct phy_device *phydev)
+{
+	int value;
+
+	mutex_lock(&phydev->lock);
+
+	value = phy_read(phydev, MII_BMCR);
+	phy_write(phydev, MII_BMCR, value & ~BMCR_PDOWN);
+
+	kszphy_config_intr(phydev);
+	mutex_unlock(&phydev->lock);
+
+	return 0;
+}
+
 static int kszphy_probe(struct phy_device *phydev)
 {
 	const struct kszphy_type *type = phydev->drv->driver_data;
@@ -783,7 +798,7 @@ static struct phy_driver ksphy_driver[]
 	.ack_interrupt	= kszphy_ack_interrupt,
 	.config_intr	= kszphy_config_intr,
 	.suspend	= genphy_suspend,
-	.resume		= genphy_resume,
+	.resume		= kszphy_resume,
 	.driver		= { .owner = THIS_MODULE,},
 }, {
 	.phy_id		= PHY_ID_KSZ8061,
diff -druNp --no-dereference linux-libre-4.4.223-gnu/drivers/net/phy/phy.c linux-libre-4.4.224-gnu/drivers/net/phy/phy.c
--- linux-libre-4.4.223-gnu/drivers/net/phy/phy.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/drivers/net/phy/phy.c	2020-05-20 02:11:57.000000000 -0400
@@ -916,10 +916,10 @@ void phy_state_machine(struct work_struc
 		phydev->adjust_link(phydev->attached_dev);
 		break;
 	case PHY_RUNNING:
-		/* Only register a CHANGE if we are polling and link changed
-		 * since latest checking.
+		/* Only register a CHANGE if we are polling or ignoring
+		 * interrupts and link changed since latest checking.
 		 */
-		if (phydev->irq == PHY_POLL) {
+		if (!phy_interrupt_is_valid(phydev)) {
 			old_link = phydev->link;
 			err = phy_read_status(phydev);
 			if (err)
@@ -1019,13 +1019,8 @@ void phy_state_machine(struct work_struc
 	dev_dbg(&phydev->dev, "PHY state change %s -> %s\n",
 		phy_state_to_str(old_state), phy_state_to_str(phydev->state));
 
-	/* Only re-schedule a PHY state machine change if we are polling the
-	 * PHY, if PHY_IGNORE_INTERRUPT is set, then we will be moving
-	 * between states from phy_mac_interrupt()
-	 */
-	if (phydev->irq == PHY_POLL)
-		queue_delayed_work(system_power_efficient_wq, &phydev->state_queue,
-				   PHY_STATE_TIME * HZ);
+	queue_delayed_work(system_power_efficient_wq, &phydev->state_queue,
+			   PHY_STATE_TIME * HZ);
 }
 
 void phy_mac_interrupt(struct phy_device *phydev, int new_link)
diff -druNp --no-dereference linux-libre-4.4.223-gnu/drivers/net/vxlan.c linux-libre-4.4.224-gnu/drivers/net/vxlan.c
--- linux-libre-4.4.223-gnu/drivers/net/vxlan.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/drivers/net/vxlan.c	2020-05-20 02:11:57.000000000 -0400
@@ -1864,7 +1864,6 @@ static struct dst_entry *vxlan6_get_rout
 {
 	struct dst_entry *ndst;
 	struct flowi6 fl6;
-	int err;
 
 	memset(&fl6, 0, sizeof(fl6));
 	fl6.flowi6_oif = oif;
@@ -1873,11 +1872,10 @@ static struct dst_entry *vxlan6_get_rout
 	fl6.flowi6_mark = skb->mark;
 	fl6.flowi6_proto = IPPROTO_UDP;
 
-	err = ipv6_stub->ipv6_dst_lookup(vxlan->net,
-					 vxlan->vn6_sock->sock->sk,
-					 &ndst, &fl6);
-	if (err < 0)
-		return ERR_PTR(err);
+	ndst = ipv6_stub->ipv6_dst_lookup_flow(vxlan->net, vxlan->vn6_sock->sock->sk,
+					       &fl6, NULL);
+	if (unlikely(IS_ERR(ndst)))
+		return ERR_PTR(-ENETUNREACH);
 
 	*saddr = fl6.saddr;
 	return ndst;
diff -druNp --no-dereference linux-libre-4.4.223-gnu/drivers/ptp/ptp_clock.c linux-libre-4.4.224-gnu/drivers/ptp/ptp_clock.c
--- linux-libre-4.4.223-gnu/drivers/ptp/ptp_clock.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/drivers/ptp/ptp_clock.c	2020-05-20 02:11:57.000000000 -0400
@@ -171,10 +171,11 @@ static struct posix_clock_operations ptp
 	.read		= ptp_read,
 };
 
-static void delete_ptp_clock(struct posix_clock *pc)
+static void ptp_clock_release(struct device *dev)
 {
-	struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
+	struct ptp_clock *ptp = container_of(dev, struct ptp_clock, dev);
 
+	ptp_cleanup_pin_groups(ptp);
 	mutex_destroy(&ptp->tsevq_mux);
 	mutex_destroy(&ptp->pincfg_mux);
 	ida_simple_remove(&ptp_clocks_map, ptp->index);
@@ -205,7 +206,6 @@ struct ptp_clock *ptp_clock_register(str
 	}
 
 	ptp->clock.ops = ptp_clock_ops;
-	ptp->clock.release = delete_ptp_clock;
 	ptp->info = info;
 	ptp->devid = MKDEV(major, index);
 	ptp->index = index;
@@ -214,17 +214,9 @@ struct ptp_clock *ptp_clock_register(str
 	mutex_init(&ptp->pincfg_mux);
 	init_waitqueue_head(&ptp->tsev_wq);
 
-	/* Create a new device in our class. */
-	ptp->dev = device_create(ptp_class, parent, ptp->devid, ptp,
-				 "ptp%d", ptp->index);
-	if (IS_ERR(ptp->dev))
-		goto no_device;
-
-	dev_set_drvdata(ptp->dev, ptp);
-
-	err = ptp_populate_sysfs(ptp);
+	err = ptp_populate_pin_groups(ptp);
 	if (err)
-		goto no_sysfs;
+		goto no_pin_groups;
 
 	/* Register a new PPS source. */
 	if (info->pps) {
@@ -235,13 +227,24 @@ struct ptp_clock *ptp_clock_register(str
 		pps.owner = info->owner;
 		ptp->pps_source = pps_register_source(&pps, PTP_PPS_DEFAULTS);
 		if (!ptp->pps_source) {
+			err = -EINVAL;
 			pr_err("failed to register pps source\n");
 			goto no_pps;
 		}
 	}
 
-	/* Create a posix clock. */
-	err = posix_clock_register(&ptp->clock, ptp->devid);
+	/* Initialize a new device of our class in our clock structure. */
+	device_initialize(&ptp->dev);
+	ptp->dev.devt = ptp->devid;
+	ptp->dev.class = ptp_class;
+	ptp->dev.parent = parent;
+	ptp->dev.groups = ptp->pin_attr_groups;
+	ptp->dev.release = ptp_clock_release;
+	dev_set_drvdata(&ptp->dev, ptp);
+	dev_set_name(&ptp->dev, "ptp%d", ptp->index);
+
+	/* Create a posix clock and link it to the device. */
+	err = posix_clock_register(&ptp->clock, &ptp->dev);
 	if (err) {
 		pr_err("failed to create posix clock\n");
 		goto no_clock;
@@ -253,10 +256,8 @@ no_clock:
 	if (ptp->pps_source)
 		pps_unregister_source(ptp->pps_source);
 no_pps:
-	ptp_cleanup_sysfs(ptp);
-no_sysfs:
-	device_destroy(ptp_class, ptp->devid);
-no_device:
+	ptp_cleanup_pin_groups(ptp);
+no_pin_groups:
 	mutex_destroy(&ptp->tsevq_mux);
 	mutex_destroy(&ptp->pincfg_mux);
 no_slot:
@@ -274,10 +275,9 @@ int ptp_clock_unregister(struct ptp_cloc
 	/* Release the clock's resources. */
 	if (ptp->pps_source)
 		pps_unregister_source(ptp->pps_source);
-	ptp_cleanup_sysfs(ptp);
-	device_destroy(ptp_class, ptp->devid);
 
 	posix_clock_unregister(&ptp->clock);
+
 	return 0;
 }
 EXPORT_SYMBOL(ptp_clock_unregister);
diff -druNp --no-dereference linux-libre-4.4.223-gnu/drivers/ptp/ptp_private.h linux-libre-4.4.224-gnu/drivers/ptp/ptp_private.h
--- linux-libre-4.4.223-gnu/drivers/ptp/ptp_private.h	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/drivers/ptp/ptp_private.h	2020-05-20 02:11:57.000000000 -0400
@@ -40,7 +40,7 @@ struct timestamp_event_queue {
 
 struct ptp_clock {
 	struct posix_clock clock;
-	struct device *dev;
+	struct device dev;
 	struct ptp_clock_info *info;
 	dev_t devid;
 	int index; /* index into clocks.map */
@@ -54,6 +54,8 @@ struct ptp_clock {
 	struct device_attribute *pin_dev_attr;
 	struct attribute **pin_attr;
 	struct attribute_group pin_attr_group;
+	/* 1st entry is a pointer to the real group, 2nd is NULL terminator */
+	const struct attribute_group *pin_attr_groups[2];
 };
 
 /*
@@ -94,8 +96,7 @@ uint ptp_poll(struct posix_clock *pc,
 
 extern const struct attribute_group *ptp_groups[];
 
-int ptp_cleanup_sysfs(struct ptp_clock *ptp);
-
-int ptp_populate_sysfs(struct ptp_clock *ptp);
+int ptp_populate_pin_groups(struct ptp_clock *ptp);
+void ptp_cleanup_pin_groups(struct ptp_clock *ptp);
 
 #endif
diff -druNp --no-dereference linux-libre-4.4.223-gnu/drivers/ptp/ptp_sysfs.c linux-libre-4.4.224-gnu/drivers/ptp/ptp_sysfs.c
--- linux-libre-4.4.223-gnu/drivers/ptp/ptp_sysfs.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/drivers/ptp/ptp_sysfs.c	2020-05-20 02:11:57.000000000 -0400
@@ -46,27 +46,6 @@ PTP_SHOW_INT(n_periodic_outputs, n_per_o
 PTP_SHOW_INT(n_programmable_pins, n_pins);
 PTP_SHOW_INT(pps_available, pps);
 
-static struct attribute *ptp_attrs[] = {
-	&dev_attr_clock_name.attr,
-	&dev_attr_max_adjustment.attr,
-	&dev_attr_n_alarms.attr,
-	&dev_attr_n_external_timestamps.attr,
-	&dev_attr_n_periodic_outputs.attr,
-	&dev_attr_n_programmable_pins.attr,
-	&dev_attr_pps_available.attr,
-	NULL,
-};
-
-static const struct attribute_group ptp_group = {
-	.attrs = ptp_attrs,
-};
-
-const struct attribute_group *ptp_groups[] = {
-	&ptp_group,
-	NULL,
-};
-
-
 static ssize_t extts_enable_store(struct device *dev,
 				  struct device_attribute *attr,
 				  const char *buf, size_t count)
@@ -91,6 +70,7 @@ static ssize_t extts_enable_store(struct
 out:
 	return err;
 }
+static DEVICE_ATTR(extts_enable, 0220, NULL, extts_enable_store);
 
 static ssize_t extts_fifo_show(struct device *dev,
 			       struct device_attribute *attr, char *page)
@@ -124,6 +104,7 @@ out:
 	mutex_unlock(&ptp->tsevq_mux);
 	return cnt;
 }
+static DEVICE_ATTR(fifo, 0444, extts_fifo_show, NULL);
 
 static ssize_t period_store(struct device *dev,
 			    struct device_attribute *attr,
@@ -151,6 +132,7 @@ static ssize_t period_store(struct devic
 out:
 	return err;
 }
+static DEVICE_ATTR(period, 0220, NULL, period_store);
 
 static ssize_t pps_enable_store(struct device *dev,
 				struct device_attribute *attr,
@@ -177,6 +159,57 @@ static ssize_t pps_enable_store(struct d
 out:
 	return err;
 }
+static DEVICE_ATTR(pps_enable, 0220, NULL, pps_enable_store);
+
+static struct attribute *ptp_attrs[] = {
+	&dev_attr_clock_name.attr,
+
+	&dev_attr_max_adjustment.attr,
+	&dev_attr_n_alarms.attr,
+	&dev_attr_n_external_timestamps.attr,
+	&dev_attr_n_periodic_outputs.attr,
+	&dev_attr_n_programmable_pins.attr,
+	&dev_attr_pps_available.attr,
+
+	&dev_attr_extts_enable.attr,
+	&dev_attr_fifo.attr,
+	&dev_attr_period.attr,
+	&dev_attr_pps_enable.attr,
+	NULL
+};
+
+static umode_t ptp_is_attribute_visible(struct kobject *kobj,
+					struct attribute *attr, int n)
+{
+	struct device *dev = kobj_to_dev(kobj);
+	struct ptp_clock *ptp = dev_get_drvdata(dev);
+	struct ptp_clock_info *info = ptp->info;
+	umode_t mode = attr->mode;
+
+	if (attr == &dev_attr_extts_enable.attr ||
+	    attr == &dev_attr_fifo.attr) {
+		if (!info->n_ext_ts)
+			mode = 0;
+	} else if (attr == &dev_attr_period.attr) {
+		if (!info->n_per_out)
+			mode = 0;
+	} else if (attr == &dev_attr_pps_enable.attr) {
+		if (!info->pps)
+			mode = 0;
+	}
+
+	return mode;
+}
+
+static const struct attribute_group ptp_group = {
+	.is_visible	= ptp_is_attribute_visible,
+	.attrs		= ptp_attrs,
+};
+
+const struct attribute_group *ptp_groups[] = {
+	&ptp_group,
+	NULL
+};
 
 static int ptp_pin_name2index(struct ptp_clock *ptp, const char *name)
 {
@@ -235,40 +268,14 @@ static ssize_t ptp_pin_store(struct devi
 	return count;
 }
 
-static DEVICE_ATTR(extts_enable, 0220, NULL, extts_enable_store);
-static DEVICE_ATTR(fifo,         0444, extts_fifo_show, NULL);
-static DEVICE_ATTR(period,       0220, NULL, period_store);
-static DEVICE_ATTR(pps_enable,   0220, NULL, pps_enable_store);
-
-int ptp_cleanup_sysfs(struct ptp_clock *ptp)
-{
-	struct device *dev = ptp->dev;
-	struct ptp_clock_info *info = ptp->info;
-
-	if (info->n_ext_ts) {
-		device_remove_file(dev, &dev_attr_extts_enable);
-		device_remove_file(dev, &dev_attr_fifo);
-	}
-	if (info->n_per_out)
-		device_remove_file(dev, &dev_attr_period);
-
-	if (info->pps)
-		device_remove_file(dev, &dev_attr_pps_enable);
-
-	if (info->n_pins) {
-		sysfs_remove_group(&dev->kobj, &ptp->pin_attr_group);
-		kfree(ptp->pin_attr);
-		kfree(ptp->pin_dev_attr);
-	}
-	return 0;
-}
-
-static int ptp_populate_pins(struct ptp_clock *ptp)
+int ptp_populate_pin_groups(struct ptp_clock *ptp)
 {
-	struct device *dev = ptp->dev;
 	struct ptp_clock_info *info = ptp->info;
 	int err = -ENOMEM, i, n_pins = info->n_pins;
 
+	if (!n_pins)
+		return 0;
+
 	ptp->pin_dev_attr = kzalloc(n_pins * sizeof(*ptp->pin_dev_attr),
 				    GFP_KERNEL);
 	if (!ptp->pin_dev_attr)
@@ -292,61 +299,18 @@ static int ptp_populate_pins(struct ptp_
 	ptp->pin_attr_group.name = "pins";
 	ptp->pin_attr_group.attrs = ptp->pin_attr;
 
-	err = sysfs_create_group(&dev->kobj, &ptp->pin_attr_group);
-	if (err)
-		goto no_group;
+	ptp->pin_attr_groups[0] = &ptp->pin_attr_group;
+
 	return 0;
 
-no_group:
-	kfree(ptp->pin_attr);
 no_pin_attr:
 	kfree(ptp->pin_dev_attr);
 no_dev_attr:
 	return err;
 }
 
-int ptp_populate_sysfs(struct ptp_clock *ptp)
+void ptp_cleanup_pin_groups(struct ptp_clock *ptp)
 {
-	struct device *dev = ptp->dev;
-	struct ptp_clock_info *info = ptp->info;
-	int err;
-
-	if (info->n_ext_ts) {
-		err = device_create_file(dev, &dev_attr_extts_enable);
-		if (err)
-			goto out1;
-		err = device_create_file(dev, &dev_attr_fifo);
-		if (err)
-			goto out2;
-	}
-	if (info->n_per_out) {
-		err = device_create_file(dev, &dev_attr_period);
-		if (err)
-			goto out3;
-	}
-	if (info->pps) {
-		err = device_create_file(dev, &dev_attr_pps_enable);
-		if (err)
-			goto out4;
-	}
-	if (info->n_pins) {
-		err = ptp_populate_pins(ptp);
-		if (err)
-			goto out5;
-	}
-	return 0;
-out5:
-	if (info->pps)
-		device_remove_file(dev, &dev_attr_pps_enable);
-out4:
-	if (info->n_per_out)
-		device_remove_file(dev, &dev_attr_period);
-out3:
-	if (info->n_ext_ts)
-		device_remove_file(dev, &dev_attr_fifo);
-out2:
-	if (info->n_ext_ts)
-		device_remove_file(dev, &dev_attr_extts_enable);
-out1:
-	return err;
+	kfree(ptp->pin_attr);
+	kfree(ptp->pin_dev_attr);
 }
diff -druNp --no-dereference linux-libre-4.4.223-gnu/drivers/scsi/libiscsi.c linux-libre-4.4.224-gnu/drivers/scsi/libiscsi.c
--- linux-libre-4.4.223-gnu/drivers/scsi/libiscsi.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/drivers/scsi/libiscsi.c	2020-05-20 02:11:57.000000000 -0400
@@ -1982,7 +1982,7 @@ static enum blk_eh_timer_return iscsi_eh
 
 	ISCSI_DBG_EH(session, "scsi cmd %p timedout\n", sc);
 
-	spin_lock(&session->frwd_lock);
+	spin_lock_bh(&session->frwd_lock);
 	task = (struct iscsi_task *)sc->SCp.ptr;
 	if (!task) {
 		/*
@@ -2109,7 +2109,7 @@ static enum blk_eh_timer_return iscsi_eh
 done:
 	if (task)
 		task->last_timeout = jiffies;
-	spin_unlock(&session->frwd_lock);
+	spin_unlock_bh(&session->frwd_lock);
 	ISCSI_DBG_EH(session, "return %s\n", rc == BLK_EH_RESET_TIMER ?
 		     "timer reset" : "shutdown or nh");
 	return rc;
diff -druNp --no-dereference linux-libre-4.4.223-gnu/drivers/scsi/qla2xxx/qla_init.c linux-libre-4.4.224-gnu/drivers/scsi/qla2xxx/qla_init.c
--- linux-libre-4.4.223-gnu/drivers/scsi/qla2xxx/qla_init.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/drivers/scsi/qla2xxx/qla_init.c	2020-05-20 02:11:57.000000000 -0400
@@ -364,8 +364,8 @@ qla24xx_abort_sp_done(void *data, void *
 	srb_t *sp = (srb_t *)ptr;
 	struct srb_iocb *abt = &sp->u.iocb_cmd;
 
-	del_timer(&sp->u.iocb_cmd.timer);
-	complete(&abt->u.abt.comp);
+	if (del_timer(&sp->u.iocb_cmd.timer))
+		complete(&abt->u.abt.comp);
 }
 
 static int
diff -druNp --no-dereference linux-libre-4.4.223-gnu/drivers/scsi/sg.c linux-libre-4.4.224-gnu/drivers/scsi/sg.c
--- linux-libre-4.4.223-gnu/drivers/scsi/sg.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/drivers/scsi/sg.c	2020-05-20 02:11:57.000000000 -0400
@@ -706,8 +706,10 @@ sg_write(struct file *filp, const char _
 	hp->flags = input_size;	/* structure abuse ... */
 	hp->pack_id = old_hdr.pack_id;
 	hp->usr_ptr = NULL;
-	if (__copy_from_user(cmnd, buf, cmd_size))
+	if (__copy_from_user(cmnd, buf, cmd_size)) {
+		sg_remove_request(sfp, srp);
 		return -EFAULT;
+	}
 	/*
 	 * SG_DXFER_TO_FROM_DEV is functionally equivalent to SG_DXFER_FROM_DEV,
 	 * but is is possible that the app intended SG_DXFER_TO_DEV, because there
diff -druNp --no-dereference linux-libre-4.4.223-gnu/drivers/spi/spi-dw.c linux-libre-4.4.224-gnu/drivers/spi/spi-dw.c
--- linux-libre-4.4.223-gnu/drivers/spi/spi-dw.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/drivers/spi/spi-dw.c	2020-05-20 02:11:57.000000000 -0400
@@ -180,9 +180,11 @@ static inline u32 rx_max(struct dw_spi *
 
 static void dw_writer(struct dw_spi *dws)
 {
-	u32 max = tx_max(dws);
+	u32 max;
 	u16 txw = 0;
 
+	spin_lock(&dws->buf_lock);
+	max = tx_max(dws);
 	while (max--) {
 		/* Set the tx word if the transfer's original "tx" is not null */
 		if (dws->tx_end - dws->len) {
@@ -194,13 +196,16 @@ static void dw_writer(struct dw_spi *dws
 		dw_write_io_reg(dws, DW_SPI_DR, txw);
 		dws->tx += dws->n_bytes;
 	}
+	spin_unlock(&dws->buf_lock);
 }
 
 static void dw_reader(struct dw_spi *dws)
 {
-	u32 max = rx_max(dws);
+	u32 max;
 	u16 rxw;
 
+	spin_lock(&dws->buf_lock);
+	max = rx_max(dws);
 	while (max--) {
 		rxw = dw_read_io_reg(dws, DW_SPI_DR);
 		/* Care rx only if the transfer's original "rx" is not null */
@@ -212,6 +217,7 @@ static void dw_reader(struct dw_spi *dws
 		}
 		dws->rx += dws->n_bytes;
 	}
+	spin_unlock(&dws->buf_lock);
 }
 
 static void int_error_stop(struct dw_spi *dws, const char *msg)
@@ -284,6 +290,7 @@ static int dw_spi_transfer_one(struct sp
 {
 	struct dw_spi *dws = spi_master_get_devdata(master);
 	struct chip_data *chip = spi_get_ctldata(spi);
+	unsigned long flags;
 	u8 imask = 0;
 	u16 txlevel = 0;
 	u16 clk_div;
@@ -291,12 +298,13 @@ static int dw_spi_transfer_one(struct sp
 	int ret;
 
 	dws->dma_mapped = 0;
-
+	spin_lock_irqsave(&dws->buf_lock, flags);
 	dws->tx = (void *)transfer->tx_buf;
 	dws->tx_end = dws->tx + transfer->len;
 	dws->rx = transfer->rx_buf;
 	dws->rx_end = dws->rx + transfer->len;
 	dws->len = transfer->len;
+	spin_unlock_irqrestore(&dws->buf_lock, flags);
 
 	spi_enable_chip(dws, 0);
 
@@ -488,6 +496,7 @@ int dw_spi_add_host(struct device *dev,
 	dws->dma_inited = 0;
 	dws->dma_addr = (dma_addr_t)(dws->paddr + DW_SPI_DR);
 	snprintf(dws->name, sizeof(dws->name), "dw_spi%d", dws->bus_num);
+	spin_lock_init(&dws->buf_lock);
 
 	ret = request_irq(dws->irq, dw_spi_irq, IRQF_SHARED, dws->name, master);
 	if (ret < 0) {
diff -druNp --no-dereference linux-libre-4.4.223-gnu/drivers/spi/spi-dw.h linux-libre-4.4.224-gnu/drivers/spi/spi-dw.h
--- linux-libre-4.4.223-gnu/drivers/spi/spi-dw.h	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/drivers/spi/spi-dw.h	2020-05-20 02:11:57.000000000 -0400
@@ -117,6 +117,7 @@ struct dw_spi {
 	size_t			len;
 	void			*tx;
 	void			*tx_end;
+	spinlock_t		buf_lock;
 	void			*rx;
 	void			*rx_end;
 	int			dma_mapped;
diff -druNp --no-dereference linux-libre-4.4.223-gnu/drivers/usb/gadget/configfs.c linux-libre-4.4.224-gnu/drivers/usb/gadget/configfs.c
--- linux-libre-4.4.223-gnu/drivers/usb/gadget/configfs.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/drivers/usb/gadget/configfs.c	2020-05-20 02:11:57.000000000 -0400
@@ -260,6 +260,9 @@ static ssize_t gadget_dev_desc_UDC_store
 	char *name;
 	int ret;
 
+	if (strlen(page) < len)
+		return -EOVERFLOW;
+
 	name = kstrdup(page, GFP_KERNEL);
 	if (!name)
 		return -ENOMEM;
diff -druNp --no-dereference linux-libre-4.4.223-gnu/drivers/usb/gadget/legacy/audio.c linux-libre-4.4.224-gnu/drivers/usb/gadget/legacy/audio.c
--- linux-libre-4.4.223-gnu/drivers/usb/gadget/legacy/audio.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/drivers/usb/gadget/legacy/audio.c	2020-05-20 02:11:57.000000000 -0400
@@ -249,8 +249,10 @@ static int audio_bind(struct usb_composi
 		struct usb_descriptor_header *usb_desc;
 
 		usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
-		if (!usb_desc)
+		if (!usb_desc) {
+			status = -ENOMEM;
 			goto fail;
+		}
 		usb_otg_descriptor_init(cdev->gadget, usb_desc);
 		otg_desc[0] = usb_desc;
 		otg_desc[1] = NULL;
diff -druNp --no-dereference linux-libre-4.4.223-gnu/drivers/usb/gadget/legacy/cdc2.c linux-libre-4.4.224-gnu/drivers/usb/gadget/legacy/cdc2.c
--- linux-libre-4.4.223-gnu/drivers/usb/gadget/legacy/cdc2.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/drivers/usb/gadget/legacy/cdc2.c	2020-05-20 02:11:57.000000000 -0400
@@ -183,8 +183,10 @@ static int cdc_bind(struct usb_composite
 		struct usb_descriptor_header *usb_desc;
 
 		usb_desc = usb_otg_descriptor_alloc(gadget);
-		if (!usb_desc)
+		if (!usb_desc) {
+			status = -ENOMEM;
 			goto fail1;
+		}
 		usb_otg_descriptor_init(gadget, usb_desc);
 		otg_desc[0] = usb_desc;
 		otg_desc[1] = NULL;
diff -druNp --no-dereference linux-libre-4.4.223-gnu/drivers/usb/gadget/legacy/ncm.c linux-libre-4.4.224-gnu/drivers/usb/gadget/legacy/ncm.c
--- linux-libre-4.4.223-gnu/drivers/usb/gadget/legacy/ncm.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/drivers/usb/gadget/legacy/ncm.c	2020-05-20 02:11:57.000000000 -0400
@@ -162,8 +162,10 @@ static int gncm_bind(struct usb_composit
 		struct usb_descriptor_header *usb_desc;
 
 		usb_desc = usb_otg_descriptor_alloc(gadget);
-		if (!usb_desc)
+		if (!usb_desc) {
+			status = -ENOMEM;
 			goto fail;
+		}
 		usb_otg_descriptor_init(gadget, usb_desc);
 		otg_desc[0] = usb_desc;
 		otg_desc[1] = NULL;
diff -druNp --no-dereference linux-libre-4.4.223-gnu/drivers/usb/gadget/udc/net2272.c linux-libre-4.4.224-gnu/drivers/usb/gadget/udc/net2272.c
--- linux-libre-4.4.223-gnu/drivers/usb/gadget/udc/net2272.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/drivers/usb/gadget/udc/net2272.c	2020-05-20 02:11:57.000000000 -0400
@@ -2670,6 +2670,8 @@ net2272_plat_probe(struct platform_devic
  err_req:
 	release_mem_region(base, len);
  err:
+	kfree(dev);
+
 	return ret;
 }
 
diff -druNp --no-dereference linux-libre-4.4.223-gnu/drivers/usb/serial/garmin_gps.c linux-libre-4.4.224-gnu/drivers/usb/serial/garmin_gps.c
--- linux-libre-4.4.223-gnu/drivers/usb/serial/garmin_gps.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/drivers/usb/serial/garmin_gps.c	2020-05-20 02:11:57.000000000 -0400
@@ -1162,8 +1162,8 @@ static void garmin_read_process(struct g
 		   send it directly to the tty port */
 		if (garmin_data_p->flags & FLAGS_QUEUING) {
 			pkt_add(garmin_data_p, data, data_length);
-		} else if (bulk_data ||
-			   getLayerId(data) == GARMIN_LAYERID_APPL) {
+		} else if (bulk_data || (data_length >= sizeof(u32) &&
+				getLayerId(data) == GARMIN_LAYERID_APPL)) {
 
 			spin_lock_irqsave(&garmin_data_p->lock, flags);
 			garmin_data_p->flags |= APP_RESP_SEEN;
diff -druNp --no-dereference linux-libre-4.4.223-gnu/drivers/usb/serial/qcserial.c linux-libre-4.4.224-gnu/drivers/usb/serial/qcserial.c
--- linux-libre-4.4.223-gnu/drivers/usb/serial/qcserial.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/drivers/usb/serial/qcserial.c	2020-05-20 02:11:57.000000000 -0400
@@ -177,6 +177,7 @@ static const struct usb_device_id id_tab
 	{DEVICE_SWI(0x413c, 0x81b3)},	/* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card (rev3) */
 	{DEVICE_SWI(0x413c, 0x81b5)},	/* Dell Wireless 5811e QDL */
 	{DEVICE_SWI(0x413c, 0x81b6)},	/* Dell Wireless 5811e QDL */
+	{DEVICE_SWI(0x413c, 0x81cc)},	/* Dell Wireless 5816e */
 	{DEVICE_SWI(0x413c, 0x81cf)},   /* Dell Wireless 5819 */
 	{DEVICE_SWI(0x413c, 0x81d0)},   /* Dell Wireless 5819 */
 	{DEVICE_SWI(0x413c, 0x81d1)},   /* Dell Wireless 5818 */
diff -druNp --no-dereference linux-libre-4.4.223-gnu/drivers/usb/storage/unusual_uas.h linux-libre-4.4.224-gnu/drivers/usb/storage/unusual_uas.h
--- linux-libre-4.4.223-gnu/drivers/usb/storage/unusual_uas.h	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/drivers/usb/storage/unusual_uas.h	2020-05-20 02:11:57.000000000 -0400
@@ -40,6 +40,13 @@
  * and don't forget to CC: the USB development list <linux-usb@vger.kernel.org>
  */
 
+/* Reported-by: Julian Groß <julian.g@posteo.de> */
+UNUSUAL_DEV(0x059f, 0x105f, 0x0000, 0x9999,
+		"LaCie",
+		"2Big Quadra USB3",
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+		US_FL_NO_REPORT_OPCODES),
+
 /*
  * Apricorn USB3 dongle sometimes returns "USBSUSBSUSBS" in response to SCSI
  * commands in UAS mode.  Observed with the 1.28 firmware; are there others?
diff -druNp --no-dereference linux-libre-4.4.223-gnu/fs/binfmt_elf.c linux-libre-4.4.224-gnu/fs/binfmt_elf.c
--- linux-libre-4.4.223-gnu/fs/binfmt_elf.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/fs/binfmt_elf.c	2020-05-20 02:11:57.000000000 -0400
@@ -1097,6 +1097,18 @@ static int load_elf_binary(struct linux_
 	current->mm->start_stack = bprm->p;
 
 	if ((current->flags & PF_RANDOMIZE) && (randomize_va_space > 1)) {
+		/*
+		 * For architectures with ELF randomization, when executing
+		 * a loader directly (i.e. no interpreter listed in ELF
+		 * headers), move the brk area out of the mmap region
+		 * (since it grows up, and may collide early with the stack
+		 * growing down), and into the unused ELF_ET_DYN_BASE region.
+		 */
+		if (IS_ENABLED(CONFIG_ARCH_HAS_ELF_RANDOMIZE) &&
+		    loc->elf_ex.e_type == ET_DYN && !interpreter)
+			current->mm->brk = current->mm->start_brk =
+				ELF_ET_DYN_BASE;
+
 		current->mm->brk = current->mm->start_brk =
 			arch_randomize_brk(current->mm);
 #ifdef compat_brk_randomized
diff -druNp --no-dereference linux-libre-4.4.223-gnu/fs/char_dev.c linux-libre-4.4.224-gnu/fs/char_dev.c
--- linux-libre-4.4.223-gnu/fs/char_dev.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/fs/char_dev.c	2020-05-20 02:11:57.000000000 -0400
@@ -472,6 +472,85 @@ int cdev_add(struct cdev *p, dev_t dev,
 	return 0;
 }
 
+/**
+ * cdev_set_parent() - set the parent kobject for a char device
+ * @p: the cdev structure
+ * @kobj: the kobject to take a reference to
+ *
+ * cdev_set_parent() sets a parent kobject which will be referenced
+ * appropriately so the parent is not freed before the cdev. This
+ * should be called before cdev_add.
+ */
+void cdev_set_parent(struct cdev *p, struct kobject *kobj)
+{
+	WARN_ON(!kobj->state_initialized);
+	p->kobj.parent = kobj;
+}
+
+/**
+ * cdev_device_add() - add a char device and it's corresponding
+ *	struct device, linkink
+ * @dev: the device structure
+ * @cdev: the cdev structure
+ *
+ * cdev_device_add() adds the char device represented by @cdev to the system,
+ * just as cdev_add does. It then adds @dev to the system using device_add
+ * The dev_t for the char device will be taken from the struct device which
+ * needs to be initialized first. This helper function correctly takes a
+ * reference to the parent device so the parent will not get released until
+ * all references to the cdev are released.
+ *
+ * This helper uses dev->devt for the device number. If it is not set
+ * it will not add the cdev and it will be equivalent to device_add.
+ *
+ * This function should be used whenever the struct cdev and the
+ * struct device are members of the same structure whose lifetime is
+ * managed by the struct device.
+ *
+ * NOTE: Callers must assume that userspace was able to open the cdev and
+ * can call cdev fops callbacks at any time, even if this function fails.
+ */
+int cdev_device_add(struct cdev *cdev, struct device *dev)
+{
+	int rc = 0;
+
+	if (dev->devt) {
+		cdev_set_parent(cdev, &dev->kobj);
+
+		rc = cdev_add(cdev, dev->devt, 1);
+		if (rc)
+			return rc;
+	}
+
+	rc = device_add(dev);
+	if (rc)
+		cdev_del(cdev);
+
+	return rc;
+}
+
+/**
+ * cdev_device_del() - inverse of cdev_device_add
+ * @dev: the device structure
+ * @cdev: the cdev structure
+ *
+ * cdev_device_del() is a helper function to call cdev_del and device_del.
+ * It should be used whenever cdev_device_add is used.
+ *
+ * If dev->devt is not set it will not remove the cdev and will be equivalent
+ * to device_del.
+ *
+ * NOTE: This guarantees that associated sysfs callbacks are not running
+ * or runnable, however any cdevs already open will remain and their fops
+ * will still be callable even after this function returns.
+ */
+void cdev_device_del(struct cdev *cdev, struct device *dev)
+{
+	device_del(dev);
+	if (dev->devt)
+		cdev_del(cdev);
+}
+
 static void cdev_unmap(dev_t dev, unsigned count)
 {
 	kobj_unmap(cdev_map, dev, count);
@@ -483,6 +562,10 @@ static void cdev_unmap(dev_t dev, unsign
  *
  * cdev_del() removes @p from the system, possibly freeing the structure
  * itself.
+ *
+ * NOTE: This guarantees that cdev device will no longer be able to be
+ * opened, however any cdevs already open will remain and their fops will
+ * still be callable even after cdev_del returns.
  */
 void cdev_del(struct cdev *p)
 {
@@ -571,5 +654,8 @@ EXPORT_SYMBOL(cdev_init);
 EXPORT_SYMBOL(cdev_alloc);
 EXPORT_SYMBOL(cdev_del);
 EXPORT_SYMBOL(cdev_add);
+EXPORT_SYMBOL(cdev_set_parent);
+EXPORT_SYMBOL(cdev_device_add);
+EXPORT_SYMBOL(cdev_device_del);
 EXPORT_SYMBOL(__register_chrdev);
 EXPORT_SYMBOL(__unregister_chrdev);
diff -druNp --no-dereference linux-libre-4.4.223-gnu/fs/cifs/cifssmb.c linux-libre-4.4.224-gnu/fs/cifs/cifssmb.c
--- linux-libre-4.4.223-gnu/fs/cifs/cifssmb.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/fs/cifs/cifssmb.c	2020-05-20 02:11:57.000000000 -0400
@@ -184,6 +184,18 @@ cifs_reconnect_tcon(struct cifs_tcon *tc
 	 * reconnect the same SMB session
 	 */
 	mutex_lock(&ses->session_mutex);
+
+	/*
+	 * Recheck after acquire mutex. If another thread is negotiating
+	 * and the server never sends an answer the socket will be closed
+	 * and tcpStatus set to reconnect.
+	 */
+	if (server->tcpStatus == CifsNeedReconnect) {
+		rc = -EHOSTDOWN;
+		mutex_unlock(&ses->session_mutex);
+		goto out;
+	}
+
 	rc = cifs_negotiate_protocol(0, ses);
 	if (rc == 0 && ses->need_reconnect)
 		rc = cifs_setup_session(0, ses, nls_codepage);
diff -druNp --no-dereference linux-libre-4.4.223-gnu/fs/cifs/connect.c linux-libre-4.4.224-gnu/fs/cifs/connect.c
--- linux-libre-4.4.223-gnu/fs/cifs/connect.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/fs/cifs/connect.c	2020-05-20 02:11:57.000000000 -0400
@@ -548,20 +548,21 @@ static bool
 server_unresponsive(struct TCP_Server_Info *server)
 {
 	/*
-	 * We need to wait 2 echo intervals to make sure we handle such
+	 * We need to wait 3 echo intervals to make sure we handle such
 	 * situations right:
 	 * 1s  client sends a normal SMB request
-	 * 2s  client gets a response
+	 * 3s  client gets a response
 	 * 30s echo workqueue job pops, and decides we got a response recently
 	 *     and don't need to send another
 	 * ...
 	 * 65s kernel_recvmsg times out, and we see that we haven't gotten
 	 *     a response in >60s.
 	 */
-	if (server->tcpStatus == CifsGood &&
-	    time_after(jiffies, server->lstrp + 2 * SMB_ECHO_INTERVAL)) {
+	if ((server->tcpStatus == CifsGood ||
+	    server->tcpStatus == CifsNeedNegotiate) &&
+	    time_after(jiffies, server->lstrp + 3 * SMB_ECHO_INTERVAL)) {
 		cifs_dbg(VFS, "Server %s has not responded in %d seconds. Reconnecting...\n",
-			 server->hostname, (2 * SMB_ECHO_INTERVAL) / HZ);
+			 server->hostname, (3 * SMB_ECHO_INTERVAL) / HZ);
 		cifs_reconnect(server);
 		wake_up(&server->response_q);
 		return true;
diff -druNp --no-dereference linux-libre-4.4.223-gnu/fs/cifs/smb2pdu.c linux-libre-4.4.224-gnu/fs/cifs/smb2pdu.c
--- linux-libre-4.4.223-gnu/fs/cifs/smb2pdu.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/fs/cifs/smb2pdu.c	2020-05-20 02:11:57.000000000 -0400
@@ -249,6 +249,18 @@ smb2_reconnect(__le16 smb2_command, stru
 	 * the same SMB session
 	 */
 	mutex_lock(&tcon->ses->session_mutex);
+
+	/*
+	 * Recheck after acquire mutex. If another thread is negotiating
+	 * and the server never sends an answer the socket will be closed
+	 * and tcpStatus set to reconnect.
+	 */
+	if (server->tcpStatus == CifsNeedReconnect) {
+		rc = -EHOSTDOWN;
+		mutex_unlock(&tcon->ses->session_mutex);
+		goto out;
+	}
+
 	rc = cifs_negotiate_protocol(0, tcon->ses);
 	if (!rc && tcon->ses->need_reconnect) {
 		rc = cifs_setup_session(0, tcon->ses, nls_codepage);
diff -druNp --no-dereference linux-libre-4.4.223-gnu/fs/exec.c linux-libre-4.4.224-gnu/fs/exec.c
--- linux-libre-4.4.223-gnu/fs/exec.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/fs/exec.c	2020-05-20 02:11:57.000000000 -0400
@@ -1124,6 +1124,8 @@ int flush_old_exec(struct linux_binprm *
 	 */
 	set_mm_exe_file(bprm->mm, bprm->file);
 
+	would_dump(bprm, bprm->file);
+
 	/*
 	 * Release all of the old mmap stuff
 	 */
@@ -1632,8 +1634,6 @@ static int do_execveat_common(int fd, st
 	if (retval < 0)
 		goto out;
 
-	would_dump(bprm, bprm->file);
-
 	retval = exec_binprm(bprm);
 	if (retval < 0)
 		goto out;
diff -druNp --no-dereference linux-libre-4.4.223-gnu/fs/ext4/block_validity.c linux-libre-4.4.224-gnu/fs/ext4/block_validity.c
--- linux-libre-4.4.223-gnu/fs/ext4/block_validity.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/fs/ext4/block_validity.c	2020-05-20 02:11:57.000000000 -0400
@@ -152,6 +152,7 @@ static int ext4_protect_reserved_inode(s
 		return PTR_ERR(inode);
 	num = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
 	while (i < num) {
+		cond_resched();
 		map.m_lblk = i;
 		map.m_len = num - i;
 		n = ext4_map_blocks(NULL, inode, &map, 0);
diff -druNp --no-dereference linux-libre-4.4.223-gnu/include/linux/blkdev.h linux-libre-4.4.224-gnu/include/linux/blkdev.h
--- linux-libre-4.4.223-gnu/include/linux/blkdev.h	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/include/linux/blkdev.h	2020-05-20 02:11:57.000000000 -0400
@@ -431,7 +431,8 @@ struct request_queue {
 	unsigned int		sg_reserved_size;
 	int			node;
 #ifdef CONFIG_BLK_DEV_IO_TRACE
-	struct blk_trace	*blk_trace;
+	struct blk_trace __rcu	*blk_trace;
+	struct mutex		blk_trace_mutex;
 #endif
 	/*
 	 * for flush operations
diff -druNp --no-dereference linux-libre-4.4.223-gnu/include/linux/blktrace_api.h linux-libre-4.4.224-gnu/include/linux/blktrace_api.h
--- linux-libre-4.4.223-gnu/include/linux/blktrace_api.h	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/include/linux/blktrace_api.h	2020-05-20 02:11:57.000000000 -0400
@@ -51,9 +51,13 @@ void __trace_note_message(struct blk_tra
  **/
 #define blk_add_trace_msg(q, fmt, ...)					\
 	do {								\
-		struct blk_trace *bt = (q)->blk_trace;			\
+		struct blk_trace *bt;					\
+									\
+		rcu_read_lock();					\
+		bt = rcu_dereference((q)->blk_trace);			\
 		if (unlikely(bt))					\
 			__trace_note_message(bt, fmt, ##__VA_ARGS__);	\
+		rcu_read_unlock();					\
 	} while (0)
 #define BLK_TN_MAX_MSG		128
 
diff -druNp --no-dereference linux-libre-4.4.223-gnu/include/linux/cdev.h linux-libre-4.4.224-gnu/include/linux/cdev.h
--- linux-libre-4.4.223-gnu/include/linux/cdev.h	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/include/linux/cdev.h	2020-05-20 02:11:57.000000000 -0400
@@ -4,6 +4,7 @@
 #include <linux/kobject.h>
 #include <linux/kdev_t.h>
 #include <linux/list.h>
+#include <linux/device.h>
 
 struct file_operations;
 struct inode;
@@ -26,6 +27,10 @@ void cdev_put(struct cdev *p);
 
 int cdev_add(struct cdev *, dev_t, unsigned);
 
+void cdev_set_parent(struct cdev *p, struct kobject *kobj);
+int cdev_device_add(struct cdev *cdev, struct device *dev);
+void cdev_device_del(struct cdev *cdev, struct device *dev);
+
 void cdev_del(struct cdev *);
 
 void cd_forget(struct inode *);
diff -druNp --no-dereference linux-libre-4.4.223-gnu/include/linux/compiler.h linux-libre-4.4.224-gnu/include/linux/compiler.h
--- linux-libre-4.4.223-gnu/include/linux/compiler.h	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/include/linux/compiler.h	2020-05-20 02:11:57.000000000 -0400
@@ -556,4 +556,11 @@ static __always_inline void __write_once
 # define __kprobes
 # define nokprobe_inline	inline
 #endif
+
+/*
+ * This is needed in functions which generate the stack canary, see
+ * arch/x86/kernel/smpboot.c::start_secondary() for an example.
+ */
+#define prevent_tail_call_optimization()	mb()
+
 #endif /* __LINUX_COMPILER_H */
diff -druNp --no-dereference linux-libre-4.4.223-gnu/include/linux/fs.h linux-libre-4.4.224-gnu/include/linux/fs.h
--- linux-libre-4.4.223-gnu/include/linux/fs.h	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/include/linux/fs.h	2020-05-20 02:11:57.000000000 -0400
@@ -915,7 +915,7 @@ struct file_handle {
 	__u32 handle_bytes;
 	int handle_type;
 	/* file identifier */
-	unsigned char f_handle[0];
+	unsigned char f_handle[];
 };
 
 static inline struct file *get_file(struct file *f)
diff -druNp --no-dereference linux-libre-4.4.223-gnu/include/linux/pnp.h linux-libre-4.4.224-gnu/include/linux/pnp.h
--- linux-libre-4.4.223-gnu/include/linux/pnp.h	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/include/linux/pnp.h	2020-05-20 02:11:57.000000000 -0400
@@ -219,10 +219,8 @@ struct pnp_card {
 #define global_to_pnp_card(n) list_entry(n, struct pnp_card, global_list)
 #define protocol_to_pnp_card(n) list_entry(n, struct pnp_card, protocol_list)
 #define to_pnp_card(n) container_of(n, struct pnp_card, dev)
-#define pnp_for_each_card(card) \
-	for((card) = global_to_pnp_card(pnp_cards.next); \
-	(card) != global_to_pnp_card(&pnp_cards); \
-	(card) = global_to_pnp_card((card)->global_list.next))
+#define pnp_for_each_card(card)	\
+	list_for_each_entry(card, &pnp_cards, global_list)
 
 struct pnp_card_link {
 	struct pnp_card *card;
@@ -275,14 +273,9 @@ struct pnp_dev {
 #define card_to_pnp_dev(n) list_entry(n, struct pnp_dev, card_list)
 #define protocol_to_pnp_dev(n) list_entry(n, struct pnp_dev, protocol_list)
 #define	to_pnp_dev(n) container_of(n, struct pnp_dev, dev)
-#define pnp_for_each_dev(dev) \
-	for((dev) = global_to_pnp_dev(pnp_global.next); \
-	(dev) != global_to_pnp_dev(&pnp_global); \
-	(dev) = global_to_pnp_dev((dev)->global_list.next))
-#define card_for_each_dev(card,dev) \
-	for((dev) = card_to_pnp_dev((card)->devices.next); \
-	(dev) != card_to_pnp_dev(&(card)->devices); \
-	(dev) = card_to_pnp_dev((dev)->card_list.next))
+#define pnp_for_each_dev(dev) list_for_each_entry(dev, &pnp_global, global_list)
+#define card_for_each_dev(card, dev)	\
+	list_for_each_entry(dev, &(card)->devices, card_list)
 #define pnp_dev_name(dev) (dev)->name
 
 static inline void *pnp_get_drvdata(struct pnp_dev *pdev)
@@ -434,14 +427,10 @@ struct pnp_protocol {
 };
 
 #define to_pnp_protocol(n) list_entry(n, struct pnp_protocol, protocol_list)
-#define protocol_for_each_card(protocol,card) \
-	for((card) = protocol_to_pnp_card((protocol)->cards.next); \
-	(card) != protocol_to_pnp_card(&(protocol)->cards); \
-	(card) = protocol_to_pnp_card((card)->protocol_list.next))
-#define protocol_for_each_dev(protocol,dev) \
-	for((dev) = protocol_to_pnp_dev((protocol)->devices.next); \
-	(dev) != protocol_to_pnp_dev(&(protocol)->devices); \
-	(dev) = protocol_to_pnp_dev((dev)->protocol_list.next))
+#define protocol_for_each_card(protocol, card)	\
+	list_for_each_entry(card, &(protocol)->cards, protocol_list)
+#define protocol_for_each_dev(protocol, dev)	\
+	list_for_each_entry(dev, &(protocol)->devices, protocol_list)
 
 extern struct bus_type pnp_bus_type;
 
diff -druNp --no-dereference linux-libre-4.4.223-gnu/include/linux/posix-clock.h linux-libre-4.4.224-gnu/include/linux/posix-clock.h
--- linux-libre-4.4.223-gnu/include/linux/posix-clock.h	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/include/linux/posix-clock.h	2020-05-20 02:11:57.000000000 -0400
@@ -104,29 +104,32 @@ struct posix_clock_operations {
  *
  * @ops:     Functional interface to the clock
  * @cdev:    Character device instance for this clock
- * @kref:    Reference count.
+ * @dev:     Pointer to the clock's device.
  * @rwsem:   Protects the 'zombie' field from concurrent access.
  * @zombie:  If 'zombie' is true, then the hardware has disappeared.
- * @release: A function to free the structure when the reference count reaches
- *           zero. May be NULL if structure is statically allocated.
  *
  * Drivers should embed their struct posix_clock within a private
  * structure, obtaining a reference to it during callbacks using
  * container_of().
+ *
+ * Drivers should supply an initialized but not exposed struct device
+ * to posix_clock_register(). It is used to manage lifetime of the
+ * driver's private structure. It's 'release' field should be set to
+ * a release function for this private structure.
  */
 struct posix_clock {
 	struct posix_clock_operations ops;
 	struct cdev cdev;
-	struct kref kref;
+	struct device *dev;
 	struct rw_semaphore rwsem;
 	bool zombie;
-	void (*release)(struct posix_clock *clk);
 };
 
 /**
  * posix_clock_register() - register a new clock
- * @clk:   Pointer to the clock. Caller must provide 'ops' and 'release'
- * @devid: Allocated device id
+ * @clk:   Pointer to the clock. Caller must provide 'ops' field
+ * @dev:   Pointer to the initialized device. Caller must provide
+ *         'release' field
  *
  * A clock driver calls this function to register itself with the
  * clock device subsystem. If 'clk' points to dynamically allocated
@@ -135,7 +138,7 @@ struct posix_clock {
  *
  * Returns zero on success, non-zero otherwise.
  */
-int posix_clock_register(struct posix_clock *clk, dev_t devid);
+int posix_clock_register(struct posix_clock *clk, struct device *dev);
 
 /**
  * posix_clock_unregister() - unregister a clock
diff -druNp --no-dereference linux-libre-4.4.223-gnu/include/linux/tty.h linux-libre-4.4.224-gnu/include/linux/tty.h
--- linux-libre-4.4.223-gnu/include/linux/tty.h	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/include/linux/tty.h	2020-05-20 02:11:57.000000000 -0400
@@ -64,7 +64,7 @@ struct tty_buffer {
 	int read;
 	int flags;
 	/* Data points here */
-	unsigned long data[0];
+	unsigned long data[];
 };
 
 /* Values for .flags field of tty_buffer */
diff -druNp --no-dereference linux-libre-4.4.223-gnu/include/net/addrconf.h linux-libre-4.4.224-gnu/include/net/addrconf.h
--- linux-libre-4.4.223-gnu/include/net/addrconf.h	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/include/net/addrconf.h	2020-05-20 02:11:57.000000000 -0400
@@ -192,8 +192,10 @@ struct ipv6_stub {
 				 const struct in6_addr *addr);
 	int (*ipv6_sock_mc_drop)(struct sock *sk, int ifindex,
 				 const struct in6_addr *addr);
-	int (*ipv6_dst_lookup)(struct net *net, struct sock *sk,
-			       struct dst_entry **dst, struct flowi6 *fl6);
+	struct dst_entry *(*ipv6_dst_lookup_flow)(struct net *net,
+						  const struct sock *sk,
+						  struct flowi6 *fl6,
+						  const struct in6_addr *final_dst);
 	void (*udpv6_encap_enable)(void);
 	void (*ndisc_send_na)(struct net_device *dev, const struct in6_addr *daddr,
 			      const struct in6_addr *solicited_addr,
diff -druNp --no-dereference linux-libre-4.4.223-gnu/include/net/ipv6.h linux-libre-4.4.224-gnu/include/net/ipv6.h
--- linux-libre-4.4.223-gnu/include/net/ipv6.h	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/include/net/ipv6.h	2020-05-20 02:11:57.000000000 -0400
@@ -853,7 +853,7 @@ static inline struct sk_buff *ip6_finish
 
 int ip6_dst_lookup(struct net *net, struct sock *sk, struct dst_entry **dst,
 		   struct flowi6 *fl6);
-struct dst_entry *ip6_dst_lookup_flow(const struct sock *sk, struct flowi6 *fl6,
+struct dst_entry *ip6_dst_lookup_flow(struct net *net, const struct sock *sk, struct flowi6 *fl6,
 				      const struct in6_addr *final_dst);
 struct dst_entry *ip6_sk_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6,
 					 const struct in6_addr *final_dst);
diff -druNp --no-dereference linux-libre-4.4.223-gnu/include/net/netfilter/nf_conntrack.h linux-libre-4.4.224-gnu/include/net/netfilter/nf_conntrack.h
--- linux-libre-4.4.223-gnu/include/net/netfilter/nf_conntrack.h	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/include/net/netfilter/nf_conntrack.h	2020-05-20 02:11:57.000000000 -0400
@@ -98,7 +98,7 @@ struct nf_conn {
 	possible_net_t ct_net;
 
 	/* all members below initialized via memset */
-	u8 __nfct_init_offset[0];
+	struct { } __nfct_init_offset;
 
 	/* If we were expected by an expectation, this will be it */
 	struct nf_conn *master;
diff -druNp --no-dereference linux-libre-4.4.223-gnu/include/sound/rawmidi.h linux-libre-4.4.224-gnu/include/sound/rawmidi.h
--- linux-libre-4.4.223-gnu/include/sound/rawmidi.h	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/include/sound/rawmidi.h	2020-05-20 02:11:57.000000000 -0400
@@ -76,6 +76,7 @@ struct snd_rawmidi_runtime {
 	size_t avail_min;	/* min avail for wakeup */
 	size_t avail;		/* max used buffer for wakeup */
 	size_t xruns;		/* over/underruns counter */
+	int buffer_ref;		/* buffer reference count */
 	/* misc */
 	spinlock_t lock;
 	wait_queue_head_t sleep;
diff -druNp --no-dereference linux-libre-4.4.223-gnu/init/main.c linux-libre-4.4.224-gnu/init/main.c
--- linux-libre-4.4.223-gnu/init/main.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/init/main.c	2020-05-20 02:11:57.000000000 -0400
@@ -683,6 +683,8 @@ asmlinkage __visible void __init start_k
 
 	/* Do the rest non-__init'ed, we're now alive */
 	rest_init();
+
+	prevent_tail_call_optimization();
 }
 
 /* Call all constructor functions linked into the kernel. */
diff -druNp --no-dereference linux-libre-4.4.223-gnu/ipc/util.c linux-libre-4.4.224-gnu/ipc/util.c
--- linux-libre-4.4.223-gnu/ipc/util.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/ipc/util.c	2020-05-20 02:11:57.000000000 -0400
@@ -756,21 +756,21 @@ static struct kern_ipc_perm *sysvipc_fin
 			total++;
 	}
 
-	*new_pos = pos + 1;
+	ipc = NULL;
 	if (total >= ids->in_use)
-		return NULL;
+		goto out;
 
 	for (; pos < IPCMNI; pos++) {
 		ipc = idr_find(&ids->ipcs_idr, pos);
 		if (ipc != NULL) {
 			rcu_read_lock();
 			ipc_lock_object(ipc);
-			return ipc;
+			break;
 		}
 	}
-
-	/* Out of range - return NULL to terminate iteration */
-	return NULL;
+out:
+	*new_pos = pos + 1;
+	return ipc;
 }
 
 static void *sysvipc_proc_next(struct seq_file *s, void *it, loff_t *pos)
diff -druNp --no-dereference linux-libre-4.4.223-gnu/kernel/time/posix-clock.c linux-libre-4.4.224-gnu/kernel/time/posix-clock.c
--- linux-libre-4.4.223-gnu/kernel/time/posix-clock.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/kernel/time/posix-clock.c	2020-05-20 02:11:57.000000000 -0400
@@ -25,8 +25,6 @@
 #include <linux/syscalls.h>
 #include <linux/uaccess.h>
 
-static void delete_clock(struct kref *kref);
-
 /*
  * Returns NULL if the posix_clock instance attached to 'fp' is old and stale.
  */
@@ -168,7 +166,7 @@ static int posix_clock_open(struct inode
 		err = 0;
 
 	if (!err) {
-		kref_get(&clk->kref);
+		get_device(clk->dev);
 		fp->private_data = clk;
 	}
 out:
@@ -184,7 +182,7 @@ static int posix_clock_release(struct in
 	if (clk->ops.release)
 		err = clk->ops.release(clk);
 
-	kref_put(&clk->kref, delete_clock);
+	put_device(clk->dev);
 
 	fp->private_data = NULL;
 
@@ -206,38 +204,35 @@ static const struct file_operations posi
 #endif
 };
 
-int posix_clock_register(struct posix_clock *clk, dev_t devid)
+int posix_clock_register(struct posix_clock *clk, struct device *dev)
 {
 	int err;
 
-	kref_init(&clk->kref);
 	init_rwsem(&clk->rwsem);
 
 	cdev_init(&clk->cdev, &posix_clock_file_operations);
+	err = cdev_device_add(&clk->cdev, dev);
+	if (err) {
+		pr_err("%s unable to add device %d:%d\n",
+			dev_name(dev), MAJOR(dev->devt), MINOR(dev->devt));
+		return err;
+	}
 	clk->cdev.owner = clk->ops.owner;
-	err = cdev_add(&clk->cdev, devid, 1);
+	clk->dev = dev;
 
-	return err;
+	return 0;
 }
 EXPORT_SYMBOL_GPL(posix_clock_register);
 
-static void delete_clock(struct kref *kref)
-{
-	struct posix_clock *clk = container_of(kref, struct posix_clock, kref);
-
-	if (clk->release)
-		clk->release(clk);
-}
-
 void posix_clock_unregister(struct posix_clock *clk)
 {
-	cdev_del(&clk->cdev);
+	cdev_device_del(&clk->cdev, clk->dev);
 
 	down_write(&clk->rwsem);
 	clk->zombie = true;
 	up_write(&clk->rwsem);
 
-	kref_put(&clk->kref, delete_clock);
+	put_device(clk->dev);
 }
 EXPORT_SYMBOL_GPL(posix_clock_unregister);
 
diff -druNp --no-dereference linux-libre-4.4.223-gnu/kernel/trace/blktrace.c linux-libre-4.4.224-gnu/kernel/trace/blktrace.c
--- linux-libre-4.4.223-gnu/kernel/trace/blktrace.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/kernel/trace/blktrace.c	2020-05-20 02:11:57.000000000 -0400
@@ -319,11 +319,12 @@ static void put_probe_ref(void)
 
 static void blk_trace_cleanup(struct blk_trace *bt)
 {
+	synchronize_rcu();
 	blk_trace_free(bt);
 	put_probe_ref();
 }
 
-int blk_trace_remove(struct request_queue *q)
+static int __blk_trace_remove(struct request_queue *q)
 {
 	struct blk_trace *bt;
 
@@ -336,6 +337,17 @@ int blk_trace_remove(struct request_queu
 
 	return 0;
 }
+
+int blk_trace_remove(struct request_queue *q)
+{
+	int ret;
+
+	mutex_lock(&q->blk_trace_mutex);
+	ret = __blk_trace_remove(q);
+	mutex_unlock(&q->blk_trace_mutex);
+
+	return ret;
+}
 EXPORT_SYMBOL_GPL(blk_trace_remove);
 
 static ssize_t blk_dropped_read(struct file *filp, char __user *buffer,
@@ -546,9 +558,8 @@ err:
 	return ret;
 }
 
-int blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
-		    struct block_device *bdev,
-		    char __user *arg)
+static int __blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
+			     struct block_device *bdev, char __user *arg)
 {
 	struct blk_user_trace_setup buts;
 	int ret;
@@ -562,11 +573,24 @@ int blk_trace_setup(struct request_queue
 		return ret;
 
 	if (copy_to_user(arg, &buts, sizeof(buts))) {
-		blk_trace_remove(q);
+		__blk_trace_remove(q);
 		return -EFAULT;
 	}
 	return 0;
 }
+
+int blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
+		    struct block_device *bdev,
+		    char __user *arg)
+{
+	int ret;
+
+	mutex_lock(&q->blk_trace_mutex);
+	ret = __blk_trace_setup(q, name, dev, bdev, arg);
+	mutex_unlock(&q->blk_trace_mutex);
+
+	return ret;
+}
 EXPORT_SYMBOL_GPL(blk_trace_setup);
 
 #if defined(CONFIG_COMPAT) && defined(CONFIG_X86_64)
@@ -595,7 +619,7 @@ static int compat_blk_trace_setup(struct
 		return ret;
 
 	if (copy_to_user(arg, &buts.name, ARRAY_SIZE(buts.name))) {
-		blk_trace_remove(q);
+		__blk_trace_remove(q);
 		return -EFAULT;
 	}
 
@@ -603,11 +627,13 @@ static int compat_blk_trace_setup(struct
 }
 #endif
 
-int blk_trace_startstop(struct request_queue *q, int start)
+static int __blk_trace_startstop(struct request_queue *q, int start)
 {
 	int ret;
-	struct blk_trace *bt = q->blk_trace;
+	struct blk_trace *bt;
 
+	bt = rcu_dereference_protected(q->blk_trace,
+				       lockdep_is_held(&q->blk_trace_mutex));
 	if (bt == NULL)
 		return -EINVAL;
 
@@ -642,8 +668,25 @@ int blk_trace_startstop(struct request_q
 
 	return ret;
 }
+
+int blk_trace_startstop(struct request_queue *q, int start)
+{
+	int ret;
+
+	mutex_lock(&q->blk_trace_mutex);
+	ret = __blk_trace_startstop(q, start);
+	mutex_unlock(&q->blk_trace_mutex);
+
+	return ret;
+}
 EXPORT_SYMBOL_GPL(blk_trace_startstop);
 
+/*
+ * When reading or writing the blktrace sysfs files, the references to the
+ * opened sysfs or device files should prevent the underlying block device
+ * from being removed. So no further delete protection is really needed.
+ */
+
 /**
  * blk_trace_ioctl: - handle the ioctls associated with tracing
  * @bdev:	the block device
@@ -661,12 +704,12 @@ int blk_trace_ioctl(struct block_device
 	if (!q)
 		return -ENXIO;
 
-	mutex_lock(&bdev->bd_mutex);
+	mutex_lock(&q->blk_trace_mutex);
 
 	switch (cmd) {
 	case BLKTRACESETUP:
 		bdevname(bdev, b);
-		ret = blk_trace_setup(q, b, bdev->bd_dev, bdev, arg);
+		ret = __blk_trace_setup(q, b, bdev->bd_dev, bdev, arg);
 		break;
 #if defined(CONFIG_COMPAT) && defined(CONFIG_X86_64)
 	case BLKTRACESETUP32:
@@ -677,17 +720,17 @@ int blk_trace_ioctl(struct block_device
 	case BLKTRACESTART:
 		start = 1;
 	case BLKTRACESTOP:
-		ret = blk_trace_startstop(q, start);
+		ret = __blk_trace_startstop(q, start);
 		break;
 	case BLKTRACETEARDOWN:
-		ret = blk_trace_remove(q);
+		ret = __blk_trace_remove(q);
 		break;
 	default:
 		ret = -ENOTTY;
 		break;
 	}
 
-	mutex_unlock(&bdev->bd_mutex);
+	mutex_unlock(&q->blk_trace_mutex);
 	return ret;
 }
 
@@ -698,10 +741,14 @@ int blk_trace_ioctl(struct block_device
  **/
 void blk_trace_shutdown(struct request_queue *q)
 {
-	if (q->blk_trace) {
-		blk_trace_startstop(q, 0);
-		blk_trace_remove(q);
+	mutex_lock(&q->blk_trace_mutex);
+	if (rcu_dereference_protected(q->blk_trace,
+				      lockdep_is_held(&q->blk_trace_mutex))) {
+		__blk_trace_startstop(q, 0);
+		__blk_trace_remove(q);
 	}
+
+	mutex_unlock(&q->blk_trace_mutex);
 }
 
 /*
@@ -722,10 +769,14 @@ void blk_trace_shutdown(struct request_q
 static void blk_add_trace_rq(struct request_queue *q, struct request *rq,
 			     unsigned int nr_bytes, u32 what)
 {
-	struct blk_trace *bt = q->blk_trace;
+	struct blk_trace *bt;
 
-	if (likely(!bt))
+	rcu_read_lock();
+	bt = rcu_dereference(q->blk_trace);
+	if (likely(!bt)) {
+		rcu_read_unlock();
 		return;
+	}
 
 	if (rq->cmd_type == REQ_TYPE_BLOCK_PC) {
 		what |= BLK_TC_ACT(BLK_TC_PC);
@@ -736,6 +787,7 @@ static void blk_add_trace_rq(struct requ
 		__blk_add_trace(bt, blk_rq_pos(rq), nr_bytes,
 				rq->cmd_flags, what, rq->errors, 0, NULL);
 	}
+	rcu_read_unlock();
 }
 
 static void blk_add_trace_rq_abort(void *ignore,
@@ -785,13 +837,18 @@ static void blk_add_trace_rq_complete(vo
 static void blk_add_trace_bio(struct request_queue *q, struct bio *bio,
 			      u32 what, int error)
 {
-	struct blk_trace *bt = q->blk_trace;
+	struct blk_trace *bt;
 
-	if (likely(!bt))
+	rcu_read_lock();
+	bt = rcu_dereference(q->blk_trace);
+	if (likely(!bt)) {
+		rcu_read_unlock();
 		return;
+	}
 
 	__blk_add_trace(bt, bio->bi_iter.bi_sector, bio->bi_iter.bi_size,
 			bio->bi_rw, what, error, 0, NULL);
+	rcu_read_unlock();
 }
 
 static void blk_add_trace_bio_bounce(void *ignore,
@@ -836,10 +893,13 @@ static void blk_add_trace_getrq(void *ig
 	if (bio)
 		blk_add_trace_bio(q, bio, BLK_TA_GETRQ, 0);
 	else {
-		struct blk_trace *bt = q->blk_trace;
+		struct blk_trace *bt;
 
+		rcu_read_lock();
+		bt = rcu_dereference(q->blk_trace);
 		if (bt)
 			__blk_add_trace(bt, 0, 0, rw, BLK_TA_GETRQ, 0, 0, NULL);
+		rcu_read_unlock();
 	}
 }
 
@@ -851,27 +911,35 @@ static void blk_add_trace_sleeprq(void *
 	if (bio)
 		blk_add_trace_bio(q, bio, BLK_TA_SLEEPRQ, 0);
 	else {
-		struct blk_trace *bt = q->blk_trace;
+		struct blk_trace *bt;
 
+		rcu_read_lock();
+		bt = rcu_dereference(q->blk_trace);
 		if (bt)
 			__blk_add_trace(bt, 0, 0, rw, BLK_TA_SLEEPRQ,
 					0, 0, NULL);
+		rcu_read_unlock();
 	}
 }
 
 static void blk_add_trace_plug(void *ignore, struct request_queue *q)
 {
-	struct blk_trace *bt = q->blk_trace;
+	struct blk_trace *bt;
 
+	rcu_read_lock();
+	bt = rcu_dereference(q->blk_trace);
 	if (bt)
 		__blk_add_trace(bt, 0, 0, 0, BLK_TA_PLUG, 0, 0, NULL);
+	rcu_read_unlock();
 }
 
 static void blk_add_trace_unplug(void *ignore, struct request_queue *q,
 				    unsigned int depth, bool explicit)
 {
-	struct blk_trace *bt = q->blk_trace;
+	struct blk_trace *bt;
 
+	rcu_read_lock();
+	bt = rcu_dereference(q->blk_trace);
 	if (bt) {
 		__be64 rpdu = cpu_to_be64(depth);
 		u32 what;
@@ -883,14 +951,17 @@ static void blk_add_trace_unplug(void *i
 
 		__blk_add_trace(bt, 0, 0, 0, what, 0, sizeof(rpdu), &rpdu);
 	}
+	rcu_read_unlock();
 }
 
 static void blk_add_trace_split(void *ignore,
 				struct request_queue *q, struct bio *bio,
 				unsigned int pdu)
 {
-	struct blk_trace *bt = q->blk_trace;
+	struct blk_trace *bt;
 
+	rcu_read_lock();
+	bt = rcu_dereference(q->blk_trace);
 	if (bt) {
 		__be64 rpdu = cpu_to_be64(pdu);
 
@@ -898,6 +969,7 @@ static void blk_add_trace_split(void *ig
 				bio->bi_iter.bi_size, bio->bi_rw, BLK_TA_SPLIT,
 				bio->bi_error, sizeof(rpdu), &rpdu);
 	}
+	rcu_read_unlock();
 }
 
 /**
@@ -917,11 +989,15 @@ static void blk_add_trace_bio_remap(void
 				    struct request_queue *q, struct bio *bio,
 				    dev_t dev, sector_t from)
 {
-	struct blk_trace *bt = q->blk_trace;
+	struct blk_trace *bt;
 	struct blk_io_trace_remap r;
 
-	if (likely(!bt))
+	rcu_read_lock();
+	bt = rcu_dereference(q->blk_trace);
+	if (likely(!bt)) {
+		rcu_read_unlock();
 		return;
+	}
 
 	r.device_from = cpu_to_be32(dev);
 	r.device_to   = cpu_to_be32(bio->bi_bdev->bd_dev);
@@ -930,6 +1006,7 @@ static void blk_add_trace_bio_remap(void
 	__blk_add_trace(bt, bio->bi_iter.bi_sector, bio->bi_iter.bi_size,
 			bio->bi_rw, BLK_TA_REMAP, bio->bi_error,
 			sizeof(r), &r);
+	rcu_read_unlock();
 }
 
 /**
@@ -950,11 +1027,15 @@ static void blk_add_trace_rq_remap(void
 				   struct request *rq, dev_t dev,
 				   sector_t from)
 {
-	struct blk_trace *bt = q->blk_trace;
+	struct blk_trace *bt;
 	struct blk_io_trace_remap r;
 
-	if (likely(!bt))
+	rcu_read_lock();
+	bt = rcu_dereference(q->blk_trace);
+	if (likely(!bt)) {
+		rcu_read_unlock();
 		return;
+	}
 
 	r.device_from = cpu_to_be32(dev);
 	r.device_to   = cpu_to_be32(disk_devt(rq->rq_disk));
@@ -963,6 +1044,7 @@ static void blk_add_trace_rq_remap(void
 	__blk_add_trace(bt, blk_rq_pos(rq), blk_rq_bytes(rq),
 			rq_data_dir(rq), BLK_TA_REMAP, !!rq->errors,
 			sizeof(r), &r);
+	rcu_read_unlock();
 }
 
 /**
@@ -980,10 +1062,14 @@ void blk_add_driver_data(struct request_
 			 struct request *rq,
 			 void *data, size_t len)
 {
-	struct blk_trace *bt = q->blk_trace;
+	struct blk_trace *bt;
 
-	if (likely(!bt))
+	rcu_read_lock();
+	bt = rcu_dereference(q->blk_trace);
+	if (likely(!bt)) {
+		rcu_read_unlock();
 		return;
+	}
 
 	if (rq->cmd_type == REQ_TYPE_BLOCK_PC)
 		__blk_add_trace(bt, 0, blk_rq_bytes(rq), 0,
@@ -991,6 +1077,7 @@ void blk_add_driver_data(struct request_
 	else
 		__blk_add_trace(bt, blk_rq_pos(rq), blk_rq_bytes(rq), 0,
 				BLK_TA_DRV_DATA, rq->errors, len, data);
+	rcu_read_unlock();
 }
 EXPORT_SYMBOL_GPL(blk_add_driver_data);
 
@@ -1482,6 +1569,7 @@ static int blk_trace_remove_queue(struct
 		return -EINVAL;
 
 	put_probe_ref();
+	synchronize_rcu();
 	blk_trace_free(bt);
 	return 0;
 }
@@ -1642,6 +1730,7 @@ static ssize_t sysfs_blk_trace_attr_show
 	struct hd_struct *p = dev_to_part(dev);
 	struct request_queue *q;
 	struct block_device *bdev;
+	struct blk_trace *bt;
 	ssize_t ret = -ENXIO;
 
 	bdev = bdget(part_devt(p));
@@ -1652,26 +1741,28 @@ static ssize_t sysfs_blk_trace_attr_show
 	if (q == NULL)
 		goto out_bdput;
 
-	mutex_lock(&bdev->bd_mutex);
+	mutex_lock(&q->blk_trace_mutex);
 
+	bt = rcu_dereference_protected(q->blk_trace,
+				       lockdep_is_held(&q->blk_trace_mutex));
 	if (attr == &dev_attr_enable) {
-		ret = sprintf(buf, "%u\n", !!q->blk_trace);
+		ret = sprintf(buf, "%u\n", !!bt);
 		goto out_unlock_bdev;
 	}
 
-	if (q->blk_trace == NULL)
+	if (bt == NULL)
 		ret = sprintf(buf, "disabled\n");
 	else if (attr == &dev_attr_act_mask)
-		ret = blk_trace_mask2str(buf, q->blk_trace->act_mask);
+		ret = blk_trace_mask2str(buf, bt->act_mask);
 	else if (attr == &dev_attr_pid)
-		ret = sprintf(buf, "%u\n", q->blk_trace->pid);
+		ret = sprintf(buf, "%u\n", bt->pid);
 	else if (attr == &dev_attr_start_lba)
-		ret = sprintf(buf, "%llu\n", q->blk_trace->start_lba);
+		ret = sprintf(buf, "%llu\n", bt->start_lba);
 	else if (attr == &dev_attr_end_lba)
-		ret = sprintf(buf, "%llu\n", q->blk_trace->end_lba);
+		ret = sprintf(buf, "%llu\n", bt->end_lba);
 
 out_unlock_bdev:
-	mutex_unlock(&bdev->bd_mutex);
+	mutex_unlock(&q->blk_trace_mutex);
 out_bdput:
 	bdput(bdev);
 out:
@@ -1685,6 +1776,7 @@ static ssize_t sysfs_blk_trace_attr_stor
 	struct block_device *bdev;
 	struct request_queue *q;
 	struct hd_struct *p;
+	struct blk_trace *bt;
 	u64 value;
 	ssize_t ret = -EINVAL;
 
@@ -1713,10 +1805,12 @@ static ssize_t sysfs_blk_trace_attr_stor
 	if (q == NULL)
 		goto out_bdput;
 
-	mutex_lock(&bdev->bd_mutex);
+	mutex_lock(&q->blk_trace_mutex);
 
+	bt = rcu_dereference_protected(q->blk_trace,
+				       lockdep_is_held(&q->blk_trace_mutex));
 	if (attr == &dev_attr_enable) {
-		if (!!value == !!q->blk_trace) {
+		if (!!value == !!bt) {
 			ret = 0;
 			goto out_unlock_bdev;
 		}
@@ -1728,22 +1822,25 @@ static ssize_t sysfs_blk_trace_attr_stor
 	}
 
 	ret = 0;
-	if (q->blk_trace == NULL)
+	if (bt == NULL) {
 		ret = blk_trace_setup_queue(q, bdev);
+		bt = rcu_dereference_protected(q->blk_trace,
+				lockdep_is_held(&q->blk_trace_mutex));
+	}
 
 	if (ret == 0) {
 		if (attr == &dev_attr_act_mask)
-			q->blk_trace->act_mask = value;
+			bt->act_mask = value;
 		else if (attr == &dev_attr_pid)
-			q->blk_trace->pid = value;
+			bt->pid = value;
 		else if (attr == &dev_attr_start_lba)
-			q->blk_trace->start_lba = value;
+			bt->start_lba = value;
 		else if (attr == &dev_attr_end_lba)
-			q->blk_trace->end_lba = value;
+			bt->end_lba = value;
 	}
 
 out_unlock_bdev:
-	mutex_unlock(&bdev->bd_mutex);
+	mutex_unlock(&q->blk_trace_mutex);
 out_bdput:
 	bdput(bdev);
 out:
diff -druNp --no-dereference linux-libre-4.4.223-gnu/Makefile linux-libre-4.4.224-gnu/Makefile
--- linux-libre-4.4.223-gnu/Makefile	2020-05-10 18:47:55.000000000 -0400
+++ linux-libre-4.4.224-gnu/Makefile	2020-05-20 11:29:06.000000000 -0400
@@ -1,6 +1,6 @@
 VERSION = 4
 PATCHLEVEL = 4
-SUBLEVEL = 223
+SUBLEVEL = 224
 EXTRAVERSION = -gnu
 NAME = Blurry Fish Butt
 
@@ -631,7 +631,6 @@ ARCH_CFLAGS :=
 include arch/$(SRCARCH)/Makefile
 
 KBUILD_CFLAGS	+= $(call cc-option,-fno-delete-null-pointer-checks,)
-KBUILD_CFLAGS	+= $(call cc-disable-warning,maybe-uninitialized,)
 KBUILD_CFLAGS	+= $(call cc-disable-warning,frame-address,)
 KBUILD_CFLAGS	+= $(call cc-disable-warning, format-truncation)
 KBUILD_CFLAGS	+= $(call cc-disable-warning, format-overflow)
@@ -651,6 +650,7 @@ endif
 
 # Tell gcc to never replace conditional load with a non-conditional one
 KBUILD_CFLAGS	+= $(call cc-option,--param=allow-store-data-races=0)
+KBUILD_CFLAGS	+= $(call cc-option,-fno-allow-store-data-races)
 
 # check for 'asm goto'
 ifeq ($(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-goto.sh $(CC) $(KBUILD_CFLAGS)), y)
@@ -796,6 +796,17 @@ KBUILD_CFLAGS += $(call cc-disable-warni
 # disable stringop warnings in gcc 8+
 KBUILD_CFLAGS += $(call cc-disable-warning, stringop-truncation)
 
+# We'll want to enable this eventually, but it's not going away for 5.7 at least
+KBUILD_CFLAGS += $(call cc-disable-warning, zero-length-bounds)
+KBUILD_CFLAGS += $(call cc-disable-warning, array-bounds)
+KBUILD_CFLAGS += $(call cc-disable-warning, stringop-overflow)
+
+# Another good warning that we'll want to enable eventually
+KBUILD_CFLAGS += $(call cc-disable-warning, restrict)
+
+# Enabled with W=2, disabled by default as noisy
+KBUILD_CFLAGS += $(call cc-disable-warning, maybe-uninitialized)
+
 # disable invalid "can't wrap" optimizations for signed / pointers
 KBUILD_CFLAGS	+= $(call cc-option,-fno-strict-overflow)
 
diff -druNp --no-dereference linux-libre-4.4.223-gnu/mm/memory_hotplug.c linux-libre-4.4.224-gnu/mm/memory_hotplug.c
--- linux-libre-4.4.223-gnu/mm/memory_hotplug.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/mm/memory_hotplug.c	2020-05-20 02:11:57.000000000 -0400
@@ -1397,7 +1397,7 @@ int test_pages_in_a_zone(unsigned long s
 			while ((i < MAX_ORDER_NR_PAGES) &&
 				!pfn_valid_within(pfn + i))
 				i++;
-			if (i == MAX_ORDER_NR_PAGES)
+			if (i == MAX_ORDER_NR_PAGES || pfn + i >= end_pfn)
 				continue;
 			/* Check if we got outside of the zone */
 			if (zone && !zone_spans_pfn(zone, pfn + i))
@@ -1414,7 +1414,7 @@ int test_pages_in_a_zone(unsigned long s
 
 	if (zone) {
 		*valid_start = start;
-		*valid_end = end;
+		*valid_end = min(end, end_pfn);
 		return 1;
 	} else {
 		return 0;
diff -druNp --no-dereference linux-libre-4.4.223-gnu/net/batman-adv/network-coding.c linux-libre-4.4.224-gnu/net/batman-adv/network-coding.c
--- linux-libre-4.4.223-gnu/net/batman-adv/network-coding.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/net/batman-adv/network-coding.c	2020-05-20 02:11:57.000000000 -0400
@@ -991,15 +991,8 @@ static struct batadv_nc_path *batadv_nc_
  */
 static u8 batadv_nc_random_weight_tq(u8 tq)
 {
-	u8 rand_val, rand_tq;
-
-	get_random_bytes(&rand_val, sizeof(rand_val));
-
 	/* randomize the estimated packet loss (max TQ - estimated TQ) */
-	rand_tq = rand_val * (BATADV_TQ_MAX_VALUE - tq);
-
-	/* normalize the randomized packet loss */
-	rand_tq /= BATADV_TQ_MAX_VALUE;
+	u8 rand_tq = prandom_u32_max(BATADV_TQ_MAX_VALUE + 1 - tq);
 
 	/* convert to (randomized) estimated tq again */
 	return BATADV_TQ_MAX_VALUE - rand_tq;
diff -druNp --no-dereference linux-libre-4.4.223-gnu/net/core/dev.c linux-libre-4.4.224-gnu/net/core/dev.c
--- linux-libre-4.4.223-gnu/net/core/dev.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/net/core/dev.c	2020-05-20 02:11:57.000000000 -0400
@@ -6449,11 +6449,13 @@ static void netdev_sync_lower_features(s
 			netdev_dbg(upper, "Disabling feature %pNF on lower dev %s.\n",
 				   &feature, lower->name);
 			lower->wanted_features &= ~feature;
-			netdev_update_features(lower);
+			__netdev_update_features(lower);
 
 			if (unlikely(lower->features & feature))
 				netdev_WARN(upper, "failed to disable %pNF on %s!\n",
 					    &feature, lower->name);
+			else
+				netdev_features_change(lower);
 		}
 	}
 }
diff -druNp --no-dereference linux-libre-4.4.223-gnu/net/core/drop_monitor.c linux-libre-4.4.224-gnu/net/core/drop_monitor.c
--- linux-libre-4.4.223-gnu/net/core/drop_monitor.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/net/core/drop_monitor.c	2020-05-20 02:11:57.000000000 -0400
@@ -159,6 +159,7 @@ static void sched_send_work(unsigned lon
 static void trace_drop_common(struct sk_buff *skb, void *location)
 {
 	struct net_dm_alert_msg *msg;
+	struct net_dm_drop_point *point;
 	struct nlmsghdr *nlh;
 	struct nlattr *nla;
 	int i;
@@ -177,11 +178,13 @@ static void trace_drop_common(struct sk_
 	nlh = (struct nlmsghdr *)dskb->data;
 	nla = genlmsg_data(nlmsg_data(nlh));
 	msg = nla_data(nla);
+	point = msg->points;
 	for (i = 0; i < msg->entries; i++) {
-		if (!memcmp(&location, msg->points[i].pc, sizeof(void *))) {
-			msg->points[i].count++;
+		if (!memcmp(&location, &point->pc, sizeof(void *))) {
+			point->count++;
 			goto out;
 		}
+		point++;
 	}
 	if (msg->entries == dm_hit_limit)
 		goto out;
@@ -190,8 +193,8 @@ static void trace_drop_common(struct sk_
 	 */
 	__nla_reserve_nohdr(dskb, sizeof(struct net_dm_drop_point));
 	nla->nla_len += NLA_ALIGN(sizeof(struct net_dm_drop_point));
-	memcpy(msg->points[msg->entries].pc, &location, sizeof(void *));
-	msg->points[msg->entries].count = 1;
+	memcpy(point->pc, &location, sizeof(void *));
+	point->count = 1;
 	msg->entries++;
 
 	if (!timer_pending(&data->send_timer)) {
diff -druNp --no-dereference linux-libre-4.4.223-gnu/net/dccp/ipv6.c linux-libre-4.4.224-gnu/net/dccp/ipv6.c
--- linux-libre-4.4.223-gnu/net/dccp/ipv6.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/net/dccp/ipv6.c	2020-05-20 02:11:57.000000000 -0400
@@ -209,7 +209,7 @@ static int dccp_v6_send_response(const s
 	final_p = fl6_update_dst(&fl6, rcu_dereference(np->opt), &final);
 	rcu_read_unlock();
 
-	dst = ip6_dst_lookup_flow(sk, &fl6, final_p);
+	dst = ip6_dst_lookup_flow(sock_net(sk), sk, &fl6, final_p);
 	if (IS_ERR(dst)) {
 		err = PTR_ERR(dst);
 		dst = NULL;
@@ -276,7 +276,7 @@ static void dccp_v6_ctl_send_reset(const
 	security_skb_classify_flow(rxskb, flowi6_to_flowi(&fl6));
 
 	/* sk = NULL, but it is safe for now. RST socket required. */
-	dst = ip6_dst_lookup_flow(ctl_sk, &fl6, NULL);
+	dst = ip6_dst_lookup_flow(sock_net(ctl_sk), ctl_sk, &fl6, NULL);
 	if (!IS_ERR(dst)) {
 		skb_dst_set(skb, dst);
 		ip6_xmit(ctl_sk, skb, &fl6, NULL, 0);
@@ -879,7 +879,7 @@ static int dccp_v6_connect(struct sock *
 	opt = rcu_dereference_protected(np->opt, sock_owned_by_user(sk));
 	final_p = fl6_update_dst(&fl6, opt, &final);
 
-	dst = ip6_dst_lookup_flow(sk, &fl6, final_p);
+	dst = ip6_dst_lookup_flow(sock_net(sk), sk, &fl6, final_p);
 	if (IS_ERR(dst)) {
 		err = PTR_ERR(dst);
 		goto failure;
diff -druNp --no-dereference linux-libre-4.4.223-gnu/net/ipv4/cipso_ipv4.c linux-libre-4.4.224-gnu/net/ipv4/cipso_ipv4.c
--- linux-libre-4.4.223-gnu/net/ipv4/cipso_ipv4.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/net/ipv4/cipso_ipv4.c	2020-05-20 02:11:57.000000000 -0400
@@ -1343,7 +1343,8 @@ static int cipso_v4_parsetag_rbm(const s
 			return ret_val;
 		}
 
-		secattr->flags |= NETLBL_SECATTR_MLS_CAT;
+		if (secattr->attr.mls.cat)
+			secattr->flags |= NETLBL_SECATTR_MLS_CAT;
 	}
 
 	return 0;
@@ -1524,7 +1525,8 @@ static int cipso_v4_parsetag_rng(const s
 			return ret_val;
 		}
 
-		secattr->flags |= NETLBL_SECATTR_MLS_CAT;
+		if (secattr->attr.mls.cat)
+			secattr->flags |= NETLBL_SECATTR_MLS_CAT;
 	}
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.4.223-gnu/net/ipv4/ip_gre.c linux-libre-4.4.224-gnu/net/ipv4/ip_gre.c
--- linux-libre-4.4.223-gnu/net/ipv4/ip_gre.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/net/ipv4/ip_gre.c	2020-05-20 02:11:57.000000000 -0400
@@ -399,7 +399,10 @@ static int ipgre_rcv(struct sk_buff *skb
 				  iph->saddr, iph->daddr, tpi->key);
 
 	if (tunnel) {
-		skb_pop_mac_header(skb);
+		if (tunnel->dev->type != ARPHRD_NONE)
+			skb_pop_mac_header(skb);
+		else
+			skb_reset_mac_header(skb);
 		if (tunnel->collect_md) {
 			__be16 flags;
 			__be64 tun_id;
@@ -1015,6 +1018,8 @@ static void ipgre_netlink_parms(struct n
 		struct ip_tunnel *t = netdev_priv(dev);
 
 		t->collect_md = true;
+		if (dev->type == ARPHRD_IPGRE)
+			dev->type = ARPHRD_NONE;
 	}
 }
 
diff -druNp --no-dereference linux-libre-4.4.223-gnu/net/ipv4/route.c linux-libre-4.4.224-gnu/net/ipv4/route.c
--- linux-libre-4.4.223-gnu/net/ipv4/route.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/net/ipv4/route.c	2020-05-20 02:11:57.000000000 -0400
@@ -898,7 +898,7 @@ void ip_rt_send_redirect(struct sk_buff
 	/* Check for load limit; set rate_last to the latest sent
 	 * redirect.
 	 */
-	if (peer->rate_tokens == 0 ||
+	if (peer->n_redirects == 0 ||
 	    time_after(jiffies,
 		       (peer->rate_last +
 			(ip_rt_redirect_load << peer->n_redirects)))) {
diff -druNp --no-dereference linux-libre-4.4.223-gnu/net/ipv6/addrconf_core.c linux-libre-4.4.224-gnu/net/ipv6/addrconf_core.c
--- linux-libre-4.4.223-gnu/net/ipv6/addrconf_core.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/net/ipv6/addrconf_core.c	2020-05-20 02:11:57.000000000 -0400
@@ -107,15 +107,16 @@ int inet6addr_notifier_call_chain(unsign
 }
 EXPORT_SYMBOL(inet6addr_notifier_call_chain);
 
-static int eafnosupport_ipv6_dst_lookup(struct net *net, struct sock *u1,
-					struct dst_entry **u2,
-					struct flowi6 *u3)
+static struct dst_entry *eafnosupport_ipv6_dst_lookup_flow(struct net *net,
+							   const struct sock *sk,
+							   struct flowi6 *fl6,
+							   const struct in6_addr *final_dst)
 {
-	return -EAFNOSUPPORT;
+	return ERR_PTR(-EAFNOSUPPORT);
 }
 
 const struct ipv6_stub *ipv6_stub __read_mostly = &(struct ipv6_stub) {
-	.ipv6_dst_lookup = eafnosupport_ipv6_dst_lookup,
+	.ipv6_dst_lookup_flow = eafnosupport_ipv6_dst_lookup_flow,
 };
 EXPORT_SYMBOL_GPL(ipv6_stub);
 
diff -druNp --no-dereference linux-libre-4.4.223-gnu/net/ipv6/af_inet6.c linux-libre-4.4.224-gnu/net/ipv6/af_inet6.c
--- linux-libre-4.4.223-gnu/net/ipv6/af_inet6.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/net/ipv6/af_inet6.c	2020-05-20 02:11:57.000000000 -0400
@@ -683,7 +683,7 @@ int inet6_sk_rebuild_header(struct sock
 					 &final);
 		rcu_read_unlock();
 
-		dst = ip6_dst_lookup_flow(sk, &fl6, final_p);
+		dst = ip6_dst_lookup_flow(sock_net(sk), sk, &fl6, final_p);
 		if (IS_ERR(dst)) {
 			sk->sk_route_caps = 0;
 			sk->sk_err_soft = -PTR_ERR(dst);
@@ -841,7 +841,7 @@ static struct pernet_operations inet6_ne
 static const struct ipv6_stub ipv6_stub_impl = {
 	.ipv6_sock_mc_join = ipv6_sock_mc_join,
 	.ipv6_sock_mc_drop = ipv6_sock_mc_drop,
-	.ipv6_dst_lookup = ip6_dst_lookup,
+	.ipv6_dst_lookup_flow = ip6_dst_lookup_flow,
 	.udpv6_encap_enable = udpv6_encap_enable,
 	.ndisc_send_na = ndisc_send_na,
 	.nd_tbl	= &nd_tbl,
@@ -1029,11 +1029,11 @@ netfilter_fail:
 igmp_fail:
 	ndisc_cleanup();
 ndisc_fail:
-	ip6_mr_cleanup();
+	icmpv6_cleanup();
 icmp_fail:
-	unregister_pernet_subsys(&inet6_net_ops);
+	ip6_mr_cleanup();
 ipmr_fail:
-	icmpv6_cleanup();
+	unregister_pernet_subsys(&inet6_net_ops);
 register_pernet_fail:
 	sock_unregister(PF_INET6);
 	rtnl_unregister_all(PF_INET6);
diff -druNp --no-dereference linux-libre-4.4.223-gnu/net/ipv6/datagram.c linux-libre-4.4.224-gnu/net/ipv6/datagram.c
--- linux-libre-4.4.223-gnu/net/ipv6/datagram.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/net/ipv6/datagram.c	2020-05-20 02:11:57.000000000 -0400
@@ -179,7 +179,7 @@ ipv4_connected:
 	final_p = fl6_update_dst(&fl6, opt, &final);
 	rcu_read_unlock();
 
-	dst = ip6_dst_lookup_flow(sk, &fl6, final_p);
+	dst = ip6_dst_lookup_flow(sock_net(sk), sk, &fl6, final_p);
 	err = 0;
 	if (IS_ERR(dst)) {
 		err = PTR_ERR(dst);
diff -druNp --no-dereference linux-libre-4.4.223-gnu/net/ipv6/icmp.c linux-libre-4.4.224-gnu/net/ipv6/icmp.c
--- linux-libre-4.4.223-gnu/net/ipv6/icmp.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/net/ipv6/icmp.c	2020-05-20 02:11:57.000000000 -0400
@@ -445,8 +445,10 @@ static void icmp6_send(struct sk_buff *s
 
 	if (__ipv6_addr_needs_scope_id(addr_type))
 		iif = skb->dev->ifindex;
-	else
-		iif = l3mdev_master_ifindex(skb_dst(skb)->dev);
+	else {
+		dst = skb_dst(skb);
+		iif = l3mdev_master_ifindex(dst ? dst->dev : skb->dev);
+	}
 
 	/*
 	 *	Must not send error if the source does not uniquely
diff -druNp --no-dereference linux-libre-4.4.223-gnu/net/ipv6/inet6_connection_sock.c linux-libre-4.4.224-gnu/net/ipv6/inet6_connection_sock.c
--- linux-libre-4.4.223-gnu/net/ipv6/inet6_connection_sock.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/net/ipv6/inet6_connection_sock.c	2020-05-20 02:11:57.000000000 -0400
@@ -88,7 +88,7 @@ struct dst_entry *inet6_csk_route_req(co
 	fl6->fl6_sport = htons(ireq->ir_num);
 	security_req_classify_flow(req, flowi6_to_flowi(fl6));
 
-	dst = ip6_dst_lookup_flow(sk, fl6, final_p);
+	dst = ip6_dst_lookup_flow(sock_net(sk), sk, fl6, final_p);
 	if (IS_ERR(dst))
 		return NULL;
 
@@ -142,7 +142,7 @@ static struct dst_entry *inet6_csk_route
 
 	dst = __inet6_csk_dst_check(sk, np->dst_cookie);
 	if (!dst) {
-		dst = ip6_dst_lookup_flow(sk, fl6, final_p);
+		dst = ip6_dst_lookup_flow(sock_net(sk), sk, fl6, final_p);
 
 		if (!IS_ERR(dst))
 			ip6_dst_store(sk, dst, NULL, NULL);
diff -druNp --no-dereference linux-libre-4.4.223-gnu/net/ipv6/ip6_output.c linux-libre-4.4.224-gnu/net/ipv6/ip6_output.c
--- linux-libre-4.4.223-gnu/net/ipv6/ip6_output.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/net/ipv6/ip6_output.c	2020-05-20 02:11:57.000000000 -0400
@@ -1057,13 +1057,13 @@ EXPORT_SYMBOL_GPL(ip6_dst_lookup);
  *	It returns a valid dst pointer on success, or a pointer encoded
  *	error code.
  */
-struct dst_entry *ip6_dst_lookup_flow(const struct sock *sk, struct flowi6 *fl6,
+struct dst_entry *ip6_dst_lookup_flow(struct net *net, const struct sock *sk, struct flowi6 *fl6,
 				      const struct in6_addr *final_dst)
 {
 	struct dst_entry *dst = NULL;
 	int err;
 
-	err = ip6_dst_lookup_tail(sock_net(sk), sk, &dst, fl6);
+	err = ip6_dst_lookup_tail(net, sk, &dst, fl6);
 	if (err)
 		return ERR_PTR(err);
 	if (final_dst)
@@ -1071,7 +1071,7 @@ struct dst_entry *ip6_dst_lookup_flow(co
 	if (!fl6->flowi6_oif)
 		fl6->flowi6_oif = l3mdev_fib_oif(dst->dev);
 
-	return xfrm_lookup_route(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0);
+	return xfrm_lookup_route(net, dst, flowi6_to_flowi(fl6), sk, 0);
 }
 EXPORT_SYMBOL_GPL(ip6_dst_lookup_flow);
 
@@ -1096,7 +1096,7 @@ struct dst_entry *ip6_sk_dst_lookup_flow
 
 	dst = ip6_sk_dst_check(sk, dst, fl6);
 	if (!dst)
-		dst = ip6_dst_lookup_flow(sk, fl6, final_dst);
+		dst = ip6_dst_lookup_flow(sock_net(sk), sk, fl6, final_dst);
 
 	return dst;
 }
diff -druNp --no-dereference linux-libre-4.4.223-gnu/net/ipv6/raw.c linux-libre-4.4.224-gnu/net/ipv6/raw.c
--- linux-libre-4.4.223-gnu/net/ipv6/raw.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/net/ipv6/raw.c	2020-05-20 02:11:57.000000000 -0400
@@ -889,7 +889,7 @@ static int rawv6_sendmsg(struct sock *sk
 	if (hdrincl)
 		fl6.flowi6_flags |= FLOWI_FLAG_KNOWN_NH;
 
-	dst = ip6_dst_lookup_flow(sk, &fl6, final_p);
+	dst = ip6_dst_lookup_flow(sock_net(sk), sk, &fl6, final_p);
 	if (IS_ERR(dst)) {
 		err = PTR_ERR(dst);
 		goto out;
diff -druNp --no-dereference linux-libre-4.4.223-gnu/net/ipv6/syncookies.c linux-libre-4.4.224-gnu/net/ipv6/syncookies.c
--- linux-libre-4.4.223-gnu/net/ipv6/syncookies.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/net/ipv6/syncookies.c	2020-05-20 02:11:57.000000000 -0400
@@ -231,7 +231,7 @@ struct sock *cookie_v6_check(struct sock
 		fl6.fl6_sport = inet_sk(sk)->inet_sport;
 		security_req_classify_flow(req, flowi6_to_flowi(&fl6));
 
-		dst = ip6_dst_lookup_flow(sk, &fl6, final_p);
+		dst = ip6_dst_lookup_flow(sock_net(sk), sk, &fl6, final_p);
 		if (IS_ERR(dst))
 			goto out_free;
 	}
diff -druNp --no-dereference linux-libre-4.4.223-gnu/net/ipv6/tcp_ipv6.c linux-libre-4.4.224-gnu/net/ipv6/tcp_ipv6.c
--- linux-libre-4.4.223-gnu/net/ipv6/tcp_ipv6.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/net/ipv6/tcp_ipv6.c	2020-05-20 02:11:57.000000000 -0400
@@ -245,7 +245,7 @@ static int tcp_v6_connect(struct sock *s
 
 	security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
 
-	dst = ip6_dst_lookup_flow(sk, &fl6, final_p);
+	dst = ip6_dst_lookup_flow(sock_net(sk), sk, &fl6, final_p);
 	if (IS_ERR(dst)) {
 		err = PTR_ERR(dst);
 		goto failure;
@@ -831,7 +831,7 @@ static void tcp_v6_send_response(const s
 	 * Underlying function will use this to retrieve the network
 	 * namespace
 	 */
-	dst = ip6_dst_lookup_flow(ctl_sk, &fl6, NULL);
+	dst = ip6_dst_lookup_flow(sock_net(ctl_sk), ctl_sk, &fl6, NULL);
 	if (!IS_ERR(dst)) {
 		skb_dst_set(buff, dst);
 		ip6_xmit(ctl_sk, buff, &fl6, NULL, tclass);
diff -druNp --no-dereference linux-libre-4.4.223-gnu/net/l2tp/l2tp_ip6.c linux-libre-4.4.224-gnu/net/l2tp/l2tp_ip6.c
--- linux-libre-4.4.223-gnu/net/l2tp/l2tp_ip6.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/net/l2tp/l2tp_ip6.c	2020-05-20 02:11:57.000000000 -0400
@@ -619,7 +619,7 @@ static int l2tp_ip6_sendmsg(struct sock
 
 	security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
 
-	dst = ip6_dst_lookup_flow(sk, &fl6, final_p);
+	dst = ip6_dst_lookup_flow(sock_net(sk), sk, &fl6, final_p);
 	if (IS_ERR(dst)) {
 		err = PTR_ERR(dst);
 		goto out;
diff -druNp --no-dereference linux-libre-4.4.223-gnu/net/mpls/af_mpls.c linux-libre-4.4.224-gnu/net/mpls/af_mpls.c
--- linux-libre-4.4.223-gnu/net/mpls/af_mpls.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/net/mpls/af_mpls.c	2020-05-20 02:11:57.000000000 -0400
@@ -470,16 +470,15 @@ static struct net_device *inet6_fib_look
 	struct net_device *dev;
 	struct dst_entry *dst;
 	struct flowi6 fl6;
-	int err;
 
 	if (!ipv6_stub)
 		return ERR_PTR(-EAFNOSUPPORT);
 
 	memset(&fl6, 0, sizeof(fl6));
 	memcpy(&fl6.daddr, addr, sizeof(struct in6_addr));
-	err = ipv6_stub->ipv6_dst_lookup(net, NULL, &dst, &fl6);
-	if (err)
-		return ERR_PTR(err);
+	dst = ipv6_stub->ipv6_dst_lookup_flow(net, NULL, &fl6, NULL);
+	if (IS_ERR(dst))
+		return ERR_CAST(dst);
 
 	dev = dst->dev;
 	dev_hold(dev);
diff -druNp --no-dereference linux-libre-4.4.223-gnu/net/netfilter/nf_conntrack_core.c linux-libre-4.4.224-gnu/net/netfilter/nf_conntrack_core.c
--- linux-libre-4.4.223-gnu/net/netfilter/nf_conntrack_core.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/net/netfilter/nf_conntrack_core.c	2020-05-20 02:11:57.000000000 -0400
@@ -898,9 +898,9 @@ __nf_conntrack_alloc(struct net *net,
 	/* Don't set timer yet: wait for confirmation */
 	setup_timer(&ct->timeout, death_by_timeout, (unsigned long)ct);
 	write_pnet(&ct->ct_net, net);
-	memset(&ct->__nfct_init_offset[0], 0,
+	memset(&ct->__nfct_init_offset, 0,
 	       offsetof(struct nf_conn, proto) -
-	       offsetof(struct nf_conn, __nfct_init_offset[0]));
+	       offsetof(struct nf_conn, __nfct_init_offset));
 
 	if (zone && nf_ct_zone_add(ct, GFP_ATOMIC, zone) < 0)
 		goto out_free;
diff -druNp --no-dereference linux-libre-4.4.223-gnu/net/netlabel/netlabel_kapi.c linux-libre-4.4.224-gnu/net/netlabel/netlabel_kapi.c
--- linux-libre-4.4.223-gnu/net/netlabel/netlabel_kapi.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/net/netlabel/netlabel_kapi.c	2020-05-20 02:11:57.000000000 -0400
@@ -605,6 +605,12 @@ int netlbl_catmap_getlong(struct netlbl_
 	if ((off & (BITS_PER_LONG - 1)) != 0)
 		return -EINVAL;
 
+	/* a null catmap is equivalent to an empty one */
+	if (!catmap) {
+		*offset = (u32)-1;
+		return 0;
+	}
+
 	if (off < catmap->startbit) {
 		off = catmap->startbit;
 		*offset = off;
diff -druNp --no-dereference linux-libre-4.4.223-gnu/net/openvswitch/actions.c linux-libre-4.4.224-gnu/net/openvswitch/actions.c
--- linux-libre-4.4.223-gnu/net/openvswitch/actions.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/net/openvswitch/actions.c	2020-05-20 02:11:57.000000000 -0400
@@ -143,8 +143,7 @@ static void update_ethertype(struct sk_b
 	if (skb->ip_summed == CHECKSUM_COMPLETE) {
 		__be16 diff[] = { ~(hdr->h_proto), ethertype };
 
-		skb->csum = ~csum_partial((char *)diff, sizeof(diff),
-					~skb->csum);
+		skb->csum = csum_partial((char *)diff, sizeof(diff), skb->csum);
 	}
 
 	hdr->h_proto = ethertype;
@@ -227,8 +226,7 @@ static int set_mpls(struct sk_buff *skb,
 	if (skb->ip_summed == CHECKSUM_COMPLETE) {
 		__be32 diff[] = { ~(*stack), lse };
 
-		skb->csum = ~csum_partial((char *)diff, sizeof(diff),
-					  ~skb->csum);
+		skb->csum = csum_partial((char *)diff, sizeof(diff), skb->csum);
 	}
 
 	*stack = lse;
diff -druNp --no-dereference linux-libre-4.4.223-gnu/net/sched/sch_choke.c linux-libre-4.4.224-gnu/net/sched/sch_choke.c
--- linux-libre-4.4.223-gnu/net/sched/sch_choke.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/net/sched/sch_choke.c	2020-05-20 02:11:57.000000000 -0400
@@ -396,7 +396,8 @@ static void choke_reset(struct Qdisc *sc
 		qdisc_drop(skb, sch);
 	}
 
-	memset(q->tab, 0, (q->tab_mask + 1) * sizeof(struct sk_buff *));
+	if (q->tab)
+		memset(q->tab, 0, (q->tab_mask + 1) * sizeof(struct sk_buff *));
 	q->head = q->tail = 0;
 	red_restart(&q->vars);
 }
diff -druNp --no-dereference linux-libre-4.4.223-gnu/net/sched/sch_sfq.c linux-libre-4.4.224-gnu/net/sched/sch_sfq.c
--- linux-libre-4.4.223-gnu/net/sched/sch_sfq.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/net/sched/sch_sfq.c	2020-05-20 02:11:57.000000000 -0400
@@ -635,6 +635,15 @@ static int sfq_change(struct Qdisc *sch,
 	if (ctl->divisor &&
 	    (!is_power_of_2(ctl->divisor) || ctl->divisor > 65536))
 		return -EINVAL;
+
+	/* slot->allot is a short, make sure quantum is not too big. */
+	if (ctl->quantum) {
+		unsigned int scaled = SFQ_ALLOT_SIZE(ctl->quantum);
+
+		if (scaled <= 0 || scaled > SHRT_MAX)
+			return -EINVAL;
+	}
+
 	if (ctl_v1 && !red_check_params(ctl_v1->qth_min, ctl_v1->qth_max,
 					ctl_v1->Wlog))
 		return -EINVAL;
diff -druNp --no-dereference linux-libre-4.4.223-gnu/net/sctp/ipv6.c linux-libre-4.4.224-gnu/net/sctp/ipv6.c
--- linux-libre-4.4.223-gnu/net/sctp/ipv6.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/net/sctp/ipv6.c	2020-05-20 02:11:57.000000000 -0400
@@ -268,7 +268,7 @@ static void sctp_v6_get_dst(struct sctp_
 	final_p = fl6_update_dst(fl6, rcu_dereference(np->opt), &final);
 	rcu_read_unlock();
 
-	dst = ip6_dst_lookup_flow(sk, fl6, final_p);
+	dst = ip6_dst_lookup_flow(sock_net(sk), sk, fl6, final_p);
 	if (!asoc || saddr) {
 		t->dst = dst;
 		memcpy(fl, &_fl, sizeof(_fl));
@@ -326,7 +326,7 @@ static void sctp_v6_get_dst(struct sctp_
 		fl6->saddr = laddr->a.v6.sin6_addr;
 		fl6->fl6_sport = laddr->a.v6.sin6_port;
 		final_p = fl6_update_dst(fl6, rcu_dereference(np->opt), &final);
-		bdst = ip6_dst_lookup_flow(sk, fl6, final_p);
+		bdst = ip6_dst_lookup_flow(sock_net(sk), sk, fl6, final_p);
 
 		if (IS_ERR(bdst))
 			continue;
diff -druNp --no-dereference linux-libre-4.4.223-gnu/net/tipc/udp_media.c linux-libre-4.4.224-gnu/net/tipc/udp_media.c
--- linux-libre-4.4.223-gnu/net/tipc/udp_media.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/net/tipc/udp_media.c	2020-05-20 02:11:57.000000000 -0400
@@ -200,10 +200,13 @@ static int tipc_udp_send_msg(struct net
 			.saddr = src->ipv6,
 			.flowi6_proto = IPPROTO_UDP
 		};
-		err = ipv6_stub->ipv6_dst_lookup(net, ub->ubsock->sk, &ndst,
-						 &fl6);
-		if (err)
+		ndst = ipv6_stub->ipv6_dst_lookup_flow(net,
+						       ub->ubsock->sk,
+						       &fl6, NULL);
+		if (IS_ERR(ndst)) {
+			err = PTR_ERR(ndst);
 			goto tx_error;
+		}
 		ttl = ip6_dst_hoplimit(ndst);
 		err = udp_tunnel6_xmit_skb(ndst, ub->ubsock->sk, skb,
 					   ndst->dev, &src->ipv6,
diff -druNp --no-dereference linux-libre-4.4.223-gnu/scripts/decodecode linux-libre-4.4.224-gnu/scripts/decodecode
--- linux-libre-4.4.223-gnu/scripts/decodecode	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/scripts/decodecode	2020-05-20 02:11:57.000000000 -0400
@@ -98,7 +98,7 @@ faultlinenum=$(( $(wc -l $T.oo  | cut -d
 faultline=`cat $T.dis | head -1 | cut -d":" -f2-`
 faultline=`echo "$faultline" | sed -e 's/\[/\\\[/g; s/\]/\\\]/g'`
 
-cat $T.oo | sed -e "${faultlinenum}s/^\(.*:\)\(.*\)/\1\*\2\t\t<-- trapping instruction/"
+cat $T.oo | sed -e "${faultlinenum}s/^\([^:]*:\)\(.*\)/\1\*\2\t\t<-- trapping instruction/"
 echo
 cat $T.aa
 cleanup
diff -druNp --no-dereference linux-libre-4.4.223-gnu/sound/core/rawmidi.c linux-libre-4.4.224-gnu/sound/core/rawmidi.c
--- linux-libre-4.4.223-gnu/sound/core/rawmidi.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/sound/core/rawmidi.c	2020-05-20 02:11:57.000000000 -0400
@@ -108,6 +108,17 @@ static void snd_rawmidi_input_event_work
 		runtime->event(runtime->substream);
 }
 
+/* buffer refcount management: call with runtime->lock held */
+static inline void snd_rawmidi_buffer_ref(struct snd_rawmidi_runtime *runtime)
+{
+	runtime->buffer_ref++;
+}
+
+static inline void snd_rawmidi_buffer_unref(struct snd_rawmidi_runtime *runtime)
+{
+	runtime->buffer_ref--;
+}
+
 static int snd_rawmidi_runtime_create(struct snd_rawmidi_substream *substream)
 {
 	struct snd_rawmidi_runtime *runtime;
@@ -125,7 +136,7 @@ static int snd_rawmidi_runtime_create(st
 		runtime->avail = 0;
 	else
 		runtime->avail = runtime->buffer_size;
-	if ((runtime->buffer = kmalloc(runtime->buffer_size, GFP_KERNEL)) == NULL) {
+	if ((runtime->buffer = kzalloc(runtime->buffer_size, GFP_KERNEL)) == NULL) {
 		kfree(runtime);
 		return -ENOMEM;
 	}
@@ -650,10 +661,15 @@ int snd_rawmidi_output_params(struct snd
 		return -EINVAL;
 	}
 	if (params->buffer_size != runtime->buffer_size) {
-		newbuf = kmalloc(params->buffer_size, GFP_KERNEL);
+		newbuf = kzalloc(params->buffer_size, GFP_KERNEL);
 		if (!newbuf)
 			return -ENOMEM;
 		spin_lock_irq(&runtime->lock);
+		if (runtime->buffer_ref) {
+			spin_unlock_irq(&runtime->lock);
+			kfree(newbuf);
+			return -EBUSY;
+		}
 		oldbuf = runtime->buffer;
 		runtime->buffer = newbuf;
 		runtime->buffer_size = params->buffer_size;
@@ -962,8 +978,10 @@ static long snd_rawmidi_kernel_read1(str
 	long result = 0, count1;
 	struct snd_rawmidi_runtime *runtime = substream->runtime;
 	unsigned long appl_ptr;
+	int err = 0;
 
 	spin_lock_irqsave(&runtime->lock, flags);
+	snd_rawmidi_buffer_ref(runtime);
 	while (count > 0 && runtime->avail) {
 		count1 = runtime->buffer_size - runtime->appl_ptr;
 		if (count1 > count)
@@ -982,16 +1000,19 @@ static long snd_rawmidi_kernel_read1(str
 		if (userbuf) {
 			spin_unlock_irqrestore(&runtime->lock, flags);
 			if (copy_to_user(userbuf + result,
-					 runtime->buffer + appl_ptr, count1)) {
-				return result > 0 ? result : -EFAULT;
-			}
+					 runtime->buffer + appl_ptr, count1))
+				err = -EFAULT;
 			spin_lock_irqsave(&runtime->lock, flags);
+			if (err)
+				goto out;
 		}
 		result += count1;
 		count -= count1;
 	}
+ out:
+	snd_rawmidi_buffer_unref(runtime);
 	spin_unlock_irqrestore(&runtime->lock, flags);
-	return result;
+	return result > 0 ? result : err;
 }
 
 long snd_rawmidi_kernel_read(struct snd_rawmidi_substream *substream,
@@ -1262,6 +1283,7 @@ static long snd_rawmidi_kernel_write1(st
 			return -EAGAIN;
 		}
 	}
+	snd_rawmidi_buffer_ref(runtime);
 	while (count > 0 && runtime->avail > 0) {
 		count1 = runtime->buffer_size - runtime->appl_ptr;
 		if (count1 > count)
@@ -1293,6 +1315,7 @@ static long snd_rawmidi_kernel_write1(st
 	}
       __end:
 	count1 = runtime->avail < runtime->buffer_size;
+	snd_rawmidi_buffer_unref(runtime);
 	spin_unlock_irqrestore(&runtime->lock, flags);
 	if (count1)
 		snd_rawmidi_output_trigger(substream, 1);
diff -druNp --no-dereference linux-libre-4.4.223-gnu/sound/pci/hda/patch_realtek.c linux-libre-4.4.224-gnu/sound/pci/hda/patch_realtek.c
--- linux-libre-4.4.223-gnu/sound/pci/hda/patch_realtek.c	2020-05-10 04:26:37.000000000 -0400
+++ linux-libre-4.4.224-gnu/sound/pci/hda/patch_realtek.c	2020-05-20 02:11:57.000000000 -0400
@@ -4840,6 +4840,7 @@ enum {
 	ALC269_FIXUP_HP_LINE1_MIC1_LED,
 	ALC269_FIXUP_INV_DMIC,
 	ALC269_FIXUP_LENOVO_DOCK,
+	ALC269_FIXUP_LENOVO_DOCK_LIMIT_BOOST,
 	ALC269_FIXUP_NO_SHUTUP,
 	ALC286_FIXUP_SONY_MIC_NO_PRESENCE,
 	ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT,
@@ -5106,6 +5107,12 @@ static const struct hda_fixup alc269_fix
 		.chained = true,
 		.chain_id = ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT
 	},
+	[ALC269_FIXUP_LENOVO_DOCK_LIMIT_BOOST] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = alc269_fixup_limit_int_mic_boost,
+		.chained = true,
+		.chain_id = ALC269_FIXUP_LENOVO_DOCK,
+	},
 	[ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT] = {
 		.type = HDA_FIXUP_FUNC,
 		.v.func = alc269_fixup_pincfg_no_hp_to_lineout,
@@ -5760,7 +5767,7 @@ static const struct snd_pci_quirk alc269
 	SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE),
 	SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE),
 	SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE),
-	SND_PCI_QUIRK(0x17aa, 0x21f6, "Thinkpad T530", ALC269_FIXUP_LENOVO_DOCK),
+	SND_PCI_QUIRK(0x17aa, 0x21f6, "Thinkpad T530", ALC269_FIXUP_LENOVO_DOCK_LIMIT_BOOST),
 	SND_PCI_QUIRK(0x17aa, 0x21fa, "Thinkpad X230", ALC269_FIXUP_LENOVO_DOCK),
 	SND_PCI_QUIRK(0x17aa, 0x21f3, "Thinkpad T430", ALC269_FIXUP_LENOVO_DOCK),
 	SND_PCI_QUIRK(0x17aa, 0x21fb, "Thinkpad T430s", ALC269_FIXUP_LENOVO_DOCK),
@@ -5870,6 +5877,7 @@ static const struct hda_model_fixup alc2
 	{.id = ALC269_FIXUP_HEADSET_MODE, .name = "headset-mode"},
 	{.id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC, .name = "headset-mode-no-hp-mic"},
 	{.id = ALC269_FIXUP_LENOVO_DOCK, .name = "lenovo-dock"},
+	{.id = ALC269_FIXUP_LENOVO_DOCK_LIMIT_BOOST, .name = "lenovo-dock-limit-boost"},
 	{.id = ALC269_FIXUP_HP_GPIO_LED, .name = "hp-gpio-led"},
 	{.id = ALC269_FIXUP_HP_DOCK_GPIO_MIC1_LED, .name = "hp-dock-gpio-mic1-led"},
 	{.id = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "dell-headset-multi"},
@@ -6333,8 +6341,6 @@ static int patch_alc269(struct hda_codec
 		alc_update_coef_idx(codec, 0x36, 1 << 13, 1 << 5); /* Switch pcbeep path to Line in path*/
 		break;
 	case 0x10ec0225:
-		codec->power_save_node = 1;
-		/* fall through */
 	case 0x10ec0295:
 	case 0x10ec0299:
 		spec->codec_variant = ALC269_TYPE_ALC225;
