diff -druNp --no-dereference linux-libre-4.12.2-gnu/arch/arm/include/asm/elf.h linux-libre-4.12.3-gnu/arch/arm/include/asm/elf.h
--- linux-libre-4.12.2-gnu/arch/arm/include/asm/elf.h	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/arch/arm/include/asm/elf.h	2017-07-21 00:59:24.000000000 -0400
@@ -112,12 +112,8 @@ int dump_task_regs(struct task_struct *t
 #define CORE_DUMP_USE_REGSET
 #define ELF_EXEC_PAGESIZE	4096
 
-/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
-   use of this is to invoke "./ld.so someprog" to test out a new version of
-   the loader.  We need to make sure that it is out of the way of the program
-   that it will "exec", and that there is sufficient room for the brk.  */
-
-#define ELF_ET_DYN_BASE	(TASK_SIZE / 3 * 2)
+/* This is the base location for PIE (ET_DYN with INTERP) loads. */
+#define ELF_ET_DYN_BASE		0x400000UL
 
 /* When the program starts, a1 contains a pointer to a function to be 
    registered with atexit, as per the SVR4 ABI.  A value of 0 means we 
diff -druNp --no-dereference linux-libre-4.12.2-gnu/arch/arm64/boot/dts/marvell/armada-37xx.dtsi linux-libre-4.12.3-gnu/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
--- linux-libre-4.12.2-gnu/arch/arm64/boot/dts/marvell/armada-37xx.dtsi	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/arch/arm64/boot/dts/marvell/armada-37xx.dtsi	2017-07-21 00:59:24.000000000 -0400
@@ -75,14 +75,10 @@
 
 	timer {
 		compatible = "arm,armv8-timer";
-		interrupts = <GIC_PPI 13
-			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
-			     <GIC_PPI 14
-			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
-			     <GIC_PPI 11
-			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
-			     <GIC_PPI 10
-			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
+		interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_PPI 14 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_PPI 11 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_PPI 10 IRQ_TYPE_LEVEL_HIGH>;
 	};
 
 	soc {
diff -druNp --no-dereference linux-libre-4.12.2-gnu/arch/arm64/include/asm/elf.h linux-libre-4.12.3-gnu/arch/arm64/include/asm/elf.h
--- linux-libre-4.12.2-gnu/arch/arm64/include/asm/elf.h	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/arch/arm64/include/asm/elf.h	2017-07-21 00:59:24.000000000 -0400
@@ -113,12 +113,11 @@
 #define ELF_EXEC_PAGESIZE	PAGE_SIZE
 
 /*
- * This is the location that an ET_DYN program is loaded if exec'ed.  Typical
- * use of this is to invoke "./ld.so someprog" to test out a new version of
- * the loader.  We need to make sure that it is out of the way of the program
- * that it will "exec", and that there is sufficient room for the brk.
+ * This is the base location for PIE (ET_DYN with INTERP) loads. On
+ * 64-bit, this is raised to 4GB to leave the entire 32-bit address
+ * space open for things that want to use the area for 32-bit pointers.
  */
-#define ELF_ET_DYN_BASE	(2 * TASK_SIZE_64 / 3)
+#define ELF_ET_DYN_BASE		0x100000000UL
 
 #ifndef __ASSEMBLY__
 
@@ -142,6 +141,7 @@ typedef struct user_fpsimd_state elf_fpr
 ({									\
 	clear_bit(TIF_32BIT, &current->mm->context.flags);		\
 	clear_thread_flag(TIF_32BIT);					\
+	current->personality &= ~READ_IMPLIES_EXEC;			\
 })
 
 /* update AT_VECTOR_SIZE_ARCH if the number of NEW_AUX_ENT entries changes */
@@ -173,7 +173,8 @@ extern int arch_setup_additional_pages(s
 
 #ifdef CONFIG_COMPAT
 
-#define COMPAT_ELF_ET_DYN_BASE		(2 * TASK_SIZE_32 / 3)
+/* PIE load location for compat arm. Must match ARM ELF_ET_DYN_BASE. */
+#define COMPAT_ELF_ET_DYN_BASE		0x000400000UL
 
 /* AArch32 registers. */
 #define COMPAT_ELF_NGREG		18
@@ -187,6 +188,11 @@ typedef compat_elf_greg_t		compat_elf_gr
 					 ((x)->e_flags & EF_ARM_EABI_MASK))
 
 #define compat_start_thread		compat_start_thread
+/*
+ * Unlike the native SET_PERSONALITY macro, the compat version inherits
+ * READ_IMPLIES_EXEC across a fork() since this is the behaviour on
+ * arch/arm/.
+ */
 #define COMPAT_SET_PERSONALITY(ex)					\
 ({									\
 	set_bit(TIF_32BIT, &current->mm->context.flags);		\
diff -druNp --no-dereference linux-libre-4.12.2-gnu/arch/parisc/include/asm/dma-mapping.h linux-libre-4.12.3-gnu/arch/parisc/include/asm/dma-mapping.h
--- linux-libre-4.12.2-gnu/arch/parisc/include/asm/dma-mapping.h	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/arch/parisc/include/asm/dma-mapping.h	2017-07-21 00:59:24.000000000 -0400
@@ -20,6 +20,8 @@
 ** flush/purge and allocate "regular" cacheable pages for everything.
 */
 
+#define DMA_ERROR_CODE	(~(dma_addr_t)0)
+
 #ifdef CONFIG_PA11
 extern const struct dma_map_ops pcxl_dma_ops;
 extern const struct dma_map_ops pcx_dma_ops;
@@ -54,12 +56,13 @@ parisc_walk_tree(struct device *dev)
 			break;
 		}
 	}
-	BUG_ON(!dev->platform_data);
 	return dev->platform_data;
 }
-		
-#define GET_IOC(dev) (HBA_DATA(parisc_walk_tree(dev))->iommu)
-	
+
+#define GET_IOC(dev) ({					\
+	void *__pdata = parisc_walk_tree(dev);		\
+	__pdata ? HBA_DATA(__pdata)->iommu : NULL;	\
+})
 
 #ifdef CONFIG_IOMMU_CCIO
 struct parisc_device;
diff -druNp --no-dereference linux-libre-4.12.2-gnu/arch/parisc/include/asm/mmu_context.h linux-libre-4.12.3-gnu/arch/parisc/include/asm/mmu_context.h
--- linux-libre-4.12.2-gnu/arch/parisc/include/asm/mmu_context.h	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/arch/parisc/include/asm/mmu_context.h	2017-07-21 00:59:24.000000000 -0400
@@ -49,15 +49,26 @@ static inline void load_context(mm_conte
 	mtctl(__space_to_prot(context), 8);
 }
 
-static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk)
+static inline void switch_mm_irqs_off(struct mm_struct *prev,
+		struct mm_struct *next, struct task_struct *tsk)
 {
-
 	if (prev != next) {
 		mtctl(__pa(next->pgd), 25);
 		load_context(next->context);
 	}
 }
 
+static inline void switch_mm(struct mm_struct *prev,
+		struct mm_struct *next, struct task_struct *tsk)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	switch_mm_irqs_off(prev, next, tsk);
+	local_irq_restore(flags);
+}
+#define switch_mm_irqs_off switch_mm_irqs_off
+
 #define deactivate_mm(tsk,mm)	do { } while (0)
 
 static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next)
diff -druNp --no-dereference linux-libre-4.12.2-gnu/arch/parisc/kernel/syscall_table.S linux-libre-4.12.3-gnu/arch/parisc/kernel/syscall_table.S
--- linux-libre-4.12.2-gnu/arch/parisc/kernel/syscall_table.S	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/arch/parisc/kernel/syscall_table.S	2017-07-21 00:59:24.000000000 -0400
@@ -361,7 +361,7 @@
 	ENTRY_SAME(ni_syscall)	/* 263: reserved for vserver */
 	ENTRY_SAME(add_key)
 	ENTRY_SAME(request_key)		/* 265 */
-	ENTRY_SAME(keyctl)
+	ENTRY_COMP(keyctl)
 	ENTRY_SAME(ioprio_set)
 	ENTRY_SAME(ioprio_get)
 	ENTRY_SAME(inotify_init)
diff -druNp --no-dereference linux-libre-4.12.2-gnu/arch/parisc/mm/fault.c linux-libre-4.12.3-gnu/arch/parisc/mm/fault.c
--- linux-libre-4.12.2-gnu/arch/parisc/mm/fault.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/arch/parisc/mm/fault.c	2017-07-21 00:59:24.000000000 -0400
@@ -367,7 +367,7 @@ bad_area:
 		case 15:	/* Data TLB miss fault/Data page fault */
 			/* send SIGSEGV when outside of vma */
 			if (!vma ||
-			    address < vma->vm_start || address > vma->vm_end) {
+			    address < vma->vm_start || address >= vma->vm_end) {
 				si.si_signo = SIGSEGV;
 				si.si_code = SEGV_MAPERR;
 				break;
diff -druNp --no-dereference linux-libre-4.12.2-gnu/arch/powerpc/include/asm/elf.h linux-libre-4.12.3-gnu/arch/powerpc/include/asm/elf.h
--- linux-libre-4.12.2-gnu/arch/powerpc/include/asm/elf.h	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/arch/powerpc/include/asm/elf.h	2017-07-21 00:59:24.000000000 -0400
@@ -23,12 +23,13 @@
 #define CORE_DUMP_USE_REGSET
 #define ELF_EXEC_PAGESIZE	PAGE_SIZE
 
-/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
-   use of this is to invoke "./ld.so someprog" to test out a new version of
-   the loader.  We need to make sure that it is out of the way of the program
-   that it will "exec", and that there is sufficient room for the brk.  */
-
-#define ELF_ET_DYN_BASE	0x20000000
+/*
+ * This is the base location for PIE (ET_DYN with INTERP) loads. On
+ * 64-bit, this is raised to 4GB to leave the entire 32-bit address
+ * space open for things that want to use the area for 32-bit pointers.
+ */
+#define ELF_ET_DYN_BASE		(is_32bit_task() ? 0x000400000UL : \
+						   0x100000000UL)
 
 #define ELF_CORE_EFLAGS (is_elf2_task() ? 2 : 0)
 
diff -druNp --no-dereference linux-libre-4.12.2-gnu/arch/powerpc/kernel/misc_64.S linux-libre-4.12.3-gnu/arch/powerpc/kernel/misc_64.S
--- linux-libre-4.12.2-gnu/arch/powerpc/kernel/misc_64.S	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/arch/powerpc/kernel/misc_64.S	2017-07-21 00:59:24.000000000 -0400
@@ -614,6 +614,18 @@ _GLOBAL(kexec_sequence)
 	li	r0,0
 	std	r0,16(r1)
 
+BEGIN_FTR_SECTION
+	/*
+	 * This is the best time to turn AMR/IAMR off.
+	 * key 0 is used in radix for supervisor<->user
+	 * protection, but on hash key 0 is reserved
+	 * ideally we want to enter with a clean state.
+	 * NOTE, we rely on r0 being 0 from above.
+	 */
+	mtspr	SPRN_IAMR,r0
+	mtspr	SPRN_AMOR,r0
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
+
 	/* save regs for local vars on new stack.
 	 * yes, we won't go back, but ...
 	 */
diff -druNp --no-dereference linux-libre-4.12.2-gnu/arch/powerpc/kvm/book3s_xive.c linux-libre-4.12.3-gnu/arch/powerpc/kvm/book3s_xive.c
--- linux-libre-4.12.2-gnu/arch/powerpc/kvm/book3s_xive.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/arch/powerpc/kvm/book3s_xive.c	2017-07-21 00:59:24.000000000 -0400
@@ -1257,8 +1257,8 @@ static void xive_pre_save_scan(struct kv
 		if (!xc)
 			continue;
 		for (j = 0; j < KVMPPC_XIVE_Q_COUNT; j++) {
-			if (xc->queues[i].qpage)
-				xive_pre_save_queue(xive, &xc->queues[i]);
+			if (xc->queues[j].qpage)
+				xive_pre_save_queue(xive, &xc->queues[j]);
 		}
 	}
 
diff -druNp --no-dereference linux-libre-4.12.2-gnu/arch/s390/include/asm/elf.h linux-libre-4.12.3-gnu/arch/s390/include/asm/elf.h
--- linux-libre-4.12.2-gnu/arch/s390/include/asm/elf.h	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/arch/s390/include/asm/elf.h	2017-07-21 00:59:24.000000000 -0400
@@ -161,14 +161,13 @@ extern unsigned int vdso_enabled;
 #define CORE_DUMP_USE_REGSET
 #define ELF_EXEC_PAGESIZE	4096
 
-/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
-   use of this is to invoke "./ld.so someprog" to test out a new version of
-   the loader.  We need to make sure that it is out of the way of the program
-   that it will "exec", and that there is sufficient room for the brk. 64-bit
-   tasks are aligned to 4GB. */
-#define ELF_ET_DYN_BASE (is_compat_task() ? \
-				(STACK_TOP / 3 * 2) : \
-				(STACK_TOP / 3 * 2) & ~((1UL << 32) - 1))
+/*
+ * This is the base location for PIE (ET_DYN with INTERP) loads. On
+ * 64-bit, this is raised to 4GB to leave the entire 32-bit address
+ * space open for things that want to use the area for 32-bit pointers.
+ */
+#define ELF_ET_DYN_BASE		(is_compat_task() ? 0x000400000UL : \
+						    0x100000000UL)
 
 /* This yields a mask that user programs can use to figure out what
    instruction set this CPU supports. */
diff -druNp --no-dereference linux-libre-4.12.2-gnu/arch/sparc/include/asm/asm-prototypes.h linux-libre-4.12.3-gnu/arch/sparc/include/asm/asm-prototypes.h
--- linux-libre-4.12.2-gnu/arch/sparc/include/asm/asm-prototypes.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.12.3-gnu/arch/sparc/include/asm/asm-prototypes.h	2017-07-21 00:59:24.000000000 -0400
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved.
+ */
+
+#include <asm/xor.h>
+#include <asm/checksum.h>
+#include <asm/trap_block.h>
+#include <asm/uaccess.h>
+#include <asm/atomic.h>
+#include <asm/ftrace.h>
+#include <asm/cacheflush.h>
+#include <asm/oplib.h>
+#include <linux/atomic.h>
+
+void *__memscan_zero(void *, size_t);
+void *__memscan_generic(void *, int, size_t);
+void *__bzero(void *, size_t);
+void VISenter(void); /* Dummy prototype to supress warning */
+#undef memcpy
+#undef memset
+void *memcpy(void *dest, const void *src, size_t n);
+void *memset(void *s, int c, size_t n);
+typedef int TItype __attribute__((mode(TI)));
+TItype __multi3(TItype a, TItype b);
diff -druNp --no-dereference linux-libre-4.12.2-gnu/arch/sparc/lib/atomic_64.S linux-libre-4.12.3-gnu/arch/sparc/lib/atomic_64.S
--- linux-libre-4.12.2-gnu/arch/sparc/lib/atomic_64.S	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/arch/sparc/lib/atomic_64.S	2017-07-21 00:59:24.000000000 -0400
@@ -62,19 +62,23 @@ ENTRY(atomic_fetch_##op) /* %o0 = increm
 ENDPROC(atomic_fetch_##op);						\
 EXPORT_SYMBOL(atomic_fetch_##op);
 
-#define ATOMIC_OPS(op) ATOMIC_OP(op) ATOMIC_OP_RETURN(op) ATOMIC_FETCH_OP(op)
+ATOMIC_OP(add)
+ATOMIC_OP_RETURN(add)
+ATOMIC_FETCH_OP(add)
 
-ATOMIC_OPS(add)
-ATOMIC_OPS(sub)
+ATOMIC_OP(sub)
+ATOMIC_OP_RETURN(sub)
+ATOMIC_FETCH_OP(sub)
 
-#undef ATOMIC_OPS
-#define ATOMIC_OPS(op) ATOMIC_OP(op) ATOMIC_FETCH_OP(op)
+ATOMIC_OP(and)
+ATOMIC_FETCH_OP(and)
 
-ATOMIC_OPS(and)
-ATOMIC_OPS(or)
-ATOMIC_OPS(xor)
+ATOMIC_OP(or)
+ATOMIC_FETCH_OP(or)
+
+ATOMIC_OP(xor)
+ATOMIC_FETCH_OP(xor)
 
-#undef ATOMIC_OPS
 #undef ATOMIC_FETCH_OP
 #undef ATOMIC_OP_RETURN
 #undef ATOMIC_OP
@@ -124,19 +128,23 @@ ENTRY(atomic64_fetch_##op) /* %o0 = incr
 ENDPROC(atomic64_fetch_##op);						\
 EXPORT_SYMBOL(atomic64_fetch_##op);
 
-#define ATOMIC64_OPS(op) ATOMIC64_OP(op) ATOMIC64_OP_RETURN(op) ATOMIC64_FETCH_OP(op)
+ATOMIC64_OP(add)
+ATOMIC64_OP_RETURN(add)
+ATOMIC64_FETCH_OP(add)
 
-ATOMIC64_OPS(add)
-ATOMIC64_OPS(sub)
+ATOMIC64_OP(sub)
+ATOMIC64_OP_RETURN(sub)
+ATOMIC64_FETCH_OP(sub)
 
-#undef ATOMIC64_OPS
-#define ATOMIC64_OPS(op) ATOMIC64_OP(op) ATOMIC64_FETCH_OP(op)
+ATOMIC64_OP(and)
+ATOMIC64_FETCH_OP(and)
 
-ATOMIC64_OPS(and)
-ATOMIC64_OPS(or)
-ATOMIC64_OPS(xor)
+ATOMIC64_OP(or)
+ATOMIC64_FETCH_OP(or)
+
+ATOMIC64_OP(xor)
+ATOMIC64_FETCH_OP(xor)
 
-#undef ATOMIC64_OPS
 #undef ATOMIC64_FETCH_OP
 #undef ATOMIC64_OP_RETURN
 #undef ATOMIC64_OP
diff -druNp --no-dereference linux-libre-4.12.2-gnu/arch/sparc/lib/checksum_64.S linux-libre-4.12.3-gnu/arch/sparc/lib/checksum_64.S
--- linux-libre-4.12.2-gnu/arch/sparc/lib/checksum_64.S	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/arch/sparc/lib/checksum_64.S	2017-07-21 00:59:24.000000000 -0400
@@ -38,6 +38,7 @@ csum_partial_fix_alignment:
 
 	.align		32
 	.globl		csum_partial
+	.type		csum_partial,#function
 	EXPORT_SYMBOL(csum_partial)
 csum_partial:		/* %o0=buff, %o1=len, %o2=sum */
 	prefetch	[%o0 + 0x000], #n_reads
diff -druNp --no-dereference linux-libre-4.12.2-gnu/arch/sparc/lib/csum_copy.S linux-libre-4.12.3-gnu/arch/sparc/lib/csum_copy.S
--- linux-libre-4.12.2-gnu/arch/sparc/lib/csum_copy.S	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/arch/sparc/lib/csum_copy.S	2017-07-21 00:59:24.000000000 -0400
@@ -65,6 +65,7 @@
 	 add		%o5, %o4, %o4
 
 	.globl		FUNC_NAME
+	.type		FUNC_NAME,#function
 	EXPORT_SYMBOL(FUNC_NAME)
 FUNC_NAME:		/* %o0=src, %o1=dst, %o2=len, %o3=sum */
 	LOAD(prefetch, %o0 + 0x000, #n_reads)
diff -druNp --no-dereference linux-libre-4.12.2-gnu/arch/sparc/lib/memscan_64.S linux-libre-4.12.3-gnu/arch/sparc/lib/memscan_64.S
--- linux-libre-4.12.2-gnu/arch/sparc/lib/memscan_64.S	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/arch/sparc/lib/memscan_64.S	2017-07-21 00:59:24.000000000 -0400
@@ -14,6 +14,8 @@
 	.text
 	.align	32
 	.globl		__memscan_zero, __memscan_generic
+	.type		__memscan_zero,#function
+	.type		__memscan_generic,#function
 	.globl		memscan
 	EXPORT_SYMBOL(__memscan_zero)
 	EXPORT_SYMBOL(__memscan_generic)
diff -druNp --no-dereference linux-libre-4.12.2-gnu/arch/sparc/lib/memset.S linux-libre-4.12.3-gnu/arch/sparc/lib/memset.S
--- linux-libre-4.12.2-gnu/arch/sparc/lib/memset.S	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/arch/sparc/lib/memset.S	2017-07-21 00:59:24.000000000 -0400
@@ -63,6 +63,7 @@
 __bzero_begin:
 
 	.globl	__bzero
+	.type	__bzero,#function
 	.globl	memset
 	EXPORT_SYMBOL(__bzero)
 	EXPORT_SYMBOL(memset)
diff -druNp --no-dereference linux-libre-4.12.2-gnu/arch/sparc/mm/gup.c linux-libre-4.12.3-gnu/arch/sparc/mm/gup.c
--- linux-libre-4.12.2-gnu/arch/sparc/mm/gup.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/arch/sparc/mm/gup.c	2017-07-21 00:59:24.000000000 -0400
@@ -78,8 +78,8 @@ static int gup_huge_pmd(pmd_t *pmdp, pmd
 		return 0;
 
 	refs = 0;
-	head = pmd_page(pmd);
-	page = head + ((addr & ~PMD_MASK) >> PAGE_SHIFT);
+	page = pmd_page(pmd) + ((addr & ~PMD_MASK) >> PAGE_SHIFT);
+	head = compound_head(page);
 	do {
 		VM_BUG_ON(compound_head(page) != head);
 		pages[*nr] = page;
diff -druNp --no-dereference linux-libre-4.12.2-gnu/arch/x86/crypto/sha1_ssse3_glue.c linux-libre-4.12.3-gnu/arch/x86/crypto/sha1_ssse3_glue.c
--- linux-libre-4.12.2-gnu/arch/x86/crypto/sha1_ssse3_glue.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/arch/x86/crypto/sha1_ssse3_glue.c	2017-07-21 00:59:24.000000000 -0400
@@ -201,7 +201,7 @@ asmlinkage void sha1_transform_avx2(u32
 
 static bool avx2_usable(void)
 {
-	if (avx_usable() && boot_cpu_has(X86_FEATURE_AVX2)
+	if (false && avx_usable() && boot_cpu_has(X86_FEATURE_AVX2)
 		&& boot_cpu_has(X86_FEATURE_BMI1)
 		&& boot_cpu_has(X86_FEATURE_BMI2))
 		return true;
diff -druNp --no-dereference linux-libre-4.12.2-gnu/arch/x86/include/asm/elf.h linux-libre-4.12.3-gnu/arch/x86/include/asm/elf.h
--- linux-libre-4.12.2-gnu/arch/x86/include/asm/elf.h	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/arch/x86/include/asm/elf.h	2017-07-21 00:59:24.000000000 -0400
@@ -245,12 +245,13 @@ extern int force_personality32;
 #define CORE_DUMP_USE_REGSET
 #define ELF_EXEC_PAGESIZE	4096
 
-/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
-   use of this is to invoke "./ld.so someprog" to test out a new version of
-   the loader.  We need to make sure that it is out of the way of the program
-   that it will "exec", and that there is sufficient room for the brk.  */
-
-#define ELF_ET_DYN_BASE		(TASK_SIZE / 3 * 2)
+/*
+ * This is the base location for PIE (ET_DYN with INTERP) loads. On
+ * 64-bit, this is raised to 4GB to leave the entire 32-bit address
+ * space open for things that want to use the area for 32-bit pointers.
+ */
+#define ELF_ET_DYN_BASE		(mmap_is_ia32() ? 0x000400000UL : \
+						  0x100000000UL)
 
 /* This yields a mask that user programs can use to figure out what
    instruction set this CPU supports.  This could be done in user space,
diff -druNp --no-dereference linux-libre-4.12.2-gnu/arch/x86/include/asm/msr-index.h linux-libre-4.12.3-gnu/arch/x86/include/asm/msr-index.h
--- linux-libre-4.12.2-gnu/arch/x86/include/asm/msr-index.h	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/arch/x86/include/asm/msr-index.h	2017-07-21 00:59:24.000000000 -0400
@@ -420,6 +420,8 @@
 #define MSR_IA32_TSC_ADJUST             0x0000003b
 #define MSR_IA32_BNDCFGS		0x00000d90
 
+#define MSR_IA32_BNDCFGS_RSVD		0x00000ffc
+
 #define MSR_IA32_XSS			0x00000da0
 
 #define FEATURE_CONTROL_LOCKED				(1<<0)
diff -druNp --no-dereference linux-libre-4.12.2-gnu/arch/x86/kvm/cpuid.h linux-libre-4.12.3-gnu/arch/x86/kvm/cpuid.h
--- linux-libre-4.12.2-gnu/arch/x86/kvm/cpuid.h	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/arch/x86/kvm/cpuid.h	2017-07-21 00:59:24.000000000 -0400
@@ -144,6 +144,14 @@ static inline bool guest_cpuid_has_rtm(s
 	return best && (best->ebx & bit(X86_FEATURE_RTM));
 }
 
+static inline bool guest_cpuid_has_mpx(struct kvm_vcpu *vcpu)
+{
+	struct kvm_cpuid_entry2 *best;
+
+	best = kvm_find_cpuid_entry(vcpu, 7, 0);
+	return best && (best->ebx & bit(X86_FEATURE_MPX));
+}
+
 static inline bool guest_cpuid_has_rdtscp(struct kvm_vcpu *vcpu)
 {
 	struct kvm_cpuid_entry2 *best;
diff -druNp --no-dereference linux-libre-4.12.2-gnu/arch/x86/kvm/vmx.c linux-libre-4.12.3-gnu/arch/x86/kvm/vmx.c
--- linux-libre-4.12.2-gnu/arch/x86/kvm/vmx.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/arch/x86/kvm/vmx.c	2017-07-21 00:59:24.000000000 -0400
@@ -3195,7 +3195,8 @@ static int vmx_get_msr(struct kvm_vcpu *
 		msr_info->data = vmcs_readl(GUEST_SYSENTER_ESP);
 		break;
 	case MSR_IA32_BNDCFGS:
-		if (!kvm_mpx_supported())
+		if (!kvm_mpx_supported() ||
+		    (!msr_info->host_initiated && !guest_cpuid_has_mpx(vcpu)))
 			return 1;
 		msr_info->data = vmcs_read64(GUEST_BNDCFGS);
 		break;
@@ -3277,7 +3278,11 @@ static int vmx_set_msr(struct kvm_vcpu *
 		vmcs_writel(GUEST_SYSENTER_ESP, data);
 		break;
 	case MSR_IA32_BNDCFGS:
-		if (!kvm_mpx_supported())
+		if (!kvm_mpx_supported() ||
+		    (!msr_info->host_initiated && !guest_cpuid_has_mpx(vcpu)))
+			return 1;
+		if (is_noncanonical_address(data & PAGE_MASK) ||
+		    (data & MSR_IA32_BNDCFGS_RSVD))
 			return 1;
 		vmcs_write64(GUEST_BNDCFGS, data);
 		break;
@@ -6547,7 +6552,6 @@ static __init int hardware_setup(void)
 	vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_CS, false);
 	vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_ESP, false);
 	vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_EIP, false);
-	vmx_disable_intercept_for_msr(MSR_IA32_BNDCFGS, true);
 
 	memcpy(vmx_msr_bitmap_legacy_x2apic_apicv,
 			vmx_msr_bitmap_legacy, PAGE_SIZE);
diff -druNp --no-dereference linux-libre-4.12.2-gnu/drivers/base/power/sysfs.c linux-libre-4.12.3-gnu/drivers/base/power/sysfs.c
--- linux-libre-4.12.2-gnu/drivers/base/power/sysfs.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/drivers/base/power/sysfs.c	2017-07-21 00:59:24.000000000 -0400
@@ -272,6 +272,8 @@ static ssize_t pm_qos_latency_tolerance_
 			value = PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT;
 		else if (!strcmp(buf, "any") || !strcmp(buf, "any\n"))
 			value = PM_QOS_LATENCY_ANY;
+		else
+			return -EINVAL;
 	}
 	ret = dev_pm_qos_update_user_latency_tolerance(dev, value);
 	return ret < 0 ? ret : n;
diff -druNp --no-dereference linux-libre-4.12.2-gnu/drivers/base/power/wakeup.c linux-libre-4.12.3-gnu/drivers/base/power/wakeup.c
--- linux-libre-4.12.2-gnu/drivers/base/power/wakeup.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/drivers/base/power/wakeup.c	2017-07-21 00:59:24.000000000 -0400
@@ -60,6 +60,8 @@ static LIST_HEAD(wakeup_sources);
 
 static DECLARE_WAIT_QUEUE_HEAD(wakeup_count_wait_queue);
 
+DEFINE_STATIC_SRCU(wakeup_srcu);
+
 static struct wakeup_source deleted_ws = {
 	.name = "deleted",
 	.lock =  __SPIN_LOCK_UNLOCKED(deleted_ws.lock),
@@ -198,7 +200,7 @@ void wakeup_source_remove(struct wakeup_
 	spin_lock_irqsave(&events_lock, flags);
 	list_del_rcu(&ws->entry);
 	spin_unlock_irqrestore(&events_lock, flags);
-	synchronize_rcu();
+	synchronize_srcu(&wakeup_srcu);
 }
 EXPORT_SYMBOL_GPL(wakeup_source_remove);
 
@@ -332,12 +334,12 @@ void device_wakeup_detach_irq(struct dev
 void device_wakeup_arm_wake_irqs(void)
 {
 	struct wakeup_source *ws;
+	int srcuidx;
 
-	rcu_read_lock();
+	srcuidx = srcu_read_lock(&wakeup_srcu);
 	list_for_each_entry_rcu(ws, &wakeup_sources, entry)
 		dev_pm_arm_wake_irq(ws->wakeirq);
-
-	rcu_read_unlock();
+	srcu_read_unlock(&wakeup_srcu, srcuidx);
 }
 
 /**
@@ -348,12 +350,12 @@ void device_wakeup_arm_wake_irqs(void)
 void device_wakeup_disarm_wake_irqs(void)
 {
 	struct wakeup_source *ws;
+	int srcuidx;
 
-	rcu_read_lock();
+	srcuidx = srcu_read_lock(&wakeup_srcu);
 	list_for_each_entry_rcu(ws, &wakeup_sources, entry)
 		dev_pm_disarm_wake_irq(ws->wakeirq);
-
-	rcu_read_unlock();
+	srcu_read_unlock(&wakeup_srcu, srcuidx);
 }
 
 /**
@@ -804,10 +806,10 @@ EXPORT_SYMBOL_GPL(pm_wakeup_dev_event);
 void pm_print_active_wakeup_sources(void)
 {
 	struct wakeup_source *ws;
-	int active = 0;
+	int srcuidx, active = 0;
 	struct wakeup_source *last_activity_ws = NULL;
 
-	rcu_read_lock();
+	srcuidx = srcu_read_lock(&wakeup_srcu);
 	list_for_each_entry_rcu(ws, &wakeup_sources, entry) {
 		if (ws->active) {
 			pr_debug("active wakeup source: %s\n", ws->name);
@@ -823,7 +825,7 @@ void pm_print_active_wakeup_sources(void
 	if (!active && last_activity_ws)
 		pr_debug("last active wakeup source: %s\n",
 			last_activity_ws->name);
-	rcu_read_unlock();
+	srcu_read_unlock(&wakeup_srcu, srcuidx);
 }
 EXPORT_SYMBOL_GPL(pm_print_active_wakeup_sources);
 
@@ -950,8 +952,9 @@ void pm_wakep_autosleep_enabled(bool set
 {
 	struct wakeup_source *ws;
 	ktime_t now = ktime_get();
+	int srcuidx;
 
-	rcu_read_lock();
+	srcuidx = srcu_read_lock(&wakeup_srcu);
 	list_for_each_entry_rcu(ws, &wakeup_sources, entry) {
 		spin_lock_irq(&ws->lock);
 		if (ws->autosleep_enabled != set) {
@@ -965,7 +968,7 @@ void pm_wakep_autosleep_enabled(bool set
 		}
 		spin_unlock_irq(&ws->lock);
 	}
-	rcu_read_unlock();
+	srcu_read_unlock(&wakeup_srcu, srcuidx);
 }
 #endif /* CONFIG_PM_AUTOSLEEP */
 
@@ -1026,15 +1029,16 @@ static int print_wakeup_source_stats(str
 static int wakeup_sources_stats_show(struct seq_file *m, void *unused)
 {
 	struct wakeup_source *ws;
+	int srcuidx;
 
 	seq_puts(m, "name\t\tactive_count\tevent_count\twakeup_count\t"
 		"expire_count\tactive_since\ttotal_time\tmax_time\t"
 		"last_change\tprevent_suspend_time\n");
 
-	rcu_read_lock();
+	srcuidx = srcu_read_lock(&wakeup_srcu);
 	list_for_each_entry_rcu(ws, &wakeup_sources, entry)
 		print_wakeup_source_stats(m, ws);
-	rcu_read_unlock();
+	srcu_read_unlock(&wakeup_srcu, srcuidx);
 
 	print_wakeup_source_stats(m, &deleted_ws);
 
diff -druNp --no-dereference linux-libre-4.12.2-gnu/drivers/crypto/atmel-sha.c linux-libre-4.12.3-gnu/drivers/crypto/atmel-sha.c
--- linux-libre-4.12.2-gnu/drivers/crypto/atmel-sha.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/drivers/crypto/atmel-sha.c	2017-07-21 00:59:24.000000000 -0400
@@ -1204,7 +1204,9 @@ static int atmel_sha_finup(struct ahash_
 	ctx->flags |= SHA_FLAGS_FINUP;
 
 	err1 = atmel_sha_update(req);
-	if (err1 == -EINPROGRESS || err1 == -EBUSY)
+	if (err1 == -EINPROGRESS ||
+	    (err1 == -EBUSY && (ahash_request_flags(req) &
+				CRYPTO_TFM_REQ_MAY_BACKLOG)))
 		return err1;
 
 	/*
diff -druNp --no-dereference linux-libre-4.12.2-gnu/drivers/crypto/caam/caamalg.c linux-libre-4.12.3-gnu/drivers/crypto/caam/caamalg.c
--- linux-libre-4.12.2-gnu/drivers/crypto/caam/caamalg.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/drivers/crypto/caam/caamalg.c	2017-07-21 00:59:24.000000000 -0400
@@ -882,10 +882,10 @@ static void ablkcipher_encrypt_done(stru
 {
 	struct ablkcipher_request *req = context;
 	struct ablkcipher_edesc *edesc;
-#ifdef DEBUG
 	struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
 	int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
 
+#ifdef DEBUG
 	dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
 #endif
 
@@ -904,6 +904,14 @@ static void ablkcipher_encrypt_done(stru
 #endif
 
 	ablkcipher_unmap(jrdev, edesc, req);
+
+	/*
+	 * The crypto API expects us to set the IV (req->info) to the last
+	 * ciphertext block. This is used e.g. by the CTS mode.
+	 */
+	scatterwalk_map_and_copy(req->info, req->dst, req->nbytes - ivsize,
+				 ivsize, 0);
+
 	kfree(edesc);
 
 	ablkcipher_request_complete(req, err);
@@ -914,10 +922,10 @@ static void ablkcipher_decrypt_done(stru
 {
 	struct ablkcipher_request *req = context;
 	struct ablkcipher_edesc *edesc;
-#ifdef DEBUG
 	struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
 	int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
 
+#ifdef DEBUG
 	dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
 #endif
 
@@ -935,6 +943,14 @@ static void ablkcipher_decrypt_done(stru
 #endif
 
 	ablkcipher_unmap(jrdev, edesc, req);
+
+	/*
+	 * The crypto API expects us to set the IV (req->info) to the last
+	 * ciphertext block.
+	 */
+	scatterwalk_map_and_copy(req->info, req->src, req->nbytes - ivsize,
+				 ivsize, 0);
+
 	kfree(edesc);
 
 	ablkcipher_request_complete(req, err);
diff -druNp --no-dereference linux-libre-4.12.2-gnu/drivers/crypto/caam/caamhash.c linux-libre-4.12.3-gnu/drivers/crypto/caam/caamhash.c
--- linux-libre-4.12.2-gnu/drivers/crypto/caam/caamhash.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/drivers/crypto/caam/caamhash.c	2017-07-21 00:59:24.000000000 -0400
@@ -396,7 +396,7 @@ static int hash_digest_key(struct caam_h
 	ret = caam_jr_enqueue(jrdev, desc, split_key_done, &result);
 	if (!ret) {
 		/* in progress */
-		wait_for_completion_interruptible(&result.completion);
+		wait_for_completion(&result.completion);
 		ret = result.err;
 #ifdef DEBUG
 		print_hex_dump(KERN_ERR,
diff -druNp --no-dereference linux-libre-4.12.2-gnu/drivers/crypto/caam/key_gen.c linux-libre-4.12.3-gnu/drivers/crypto/caam/key_gen.c
--- linux-libre-4.12.2-gnu/drivers/crypto/caam/key_gen.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/drivers/crypto/caam/key_gen.c	2017-07-21 00:59:24.000000000 -0400
@@ -149,7 +149,7 @@ int gen_split_key(struct device *jrdev,
 	ret = caam_jr_enqueue(jrdev, desc, split_key_done, &result);
 	if (!ret) {
 		/* in progress */
-		wait_for_completion_interruptible(&result.completion);
+		wait_for_completion(&result.completion);
 		ret = result.err;
 #ifdef DEBUG
 		print_hex_dump(KERN_ERR, "ctx.key@"__stringify(__LINE__)": ",
diff -druNp --no-dereference linux-libre-4.12.2-gnu/drivers/crypto/talitos.c linux-libre-4.12.3-gnu/drivers/crypto/talitos.c
--- linux-libre-4.12.2-gnu/drivers/crypto/talitos.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/drivers/crypto/talitos.c	2017-07-21 00:59:24.000000000 -0400
@@ -816,7 +816,7 @@ static void talitos_unregister_rng(struc
  * HMAC_SNOOP_NO_AFEA (HSNA) instead of type IPSEC_ESP
  */
 #define TALITOS_CRA_PRIORITY_AEAD_HSNA	(TALITOS_CRA_PRIORITY - 1)
-#define TALITOS_MAX_KEY_SIZE		96
+#define TALITOS_MAX_KEY_SIZE		(AES_MAX_KEY_SIZE + SHA512_BLOCK_SIZE)
 #define TALITOS_MAX_IV_LENGTH		16 /* max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */
 
 struct talitos_ctx {
@@ -1495,6 +1495,11 @@ static int ablkcipher_setkey(struct cryp
 {
 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
 
+	if (keylen > TALITOS_MAX_KEY_SIZE) {
+		crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
+		return -EINVAL;
+	}
+
 	memcpy(&ctx->key, key, keylen);
 	ctx->keylen = keylen;
 
diff -druNp --no-dereference linux-libre-4.12.2-gnu/drivers/firmware/efi/efi.c linux-libre-4.12.3-gnu/drivers/firmware/efi/efi.c
--- linux-libre-4.12.2-gnu/drivers/firmware/efi/efi.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/drivers/firmware/efi/efi.c	2017-07-21 00:59:24.000000000 -0400
@@ -528,7 +528,8 @@ int __init efi_config_parse_tables(void
 		}
 	}
 
-	efi_memattr_init();
+	if (efi_enabled(EFI_MEMMAP))
+		efi_memattr_init();
 
 	/* Parse the EFI Properties table if it exists */
 	if (efi.properties_table != EFI_INVALID_TABLE_ADDR) {
diff -druNp --no-dereference linux-libre-4.12.2-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c linux-libre-4.12.3-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
--- linux-libre-4.12.2-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c	2017-07-15 13:29:57.000000000 -0400
+++ linux-libre-4.12.3-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c	2017-07-21 05:02:55.000000000 -0400
@@ -1665,7 +1665,8 @@ static void gfx_v6_0_gpu_init(struct amd
 	WREG32(mmBIF_FB_EN, BIF_FB_EN__FB_READ_EN_MASK | BIF_FB_EN__FB_WRITE_EN_MASK);
 
 	mc_shared_chmap = RREG32(mmMC_SHARED_CHMAP);
-	mc_arb_ramcfg = RREG32(mmMC_ARB_RAMCFG);
+	adev->gfx.config.mc_arb_ramcfg = RREG32(mmMC_ARB_RAMCFG);
+	mc_arb_ramcfg = adev->gfx.config.mc_arb_ramcfg;
 
 	adev->gfx.config.num_tile_pipes = adev->gfx.config.max_tile_pipes;
 	adev->gfx.config.mem_max_burst_length_bytes = 256;
diff -druNp --no-dereference linux-libre-4.12.2-gnu/drivers/hv/hv.c linux-libre-4.12.3-gnu/drivers/hv/hv.c
--- linux-libre-4.12.2-gnu/drivers/hv/hv.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/drivers/hv/hv.c	2017-07-21 00:59:24.000000000 -0400
@@ -82,10 +82,15 @@ int hv_post_message(union hv_connection_
 	aligned_msg->message_type = message_type;
 	aligned_msg->payload_size = payload_size;
 	memcpy((void *)aligned_msg->payload, payload, payload_size);
-	put_cpu_ptr(hv_cpu);
 
 	status = hv_do_hypercall(HVCALL_POST_MESSAGE, aligned_msg, NULL);
 
+	/* Preemption must remain disabled until after the hypercall
+	 * so some other thread can't get scheduled onto this cpu and
+	 * corrupt the per-cpu post_msg_page
+	 */
+	put_cpu_ptr(hv_cpu);
+
 	return status & 0xFFFF;
 }
 
diff -druNp --no-dereference linux-libre-4.12.2-gnu/drivers/irqchip/irq-gic-v3.c linux-libre-4.12.3-gnu/drivers/irqchip/irq-gic-v3.c
--- linux-libre-4.12.2-gnu/drivers/irqchip/irq-gic-v3.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/drivers/irqchip/irq-gic-v3.c	2017-07-21 00:59:24.000000000 -0400
@@ -645,6 +645,9 @@ static int gic_set_affinity(struct irq_d
 	int enabled;
 	u64 val;
 
+	if (cpu >= nr_cpu_ids)
+		return -EINVAL;
+
 	if (gic_irq_in_rdist(d))
 		return -EINVAL;
 
diff -druNp --no-dereference linux-libre-4.12.2-gnu/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c linux-libre-4.12.3-gnu/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c
--- linux-libre-4.12.2-gnu/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c	2017-07-21 00:59:24.000000000 -0400
@@ -221,7 +221,7 @@ static int cn23xx_pf_soft_reset(struct o
 	/* Wait for 100ms as Octeon resets. */
 	mdelay(100);
 
-	if (octeon_read_csr64(oct, CN23XX_SLI_SCRATCH1) == 0x1234ULL) {
+	if (octeon_read_csr64(oct, CN23XX_SLI_SCRATCH1)) {
 		dev_err(&oct->pci_dev->dev, "OCTEON[%d]: Soft reset failed\n",
 			oct->octeon_id);
 		return 1;
diff -druNp --no-dereference linux-libre-4.12.2-gnu/drivers/net/ethernet/cavium/liquidio/cn66xx_device.c linux-libre-4.12.3-gnu/drivers/net/ethernet/cavium/liquidio/cn66xx_device.c
--- linux-libre-4.12.2-gnu/drivers/net/ethernet/cavium/liquidio/cn66xx_device.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/drivers/net/ethernet/cavium/liquidio/cn66xx_device.c	2017-07-21 00:59:24.000000000 -0400
@@ -44,7 +44,7 @@ int lio_cn6xxx_soft_reset(struct octeon_
 	/* Wait for 10ms as Octeon resets. */
 	mdelay(100);
 
-	if (octeon_read_csr64(oct, CN6XXX_SLI_SCRATCH1) == 0x1234ULL) {
+	if (octeon_read_csr64(oct, CN6XXX_SLI_SCRATCH1)) {
 		dev_err(&oct->pci_dev->dev, "Soft reset failed\n");
 		return 1;
 	}
diff -druNp --no-dereference linux-libre-4.12.2-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c linux-libre-4.12.3-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
--- linux-libre-4.12.2-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c	2017-07-15 13:51:31.000000000 -0400
+++ linux-libre-4.12.3-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c	2017-07-21 05:24:04.000000000 -0400
@@ -2053,12 +2053,12 @@ static void detach_ulds(struct adapter *
 
 	mutex_lock(&uld_mutex);
 	list_del(&adap->list_node);
+
 	for (i = 0; i < CXGB4_ULD_MAX; i++)
-		if (adap->uld && adap->uld[i].handle) {
+		if (adap->uld && adap->uld[i].handle)
 			adap->uld[i].state_change(adap->uld[i].handle,
 					     CXGB4_STATE_DETACH);
-			adap->uld[i].handle = NULL;
-		}
+
 	if (netevent_registered && list_empty(&adapter_list)) {
 		unregister_netevent_notifier(&cxgb4_netevent_nb);
 		netevent_registered = false;
@@ -5084,8 +5084,10 @@ static void remove_one(struct pci_dev *p
 		 */
 		destroy_workqueue(adapter->workq);
 
-		if (is_uld(adapter))
+		if (is_uld(adapter)) {
 			detach_ulds(adapter);
+			t4_uld_clean_up(adapter);
+		}
 
 		disable_interrupts(adapter);
 
@@ -5162,7 +5164,11 @@ static void shutdown_one(struct pci_dev
 			if (adapter->port[i]->reg_state == NETREG_REGISTERED)
 				cxgb_close(adapter->port[i]);
 
-		t4_uld_clean_up(adapter);
+		if (is_uld(adapter)) {
+			detach_ulds(adapter);
+			t4_uld_clean_up(adapter);
+		}
+
 		disable_interrupts(adapter);
 		disable_msi(adapter);
 
diff -druNp --no-dereference linux-libre-4.12.2-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c linux-libre-4.12.3-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c
--- linux-libre-4.12.2-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c	2017-07-21 00:59:24.000000000 -0400
@@ -589,22 +589,37 @@ void t4_uld_mem_free(struct adapter *ada
 	kfree(adap->uld);
 }
 
+/* This function should be called with uld_mutex taken. */
+static void cxgb4_shutdown_uld_adapter(struct adapter *adap, enum cxgb4_uld type)
+{
+	if (adap->uld[type].handle) {
+		adap->uld[type].handle = NULL;
+		adap->uld[type].add = NULL;
+		release_sge_txq_uld(adap, type);
+
+		if (adap->flags & FULL_INIT_DONE)
+			quiesce_rx_uld(adap, type);
+
+		if (adap->flags & USING_MSIX)
+			free_msix_queue_irqs_uld(adap, type);
+
+		free_sge_queues_uld(adap, type);
+		free_queues_uld(adap, type);
+	}
+}
+
 void t4_uld_clean_up(struct adapter *adap)
 {
 	unsigned int i;
 
-	if (!adap->uld)
-		return;
+	mutex_lock(&uld_mutex);
 	for (i = 0; i < CXGB4_ULD_MAX; i++) {
 		if (!adap->uld[i].handle)
 			continue;
-		if (adap->flags & FULL_INIT_DONE)
-			quiesce_rx_uld(adap, i);
-		if (adap->flags & USING_MSIX)
-			free_msix_queue_irqs_uld(adap, i);
-		free_sge_queues_uld(adap, i);
-		free_queues_uld(adap, i);
+
+		cxgb4_shutdown_uld_adapter(adap, i);
 	}
+	mutex_unlock(&uld_mutex);
 }
 
 static void uld_init(struct adapter *adap, struct cxgb4_lld_info *lld)
@@ -782,15 +797,8 @@ int cxgb4_unregister_uld(enum cxgb4_uld
 			continue;
 		if (type == CXGB4_ULD_ISCSIT && is_t4(adap->params.chip))
 			continue;
-		adap->uld[type].handle = NULL;
-		adap->uld[type].add = NULL;
-		release_sge_txq_uld(adap, type);
-		if (adap->flags & FULL_INIT_DONE)
-			quiesce_rx_uld(adap, type);
-		if (adap->flags & USING_MSIX)
-			free_msix_queue_irqs_uld(adap, type);
-		free_sge_queues_uld(adap, type);
-		free_queues_uld(adap, type);
+
+		cxgb4_shutdown_uld_adapter(adap, type);
 	}
 	mutex_unlock(&uld_mutex);
 
diff -druNp --no-dereference linux-libre-4.12.2-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c linux-libre-4.12.3-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
--- linux-libre-4.12.2-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c	2017-07-21 00:59:24.000000000 -0400
@@ -464,6 +464,8 @@ static void mlx5e_dcbnl_getpermhwaddr(st
 	if (!perm_addr)
 		return;
 
+	memset(perm_addr, 0xff, MAX_ADDR_LEN);
+
 	mlx5_query_nic_vport_mac_address(priv->mdev, 0, perm_addr);
 }
 
diff -druNp --no-dereference linux-libre-4.12.2-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_main.c linux-libre-4.12.3-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
--- linux-libre-4.12.2-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_main.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_main.c	2017-07-21 00:59:24.000000000 -0400
@@ -3053,8 +3053,6 @@ mlx5e_get_stats(struct net_device *dev,
 		PPORT_802_3_GET(pstats, a_frame_check_sequence_errors);
 	stats->rx_frame_errors = PPORT_802_3_GET(pstats, a_alignment_errors);
 	stats->tx_aborted_errors = PPORT_2863_GET(pstats, if_out_discards);
-	stats->tx_carrier_errors =
-		PPORT_802_3_GET(pstats, a_symbol_error_during_carrier);
 	stats->rx_errors = stats->rx_length_errors + stats->rx_crc_errors +
 			   stats->rx_frame_errors;
 	stats->tx_errors = stats->tx_aborted_errors + stats->tx_carrier_errors;
diff -druNp --no-dereference linux-libre-4.12.2-gnu/drivers/net/ethernet/mellanox/mlx5/core/health.c linux-libre-4.12.3-gnu/drivers/net/ethernet/mellanox/mlx5/core/health.c
--- linux-libre-4.12.2-gnu/drivers/net/ethernet/mellanox/mlx5/core/health.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/drivers/net/ethernet/mellanox/mlx5/core/health.c	2017-07-21 00:59:24.000000000 -0400
@@ -67,6 +67,7 @@ enum {
 
 enum {
 	MLX5_DROP_NEW_HEALTH_WORK,
+	MLX5_DROP_NEW_RECOVERY_WORK,
 };
 
 static u8 get_nic_state(struct mlx5_core_dev *dev)
@@ -193,7 +194,7 @@ static void health_care(struct work_stru
 	mlx5_handle_bad_state(dev);
 
 	spin_lock(&health->wq_lock);
-	if (!test_bit(MLX5_DROP_NEW_HEALTH_WORK, &health->flags))
+	if (!test_bit(MLX5_DROP_NEW_RECOVERY_WORK, &health->flags))
 		schedule_delayed_work(&health->recover_work, recover_delay);
 	else
 		dev_err(&dev->pdev->dev,
@@ -313,6 +314,7 @@ void mlx5_start_health_poll(struct mlx5_
 	init_timer(&health->timer);
 	health->sick = 0;
 	clear_bit(MLX5_DROP_NEW_HEALTH_WORK, &health->flags);
+	clear_bit(MLX5_DROP_NEW_RECOVERY_WORK, &health->flags);
 	health->health = &dev->iseg->health;
 	health->health_counter = &dev->iseg->health_counter;
 
@@ -335,11 +337,22 @@ void mlx5_drain_health_wq(struct mlx5_co
 
 	spin_lock(&health->wq_lock);
 	set_bit(MLX5_DROP_NEW_HEALTH_WORK, &health->flags);
+	set_bit(MLX5_DROP_NEW_RECOVERY_WORK, &health->flags);
 	spin_unlock(&health->wq_lock);
 	cancel_delayed_work_sync(&health->recover_work);
 	cancel_work_sync(&health->work);
 }
 
+void mlx5_drain_health_recovery(struct mlx5_core_dev *dev)
+{
+	struct mlx5_core_health *health = &dev->priv.health;
+
+	spin_lock(&health->wq_lock);
+	set_bit(MLX5_DROP_NEW_RECOVERY_WORK, &health->flags);
+	spin_unlock(&health->wq_lock);
+	cancel_delayed_work_sync(&dev->priv.health.recover_work);
+}
+
 void mlx5_health_cleanup(struct mlx5_core_dev *dev)
 {
 	struct mlx5_core_health *health = &dev->priv.health;
diff -druNp --no-dereference linux-libre-4.12.2-gnu/drivers/net/ethernet/mellanox/mlx5/core/main.c linux-libre-4.12.3-gnu/drivers/net/ethernet/mellanox/mlx5/core/main.c
--- linux-libre-4.12.2-gnu/drivers/net/ethernet/mellanox/mlx5/core/main.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/drivers/net/ethernet/mellanox/mlx5/core/main.c	2017-07-21 00:59:24.000000000 -0400
@@ -1020,7 +1020,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);
@@ -1228,7 +1228,7 @@ static int mlx5_unload_one(struct mlx5_c
 	int err = 0;
 
 	if (cleanup)
-		mlx5_drain_health_wq(dev);
+		mlx5_drain_health_recovery(dev);
 
 	mutex_lock(&dev->intf_state_mutex);
 	if (test_bit(MLX5_INTERFACE_STATE_DOWN, &dev->intf_state)) {
diff -druNp --no-dereference linux-libre-4.12.2-gnu/drivers/net/ethernet/sfc/ef10.c linux-libre-4.12.3-gnu/drivers/net/ethernet/sfc/ef10.c
--- linux-libre-4.12.2-gnu/drivers/net/ethernet/sfc/ef10.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/drivers/net/ethernet/sfc/ef10.c	2017-07-21 00:59:24.000000000 -0400
@@ -5034,12 +5034,9 @@ static void efx_ef10_filter_uc_addr_list
 	struct efx_ef10_filter_table *table = efx->filter_state;
 	struct net_device *net_dev = efx->net_dev;
 	struct netdev_hw_addr *uc;
-	int addr_count;
 	unsigned int i;
 
-	addr_count = netdev_uc_count(net_dev);
 	table->uc_promisc = !!(net_dev->flags & IFF_PROMISC);
-	table->dev_uc_count = 1 + addr_count;
 	ether_addr_copy(table->dev_uc_list[0].addr, net_dev->dev_addr);
 	i = 1;
 	netdev_for_each_uc_addr(uc, net_dev) {
@@ -5050,6 +5047,8 @@ static void efx_ef10_filter_uc_addr_list
 		ether_addr_copy(table->dev_uc_list[i].addr, uc->addr);
 		i++;
 	}
+
+	table->dev_uc_count = i;
 }
 
 static void efx_ef10_filter_mc_addr_list(struct efx_nic *efx)
@@ -5057,12 +5056,11 @@ static void efx_ef10_filter_mc_addr_list
 	struct efx_ef10_filter_table *table = efx->filter_state;
 	struct net_device *net_dev = efx->net_dev;
 	struct netdev_hw_addr *mc;
-	unsigned int i, addr_count;
+	unsigned int i;
 
 	table->mc_overflow = false;
 	table->mc_promisc = !!(net_dev->flags & (IFF_PROMISC | IFF_ALLMULTI));
 
-	addr_count = netdev_mc_count(net_dev);
 	i = 0;
 	netdev_for_each_mc_addr(mc, net_dev) {
 		if (i >= EFX_EF10_FILTER_DEV_MC_MAX) {
diff -druNp --no-dereference linux-libre-4.12.2-gnu/drivers/net/geneve.c linux-libre-4.12.3-gnu/drivers/net/geneve.c
--- linux-libre-4.12.2-gnu/drivers/net/geneve.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/drivers/net/geneve.c	2017-07-21 00:59:24.000000000 -0400
@@ -45,9 +45,17 @@ struct geneve_net {
 
 static unsigned int geneve_net_id;
 
+struct geneve_dev_node {
+	struct hlist_node hlist;
+	struct geneve_dev *geneve;
+};
+
 /* Pseudo network device */
 struct geneve_dev {
-	struct hlist_node  hlist;	/* vni hash table */
+	struct geneve_dev_node hlist4;	/* vni hash table for IPv4 socket */
+#if IS_ENABLED(CONFIG_IPV6)
+	struct geneve_dev_node hlist6;	/* vni hash table for IPv6 socket */
+#endif
 	struct net	   *net;	/* netns for packet i/o */
 	struct net_device  *dev;	/* netdev for geneve tunnel */
 	struct ip_tunnel_info info;
@@ -123,16 +131,16 @@ static struct geneve_dev *geneve_lookup(
 					__be32 addr, u8 vni[])
 {
 	struct hlist_head *vni_list_head;
-	struct geneve_dev *geneve;
+	struct geneve_dev_node *node;
 	__u32 hash;
 
 	/* Find the device for this VNI */
 	hash = geneve_net_vni_hash(vni);
 	vni_list_head = &gs->vni_list[hash];
-	hlist_for_each_entry_rcu(geneve, vni_list_head, hlist) {
-		if (eq_tun_id_and_vni((u8 *)&geneve->info.key.tun_id, vni) &&
-		    addr == geneve->info.key.u.ipv4.dst)
-			return geneve;
+	hlist_for_each_entry_rcu(node, vni_list_head, hlist) {
+		if (eq_tun_id_and_vni((u8 *)&node->geneve->info.key.tun_id, vni) &&
+		    addr == node->geneve->info.key.u.ipv4.dst)
+			return node->geneve;
 	}
 	return NULL;
 }
@@ -142,16 +150,16 @@ static struct geneve_dev *geneve6_lookup
 					 struct in6_addr addr6, u8 vni[])
 {
 	struct hlist_head *vni_list_head;
-	struct geneve_dev *geneve;
+	struct geneve_dev_node *node;
 	__u32 hash;
 
 	/* Find the device for this VNI */
 	hash = geneve_net_vni_hash(vni);
 	vni_list_head = &gs->vni_list[hash];
-	hlist_for_each_entry_rcu(geneve, vni_list_head, hlist) {
-		if (eq_tun_id_and_vni((u8 *)&geneve->info.key.tun_id, vni) &&
-		    ipv6_addr_equal(&addr6, &geneve->info.key.u.ipv6.dst))
-			return geneve;
+	hlist_for_each_entry_rcu(node, vni_list_head, hlist) {
+		if (eq_tun_id_and_vni((u8 *)&node->geneve->info.key.tun_id, vni) &&
+		    ipv6_addr_equal(&addr6, &node->geneve->info.key.u.ipv6.dst))
+			return node->geneve;
 	}
 	return NULL;
 }
@@ -579,6 +587,7 @@ static int geneve_sock_add(struct geneve
 {
 	struct net *net = geneve->net;
 	struct geneve_net *gn = net_generic(net, geneve_net_id);
+	struct geneve_dev_node *node;
 	struct geneve_sock *gs;
 	__u8 vni[3];
 	__u32 hash;
@@ -597,15 +606,20 @@ static int geneve_sock_add(struct geneve
 out:
 	gs->collect_md = geneve->collect_md;
 #if IS_ENABLED(CONFIG_IPV6)
-	if (ipv6)
+	if (ipv6) {
 		rcu_assign_pointer(geneve->sock6, gs);
-	else
+		node = &geneve->hlist6;
+	} else
 #endif
+	{
 		rcu_assign_pointer(geneve->sock4, gs);
+		node = &geneve->hlist4;
+	}
+	node->geneve = geneve;
 
 	tunnel_id_to_vni(geneve->info.key.tun_id, vni);
 	hash = geneve_net_vni_hash(vni);
-	hlist_add_head_rcu(&geneve->hlist, &gs->vni_list[hash]);
+	hlist_add_head_rcu(&node->hlist, &gs->vni_list[hash]);
 	return 0;
 }
 
@@ -632,8 +646,10 @@ static int geneve_stop(struct net_device
 {
 	struct geneve_dev *geneve = netdev_priv(dev);
 
-	if (!hlist_unhashed(&geneve->hlist))
-		hlist_del_rcu(&geneve->hlist);
+	hlist_del_init_rcu(&geneve->hlist4.hlist);
+#if IS_ENABLED(CONFIG_IPV6)
+	hlist_del_init_rcu(&geneve->hlist6.hlist);
+#endif
 	geneve_sock_release(geneve);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.12.2-gnu/drivers/net/tap.c linux-libre-4.12.3-gnu/drivers/net/tap.c
--- linux-libre-4.12.2-gnu/drivers/net/tap.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/drivers/net/tap.c	2017-07-21 00:59:24.000000000 -0400
@@ -106,7 +106,7 @@ struct major_info {
 	struct rcu_head rcu;
 	dev_t major;
 	struct idr minor_idr;
-	struct mutex minor_lock;
+	spinlock_t minor_lock;
 	const char *device_name;
 	struct list_head next;
 };
@@ -416,15 +416,15 @@ int tap_get_minor(dev_t major, struct ta
 		goto unlock;
 	}
 
-	mutex_lock(&tap_major->minor_lock);
-	retval = idr_alloc(&tap_major->minor_idr, tap, 1, TAP_NUM_DEVS, GFP_KERNEL);
+	spin_lock(&tap_major->minor_lock);
+	retval = idr_alloc(&tap_major->minor_idr, tap, 1, TAP_NUM_DEVS, GFP_ATOMIC);
 	if (retval >= 0) {
 		tap->minor = retval;
 	} else if (retval == -ENOSPC) {
 		netdev_err(tap->dev, "Too many tap devices\n");
 		retval = -EINVAL;
 	}
-	mutex_unlock(&tap_major->minor_lock);
+	spin_unlock(&tap_major->minor_lock);
 
 unlock:
 	rcu_read_unlock();
@@ -442,12 +442,12 @@ void tap_free_minor(dev_t major, struct
 		goto unlock;
 	}
 
-	mutex_lock(&tap_major->minor_lock);
+	spin_lock(&tap_major->minor_lock);
 	if (tap->minor) {
 		idr_remove(&tap_major->minor_idr, tap->minor);
 		tap->minor = 0;
 	}
-	mutex_unlock(&tap_major->minor_lock);
+	spin_unlock(&tap_major->minor_lock);
 
 unlock:
 	rcu_read_unlock();
@@ -467,13 +467,13 @@ static struct tap_dev *dev_get_by_tap_fi
 		goto unlock;
 	}
 
-	mutex_lock(&tap_major->minor_lock);
+	spin_lock(&tap_major->minor_lock);
 	tap = idr_find(&tap_major->minor_idr, minor);
 	if (tap) {
 		dev = tap->dev;
 		dev_hold(dev);
 	}
-	mutex_unlock(&tap_major->minor_lock);
+	spin_unlock(&tap_major->minor_lock);
 
 unlock:
 	rcu_read_unlock();
@@ -1227,7 +1227,7 @@ static int tap_list_add(dev_t major, con
 	tap_major->major = MAJOR(major);
 
 	idr_init(&tap_major->minor_idr);
-	mutex_init(&tap_major->minor_lock);
+	spin_lock_init(&tap_major->minor_lock);
 
 	tap_major->device_name = device_name;
 
diff -druNp --no-dereference linux-libre-4.12.2-gnu/drivers/net/virtio_net.c linux-libre-4.12.3-gnu/drivers/net/virtio_net.c
--- linux-libre-4.12.2-gnu/drivers/net/virtio_net.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/drivers/net/virtio_net.c	2017-07-21 00:59:24.000000000 -0400
@@ -2221,6 +2221,7 @@ static int virtnet_find_vqs(struct virtn
 	kfree(names);
 	kfree(callbacks);
 	kfree(vqs);
+	kfree(ctx);
 
 	return 0;
 
diff -druNp --no-dereference linux-libre-4.12.2-gnu/drivers/net/vrf.c linux-libre-4.12.3-gnu/drivers/net/vrf.c
--- linux-libre-4.12.2-gnu/drivers/net/vrf.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/drivers/net/vrf.c	2017-07-21 00:59:24.000000000 -0400
@@ -926,15 +926,10 @@ static int vrf_del_slave(struct net_devi
 static void vrf_dev_uninit(struct net_device *dev)
 {
 	struct net_vrf *vrf = netdev_priv(dev);
-	struct net_device *port_dev;
-	struct list_head *iter;
 
 	vrf_rtable_release(dev, vrf);
 	vrf_rt6_release(dev, vrf);
 
-	netdev_for_each_lower_dev(dev, port_dev, iter)
-		vrf_del_slave(dev, port_dev);
-
 	free_percpu(dev->dstats);
 	dev->dstats = NULL;
 }
@@ -1389,6 +1384,12 @@ static int vrf_validate(struct nlattr *t
 
 static void vrf_dellink(struct net_device *dev, struct list_head *head)
 {
+	struct net_device *port_dev;
+	struct list_head *iter;
+
+	netdev_for_each_lower_dev(dev, port_dev, iter)
+		vrf_del_slave(dev, port_dev);
+
 	unregister_netdevice_queue(dev, head);
 }
 
diff -druNp --no-dereference linux-libre-4.12.2-gnu/drivers/net/vxlan.c linux-libre-4.12.3-gnu/drivers/net/vxlan.c
--- linux-libre-4.12.2-gnu/drivers/net/vxlan.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/drivers/net/vxlan.c	2017-07-21 00:59:24.000000000 -0400
@@ -228,15 +228,15 @@ static struct vxlan_sock *vxlan_find_soc
 
 static struct vxlan_dev *vxlan_vs_find_vni(struct vxlan_sock *vs, __be32 vni)
 {
-	struct vxlan_dev *vxlan;
+	struct vxlan_dev_node *node;
 
 	/* For flow based devices, map all packets to VNI 0 */
 	if (vs->flags & VXLAN_F_COLLECT_METADATA)
 		vni = 0;
 
-	hlist_for_each_entry_rcu(vxlan, vni_head(vs, vni), hlist) {
-		if (vxlan->default_dst.remote_vni == vni)
-			return vxlan;
+	hlist_for_each_entry_rcu(node, vni_head(vs, vni), hlist) {
+		if (node->vxlan->default_dst.remote_vni == vni)
+			return node->vxlan;
 	}
 
 	return NULL;
@@ -2365,17 +2365,22 @@ static void vxlan_vs_del_dev(struct vxla
 	struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
 
 	spin_lock(&vn->sock_lock);
-	hlist_del_init_rcu(&vxlan->hlist);
+	hlist_del_init_rcu(&vxlan->hlist4.hlist);
+#if IS_ENABLED(CONFIG_IPV6)
+	hlist_del_init_rcu(&vxlan->hlist6.hlist);
+#endif
 	spin_unlock(&vn->sock_lock);
 }
 
-static void vxlan_vs_add_dev(struct vxlan_sock *vs, struct vxlan_dev *vxlan)
+static void vxlan_vs_add_dev(struct vxlan_sock *vs, struct vxlan_dev *vxlan,
+			     struct vxlan_dev_node *node)
 {
 	struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
 	__be32 vni = vxlan->default_dst.remote_vni;
 
+	node->vxlan = vxlan;
 	spin_lock(&vn->sock_lock);
-	hlist_add_head_rcu(&vxlan->hlist, vni_head(vs, vni));
+	hlist_add_head_rcu(&node->hlist, vni_head(vs, vni));
 	spin_unlock(&vn->sock_lock);
 }
 
@@ -2819,6 +2824,7 @@ static int __vxlan_sock_add(struct vxlan
 {
 	struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
 	struct vxlan_sock *vs = NULL;
+	struct vxlan_dev_node *node;
 
 	if (!vxlan->cfg.no_share) {
 		spin_lock(&vn->sock_lock);
@@ -2836,12 +2842,16 @@ static int __vxlan_sock_add(struct vxlan
 	if (IS_ERR(vs))
 		return PTR_ERR(vs);
 #if IS_ENABLED(CONFIG_IPV6)
-	if (ipv6)
+	if (ipv6) {
 		rcu_assign_pointer(vxlan->vn6_sock, vs);
-	else
+		node = &vxlan->hlist6;
+	} else
 #endif
+	{
 		rcu_assign_pointer(vxlan->vn4_sock, vs);
-	vxlan_vs_add_dev(vs, vxlan);
+		node = &vxlan->hlist4;
+	}
+	vxlan_vs_add_dev(vs, vxlan, node);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.12.2-gnu/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c linux-libre-4.12.3-gnu/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
--- linux-libre-4.12.2-gnu/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c	2017-07-21 00:59:24.000000000 -0400
@@ -706,7 +706,7 @@ done:
 int brcmf_sdiod_recv_chain(struct brcmf_sdio_dev *sdiodev,
 			   struct sk_buff_head *pktq, uint totlen)
 {
-	struct sk_buff *glom_skb;
+	struct sk_buff *glom_skb = NULL;
 	struct sk_buff *skb;
 	u32 addr = sdiodev->sbwad;
 	int err = 0;
@@ -727,10 +727,8 @@ int brcmf_sdiod_recv_chain(struct brcmf_
 			return -ENOMEM;
 		err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, false, addr,
 					 glom_skb);
-		if (err) {
-			brcmu_pkt_buf_free_skb(glom_skb);
+		if (err)
 			goto done;
-		}
 
 		skb_queue_walk(pktq, skb) {
 			memcpy(skb->data, glom_skb->data, skb->len);
@@ -741,6 +739,7 @@ int brcmf_sdiod_recv_chain(struct brcmf_
 					    pktq);
 
 done:
+	brcmu_pkt_buf_free_skb(glom_skb);
 	return err;
 }
 
diff -druNp --no-dereference linux-libre-4.12.2-gnu/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c linux-libre-4.12.3-gnu/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
--- linux-libre-4.12.2-gnu/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c	2017-07-21 00:59:24.000000000 -0400
@@ -4851,6 +4851,11 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wip
 		cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true,
 					GFP_KERNEL);
 	} else if (ieee80211_is_action(mgmt->frame_control)) {
+		if (len > BRCMF_FIL_ACTION_FRAME_SIZE + DOT11_MGMT_HDR_LEN) {
+			brcmf_err("invalid action frame length\n");
+			err = -EINVAL;
+			goto exit;
+		}
 		af_params = kzalloc(sizeof(*af_params), GFP_KERNEL);
 		if (af_params == NULL) {
 			brcmf_err("unable to allocate frame\n");
@@ -6850,7 +6855,7 @@ struct brcmf_cfg80211_info *brcmf_cfg802
 	wiphy = wiphy_new(ops, sizeof(struct brcmf_cfg80211_info));
 	if (!wiphy) {
 		brcmf_err("Could not allocate wiphy device\n");
-		return NULL;
+		goto ops_out;
 	}
 	memcpy(wiphy->perm_addr, drvr->mac, ETH_ALEN);
 	set_wiphy_dev(wiphy, busdev);
@@ -6993,6 +6998,7 @@ priv_out:
 	ifp->vif = NULL;
 wiphy_out:
 	brcmf_free_wiphy(wiphy);
+ops_out:
 	kfree(ops);
 	return NULL;
 }
diff -druNp --no-dereference linux-libre-4.12.2-gnu/drivers/nvmem/core.c linux-libre-4.12.3-gnu/drivers/nvmem/core.c
--- linux-libre-4.12.2-gnu/drivers/nvmem/core.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/drivers/nvmem/core.c	2017-07-21 00:59:24.000000000 -0400
@@ -489,21 +489,24 @@ struct nvmem_device *nvmem_register(cons
 
 	rval = device_add(&nvmem->dev);
 	if (rval)
-		goto out;
+		goto err_put_device;
 
 	if (config->compat) {
 		rval = nvmem_setup_compat(nvmem, config);
 		if (rval)
-			goto out;
+			goto err_device_del;
 	}
 
 	if (config->cells)
 		nvmem_add_cells(nvmem, config);
 
 	return nvmem;
-out:
-	ida_simple_remove(&nvmem_ida, nvmem->id);
-	kfree(nvmem);
+
+err_device_del:
+	device_del(&nvmem->dev);
+err_put_device:
+	put_device(&nvmem->dev);
+
 	return ERR_PTR(rval);
 }
 EXPORT_SYMBOL_GPL(nvmem_register);
diff -druNp --no-dereference linux-libre-4.12.2-gnu/drivers/parisc/ccio-dma.c linux-libre-4.12.3-gnu/drivers/parisc/ccio-dma.c
--- linux-libre-4.12.2-gnu/drivers/parisc/ccio-dma.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/drivers/parisc/ccio-dma.c	2017-07-21 00:59:24.000000000 -0400
@@ -741,6 +741,8 @@ ccio_map_single(struct device *dev, void
 
 	BUG_ON(!dev);
 	ioc = GET_IOC(dev);
+	if (!ioc)
+		return DMA_ERROR_CODE;
 
 	BUG_ON(size <= 0);
 
@@ -814,6 +816,10 @@ ccio_unmap_page(struct device *dev, dma_
 	
 	BUG_ON(!dev);
 	ioc = GET_IOC(dev);
+	if (!ioc) {
+		WARN_ON(!ioc);
+		return;
+	}
 
 	DBG_RUN("%s() iovp 0x%lx/%x\n",
 		__func__, (long)iova, size);
@@ -918,6 +924,8 @@ ccio_map_sg(struct device *dev, struct s
 	
 	BUG_ON(!dev);
 	ioc = GET_IOC(dev);
+	if (!ioc)
+		return 0;
 	
 	DBG_RUN_SG("%s() START %d entries\n", __func__, nents);
 
@@ -990,6 +998,10 @@ ccio_unmap_sg(struct device *dev, struct
 
 	BUG_ON(!dev);
 	ioc = GET_IOC(dev);
+	if (!ioc) {
+		WARN_ON(!ioc);
+		return;
+	}
 
 	DBG_RUN_SG("%s() START %d entries, %p,%x\n",
 		__func__, nents, sg_virt(sglist), sglist->length);
diff -druNp --no-dereference linux-libre-4.12.2-gnu/drivers/parisc/dino.c linux-libre-4.12.3-gnu/drivers/parisc/dino.c
--- linux-libre-4.12.2-gnu/drivers/parisc/dino.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/drivers/parisc/dino.c	2017-07-21 00:59:24.000000000 -0400
@@ -154,7 +154,10 @@ struct dino_device
 };
 
 /* Looks nice and keeps the compiler happy */
-#define DINO_DEV(d) ((struct dino_device *) d)
+#define DINO_DEV(d) ({				\
+	void *__pdata = d;			\
+	BUG_ON(!__pdata);			\
+	(struct dino_device *)__pdata; })
 
 
 /*
diff -druNp --no-dereference linux-libre-4.12.2-gnu/drivers/parisc/lba_pci.c linux-libre-4.12.3-gnu/drivers/parisc/lba_pci.c
--- linux-libre-4.12.2-gnu/drivers/parisc/lba_pci.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/drivers/parisc/lba_pci.c	2017-07-21 00:59:24.000000000 -0400
@@ -111,8 +111,10 @@ static u32 lba_t32;
 
 
 /* Looks nice and keeps the compiler happy */
-#define LBA_DEV(d) ((struct lba_device *) (d))
-
+#define LBA_DEV(d) ({				\
+	void *__pdata = d;			\
+	BUG_ON(!__pdata);			\
+	(struct lba_device *)__pdata; })
 
 /*
 ** Only allow 8 subsidiary busses per LBA
diff -druNp --no-dereference linux-libre-4.12.2-gnu/drivers/parisc/sba_iommu.c linux-libre-4.12.3-gnu/drivers/parisc/sba_iommu.c
--- linux-libre-4.12.2-gnu/drivers/parisc/sba_iommu.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/drivers/parisc/sba_iommu.c	2017-07-21 00:59:24.000000000 -0400
@@ -691,6 +691,8 @@ static int sba_dma_supported( struct dev
 		return 0;
 
 	ioc = GET_IOC(dev);
+	if (!ioc)
+		return 0;
 
 	/*
 	 * check if mask is >= than the current max IO Virt Address
@@ -722,6 +724,8 @@ sba_map_single(struct device *dev, void
 	int pide;
 
 	ioc = GET_IOC(dev);
+	if (!ioc)
+		return DMA_ERROR_CODE;
 
 	/* save offset bits */
 	offset = ((dma_addr_t) (long) addr) & ~IOVP_MASK;
@@ -813,6 +817,10 @@ sba_unmap_page(struct device *dev, dma_a
 	DBG_RUN("%s() iovp 0x%lx/%x\n", __func__, (long) iova, size);
 
 	ioc = GET_IOC(dev);
+	if (!ioc) {
+		WARN_ON(!ioc);
+		return;
+	}
 	offset = iova & ~IOVP_MASK;
 	iova ^= offset;        /* clear offset bits */
 	size += offset;
@@ -952,6 +960,8 @@ sba_map_sg(struct device *dev, struct sc
 	DBG_RUN_SG("%s() START %d entries\n", __func__, nents);
 
 	ioc = GET_IOC(dev);
+	if (!ioc)
+		return 0;
 
 	/* Fast path single entry scatterlists. */
 	if (nents == 1) {
@@ -1037,6 +1047,10 @@ sba_unmap_sg(struct device *dev, struct
 		__func__, nents, sg_virt(sglist), sglist->length);
 
 	ioc = GET_IOC(dev);
+	if (!ioc) {
+		WARN_ON(!ioc);
+		return;
+	}
 
 #ifdef SBA_COLLECT_STATS
 	ioc->usg_calls++;
diff -druNp --no-dereference linux-libre-4.12.2-gnu/drivers/staging/android/uapi/ion.h linux-libre-4.12.3-gnu/drivers/staging/android/uapi/ion.h
--- linux-libre-4.12.2-gnu/drivers/staging/android/uapi/ion.h	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/drivers/staging/android/uapi/ion.h	2017-07-21 00:59:24.000000000 -0400
@@ -131,24 +131,6 @@ struct ion_heap_query {
 				      struct ion_allocation_data)
 
 /**
- * DOC: ION_IOC_FREE - free memory
- *
- * Takes an ion_handle_data struct and frees the handle.
- */
-#define ION_IOC_FREE		_IOWR(ION_IOC_MAGIC, 1, struct ion_handle_data)
-
-/**
- * DOC: ION_IOC_SHARE - creates a file descriptor to use to share an allocation
- *
- * Takes an ion_fd_data struct with the handle field populated with a valid
- * opaque handle.  Returns the struct with the fd field set to a file
- * descriptor open in the current address space.  This file descriptor
- * can then be passed to another process.  The corresponding opaque handle can
- * be retrieved via ION_IOC_IMPORT.
- */
-#define ION_IOC_SHARE		_IOWR(ION_IOC_MAGIC, 4, struct ion_fd_data)
-
-/**
  * DOC: ION_IOC_HEAP_QUERY - information about available heaps
  *
  * Takes an ion_heap_query structure and populates information about
diff -druNp --no-dereference linux-libre-4.12.2-gnu/drivers/tty/vt/vt.c linux-libre-4.12.3-gnu/drivers/tty/vt/vt.c
--- linux-libre-4.12.2-gnu/drivers/tty/vt/vt.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/drivers/tty/vt/vt.c	2017-07-21 00:59:24.000000000 -0400
@@ -2709,13 +2709,13 @@ int tioclinux(struct tty_struct *tty, un
 	 * related to the kernel should not use this.
 	 */
 			data = vt_get_shift_state();
-			ret = __put_user(data, p);
+			ret = put_user(data, p);
 			break;
 		case TIOCL_GETMOUSEREPORTING:
 			console_lock();	/* May be overkill */
 			data = mouse_reporting();
 			console_unlock();
-			ret = __put_user(data, p);
+			ret = put_user(data, p);
 			break;
 		case TIOCL_SETVESABLANK:
 			console_lock();
@@ -2724,7 +2724,7 @@ int tioclinux(struct tty_struct *tty, un
 			break;
 		case TIOCL_GETKMSGREDIRECT:
 			data = vt_get_kmsg_redirect();
-			ret = __put_user(data, p);
+			ret = put_user(data, p);
 			break;
 		case TIOCL_SETKMSGREDIRECT:
 			if (!capable(CAP_SYS_ADMIN)) {
diff -druNp --no-dereference linux-libre-4.12.2-gnu/fs/binfmt_elf.c linux-libre-4.12.3-gnu/fs/binfmt_elf.c
--- linux-libre-4.12.2-gnu/fs/binfmt_elf.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/fs/binfmt_elf.c	2017-07-21 00:59:24.000000000 -0400
@@ -927,17 +927,60 @@ static int load_elf_binary(struct linux_
 		elf_flags = MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE;
 
 		vaddr = elf_ppnt->p_vaddr;
+		/*
+		 * If we are loading ET_EXEC or we have already performed
+		 * the ET_DYN load_addr calculations, proceed normally.
+		 */
 		if (loc->elf_ex.e_type == ET_EXEC || load_addr_set) {
 			elf_flags |= MAP_FIXED;
 		} else if (loc->elf_ex.e_type == ET_DYN) {
-			/* Try and get dynamic programs out of the way of the
-			 * default mmap base, as well as whatever program they
-			 * might try to exec.  This is because the brk will
-			 * follow the loader, and is not movable.  */
-			load_bias = ELF_ET_DYN_BASE - vaddr;
-			if (current->flags & PF_RANDOMIZE)
-				load_bias += arch_mmap_rnd();
-			load_bias = ELF_PAGESTART(load_bias);
+			/*
+			 * This logic is run once for the first LOAD Program
+			 * Header for ET_DYN binaries to calculate the
+			 * randomization (load_bias) for all the LOAD
+			 * Program Headers, and to calculate the entire
+			 * size of the ELF mapping (total_size). (Note that
+			 * load_addr_set is set to true later once the
+			 * initial mapping is performed.)
+			 *
+			 * There are effectively two types of ET_DYN
+			 * binaries: programs (i.e. PIE: ET_DYN with INTERP)
+			 * and loaders (ET_DYN without INTERP, since they
+			 * _are_ the ELF interpreter). The loaders must
+			 * be loaded away from programs since the program
+			 * may otherwise collide with the loader (especially
+			 * for ET_EXEC which does not have a randomized
+			 * position). For example to handle invocations of
+			 * "./ld.so someprog" to test out a new version of
+			 * the loader, the subsequent program that the
+			 * loader loads must avoid the loader itself, so
+			 * they cannot share the same load range. Sufficient
+			 * room for the brk must be allocated with the
+			 * loader as well, since brk must be available with
+			 * the loader.
+			 *
+			 * Therefore, programs are loaded offset from
+			 * ELF_ET_DYN_BASE and loaders are loaded into the
+			 * independently randomized mmap region (0 load_bias
+			 * without MAP_FIXED).
+			 */
+			if (elf_interpreter) {
+				load_bias = ELF_ET_DYN_BASE;
+				if (current->flags & PF_RANDOMIZE)
+					load_bias += arch_mmap_rnd();
+				elf_flags |= MAP_FIXED;
+			} else
+				load_bias = 0;
+
+			/*
+			 * Since load_bias is used for all subsequent loading
+			 * calculations, we must lower it by the first vaddr
+			 * so that the remaining calculations based on the
+			 * ELF vaddrs will be correctly offset. The result
+			 * is then page aligned.
+			 */
+			load_bias = ELF_PAGESTART(load_bias - vaddr);
+
 			total_size = total_mapping_size(elf_phdata,
 							loc->elf_ex.e_phnum);
 			if (!total_size) {
diff -druNp --no-dereference linux-libre-4.12.2-gnu/fs/dcache.c linux-libre-4.12.3-gnu/fs/dcache.c
--- linux-libre-4.12.2-gnu/fs/dcache.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/fs/dcache.c	2017-07-21 00:59:24.000000000 -0400
@@ -1133,11 +1133,12 @@ void shrink_dcache_sb(struct super_block
 		LIST_HEAD(dispose);
 
 		freed = list_lru_walk(&sb->s_dentry_lru,
-			dentry_lru_isolate_shrink, &dispose, UINT_MAX);
+			dentry_lru_isolate_shrink, &dispose, 1024);
 
 		this_cpu_sub(nr_dentry_unused, freed);
 		shrink_dentry_list(&dispose);
-	} while (freed > 0);
+		cond_resched();
+	} while (list_lru_count(&sb->s_dentry_lru) > 0);
 }
 EXPORT_SYMBOL(shrink_dcache_sb);
 
diff -druNp --no-dereference linux-libre-4.12.2-gnu/fs/exec.c linux-libre-4.12.3-gnu/fs/exec.c
--- linux-libre-4.12.2-gnu/fs/exec.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/fs/exec.c	2017-07-21 00:59:24.000000000 -0400
@@ -220,8 +220,7 @@ static struct page *get_arg_page(struct
 
 	if (write) {
 		unsigned long size = bprm->vma->vm_end - bprm->vma->vm_start;
-		unsigned long ptr_size;
-		struct rlimit *rlim;
+		unsigned long ptr_size, limit;
 
 		/*
 		 * Since the stack will hold pointers to the strings, we
@@ -250,14 +249,16 @@ static struct page *get_arg_page(struct
 			return page;
 
 		/*
-		 * Limit to 1/4-th the stack size for the argv+env strings.
+		 * Limit to 1/4 of the max stack size or 3/4 of _STK_LIM
+		 * (whichever is smaller) for the argv+env strings.
 		 * This ensures that:
 		 *  - the remaining binfmt code will not run out of stack space,
 		 *  - the program will have a reasonable amount of stack left
 		 *    to work from.
 		 */
-		rlim = current->signal->rlim;
-		if (size > READ_ONCE(rlim[RLIMIT_STACK].rlim_cur) / 4)
+		limit = _STK_LIM / 4 * 3;
+		limit = min(limit, rlimit(RLIMIT_STACK) / 4);
+		if (size > limit)
 			goto fail;
 	}
 
diff -druNp --no-dereference linux-libre-4.12.2-gnu/fs/mount.h linux-libre-4.12.3-gnu/fs/mount.h
--- linux-libre-4.12.2-gnu/fs/mount.h	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/fs/mount.h	2017-07-21 00:59:24.000000000 -0400
@@ -58,6 +58,7 @@ struct mount {
 	struct mnt_namespace *mnt_ns;	/* containing namespace */
 	struct mountpoint *mnt_mp;	/* where is it mounted */
 	struct hlist_node mnt_mp_list;	/* list mounts with the same mountpoint */
+	struct list_head mnt_umounting; /* list entry for umount propagation */
 #ifdef CONFIG_FSNOTIFY
 	struct fsnotify_mark_connector __rcu *mnt_fsnotify_marks;
 	__u32 mnt_fsnotify_mask;
diff -druNp --no-dereference linux-libre-4.12.2-gnu/fs/namespace.c linux-libre-4.12.3-gnu/fs/namespace.c
--- linux-libre-4.12.2-gnu/fs/namespace.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/fs/namespace.c	2017-07-21 00:59:24.000000000 -0400
@@ -236,6 +236,7 @@ static struct mount *alloc_vfsmnt(const
 		INIT_LIST_HEAD(&mnt->mnt_slave_list);
 		INIT_LIST_HEAD(&mnt->mnt_slave);
 		INIT_HLIST_NODE(&mnt->mnt_mp_list);
+		INIT_LIST_HEAD(&mnt->mnt_umounting);
 		init_fs_pin(&mnt->mnt_umount, drop_mountpoint);
 	}
 	return mnt;
diff -druNp --no-dereference linux-libre-4.12.2-gnu/fs/pnode.c linux-libre-4.12.3-gnu/fs/pnode.c
--- linux-libre-4.12.2-gnu/fs/pnode.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/fs/pnode.c	2017-07-21 00:59:24.000000000 -0400
@@ -24,6 +24,11 @@ static inline struct mount *first_slave(
 	return list_entry(p->mnt_slave_list.next, struct mount, mnt_slave);
 }
 
+static inline struct mount *last_slave(struct mount *p)
+{
+	return list_entry(p->mnt_slave_list.prev, struct mount, mnt_slave);
+}
+
 static inline struct mount *next_slave(struct mount *p)
 {
 	return list_entry(p->mnt_slave.next, struct mount, mnt_slave);
@@ -162,6 +167,19 @@ static struct mount *propagation_next(st
 	}
 }
 
+static struct mount *skip_propagation_subtree(struct mount *m,
+						struct mount *origin)
+{
+	/*
+	 * Advance m such that propagation_next will not return
+	 * the slaves of m.
+	 */
+	if (!IS_MNT_NEW(m) && !list_empty(&m->mnt_slave_list))
+		m = last_slave(m);
+
+	return m;
+}
+
 static struct mount *next_group(struct mount *m, struct mount *origin)
 {
 	while (1) {
@@ -413,68 +431,107 @@ void propagate_mount_unlock(struct mount
 	}
 }
 
-/*
- * Mark all mounts that the MNT_LOCKED logic will allow to be unmounted.
- */
-static void mark_umount_candidates(struct mount *mnt)
+static void umount_one(struct mount *mnt, struct list_head *to_umount)
 {
-	struct mount *parent = mnt->mnt_parent;
-	struct mount *m;
-
-	BUG_ON(parent == mnt);
-
-	for (m = propagation_next(parent, parent); m;
-			m = propagation_next(m, parent)) {
-		struct mount *child = __lookup_mnt(&m->mnt,
-						mnt->mnt_mountpoint);
-		if (!child || (child->mnt.mnt_flags & MNT_UMOUNT))
-			continue;
-		if (!IS_MNT_LOCKED(child) || IS_MNT_MARKED(m)) {
-			SET_MNT_MARK(child);
-		}
-	}
+	CLEAR_MNT_MARK(mnt);
+	mnt->mnt.mnt_flags |= MNT_UMOUNT;
+	list_del_init(&mnt->mnt_child);
+	list_del_init(&mnt->mnt_umounting);
+	list_move_tail(&mnt->mnt_list, to_umount);
 }
 
 /*
  * NOTE: unmounting 'mnt' naturally propagates to all other mounts its
  * parent propagates to.
  */
-static void __propagate_umount(struct mount *mnt)
+static bool __propagate_umount(struct mount *mnt,
+			       struct list_head *to_umount,
+			       struct list_head *to_restore)
 {
-	struct mount *parent = mnt->mnt_parent;
-	struct mount *m;
+	bool progress = false;
+	struct mount *child;
 
-	BUG_ON(parent == mnt);
+	/*
+	 * The state of the parent won't change if this mount is
+	 * already unmounted or marked as without children.
+	 */
+	if (mnt->mnt.mnt_flags & (MNT_UMOUNT | MNT_MARKED))
+		goto out;
 
-	for (m = propagation_next(parent, parent); m;
-			m = propagation_next(m, parent)) {
-		struct mount *topper;
-		struct mount *child = __lookup_mnt(&m->mnt,
-						mnt->mnt_mountpoint);
-		/*
-		 * umount the child only if the child has no children
-		 * and the child is marked safe to unmount.
-		 */
-		if (!child || !IS_MNT_MARKED(child))
+	/* Verify topper is the only grandchild that has not been
+	 * speculatively unmounted.
+	 */
+	list_for_each_entry(child, &mnt->mnt_mounts, mnt_child) {
+		if (child->mnt_mountpoint == mnt->mnt.mnt_root)
 			continue;
-		CLEAR_MNT_MARK(child);
+		if (!list_empty(&child->mnt_umounting) && IS_MNT_MARKED(child))
+			continue;
+		/* Found a mounted child */
+		goto children;
+	}
 
-		/* If there is exactly one mount covering all of child
-		 * replace child with that mount.
-		 */
-		topper = find_topper(child);
-		if (topper)
-			mnt_change_mountpoint(child->mnt_parent, child->mnt_mp,
-					      topper);
+	/* Mark mounts that can be unmounted if not locked */
+	SET_MNT_MARK(mnt);
+	progress = true;
 
-		if (list_empty(&child->mnt_mounts)) {
-			list_del_init(&child->mnt_child);
-			child->mnt.mnt_flags |= MNT_UMOUNT;
-			list_move_tail(&child->mnt_list, &mnt->mnt_list);
+	/* If a mount is without children and not locked umount it. */
+	if (!IS_MNT_LOCKED(mnt)) {
+		umount_one(mnt, to_umount);
+	} else {
+children:
+		list_move_tail(&mnt->mnt_umounting, to_restore);
+	}
+out:
+	return progress;
+}
+
+static void umount_list(struct list_head *to_umount,
+			struct list_head *to_restore)
+{
+	struct mount *mnt, *child, *tmp;
+	list_for_each_entry(mnt, to_umount, mnt_list) {
+		list_for_each_entry_safe(child, tmp, &mnt->mnt_mounts, mnt_child) {
+			/* topper? */
+			if (child->mnt_mountpoint == mnt->mnt.mnt_root)
+				list_move_tail(&child->mnt_umounting, to_restore);
+			else
+				umount_one(child, to_umount);
 		}
 	}
 }
 
+static void restore_mounts(struct list_head *to_restore)
+{
+	/* Restore mounts to a clean working state */
+	while (!list_empty(to_restore)) {
+		struct mount *mnt, *parent;
+		struct mountpoint *mp;
+
+		mnt = list_first_entry(to_restore, struct mount, mnt_umounting);
+		CLEAR_MNT_MARK(mnt);
+		list_del_init(&mnt->mnt_umounting);
+
+		/* Should this mount be reparented? */
+		mp = mnt->mnt_mp;
+		parent = mnt->mnt_parent;
+		while (parent->mnt.mnt_flags & MNT_UMOUNT) {
+			mp = parent->mnt_mp;
+			parent = parent->mnt_parent;
+		}
+		if (parent != mnt->mnt_parent)
+			mnt_change_mountpoint(parent, mp, mnt);
+	}
+}
+
+static void cleanup_umount_visitations(struct list_head *visited)
+{
+	while (!list_empty(visited)) {
+		struct mount *mnt =
+			list_first_entry(visited, struct mount, mnt_umounting);
+		list_del_init(&mnt->mnt_umounting);
+	}
+}
+
 /*
  * collect all mounts that receive propagation from the mount in @list,
  * and return these additional mounts in the same list.
@@ -485,11 +542,68 @@ static void __propagate_umount(struct mo
 int propagate_umount(struct list_head *list)
 {
 	struct mount *mnt;
+	LIST_HEAD(to_restore);
+	LIST_HEAD(to_umount);
+	LIST_HEAD(visited);
 
-	list_for_each_entry_reverse(mnt, list, mnt_list)
-		mark_umount_candidates(mnt);
+	/* Find candidates for unmounting */
+	list_for_each_entry_reverse(mnt, list, mnt_list) {
+		struct mount *parent = mnt->mnt_parent;
+		struct mount *m;
+
+		/*
+		 * If this mount has already been visited it is known that it's
+		 * entire peer group and all of their slaves in the propagation
+		 * tree for the mountpoint has already been visited and there is
+		 * no need to visit them again.
+		 */
+		if (!list_empty(&mnt->mnt_umounting))
+			continue;
+
+		list_add_tail(&mnt->mnt_umounting, &visited);
+		for (m = propagation_next(parent, parent); m;
+		     m = propagation_next(m, parent)) {
+			struct mount *child = __lookup_mnt(&m->mnt,
+							   mnt->mnt_mountpoint);
+			if (!child)
+				continue;
+
+			if (!list_empty(&child->mnt_umounting)) {
+				/*
+				 * If the child has already been visited it is
+				 * know that it's entire peer group and all of
+				 * their slaves in the propgation tree for the
+				 * mountpoint has already been visited and there
+				 * is no need to visit this subtree again.
+				 */
+				m = skip_propagation_subtree(m, parent);
+				continue;
+			} else if (child->mnt.mnt_flags & MNT_UMOUNT) {
+				/*
+				 * We have come accross an partially unmounted
+				 * mount in list that has not been visited yet.
+				 * Remember it has been visited and continue
+				 * about our merry way.
+				 */
+				list_add_tail(&child->mnt_umounting, &visited);
+				continue;
+			}
+
+			/* Check the child and parents while progress is made */
+			while (__propagate_umount(child,
+						  &to_umount, &to_restore)) {
+				/* Is the parent a umount candidate? */
+				child = child->mnt_parent;
+				if (list_empty(&child->mnt_umounting))
+					break;
+			}
+		}
+	}
+
+	umount_list(&to_umount, &to_restore);
+	restore_mounts(&to_restore);
+	cleanup_umount_visitations(&visited);
+	list_splice_tail(&to_umount, list);
 
-	list_for_each_entry(mnt, list, mnt_list)
-		__propagate_umount(mnt);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.12.2-gnu/fs/pstore/platform.c linux-libre-4.12.3-gnu/fs/pstore/platform.c
--- linux-libre-4.12.2-gnu/fs/pstore/platform.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/fs/pstore/platform.c	2017-07-21 00:59:24.000000000 -0400
@@ -846,8 +846,10 @@ void pstore_get_backend_records(struct p
 		record->size = psi->read(record);
 
 		/* No more records left in backend? */
-		if (record->size <= 0)
+		if (record->size <= 0) {
+			kfree(record);
 			break;
+		}
 
 		decompress_record(record);
 		rc = pstore_mkfile(root, record);
diff -druNp --no-dereference linux-libre-4.12.2-gnu/include/linux/compiler-clang.h linux-libre-4.12.3-gnu/include/linux/compiler-clang.h
--- linux-libre-4.12.2-gnu/include/linux/compiler-clang.h	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/include/linux/compiler-clang.h	2017-07-21 00:59:24.000000000 -0400
@@ -15,11 +15,3 @@
  * with any version that can compile the kernel
  */
 #define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__)
-
-/*
- * GCC does not warn about unused static inline functions for
- * -Wunused-function.  This turns out to avoid the need for complex #ifdef
- * directives.  Suppress the warning in clang as well.
- */
-#undef inline
-#define inline inline __attribute__((unused)) notrace
diff -druNp --no-dereference linux-libre-4.12.2-gnu/include/linux/compiler-gcc.h linux-libre-4.12.3-gnu/include/linux/compiler-gcc.h
--- linux-libre-4.12.2-gnu/include/linux/compiler-gcc.h	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/include/linux/compiler-gcc.h	2017-07-21 00:59:24.000000000 -0400
@@ -66,18 +66,22 @@
 
 /*
  * Force always-inline if the user requests it so via the .config,
- * or if gcc is too old:
+ * or if gcc is too old.
+ * GCC does not warn about unused static inline functions for
+ * -Wunused-function.  This turns out to avoid the need for complex #ifdef
+ * directives.  Suppress the warning in clang as well by using "unused"
+ * function attribute, which is redundant but not harmful for gcc.
  */
 #if !defined(CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING) ||		\
     !defined(CONFIG_OPTIMIZE_INLINING) || (__GNUC__ < 4)
-#define inline		inline		__attribute__((always_inline)) notrace
-#define __inline__	__inline__	__attribute__((always_inline)) notrace
-#define __inline	__inline	__attribute__((always_inline)) notrace
+#define inline inline		__attribute__((always_inline,unused)) notrace
+#define __inline__ __inline__	__attribute__((always_inline,unused)) notrace
+#define __inline __inline	__attribute__((always_inline,unused)) notrace
 #else
 /* A lot of inline functions can cause havoc with function tracing */
-#define inline		inline		notrace
-#define __inline__	__inline__	notrace
-#define __inline	__inline	notrace
+#define inline inline		__attribute__((unused)) notrace
+#define __inline__ __inline__	__attribute__((unused)) notrace
+#define __inline __inline	__attribute__((unused)) notrace
 #endif
 
 #define __always_inline	inline __attribute__((always_inline))
diff -druNp --no-dereference linux-libre-4.12.2-gnu/include/linux/list_lru.h linux-libre-4.12.3-gnu/include/linux/list_lru.h
--- linux-libre-4.12.2-gnu/include/linux/list_lru.h	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/include/linux/list_lru.h	2017-07-21 00:59:24.000000000 -0400
@@ -44,6 +44,7 @@ struct list_lru_node {
 	/* for cgroup aware lrus points to per cgroup lists, otherwise NULL */
 	struct list_lru_memcg	*memcg_lrus;
 #endif
+	long nr_items;
 } ____cacheline_aligned_in_smp;
 
 struct list_lru {
diff -druNp --no-dereference linux-libre-4.12.2-gnu/include/linux/mlx5/driver.h linux-libre-4.12.3-gnu/include/linux/mlx5/driver.h
--- linux-libre-4.12.2-gnu/include/linux/mlx5/driver.h	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/include/linux/mlx5/driver.h	2017-07-21 00:59:24.000000000 -0400
@@ -925,6 +925,7 @@ int mlx5_health_init(struct mlx5_core_de
 void mlx5_start_health_poll(struct mlx5_core_dev *dev);
 void mlx5_stop_health_poll(struct mlx5_core_dev *dev);
 void mlx5_drain_health_wq(struct mlx5_core_dev *dev);
+void mlx5_drain_health_recovery(struct mlx5_core_dev *dev);
 int mlx5_buf_alloc_node(struct mlx5_core_dev *dev, int size,
 			struct mlx5_buf *buf, int node);
 int mlx5_buf_alloc(struct mlx5_core_dev *dev, int size, struct mlx5_buf *buf);
diff -druNp --no-dereference linux-libre-4.12.2-gnu/include/net/ip6_route.h linux-libre-4.12.3-gnu/include/net/ip6_route.h
--- linux-libre-4.12.2-gnu/include/net/ip6_route.h	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/include/net/ip6_route.h	2017-07-21 00:59:24.000000000 -0400
@@ -22,6 +22,7 @@ struct route_info {
 #include <net/flow.h>
 #include <net/ip6_fib.h>
 #include <net/sock.h>
+#include <net/lwtunnel.h>
 #include <linux/ip.h>
 #include <linux/ipv6.h>
 #include <linux/route.h>
@@ -233,4 +234,11 @@ static inline struct in6_addr *rt6_nexth
 		return daddr;
 }
 
+static inline bool rt6_duplicate_nexthop(struct rt6_info *a, struct rt6_info *b)
+{
+	return a->dst.dev == b->dst.dev &&
+	       a->rt6i_idev == b->rt6i_idev &&
+	       ipv6_addr_equal(&a->rt6i_gateway, &b->rt6i_gateway) &&
+	       !lwtunnel_cmp_encap(a->dst.lwtstate, b->dst.lwtstate);
+}
 #endif
diff -druNp --no-dereference linux-libre-4.12.2-gnu/include/net/vxlan.h linux-libre-4.12.3-gnu/include/net/vxlan.h
--- linux-libre-4.12.2-gnu/include/net/vxlan.h	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/include/net/vxlan.h	2017-07-21 00:59:24.000000000 -0400
@@ -221,9 +221,17 @@ struct vxlan_config {
 	bool			no_share;
 };
 
+struct vxlan_dev_node {
+	struct hlist_node hlist;
+	struct vxlan_dev *vxlan;
+};
+
 /* Pseudo network device */
 struct vxlan_dev {
-	struct hlist_node hlist;	/* vni hash table */
+	struct vxlan_dev_node hlist4;	/* vni hash table for IPv4 socket */
+#if IS_ENABLED(CONFIG_IPV6)
+	struct vxlan_dev_node hlist6;	/* vni hash table for IPv6 socket */
+#endif
 	struct list_head  next;		/* vxlan's per namespace list */
 	struct vxlan_sock __rcu *vn4_sock;	/* listening socket for IPv4 */
 #if IS_ENABLED(CONFIG_IPV6)
diff -druNp --no-dereference linux-libre-4.12.2-gnu/include/uapi/linux/sched/types.h linux-libre-4.12.3-gnu/include/uapi/linux/sched/types.h
--- linux-libre-4.12.2-gnu/include/uapi/linux/sched/types.h	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/include/uapi/linux/sched/types.h	2017-07-21 00:59:24.000000000 -0400
@@ -54,21 +54,21 @@ struct sched_param {
  * available in the scheduling class file or in Documentation/.
  */
 struct sched_attr {
-	u32 size;
+	__u32 size;
 
-	u32 sched_policy;
-	u64 sched_flags;
+	__u32 sched_policy;
+	__u64 sched_flags;
 
 	/* SCHED_NORMAL, SCHED_BATCH */
-	s32 sched_nice;
+	__s32 sched_nice;
 
 	/* SCHED_FIFO, SCHED_RR */
-	u32 sched_priority;
+	__u32 sched_priority;
 
 	/* SCHED_DEADLINE */
-	u64 sched_runtime;
-	u64 sched_deadline;
-	u64 sched_period;
+	__u64 sched_runtime;
+	__u64 sched_deadline;
+	__u64 sched_period;
 };
 
 #endif /* _UAPI_LINUX_SCHED_TYPES_H */
diff -druNp --no-dereference linux-libre-4.12.2-gnu/kernel/extable.c linux-libre-4.12.3-gnu/kernel/extable.c
--- linux-libre-4.12.2-gnu/kernel/extable.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/kernel/extable.c	2017-07-21 00:59:24.000000000 -0400
@@ -69,7 +69,7 @@ static inline int init_kernel_text(unsig
 	return 0;
 }
 
-int core_kernel_text(unsigned long addr)
+int notrace core_kernel_text(unsigned long addr)
 {
 	if (addr >= (unsigned long)_stext &&
 	    addr < (unsigned long)_etext)
diff -druNp --no-dereference linux-libre-4.12.2-gnu/kernel/rcu/tree_plugin.h linux-libre-4.12.3-gnu/kernel/rcu/tree_plugin.h
--- linux-libre-4.12.2-gnu/kernel/rcu/tree_plugin.h	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/kernel/rcu/tree_plugin.h	2017-07-21 00:59:24.000000000 -0400
@@ -1769,6 +1769,7 @@ static void wake_nocb_leader(struct rcu_
 	if (READ_ONCE(rdp_leader->nocb_leader_sleep) || force) {
 		/* Prior smp_mb__after_atomic() orders against prior enqueue. */
 		WRITE_ONCE(rdp_leader->nocb_leader_sleep, false);
+		smp_mb(); /* ->nocb_leader_sleep before swake_up(). */
 		swake_up(&rdp_leader->nocb_wq);
 	}
 }
@@ -2023,6 +2024,7 @@ wait_again:
 	 * nocb_gp_head, where they await a grace period.
 	 */
 	gotcbs = false;
+	smp_mb(); /* wakeup before ->nocb_head reads. */
 	for (rdp = my_rdp; rdp; rdp = rdp->nocb_next_follower) {
 		rdp->nocb_gp_head = READ_ONCE(rdp->nocb_head);
 		if (!rdp->nocb_gp_head)
diff -druNp --no-dereference linux-libre-4.12.2-gnu/kernel/sched/topology.c linux-libre-4.12.3-gnu/kernel/sched/topology.c
--- linux-libre-4.12.2-gnu/kernel/sched/topology.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/kernel/sched/topology.c	2017-07-21 00:59:24.000000000 -0400
@@ -480,6 +480,9 @@ enum s_alloc {
  * Build an iteration mask that can exclude certain CPUs from the upwards
  * domain traversal.
  *
+ * Only CPUs that can arrive at this group should be considered to continue
+ * balancing.
+ *
  * Asymmetric node setups can result in situations where the domain tree is of
  * unequal depth, make sure to skip domains that already cover the entire
  * range.
@@ -490,18 +493,31 @@ enum s_alloc {
  */
 static void build_group_mask(struct sched_domain *sd, struct sched_group *sg)
 {
-	const struct cpumask *span = sched_domain_span(sd);
+	const struct cpumask *sg_span = sched_group_cpus(sg);
 	struct sd_data *sdd = sd->private;
 	struct sched_domain *sibling;
 	int i;
 
-	for_each_cpu(i, span) {
+	for_each_cpu(i, sg_span) {
 		sibling = *per_cpu_ptr(sdd->sd, i);
-		if (!cpumask_test_cpu(i, sched_domain_span(sibling)))
+
+		/*
+		 * Can happen in the asymmetric case, where these siblings are
+		 * unused. The mask will not be empty because those CPUs that
+		 * do have the top domain _should_ span the domain.
+		 */
+		if (!sibling->child)
+			continue;
+
+		/* If we would not end up here, we can't continue from here */
+		if (!cpumask_equal(sg_span, sched_domain_span(sibling->child)))
 			continue;
 
 		cpumask_set_cpu(i, sched_group_mask(sg));
 	}
+
+	/* We must not have empty masks here */
+	WARN_ON_ONCE(cpumask_empty(sched_group_mask(sg)));
 }
 
 /*
@@ -525,7 +541,7 @@ build_overlap_sched_groups(struct sched_
 
 	cpumask_clear(covered);
 
-	for_each_cpu(i, span) {
+	for_each_cpu_wrap(i, span, cpu) {
 		struct cpumask *sg_span;
 
 		if (cpumask_test_cpu(i, covered))
diff -druNp --no-dereference linux-libre-4.12.2-gnu/Makefile linux-libre-4.12.3-gnu/Makefile
--- linux-libre-4.12.2-gnu/Makefile	2017-07-15 13:22:13.000000000 -0400
+++ linux-libre-4.12.3-gnu/Makefile	2017-07-21 04:55:43.000000000 -0400
@@ -1,6 +1,6 @@
 VERSION = 4
 PATCHLEVEL = 12
-SUBLEVEL = 2
+SUBLEVEL = 3
 EXTRAVERSION = -gnu
 NAME = Fearless Coyote
 
diff -druNp --no-dereference linux-libre-4.12.2-gnu/mm/huge_memory.c linux-libre-4.12.3-gnu/mm/huge_memory.c
--- linux-libre-4.12.2-gnu/mm/huge_memory.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/mm/huge_memory.c	2017-07-21 00:59:24.000000000 -0400
@@ -1575,8 +1575,8 @@ bool madvise_free_huge_pmd(struct mmu_ga
 		get_page(page);
 		spin_unlock(ptl);
 		split_huge_page(page);
-		put_page(page);
 		unlock_page(page);
+		put_page(page);
 		goto out_unlocked;
 	}
 
diff -druNp --no-dereference linux-libre-4.12.2-gnu/mm/list_lru.c linux-libre-4.12.3-gnu/mm/list_lru.c
--- linux-libre-4.12.2-gnu/mm/list_lru.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/mm/list_lru.c	2017-07-21 00:59:24.000000000 -0400
@@ -117,6 +117,7 @@ bool list_lru_add(struct list_lru *lru,
 		l = list_lru_from_kmem(nlru, item);
 		list_add_tail(item, &l->list);
 		l->nr_items++;
+		nlru->nr_items++;
 		spin_unlock(&nlru->lock);
 		return true;
 	}
@@ -136,6 +137,7 @@ bool list_lru_del(struct list_lru *lru,
 		l = list_lru_from_kmem(nlru, item);
 		list_del_init(item);
 		l->nr_items--;
+		nlru->nr_items--;
 		spin_unlock(&nlru->lock);
 		return true;
 	}
@@ -183,15 +185,10 @@ EXPORT_SYMBOL_GPL(list_lru_count_one);
 
 unsigned long list_lru_count_node(struct list_lru *lru, int nid)
 {
-	long count = 0;
-	int memcg_idx;
+	struct list_lru_node *nlru;
 
-	count += __list_lru_count_one(lru, nid, -1);
-	if (list_lru_memcg_aware(lru)) {
-		for_each_memcg_cache_index(memcg_idx)
-			count += __list_lru_count_one(lru, nid, memcg_idx);
-	}
-	return count;
+	nlru = &lru->node[nid];
+	return nlru->nr_items;
 }
 EXPORT_SYMBOL_GPL(list_lru_count_node);
 
@@ -226,6 +223,7 @@ restart:
 			assert_spin_locked(&nlru->lock);
 		case LRU_REMOVED:
 			isolated++;
+			nlru->nr_items--;
 			/*
 			 * If the lru lock has been dropped, our list
 			 * traversal is now invalid and so we have to
diff -druNp --no-dereference linux-libre-4.12.2-gnu/mm/mmap.c linux-libre-4.12.3-gnu/mm/mmap.c
--- linux-libre-4.12.2-gnu/mm/mmap.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/mm/mmap.c	2017-07-21 00:59:24.000000000 -0400
@@ -2232,7 +2232,7 @@ int expand_upwards(struct vm_area_struct
 
 	/* Guard against exceeding limits of the address space. */
 	address &= PAGE_MASK;
-	if (address >= TASK_SIZE)
+	if (address >= (TASK_SIZE & PAGE_MASK))
 		return -ENOMEM;
 	address += PAGE_SIZE;
 
diff -druNp --no-dereference linux-libre-4.12.2-gnu/net/bridge/br_mdb.c linux-libre-4.12.3-gnu/net/bridge/br_mdb.c
--- linux-libre-4.12.2-gnu/net/bridge/br_mdb.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/net/bridge/br_mdb.c	2017-07-21 00:59:24.000000000 -0400
@@ -323,7 +323,8 @@ static void __br_mdb_notify(struct net_d
 			__mdb_entry_to_br_ip(entry, &complete_info->ip);
 			mdb.obj.complete_priv = complete_info;
 			mdb.obj.complete = br_mdb_complete;
-			switchdev_port_obj_add(port_dev, &mdb.obj);
+			if (switchdev_port_obj_add(port_dev, &mdb.obj))
+				kfree(complete_info);
 		}
 	} else if (port_dev && type == RTM_DELMDB) {
 		switchdev_port_obj_del(port_dev, &mdb.obj);
diff -druNp --no-dereference linux-libre-4.12.2-gnu/net/core/dev.c linux-libre-4.12.3-gnu/net/core/dev.c
--- linux-libre-4.12.2-gnu/net/core/dev.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/net/core/dev.c	2017-07-21 00:59:24.000000000 -0400
@@ -7751,7 +7751,7 @@ void netdev_stats_to_stats64(struct rtnl
 {
 #if BITS_PER_LONG == 64
 	BUILD_BUG_ON(sizeof(*stats64) < sizeof(*netdev_stats));
-	memcpy(stats64, netdev_stats, sizeof(*stats64));
+	memcpy(stats64, netdev_stats, sizeof(*netdev_stats));
 	/* zero out counters that only exist in rtnl_link_stats64 */
 	memset((char *)stats64 + sizeof(*netdev_stats), 0,
 	       sizeof(*stats64) - sizeof(*netdev_stats));
diff -druNp --no-dereference linux-libre-4.12.2-gnu/net/ipv6/addrconf.c linux-libre-4.12.3-gnu/net/ipv6/addrconf.c
--- linux-libre-4.12.2-gnu/net/ipv6/addrconf.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/net/ipv6/addrconf.c	2017-07-21 00:59:24.000000000 -0400
@@ -1912,15 +1912,7 @@ static void addrconf_dad_stop(struct ine
 	if (dad_failed)
 		ifp->flags |= IFA_F_DADFAILED;
 
-	if (ifp->flags&IFA_F_PERMANENT) {
-		spin_lock_bh(&ifp->lock);
-		addrconf_del_dad_work(ifp);
-		ifp->flags |= IFA_F_TENTATIVE;
-		spin_unlock_bh(&ifp->lock);
-		if (dad_failed)
-			ipv6_ifa_notify(0, ifp);
-		in6_ifa_put(ifp);
-	} else if (ifp->flags&IFA_F_TEMPORARY) {
+	if (ifp->flags&IFA_F_TEMPORARY) {
 		struct inet6_ifaddr *ifpub;
 		spin_lock_bh(&ifp->lock);
 		ifpub = ifp->ifpub;
@@ -1933,6 +1925,14 @@ static void addrconf_dad_stop(struct ine
 			spin_unlock_bh(&ifp->lock);
 		}
 		ipv6_del_addr(ifp);
+	} else if (ifp->flags&IFA_F_PERMANENT || !dad_failed) {
+		spin_lock_bh(&ifp->lock);
+		addrconf_del_dad_work(ifp);
+		ifp->flags |= IFA_F_TENTATIVE;
+		spin_unlock_bh(&ifp->lock);
+		if (dad_failed)
+			ipv6_ifa_notify(0, ifp);
+		in6_ifa_put(ifp);
 	} else {
 		ipv6_del_addr(ifp);
 	}
diff -druNp --no-dereference linux-libre-4.12.2-gnu/net/ipv6/ip6_fib.c linux-libre-4.12.3-gnu/net/ipv6/ip6_fib.c
--- linux-libre-4.12.2-gnu/net/ipv6/ip6_fib.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/net/ipv6/ip6_fib.c	2017-07-21 00:59:24.000000000 -0400
@@ -784,10 +784,7 @@ static int fib6_add_rt2node(struct fib6_
 				goto next_iter;
 			}
 
-			if (iter->dst.dev == rt->dst.dev &&
-			    iter->rt6i_idev == rt->rt6i_idev &&
-			    ipv6_addr_equal(&iter->rt6i_gateway,
-					    &rt->rt6i_gateway)) {
+			if (rt6_duplicate_nexthop(iter, rt)) {
 				if (rt->rt6i_nsiblings)
 					rt->rt6i_nsiblings = 0;
 				if (!(iter->rt6i_flags & RTF_EXPIRES))
diff -druNp --no-dereference linux-libre-4.12.2-gnu/net/ipv6/route.c linux-libre-4.12.3-gnu/net/ipv6/route.c
--- linux-libre-4.12.2-gnu/net/ipv6/route.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/net/ipv6/route.c	2017-07-21 00:59:24.000000000 -0400
@@ -3048,17 +3048,11 @@ static int ip6_route_info_append(struct
 				 struct rt6_info *rt, struct fib6_config *r_cfg)
 {
 	struct rt6_nh *nh;
-	struct rt6_info *rtnh;
 	int err = -EEXIST;
 
 	list_for_each_entry(nh, rt6_nh_list, next) {
 		/* check if rt6_info already exists */
-		rtnh = nh->rt6_info;
-
-		if (rtnh->dst.dev == rt->dst.dev &&
-		    rtnh->rt6i_idev == rt->rt6i_idev &&
-		    ipv6_addr_equal(&rtnh->rt6i_gateway,
-				    &rt->rt6i_gateway))
+		if (rt6_duplicate_nexthop(nh->rt6_info, rt))
 			return err;
 	}
 
diff -druNp --no-dereference linux-libre-4.12.2-gnu/net/rds/tcp_listen.c linux-libre-4.12.3-gnu/net/rds/tcp_listen.c
--- linux-libre-4.12.2-gnu/net/rds/tcp_listen.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/net/rds/tcp_listen.c	2017-07-21 00:59:24.000000000 -0400
@@ -125,7 +125,7 @@ int rds_tcp_accept_one(struct socket *so
 	if (!sock) /* module unload or netns delete in progress */
 		return -ENETUNREACH;
 
-	ret = sock_create_kern(sock_net(sock->sk), sock->sk->sk_family,
+	ret = sock_create_lite(sock->sk->sk_family,
 			       sock->sk->sk_type, sock->sk->sk_protocol,
 			       &new_sock);
 	if (ret)
diff -druNp --no-dereference linux-libre-4.12.2-gnu/net/wireless/nl80211.c linux-libre-4.12.3-gnu/net/wireless/nl80211.c
--- linux-libre-4.12.2-gnu/net/wireless/nl80211.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/net/wireless/nl80211.c	2017-07-21 00:59:24.000000000 -0400
@@ -291,8 +291,7 @@ static const struct nla_policy nl80211_p
 	[NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 },
 	[NL80211_ATTR_PID] = { .type = NLA_U32 },
 	[NL80211_ATTR_4ADDR] = { .type = NLA_U8 },
-	[NL80211_ATTR_PMKID] = { .type = NLA_BINARY,
-				 .len = WLAN_PMKID_LEN },
+	[NL80211_ATTR_PMKID] = { .len = WLAN_PMKID_LEN },
 	[NL80211_ATTR_DURATION] = { .type = NLA_U32 },
 	[NL80211_ATTR_COOKIE] = { .type = NLA_U64 },
 	[NL80211_ATTR_TX_RATES] = { .type = NLA_NESTED },
@@ -348,6 +347,7 @@ static const struct nla_policy nl80211_p
 	[NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 },
 	[NL80211_ATTR_P2P_CTWINDOW] = { .type = NLA_U8 },
 	[NL80211_ATTR_P2P_OPPPS] = { .type = NLA_U8 },
+	[NL80211_ATTR_LOCAL_MESH_POWER_MODE] = {. type = NLA_U32 },
 	[NL80211_ATTR_ACL_POLICY] = {. type = NLA_U32 },
 	[NL80211_ATTR_MAC_ADDRS] = { .type = NLA_NESTED },
 	[NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 },
@@ -520,7 +520,7 @@ nl80211_bss_select_policy[NL80211_BSS_SE
 static const struct nla_policy
 nl80211_nan_func_policy[NL80211_NAN_FUNC_ATTR_MAX + 1] = {
 	[NL80211_NAN_FUNC_TYPE] = { .type = NLA_U8 },
-	[NL80211_NAN_FUNC_SERVICE_ID] = { .type = NLA_BINARY,
+	[NL80211_NAN_FUNC_SERVICE_ID] = {
 				    .len = NL80211_NAN_FUNC_SERVICE_ID_LEN },
 	[NL80211_NAN_FUNC_PUBLISH_TYPE] = { .type = NLA_U8 },
 	[NL80211_NAN_FUNC_PUBLISH_BCAST] = { .type = NLA_FLAG },
@@ -6469,6 +6469,10 @@ static int validate_scan_freqs(struct nl
 	struct nlattr *attr1, *attr2;
 	int n_channels = 0, tmp1, tmp2;
 
+	nla_for_each_nested(attr1, freqs, tmp1)
+		if (nla_len(attr1) != sizeof(u32))
+			return 0;
+
 	nla_for_each_nested(attr1, freqs, tmp1) {
 		n_channels++;
 		/*
diff -druNp --no-dereference linux-libre-4.12.2-gnu/scripts/checkpatch.pl linux-libre-4.12.3-gnu/scripts/checkpatch.pl
--- linux-libre-4.12.2-gnu/scripts/checkpatch.pl	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/scripts/checkpatch.pl	2017-07-21 00:59:24.000000000 -0400
@@ -3541,7 +3541,7 @@ sub process {
 				$fixedline =~ s/\s*=\s*$/ = {/;
 				fix_insert_line($fixlinenr, $fixedline);
 				$fixedline = $line;
-				$fixedline =~ s/^(.\s*){\s*/$1/;
+				$fixedline =~ s/^(.\s*)\{\s*/$1/;
 				fix_insert_line($fixlinenr, $fixedline);
 			}
 		}
@@ -3882,7 +3882,7 @@ sub process {
 				my $fixedline = rtrim($prevrawline) . " {";
 				fix_insert_line($fixlinenr, $fixedline);
 				$fixedline = $rawline;
-				$fixedline =~ s/^(.\s*){\s*/$1\t/;
+				$fixedline =~ s/^(.\s*)\{\s*/$1\t/;
 				if ($fixedline !~ /^\+\s*$/) {
 					fix_insert_line($fixlinenr, $fixedline);
 				}
@@ -4371,7 +4371,7 @@ sub process {
 			if (ERROR("SPACING",
 				  "space required before the open brace '{'\n" . $herecurr) &&
 			    $fix) {
-				$fixed[$fixlinenr] =~ s/^(\+.*(?:do|\))){/$1 {/;
+				$fixed[$fixlinenr] =~ s/^(\+.*(?:do|\)))\{/$1 {/;
 			}
 		}
 
diff -druNp --no-dereference linux-libre-4.12.2-gnu/security/keys/compat_dh.c linux-libre-4.12.3-gnu/security/keys/compat_dh.c
--- linux-libre-4.12.2-gnu/security/keys/compat_dh.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/security/keys/compat_dh.c	2017-07-21 00:59:24.000000000 -0400
@@ -33,6 +33,8 @@ long compat_keyctl_dh_compute(struct key
 	kdfcopy.hashname = compat_ptr(compat_kdfcopy.hashname);
 	kdfcopy.otherinfo = compat_ptr(compat_kdfcopy.otherinfo);
 	kdfcopy.otherinfolen = compat_kdfcopy.otherinfolen;
+	memcpy(kdfcopy.__spare, compat_kdfcopy.__spare,
+	       sizeof(kdfcopy.__spare));
 
 	return __keyctl_dh_compute(params, buffer, buflen, &kdfcopy);
 }
diff -druNp --no-dereference linux-libre-4.12.2-gnu/security/keys/dh.c linux-libre-4.12.3-gnu/security/keys/dh.c
--- linux-libre-4.12.2-gnu/security/keys/dh.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/security/keys/dh.c	2017-07-21 00:59:24.000000000 -0400
@@ -266,6 +266,11 @@ long __keyctl_dh_compute(struct keyctl_d
 	if (kdfcopy) {
 		char *hashname;
 
+		if (memchr_inv(kdfcopy->__spare, 0, sizeof(kdfcopy->__spare))) {
+			ret = -EINVAL;
+			goto out1;
+		}
+
 		if (buflen > KEYCTL_KDF_MAX_OUTPUT_LEN ||
 		    kdfcopy->otherinfolen > KEYCTL_KDF_MAX_OI_LEN) {
 			ret = -EMSGSIZE;
diff -druNp --no-dereference linux-libre-4.12.2-gnu/sound/pci/hda/patch_realtek.c linux-libre-4.12.3-gnu/sound/pci/hda/patch_realtek.c
--- linux-libre-4.12.2-gnu/sound/pci/hda/patch_realtek.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/sound/pci/hda/patch_realtek.c	2017-07-21 00:59:24.000000000 -0400
@@ -4964,6 +4964,7 @@ enum {
 	ALC233_FIXUP_ASUS_MIC_NO_PRESENCE,
 	ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE,
 	ALC233_FIXUP_LENOVO_MULTI_CODECS,
+	ALC294_FIXUP_LENOVO_MIC_LOCATION,
 };
 
 static const struct hda_fixup alc269_fixups[] = {
@@ -5737,6 +5738,18 @@ static const struct hda_fixup alc269_fix
 		.type = HDA_FIXUP_FUNC,
 		.v.func = alc233_alc662_fixup_lenovo_dual_codecs,
 	},
+	[ALC294_FIXUP_LENOVO_MIC_LOCATION] = {
+		.type = HDA_FIXUP_PINS,
+		.v.pins = (const struct hda_pintbl[]) {
+			/* Change the mic location from front to right, otherwise there are
+			   two front mics with the same name, pulseaudio can't handle them.
+			   This is just a temporary workaround, after applying this fixup,
+			   there will be one "Front Mic" and one "Mic" in this machine.
+			 */
+			{ 0x1a, 0x04a19040 },
+			{ }
+		},
+	},
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -5918,6 +5931,7 @@ static const struct snd_pci_quirk alc269
 	SND_PCI_QUIRK(0x17aa, 0x2233, "Thinkpad", ALC292_FIXUP_TPT460),
 	SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
 	SND_PCI_QUIRK(0x17aa, 0x30e2, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
+	SND_PCI_QUIRK(0x17aa, 0x310c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION),
 	SND_PCI_QUIRK(0x17aa, 0x3112, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
 	SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
 	SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC),
diff -druNp --no-dereference linux-libre-4.12.2-gnu/sound/x86/intel_hdmi_audio.c linux-libre-4.12.3-gnu/sound/x86/intel_hdmi_audio.c
--- linux-libre-4.12.2-gnu/sound/x86/intel_hdmi_audio.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/sound/x86/intel_hdmi_audio.c	2017-07-21 00:59:24.000000000 -0400
@@ -1665,6 +1665,11 @@ static int __maybe_unused hdmi_lpe_audio
 static void hdmi_lpe_audio_free(struct snd_card *card)
 {
 	struct snd_intelhad *ctx = card->private_data;
+	struct intel_hdmi_lpe_audio_pdata *pdata = ctx->dev->platform_data;
+
+	spin_lock_irq(&pdata->lpe_audio_slock);
+	pdata->notify_audio_lpe = NULL;
+	spin_unlock_irq(&pdata->lpe_audio_slock);
 
 	cancel_work_sync(&ctx->hdmi_audio_wq);
 
diff -druNp --no-dereference linux-libre-4.12.2-gnu/tools/lib/lockdep/uinclude/linux/lockdep.h linux-libre-4.12.3-gnu/tools/lib/lockdep/uinclude/linux/lockdep.h
--- linux-libre-4.12.2-gnu/tools/lib/lockdep/uinclude/linux/lockdep.h	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/tools/lib/lockdep/uinclude/linux/lockdep.h	2017-07-21 00:59:24.000000000 -0400
@@ -8,7 +8,7 @@
 #include <linux/utsname.h>
 #include <linux/compiler.h>
 
-#define MAX_LOCK_DEPTH 2000UL
+#define MAX_LOCK_DEPTH 63UL
 
 #define asmlinkage
 #define __visible
diff -druNp --no-dereference linux-libre-4.12.2-gnu/tools/testing/selftests/capabilities/test_execve.c linux-libre-4.12.3-gnu/tools/testing/selftests/capabilities/test_execve.c
--- linux-libre-4.12.2-gnu/tools/testing/selftests/capabilities/test_execve.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/tools/testing/selftests/capabilities/test_execve.c	2017-07-21 00:59:24.000000000 -0400
@@ -138,9 +138,6 @@ static void chdir_to_tmpfs(void)
 
 	if (chdir(cwd) != 0)
 		err(1, "chdir to private tmpfs");
-
-	if (umount2(".", MNT_DETACH) != 0)
-		err(1, "detach private tmpfs");
 }
 
 static void copy_fromat_to(int fromfd, const char *fromname, const char *toname)
@@ -248,7 +245,7 @@ static int do_tests(int uid, const char
 			err(1, "chown");
 		if (chmod("validate_cap_sgidnonroot", S_ISGID | 0710) != 0)
 			err(1, "chmod");
-}
+	}
 
 	capng_get_caps_process();
 
@@ -384,7 +381,7 @@ static int do_tests(int uid, const char
 	} else {
 		printf("[RUN]\tNon-root +ia, sgidnonroot => i\n");
 		exec_other_validate_cap("./validate_cap_sgidnonroot",
-						false, false, true, false);
+					false, false, true, false);
 
 		if (fork_wait()) {
 			printf("[RUN]\tNon-root +ia, sgidroot => i\n");
diff -druNp --no-dereference linux-libre-4.12.2-gnu/virt/kvm/arm/arm.c linux-libre-4.12.3-gnu/virt/kvm/arm/arm.c
--- linux-libre-4.12.2-gnu/virt/kvm/arm/arm.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/virt/kvm/arm/arm.c	2017-07-21 00:59:24.000000000 -0400
@@ -1115,9 +1115,6 @@ static void cpu_init_hyp_mode(void *dumm
 	__cpu_init_hyp_mode(pgd_ptr, hyp_stack_ptr, vector_ptr);
 	__cpu_init_stage2();
 
-	if (is_kernel_in_hyp_mode())
-		kvm_timer_init_vhe();
-
 	kvm_arm_init_debug();
 }
 
@@ -1137,6 +1134,7 @@ static void cpu_hyp_reinit(void)
 		 * event was cancelled before the CPU was reset.
 		 */
 		__cpu_init_stage2();
+		kvm_timer_init_vhe();
 	} else {
 		cpu_init_hyp_mode(NULL);
 	}
diff -druNp --no-dereference linux-libre-4.12.2-gnu/virt/kvm/vfio.c linux-libre-4.12.3-gnu/virt/kvm/vfio.c
--- linux-libre-4.12.2-gnu/virt/kvm/vfio.c	2017-07-15 07:09:20.000000000 -0400
+++ linux-libre-4.12.3-gnu/virt/kvm/vfio.c	2017-07-21 00:59:24.000000000 -0400
@@ -246,21 +246,20 @@ static int kvm_vfio_set_group(struct kvm
 				continue;
 
 			list_del(&kvg->node);
+			kvm_arch_end_assignment(dev->kvm);
+#ifdef CONFIG_SPAPR_TCE_IOMMU
+			kvm_spapr_tce_release_vfio_group(dev->kvm,
+							 kvg->vfio_group);
+#endif
+			kvm_vfio_group_set_kvm(kvg->vfio_group, NULL);
 			kvm_vfio_group_put_external_user(kvg->vfio_group);
 			kfree(kvg);
 			ret = 0;
 			break;
 		}
 
-		kvm_arch_end_assignment(dev->kvm);
-
 		mutex_unlock(&kv->lock);
 
-#ifdef CONFIG_SPAPR_TCE_IOMMU
-		kvm_spapr_tce_release_vfio_group(dev->kvm, vfio_group);
-#endif
-		kvm_vfio_group_set_kvm(vfio_group, NULL);
-
 		kvm_vfio_group_put_external_user(vfio_group);
 
 		kvm_vfio_update_coherency(dev);
