diff -druNp --no-dereference linux-libre-4.9.35-gnu/arch/arm/boot/dts/logicpd-torpedo-som.dtsi linux-libre-4.9.36-gnu/arch/arm/boot/dts/logicpd-torpedo-som.dtsi
--- linux-libre-4.9.35-gnu/arch/arm/boot/dts/logicpd-torpedo-som.dtsi	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/arch/arm/boot/dts/logicpd-torpedo-som.dtsi	2017-07-05 08:40:44.000000000 -0400
@@ -121,7 +121,7 @@
 &i2c3 {
 	clock-frequency = <400000>;
 	at24@50 {
-		compatible = "at24,24c02";
+		compatible = "atmel,24c64";
 		readonly;
 		reg = <0x50>;
 	};
diff -druNp --no-dereference linux-libre-4.9.35-gnu/arch/arm/mach-omap2/omap_device.c linux-libre-4.9.36-gnu/arch/arm/mach-omap2/omap_device.c
--- linux-libre-4.9.35-gnu/arch/arm/mach-omap2/omap_device.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/arch/arm/mach-omap2/omap_device.c	2017-07-05 08:40:44.000000000 -0400
@@ -222,6 +222,14 @@ static int _omap_device_notifier_call(st
 				dev_err(dev, "failed to idle\n");
 		}
 		break;
+	case BUS_NOTIFY_BIND_DRIVER:
+		od = to_omap_device(pdev);
+		if (od && (od->_state == OMAP_DEVICE_STATE_ENABLED) &&
+		    pm_runtime_status_suspended(dev)) {
+			od->_driver_status = BUS_NOTIFY_BIND_DRIVER;
+			pm_runtime_set_active(dev);
+		}
+		break;
 	case BUS_NOTIFY_ADD_DEVICE:
 		if (pdev->dev.of_node)
 			omap_device_build_from_dt(pdev);
diff -druNp --no-dereference linux-libre-4.9.35-gnu/arch/arm/mm/mmu.c linux-libre-4.9.36-gnu/arch/arm/mm/mmu.c
--- linux-libre-4.9.35-gnu/arch/arm/mm/mmu.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/arch/arm/mm/mmu.c	2017-07-05 08:40:44.000000000 -0400
@@ -1211,15 +1211,15 @@ void __init adjust_lowmem_bounds(void)
 
 	high_memory = __va(arm_lowmem_limit - 1) + 1;
 
+	if (!memblock_limit)
+		memblock_limit = arm_lowmem_limit;
+
 	/*
 	 * Round the memblock limit down to a pmd size.  This
 	 * helps to ensure that we will allocate memory from the
 	 * last full pmd, which should be mapped.
 	 */
-	if (memblock_limit)
-		memblock_limit = round_down(memblock_limit, PMD_SIZE);
-	if (!memblock_limit)
-		memblock_limit = arm_lowmem_limit;
+	memblock_limit = round_down(memblock_limit, PMD_SIZE);
 
 	if (!IS_ENABLED(CONFIG_HIGHMEM) || cache_is_vipt_aliasing()) {
 		if (memblock_end_of_DRAM() > arm_lowmem_limit) {
diff -druNp --no-dereference linux-libre-4.9.35-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts linux-libre-4.9.36-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
--- linux-libre-4.9.35-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts	2017-07-05 08:40:44.000000000 -0400
@@ -85,6 +85,18 @@
 	status = "okay";
 	pinctrl-0 = <&eth_pins>;
 	pinctrl-names = "default";
+	phy-handle = <&eth_phy0>;
+
+	mdio {
+		compatible = "snps,dwmac-mdio";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		eth_phy0: ethernet-phy@0 {
+			reg = <0>;
+			eee-broken-1000t;
+		};
+	};
 };
 
 &ir {
diff -druNp --no-dereference linux-libre-4.9.35-gnu/arch/arm64/include/asm/acpi.h linux-libre-4.9.36-gnu/arch/arm64/include/asm/acpi.h
--- linux-libre-4.9.35-gnu/arch/arm64/include/asm/acpi.h	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/arch/arm64/include/asm/acpi.h	2017-07-05 08:40:44.000000000 -0400
@@ -22,9 +22,9 @@
 #define ACPI_MADT_GICC_LENGTH	\
 	(acpi_gbl_FADT.header.revision < 6 ? 76 : 80)
 
-#define BAD_MADT_GICC_ENTRY(entry, end)						\
-	(!(entry) || (unsigned long)(entry) + sizeof(*(entry)) > (end) ||	\
-	 (entry)->header.length != ACPI_MADT_GICC_LENGTH)
+#define BAD_MADT_GICC_ENTRY(entry, end)					\
+	(!(entry) || (entry)->header.length != ACPI_MADT_GICC_LENGTH ||	\
+	(unsigned long)(entry) + ACPI_MADT_GICC_LENGTH > (end))
 
 /* Basic configuration for ACPI */
 #ifdef	CONFIG_ACPI
diff -druNp --no-dereference linux-libre-4.9.35-gnu/arch/arm64/include/asm/assembler.h linux-libre-4.9.36-gnu/arch/arm64/include/asm/assembler.h
--- linux-libre-4.9.35-gnu/arch/arm64/include/asm/assembler.h	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/arch/arm64/include/asm/assembler.h	2017-07-05 08:40:44.000000000 -0400
@@ -155,22 +155,25 @@ lr	.req	x30		// link register
 
 /*
  * Pseudo-ops for PC-relative adr/ldr/str <reg>, <symbol> where
- * <symbol> is within the range +/- 4 GB of the PC.
+ * <symbol> is within the range +/- 4 GB of the PC when running
+ * in core kernel context. In module context, a movz/movk sequence
+ * is used, since modules may be loaded far away from the kernel
+ * when KASLR is in effect.
  */
 	/*
 	 * @dst: destination register (64 bit wide)
 	 * @sym: name of the symbol
-	 * @tmp: optional scratch register to be used if <dst> == sp, which
-	 *       is not allowed in an adrp instruction
 	 */
-	.macro	adr_l, dst, sym, tmp=
-	.ifb	\tmp
+	.macro	adr_l, dst, sym
+#ifndef MODULE
 	adrp	\dst, \sym
 	add	\dst, \dst, :lo12:\sym
-	.else
-	adrp	\tmp, \sym
-	add	\dst, \tmp, :lo12:\sym
-	.endif
+#else
+	movz	\dst, #:abs_g3:\sym
+	movk	\dst, #:abs_g2_nc:\sym
+	movk	\dst, #:abs_g1_nc:\sym
+	movk	\dst, #:abs_g0_nc:\sym
+#endif
 	.endm
 
 	/*
@@ -181,6 +184,7 @@ lr	.req	x30		// link register
 	 *       the address
 	 */
 	.macro	ldr_l, dst, sym, tmp=
+#ifndef MODULE
 	.ifb	\tmp
 	adrp	\dst, \sym
 	ldr	\dst, [\dst, :lo12:\sym]
@@ -188,6 +192,15 @@ lr	.req	x30		// link register
 	adrp	\tmp, \sym
 	ldr	\dst, [\tmp, :lo12:\sym]
 	.endif
+#else
+	.ifb	\tmp
+	adr_l	\dst, \sym
+	ldr	\dst, [\dst]
+	.else
+	adr_l	\tmp, \sym
+	ldr	\dst, [\tmp]
+	.endif
+#endif
 	.endm
 
 	/*
@@ -197,8 +210,13 @@ lr	.req	x30		// link register
 	 *       while <src> needs to be preserved.
 	 */
 	.macro	str_l, src, sym, tmp
+#ifndef MODULE
 	adrp	\tmp, \sym
 	str	\src, [\tmp, :lo12:\sym]
+#else
+	adr_l	\tmp, \sym
+	str	\src, [\tmp]
+#endif
 	.endm
 
 	/*
diff -druNp --no-dereference linux-libre-4.9.35-gnu/arch/arm64/kernel/smp.c linux-libre-4.9.36-gnu/arch/arm64/kernel/smp.c
--- linux-libre-4.9.35-gnu/arch/arm64/kernel/smp.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/arch/arm64/kernel/smp.c	2017-07-05 08:40:44.000000000 -0400
@@ -934,7 +934,7 @@ static bool have_cpu_die(void)
 #ifdef CONFIG_HOTPLUG_CPU
 	int any_cpu = raw_smp_processor_id();
 
-	if (cpu_ops[any_cpu]->cpu_die)
+	if (cpu_ops[any_cpu] && cpu_ops[any_cpu]->cpu_die)
 		return true;
 #endif
 	return false;
diff -druNp --no-dereference linux-libre-4.9.35-gnu/arch/mips/kernel/entry.S linux-libre-4.9.36-gnu/arch/mips/kernel/entry.S
--- linux-libre-4.9.35-gnu/arch/mips/kernel/entry.S	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/arch/mips/kernel/entry.S	2017-07-05 08:40:44.000000000 -0400
@@ -11,6 +11,7 @@
 #include <asm/asm.h>
 #include <asm/asmmacro.h>
 #include <asm/compiler.h>
+#include <asm/irqflags.h>
 #include <asm/regdef.h>
 #include <asm/mipsregs.h>
 #include <asm/stackframe.h>
@@ -137,6 +138,7 @@ work_pending:
 	andi	t0, a2, _TIF_NEED_RESCHED # a2 is preloaded with TI_FLAGS
 	beqz	t0, work_notifysig
 work_resched:
+	TRACE_IRQS_OFF
 	jal	schedule
 
 	local_irq_disable		# make sure need_resched and
@@ -173,6 +175,7 @@ syscall_exit_work:
 	beqz	t0, work_pending	# trace bit set?
 	local_irq_enable		# could let syscall_trace_leave()
 					# call schedule() instead
+	TRACE_IRQS_ON
 	move	a0, sp
 	jal	syscall_trace_leave
 	b	resume_userspace
diff -druNp --no-dereference linux-libre-4.9.35-gnu/arch/mips/kernel/head.S linux-libre-4.9.36-gnu/arch/mips/kernel/head.S
--- linux-libre-4.9.35-gnu/arch/mips/kernel/head.S	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/arch/mips/kernel/head.S	2017-07-05 08:40:44.000000000 -0400
@@ -106,8 +106,8 @@ NESTED(kernel_entry, 16, sp)			# kernel
 	beq		t0, t1, dtb_found
 #endif
 	li		t1, -2
-	beq		a0, t1, dtb_found
 	move		t2, a1
+	beq		a0, t1, dtb_found
 
 	li		t2, 0
 dtb_found:
diff -druNp --no-dereference linux-libre-4.9.35-gnu/arch/mips/kernel/pm-cps.c linux-libre-4.9.36-gnu/arch/mips/kernel/pm-cps.c
--- linux-libre-4.9.35-gnu/arch/mips/kernel/pm-cps.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/arch/mips/kernel/pm-cps.c	2017-07-05 08:40:44.000000000 -0400
@@ -56,7 +56,6 @@ DECLARE_BITMAP(state_support, CPS_PM_STA
  * state. Actually per-core rather than per-CPU.
  */
 static DEFINE_PER_CPU_ALIGNED(u32*, ready_count);
-static DEFINE_PER_CPU_ALIGNED(void*, ready_count_alloc);
 
 /* Indicates online CPUs coupled with the current CPU */
 static DEFINE_PER_CPU_ALIGNED(cpumask_t, online_coupled);
@@ -642,7 +641,6 @@ static int cps_pm_online_cpu(unsigned in
 {
 	enum cps_pm_state state;
 	unsigned core = cpu_data[cpu].core;
-	unsigned dlinesz = cpu_data[cpu].dcache.linesz;
 	void *entry_fn, *core_rc;
 
 	for (state = CPS_PM_NC_WAIT; state < CPS_PM_STATE_COUNT; state++) {
@@ -662,16 +660,11 @@ static int cps_pm_online_cpu(unsigned in
 	}
 
 	if (!per_cpu(ready_count, core)) {
-		core_rc = kmalloc(dlinesz * 2, GFP_KERNEL);
+		core_rc = kmalloc(sizeof(u32), GFP_KERNEL);
 		if (!core_rc) {
 			pr_err("Failed allocate core %u ready_count\n", core);
 			return -ENOMEM;
 		}
-		per_cpu(ready_count_alloc, core) = core_rc;
-
-		/* Ensure ready_count is aligned to a cacheline boundary */
-		core_rc += dlinesz - 1;
-		core_rc = (void *)((unsigned long)core_rc & ~(dlinesz - 1));
 		per_cpu(ready_count, core) = core_rc;
 	}
 
diff -druNp --no-dereference linux-libre-4.9.35-gnu/arch/mips/kernel/traps.c linux-libre-4.9.36-gnu/arch/mips/kernel/traps.c
--- linux-libre-4.9.35-gnu/arch/mips/kernel/traps.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/arch/mips/kernel/traps.c	2017-07-05 08:40:44.000000000 -0400
@@ -199,6 +199,8 @@ void show_stack(struct task_struct *task
 {
 	struct pt_regs regs;
 	mm_segment_t old_fs = get_fs();
+
+	regs.cp0_status = KSU_KERNEL;
 	if (sp) {
 		regs.regs[29] = (unsigned long)sp;
 		regs.regs[31] = 0;
diff -druNp --no-dereference linux-libre-4.9.35-gnu/arch/powerpc/kernel/eeh.c linux-libre-4.9.36-gnu/arch/powerpc/kernel/eeh.c
--- linux-libre-4.9.35-gnu/arch/powerpc/kernel/eeh.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/arch/powerpc/kernel/eeh.c	2017-07-05 08:40:44.000000000 -0400
@@ -298,9 +298,17 @@ void eeh_slot_error_detail(struct eeh_pe
 	 *
 	 * For pHyp, we have to enable IO for log retrieval. Otherwise,
 	 * 0xFF's is always returned from PCI config space.
+	 *
+	 * When the @severity is EEH_LOG_PERM, the PE is going to be
+	 * removed. Prior to that, the drivers for devices included in
+	 * the PE will be closed. The drivers rely on working IO path
+	 * to bring the devices to quiet state. Otherwise, PCI traffic
+	 * from those devices after they are removed is like to cause
+	 * another unexpected EEH error.
 	 */
 	if (!(pe->type & EEH_PE_PHB)) {
-		if (eeh_has_flag(EEH_ENABLE_IO_FOR_LOG))
+		if (eeh_has_flag(EEH_ENABLE_IO_FOR_LOG) ||
+		    severity == EEH_LOG_PERM)
 			eeh_pci_enable(pe, EEH_OPT_THAW_MMIO);
 
 		/*
diff -druNp --no-dereference linux-libre-4.9.35-gnu/arch/s390/include/asm/ctl_reg.h linux-libre-4.9.36-gnu/arch/s390/include/asm/ctl_reg.h
--- linux-libre-4.9.35-gnu/arch/s390/include/asm/ctl_reg.h	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/arch/s390/include/asm/ctl_reg.h	2017-07-05 08:40:44.000000000 -0400
@@ -15,7 +15,9 @@
 	BUILD_BUG_ON(sizeof(addrtype) != (high - low + 1) * sizeof(long));\
 	asm volatile(							\
 		"	lctlg	%1,%2,%0\n"				\
-		: : "Q" (*(addrtype *)(&array)), "i" (low), "i" (high));\
+		:							\
+		: "Q" (*(addrtype *)(&array)), "i" (low), "i" (high)	\
+		: "memory");						\
 }
 
 #define __ctl_store(array, low, high) {					\
diff -druNp --no-dereference linux-libre-4.9.35-gnu/arch/sparc/kernel/irq_64.c linux-libre-4.9.36-gnu/arch/sparc/kernel/irq_64.c
--- linux-libre-4.9.35-gnu/arch/sparc/kernel/irq_64.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/arch/sparc/kernel/irq_64.c	2017-07-05 08:40:44.000000000 -0400
@@ -1021,7 +1021,7 @@ static void __init alloc_one_queue(unsig
 	unsigned long order = get_order(size);
 	unsigned long p;
 
-	p = __get_free_pages(GFP_KERNEL, order);
+	p = __get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
 	if (!p) {
 		prom_printf("SUN4V: Error, cannot allocate queue.\n");
 		prom_halt();
diff -druNp --no-dereference linux-libre-4.9.35-gnu/arch/sparc/kernel/traps_64.c linux-libre-4.9.36-gnu/arch/sparc/kernel/traps_64.c
--- linux-libre-4.9.35-gnu/arch/sparc/kernel/traps_64.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/arch/sparc/kernel/traps_64.c	2017-07-05 08:40:44.000000000 -0400
@@ -2051,6 +2051,73 @@ void sun4v_resum_overflow(struct pt_regs
 	atomic_inc(&sun4v_resum_oflow_cnt);
 }
 
+/* Given a set of registers, get the virtual addressi that was being accessed
+ * by the faulting instructions at tpc.
+ */
+static unsigned long sun4v_get_vaddr(struct pt_regs *regs)
+{
+	unsigned int insn;
+
+	if (!copy_from_user(&insn, (void __user *)regs->tpc, 4)) {
+		return compute_effective_address(regs, insn,
+						 (insn >> 25) & 0x1f);
+	}
+	return 0;
+}
+
+/* Attempt to handle non-resumable errors generated from userspace.
+ * Returns true if the signal was handled, false otherwise.
+ */
+bool sun4v_nonresum_error_user_handled(struct pt_regs *regs,
+				  struct sun4v_error_entry *ent) {
+
+	unsigned int attrs = ent->err_attrs;
+
+	if (attrs & SUN4V_ERR_ATTRS_MEMORY) {
+		unsigned long addr = ent->err_raddr;
+		siginfo_t info;
+
+		if (addr == ~(u64)0) {
+			/* This seems highly unlikely to ever occur */
+			pr_emerg("SUN4V NON-RECOVERABLE ERROR: Memory error detected in unknown location!\n");
+		} else {
+			unsigned long page_cnt = DIV_ROUND_UP(ent->err_size,
+							      PAGE_SIZE);
+
+			/* Break the unfortunate news. */
+			pr_emerg("SUN4V NON-RECOVERABLE ERROR: Memory failed at %016lX\n",
+				 addr);
+			pr_emerg("SUN4V NON-RECOVERABLE ERROR:   Claiming %lu ages.\n",
+				 page_cnt);
+
+			while (page_cnt-- > 0) {
+				if (pfn_valid(addr >> PAGE_SHIFT))
+					get_page(pfn_to_page(addr >> PAGE_SHIFT));
+				addr += PAGE_SIZE;
+			}
+		}
+		info.si_signo = SIGKILL;
+		info.si_errno = 0;
+		info.si_trapno = 0;
+		force_sig_info(info.si_signo, &info, current);
+
+		return true;
+	}
+	if (attrs & SUN4V_ERR_ATTRS_PIO) {
+		siginfo_t info;
+
+		info.si_signo = SIGBUS;
+		info.si_code = BUS_ADRERR;
+		info.si_addr = (void __user *)sun4v_get_vaddr(regs);
+		force_sig_info(info.si_signo, &info, current);
+
+		return true;
+	}
+
+	/* Default to doing nothing */
+	return false;
+}
+
 /* We run with %pil set to PIL_NORMAL_MAX and PSTATE_IE enabled in %pstate.
  * Log the event, clear the first word of the entry, and die.
  */
@@ -2075,6 +2142,12 @@ void sun4v_nonresum_error(struct pt_regs
 
 	put_cpu();
 
+	if (!(regs->tstate & TSTATE_PRIV) &&
+	    sun4v_nonresum_error_user_handled(regs, &local_copy)) {
+		/* DON'T PANIC: This userspace error was handled. */
+		return;
+	}
+
 #ifdef CONFIG_PCI
 	/* Check for the special PCI poke sequence. */
 	if (pci_poke_in_progress && pci_poke_cpu == cpu) {
diff -druNp --no-dereference linux-libre-4.9.35-gnu/arch/x86/boot/compressed/kaslr.c linux-libre-4.9.36-gnu/arch/x86/boot/compressed/kaslr.c
--- linux-libre-4.9.35-gnu/arch/x86/boot/compressed/kaslr.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/arch/x86/boot/compressed/kaslr.c	2017-07-05 08:40:44.000000000 -0400
@@ -430,9 +430,6 @@ void choose_random_location(unsigned lon
 {
 	unsigned long random_addr, min_addr;
 
-	/* By default, keep output position unchanged. */
-	*virt_addr = *output;
-
 	if (cmdline_find_option_bool("nokaslr")) {
 		warn("KASLR disabled: 'nokaslr' on cmdline.");
 		return;
diff -druNp --no-dereference linux-libre-4.9.35-gnu/arch/x86/boot/compressed/misc.c linux-libre-4.9.36-gnu/arch/x86/boot/compressed/misc.c
--- linux-libre-4.9.35-gnu/arch/x86/boot/compressed/misc.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/arch/x86/boot/compressed/misc.c	2017-07-05 08:40:44.000000000 -0400
@@ -338,7 +338,7 @@ asmlinkage __visible void *extract_kerne
 				  unsigned long output_len)
 {
 	const unsigned long kernel_total_size = VO__end - VO__text;
-	unsigned long virt_addr = (unsigned long)output;
+	unsigned long virt_addr = LOAD_PHYSICAL_ADDR;
 
 	/* Retain x86 boot parameters pointer passed from startup_32/64. */
 	boot_params = rmode;
@@ -397,7 +397,7 @@ asmlinkage __visible void *extract_kerne
 #ifndef CONFIG_RELOCATABLE
 	if ((unsigned long)output != LOAD_PHYSICAL_ADDR)
 		error("Destination address does not match LOAD_PHYSICAL_ADDR");
-	if ((unsigned long)output != virt_addr)
+	if (virt_addr != LOAD_PHYSICAL_ADDR)
 		error("Destination virtual address changed when not relocatable");
 #endif
 
diff -druNp --no-dereference linux-libre-4.9.35-gnu/arch/x86/boot/compressed/misc.h linux-libre-4.9.36-gnu/arch/x86/boot/compressed/misc.h
--- linux-libre-4.9.35-gnu/arch/x86/boot/compressed/misc.h	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/arch/x86/boot/compressed/misc.h	2017-07-05 08:40:44.000000000 -0400
@@ -81,8 +81,6 @@ static inline void choose_random_locatio
 					  unsigned long output_size,
 					  unsigned long *virt_addr)
 {
-	/* No change from existing output location. */
-	*virt_addr = *output;
 }
 #endif
 
diff -druNp --no-dereference linux-libre-4.9.35-gnu/arch/x86/events/core.c linux-libre-4.9.36-gnu/arch/x86/events/core.c
--- linux-libre-4.9.35-gnu/arch/x86/events/core.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/arch/x86/events/core.c	2017-07-05 08:40:44.000000000 -0400
@@ -505,6 +505,10 @@ int x86_pmu_hw_config(struct perf_event
 
 		if (event->attr.precise_ip > precise)
 			return -EOPNOTSUPP;
+
+		/* There's no sense in having PEBS for non sampling events: */
+		if (!is_sampling_event(event))
+			return -EINVAL;
 	}
 	/*
 	 * check that PEBS LBR correction does not conflict with
diff -druNp --no-dereference linux-libre-4.9.35-gnu/arch/x86/events/intel/core.c linux-libre-4.9.36-gnu/arch/x86/events/intel/core.c
--- linux-libre-4.9.35-gnu/arch/x86/events/intel/core.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/arch/x86/events/intel/core.c	2017-07-05 08:40:44.000000000 -0400
@@ -3164,13 +3164,16 @@ static void intel_pmu_cpu_starting(int c
 
 	if (x86_pmu.flags & PMU_FL_EXCL_CNTRS) {
 		for_each_cpu(i, topology_sibling_cpumask(cpu)) {
+			struct cpu_hw_events *sibling;
 			struct intel_excl_cntrs *c;
 
-			c = per_cpu(cpu_hw_events, i).excl_cntrs;
+			sibling = &per_cpu(cpu_hw_events, i);
+			c = sibling->excl_cntrs;
 			if (c && c->core_id == core_id) {
 				cpuc->kfree_on_online[1] = cpuc->excl_cntrs;
 				cpuc->excl_cntrs = c;
-				cpuc->excl_thread_id = 1;
+				if (!sibling->excl_thread_id)
+					cpuc->excl_thread_id = 1;
 				break;
 			}
 		}
@@ -3975,7 +3978,7 @@ __init int intel_pmu_init(void)
 		     x86_pmu.num_counters, INTEL_PMC_MAX_GENERIC);
 		x86_pmu.num_counters = INTEL_PMC_MAX_GENERIC;
 	}
-	x86_pmu.intel_ctrl = (1 << x86_pmu.num_counters) - 1;
+	x86_pmu.intel_ctrl = (1ULL << x86_pmu.num_counters) - 1;
 
 	if (x86_pmu.num_counters_fixed > INTEL_PMC_MAX_FIXED) {
 		WARN(1, KERN_ERR "hw perf events fixed %d > max(%d), clipping!",
diff -druNp --no-dereference linux-libre-4.9.35-gnu/arch/x86/events/intel/uncore_snbep.c linux-libre-4.9.36-gnu/arch/x86/events/intel/uncore_snbep.c
--- linux-libre-4.9.35-gnu/arch/x86/events/intel/uncore_snbep.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/arch/x86/events/intel/uncore_snbep.c	2017-07-05 08:40:44.000000000 -0400
@@ -2686,7 +2686,7 @@ static struct intel_uncore_type *hswep_m
 
 void hswep_uncore_cpu_init(void)
 {
-	int pkg = topology_phys_to_logical_pkg(0);
+	int pkg = boot_cpu_data.logical_proc_id;
 
 	if (hswep_uncore_cbox.num_boxes > boot_cpu_data.x86_max_cores)
 		hswep_uncore_cbox.num_boxes = boot_cpu_data.x86_max_cores;
diff -druNp --no-dereference linux-libre-4.9.35-gnu/arch/x86/include/asm/kvm_emulate.h linux-libre-4.9.36-gnu/arch/x86/include/asm/kvm_emulate.h
--- linux-libre-4.9.35-gnu/arch/x86/include/asm/kvm_emulate.h	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/arch/x86/include/asm/kvm_emulate.h	2017-07-05 08:40:44.000000000 -0400
@@ -221,6 +221,9 @@ struct x86_emulate_ops {
 	void (*get_cpuid)(struct x86_emulate_ctxt *ctxt,
 			  u32 *eax, u32 *ebx, u32 *ecx, u32 *edx);
 	void (*set_nmi_mask)(struct x86_emulate_ctxt *ctxt, bool masked);
+
+	unsigned (*get_hflags)(struct x86_emulate_ctxt *ctxt);
+	void (*set_hflags)(struct x86_emulate_ctxt *ctxt, unsigned hflags);
 };
 
 typedef u32 __attribute__((vector_size(16))) sse128_t;
@@ -290,7 +293,6 @@ struct x86_emulate_ctxt {
 
 	/* interruptibility state, as a result of execution of STI or MOV SS */
 	int interruptibility;
-	int emul_flags;
 
 	bool perm_ok; /* do not check permissions if true */
 	bool ud;	/* inject an #UD if host doesn't support insn */
diff -druNp --no-dereference linux-libre-4.9.35-gnu/arch/x86/kernel/tsc.c linux-libre-4.9.36-gnu/arch/x86/kernel/tsc.c
--- linux-libre-4.9.35-gnu/arch/x86/kernel/tsc.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/arch/x86/kernel/tsc.c	2017-07-05 08:40:44.000000000 -0400
@@ -694,6 +694,7 @@ unsigned long native_calibrate_tsc(void)
 			crystal_khz = 24000;	/* 24.0 MHz */
 			break;
 		case INTEL_FAM6_SKYLAKE_X:
+		case INTEL_FAM6_ATOM_DENVERTON:
 			crystal_khz = 25000;	/* 25.0 MHz */
 			break;
 		case INTEL_FAM6_ATOM_GOLDMONT:
diff -druNp --no-dereference linux-libre-4.9.35-gnu/arch/x86/kvm/emulate.c linux-libre-4.9.36-gnu/arch/x86/kvm/emulate.c
--- linux-libre-4.9.35-gnu/arch/x86/kvm/emulate.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/arch/x86/kvm/emulate.c	2017-07-05 08:40:44.000000000 -0400
@@ -2543,7 +2543,7 @@ static int em_rsm(struct x86_emulate_ctx
 	u64 smbase;
 	int ret;
 
-	if ((ctxt->emul_flags & X86EMUL_SMM_MASK) == 0)
+	if ((ctxt->ops->get_hflags(ctxt) & X86EMUL_SMM_MASK) == 0)
 		return emulate_ud(ctxt);
 
 	/*
@@ -2592,11 +2592,11 @@ static int em_rsm(struct x86_emulate_ctx
 		return X86EMUL_UNHANDLEABLE;
 	}
 
-	if ((ctxt->emul_flags & X86EMUL_SMM_INSIDE_NMI_MASK) == 0)
+	if ((ctxt->ops->get_hflags(ctxt) & X86EMUL_SMM_INSIDE_NMI_MASK) == 0)
 		ctxt->ops->set_nmi_mask(ctxt, false);
 
-	ctxt->emul_flags &= ~X86EMUL_SMM_INSIDE_NMI_MASK;
-	ctxt->emul_flags &= ~X86EMUL_SMM_MASK;
+	ctxt->ops->set_hflags(ctxt, ctxt->ops->get_hflags(ctxt) &
+		~(X86EMUL_SMM_INSIDE_NMI_MASK | X86EMUL_SMM_MASK));
 	return X86EMUL_CONTINUE;
 }
 
@@ -5312,6 +5312,7 @@ int x86_emulate_insn(struct x86_emulate_
 	const struct x86_emulate_ops *ops = ctxt->ops;
 	int rc = X86EMUL_CONTINUE;
 	int saved_dst_type = ctxt->dst.type;
+	unsigned emul_flags;
 
 	ctxt->mem_read.pos = 0;
 
@@ -5326,6 +5327,7 @@ int x86_emulate_insn(struct x86_emulate_
 		goto done;
 	}
 
+	emul_flags = ctxt->ops->get_hflags(ctxt);
 	if (unlikely(ctxt->d &
 		     (No64|Undefined|Sse|Mmx|Intercept|CheckPerm|Priv|Prot|String))) {
 		if ((ctxt->mode == X86EMUL_MODE_PROT64 && (ctxt->d & No64)) ||
@@ -5359,7 +5361,7 @@ int x86_emulate_insn(struct x86_emulate_
 				fetch_possible_mmx_operand(ctxt, &ctxt->dst);
 		}
 
-		if (unlikely(ctxt->emul_flags & X86EMUL_GUEST_MASK) && ctxt->intercept) {
+		if (unlikely(emul_flags & X86EMUL_GUEST_MASK) && ctxt->intercept) {
 			rc = emulator_check_intercept(ctxt, ctxt->intercept,
 						      X86_ICPT_PRE_EXCEPT);
 			if (rc != X86EMUL_CONTINUE)
@@ -5388,7 +5390,7 @@ int x86_emulate_insn(struct x86_emulate_
 				goto done;
 		}
 
-		if (unlikely(ctxt->emul_flags & X86EMUL_GUEST_MASK) && (ctxt->d & Intercept)) {
+		if (unlikely(emul_flags & X86EMUL_GUEST_MASK) && (ctxt->d & Intercept)) {
 			rc = emulator_check_intercept(ctxt, ctxt->intercept,
 						      X86_ICPT_POST_EXCEPT);
 			if (rc != X86EMUL_CONTINUE)
@@ -5442,7 +5444,7 @@ int x86_emulate_insn(struct x86_emulate_
 
 special_insn:
 
-	if (unlikely(ctxt->emul_flags & X86EMUL_GUEST_MASK) && (ctxt->d & Intercept)) {
+	if (unlikely(emul_flags & X86EMUL_GUEST_MASK) && (ctxt->d & Intercept)) {
 		rc = emulator_check_intercept(ctxt, ctxt->intercept,
 					      X86_ICPT_POST_MEMACCESS);
 		if (rc != X86EMUL_CONTINUE)
diff -druNp --no-dereference linux-libre-4.9.35-gnu/arch/x86/kvm/pmu_intel.c linux-libre-4.9.36-gnu/arch/x86/kvm/pmu_intel.c
--- linux-libre-4.9.35-gnu/arch/x86/kvm/pmu_intel.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/arch/x86/kvm/pmu_intel.c	2017-07-05 08:40:44.000000000 -0400
@@ -294,7 +294,7 @@ static void intel_pmu_refresh(struct kvm
 			((u64)1 << edx.split.bit_width_fixed) - 1;
 	}
 
-	pmu->global_ctrl = ((1 << pmu->nr_arch_gp_counters) - 1) |
+	pmu->global_ctrl = ((1ull << pmu->nr_arch_gp_counters) - 1) |
 		(((1ull << pmu->nr_arch_fixed_counters) - 1) << INTEL_PMC_IDX_FIXED);
 	pmu->global_ctrl_mask = ~pmu->global_ctrl;
 
diff -druNp --no-dereference linux-libre-4.9.35-gnu/arch/x86/kvm/vmx.c linux-libre-4.9.36-gnu/arch/x86/kvm/vmx.c
--- linux-libre-4.9.35-gnu/arch/x86/kvm/vmx.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/arch/x86/kvm/vmx.c	2017-07-05 08:40:44.000000000 -0400
@@ -2455,7 +2455,7 @@ static int nested_vmx_check_exception(st
 	if (!(vmcs12->exception_bitmap & (1u << nr)))
 		return 0;
 
-	nested_vmx_vmexit(vcpu, to_vmx(vcpu)->exit_reason,
+	nested_vmx_vmexit(vcpu, EXIT_REASON_EXCEPTION_NMI,
 			  vmcs_read32(VM_EXIT_INTR_INFO),
 			  vmcs_readl(EXIT_QUALIFICATION));
 	return 1;
diff -druNp --no-dereference linux-libre-4.9.35-gnu/arch/x86/kvm/x86.c linux-libre-4.9.36-gnu/arch/x86/kvm/x86.c
--- linux-libre-4.9.35-gnu/arch/x86/kvm/x86.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/arch/x86/kvm/x86.c	2017-07-05 08:40:44.000000000 -0400
@@ -4999,6 +4999,8 @@ static bool emulator_get_segment(struct
 
 	if (var.unusable) {
 		memset(desc, 0, sizeof(*desc));
+		if (base3)
+			*base3 = 0;
 		return false;
 	}
 
@@ -5154,6 +5156,16 @@ static void emulator_set_nmi_mask(struct
 	kvm_x86_ops->set_nmi_mask(emul_to_vcpu(ctxt), masked);
 }
 
+static unsigned emulator_get_hflags(struct x86_emulate_ctxt *ctxt)
+{
+	return emul_to_vcpu(ctxt)->arch.hflags;
+}
+
+static void emulator_set_hflags(struct x86_emulate_ctxt *ctxt, unsigned emul_flags)
+{
+	kvm_set_hflags(emul_to_vcpu(ctxt), emul_flags);
+}
+
 static const struct x86_emulate_ops emulate_ops = {
 	.read_gpr            = emulator_read_gpr,
 	.write_gpr           = emulator_write_gpr,
@@ -5193,6 +5205,8 @@ static const struct x86_emulate_ops emul
 	.intercept           = emulator_intercept,
 	.get_cpuid           = emulator_get_cpuid,
 	.set_nmi_mask        = emulator_set_nmi_mask,
+	.get_hflags          = emulator_get_hflags,
+	.set_hflags          = emulator_set_hflags,
 };
 
 static void toggle_interruptibility(struct kvm_vcpu *vcpu, u32 mask)
@@ -5245,7 +5259,6 @@ static void init_emulate_ctxt(struct kvm
 	BUILD_BUG_ON(HF_GUEST_MASK != X86EMUL_GUEST_MASK);
 	BUILD_BUG_ON(HF_SMM_MASK != X86EMUL_SMM_MASK);
 	BUILD_BUG_ON(HF_SMM_INSIDE_NMI_MASK != X86EMUL_SMM_INSIDE_NMI_MASK);
-	ctxt->emul_flags = vcpu->arch.hflags;
 
 	init_decode_cache(ctxt);
 	vcpu->arch.emulate_regs_need_sync_from_vcpu = false;
@@ -5636,8 +5649,6 @@ restart:
 		unsigned long rflags = kvm_x86_ops->get_rflags(vcpu);
 		toggle_interruptibility(vcpu, ctxt->interruptibility);
 		vcpu->arch.emulate_regs_need_sync_to_vcpu = false;
-		if (vcpu->arch.hflags != ctxt->emul_flags)
-			kvm_set_hflags(vcpu, ctxt->emul_flags);
 		kvm_rip_write(vcpu, ctxt->eip);
 		if (r == EMULATE_DONE)
 			kvm_vcpu_check_singlestep(vcpu, rflags, &r);
@@ -6111,7 +6122,8 @@ static int emulator_fix_hypercall(struct
 
 	kvm_x86_ops->patch_hypercall(vcpu, instruction);
 
-	return emulator_write_emulated(ctxt, rip, instruction, 3, NULL);
+	return emulator_write_emulated(ctxt, rip, instruction, 3,
+		&ctxt->exception);
 }
 
 static int dm_request_for_irq_injection(struct kvm_vcpu *vcpu)
diff -druNp --no-dereference linux-libre-4.9.35-gnu/arch/x86/mm/init_64.c linux-libre-4.9.36-gnu/arch/x86/mm/init_64.c
--- linux-libre-4.9.35-gnu/arch/x86/mm/init_64.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/arch/x86/mm/init_64.c	2017-07-05 08:40:44.000000000 -0400
@@ -94,10 +94,10 @@ __setup("noexec32=", nonx32_setup);
  */
 void sync_global_pgds(unsigned long start, unsigned long end, int removed)
 {
-	unsigned long address;
+	unsigned long addr;
 
-	for (address = start; address <= end; address += PGDIR_SIZE) {
-		const pgd_t *pgd_ref = pgd_offset_k(address);
+	for (addr = start; addr <= end; addr = ALIGN(addr + 1, PGDIR_SIZE)) {
+		const pgd_t *pgd_ref = pgd_offset_k(addr);
 		struct page *page;
 
 		/*
@@ -113,7 +113,7 @@ void sync_global_pgds(unsigned long star
 			pgd_t *pgd;
 			spinlock_t *pgt_lock;
 
-			pgd = (pgd_t *)page_address(page) + pgd_index(address);
+			pgd = (pgd_t *)page_address(page) + pgd_index(addr);
 			/* the pgt_lock only for Xen */
 			pgt_lock = &pgd_page_get_mm(page)->page_table_lock;
 			spin_lock(pgt_lock);
diff -druNp --no-dereference linux-libre-4.9.35-gnu/arch/x86/mm/mpx.c linux-libre-4.9.36-gnu/arch/x86/mm/mpx.c
--- linux-libre-4.9.35-gnu/arch/x86/mm/mpx.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/arch/x86/mm/mpx.c	2017-07-05 08:40:44.000000000 -0400
@@ -293,7 +293,7 @@ siginfo_t *mpx_generate_siginfo(struct p
 	 * We were not able to extract an address from the instruction,
 	 * probably because there was something invalid in it.
 	 */
-	if (info->si_addr == (void *)-1) {
+	if (info->si_addr == (void __user *)-1) {
 		err = -EINVAL;
 		goto err_out;
 	}
@@ -525,15 +525,7 @@ int mpx_handle_bd_fault(void)
 	if (!kernel_managing_mpx_tables(current->mm))
 		return -EINVAL;
 
-	if (do_mpx_bt_fault()) {
-		force_sig(SIGSEGV, current);
-		/*
-		 * The force_sig() is essentially "handling" this
-		 * exception, so we do not pass up the error
-		 * from do_mpx_bt_fault().
-		 */
-	}
-	return 0;
+	return do_mpx_bt_fault();
 }
 
 /*
diff -druNp --no-dereference linux-libre-4.9.35-gnu/arch/x86/mm/tlb.c linux-libre-4.9.36-gnu/arch/x86/mm/tlb.c
--- linux-libre-4.9.35-gnu/arch/x86/mm/tlb.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/arch/x86/mm/tlb.c	2017-07-05 08:40:44.000000000 -0400
@@ -263,8 +263,6 @@ void native_flush_tlb_others(const struc
 {
 	struct flush_tlb_info info;
 
-	if (end == 0)
-		end = start + PAGE_SIZE;
 	info.flush_mm = mm;
 	info.flush_start = start;
 	info.flush_end = end;
@@ -393,7 +391,7 @@ void flush_tlb_page(struct vm_area_struc
 	}
 
 	if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids)
-		flush_tlb_others(mm_cpumask(mm), mm, start, 0UL);
+		flush_tlb_others(mm_cpumask(mm), mm, start, start + PAGE_SIZE);
 
 	preempt_enable();
 }
diff -druNp --no-dereference linux-libre-4.9.35-gnu/Documentation/devicetree/bindings/net/mediatek-net.txt linux-libre-4.9.36-gnu/Documentation/devicetree/bindings/net/mediatek-net.txt
--- linux-libre-4.9.35-gnu/Documentation/devicetree/bindings/net/mediatek-net.txt	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/Documentation/devicetree/bindings/net/mediatek-net.txt	2017-07-05 08:40:44.000000000 -0400
@@ -7,7 +7,7 @@ have dual GMAC each represented by a chi
 * Ethernet controller node
 
 Required properties:
-- compatible: Should be "mediatek,mt7623-eth"
+- compatible: Should be "mediatek,mt2701-eth"
 - reg: Address and length of the register set for the device
 - interrupts: Should contain the three frame engines interrupts in numeric
 	order. These are fe_int0, fe_int1 and fe_int2.
diff -druNp --no-dereference linux-libre-4.9.35-gnu/Documentation/devicetree/bindings/net/phy.txt linux-libre-4.9.36-gnu/Documentation/devicetree/bindings/net/phy.txt
--- linux-libre-4.9.35-gnu/Documentation/devicetree/bindings/net/phy.txt	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/Documentation/devicetree/bindings/net/phy.txt	2017-07-05 08:40:44.000000000 -0400
@@ -35,6 +35,15 @@ Optional Properties:
 - broken-turn-around: If set, indicates the PHY device does not correctly
   release the turn around line low at the end of a MDIO transaction.
 
+- eee-broken-100tx:
+- eee-broken-1000t:
+- eee-broken-10gt:
+- eee-broken-1000kx:
+- eee-broken-10gkx4:
+- eee-broken-10gkr:
+  Mark the corresponding energy efficient ethernet mode as broken and
+  request the ethernet to stop advertising it.
+
 Example:
 
 ethernet-phy@0 {
diff -druNp --no-dereference linux-libre-4.9.35-gnu/Documentation/devicetree/bindings/net/ti,dp83867.txt linux-libre-4.9.36-gnu/Documentation/devicetree/bindings/net/ti,dp83867.txt
--- linux-libre-4.9.35-gnu/Documentation/devicetree/bindings/net/ti,dp83867.txt	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/Documentation/devicetree/bindings/net/ti,dp83867.txt	2017-07-05 08:40:44.000000000 -0400
@@ -3,9 +3,11 @@
 Required properties:
 	- reg - The ID number for the phy, usually a small integer
 	- ti,rx-internal-delay - RGMII Receive Clock Delay - see dt-bindings/net/ti-dp83867.h
-		for applicable values
+		for applicable values. Required only if interface type is
+		PHY_INTERFACE_MODE_RGMII_ID or PHY_INTERFACE_MODE_RGMII_RXID
 	- ti,tx-internal-delay - RGMII Transmit Clock Delay - see dt-bindings/net/ti-dp83867.h
-		for applicable values
+		for applicable values. Required only if interface type is
+		PHY_INTERFACE_MODE_RGMII_ID or PHY_INTERFACE_MODE_RGMII_TXID
 	- ti,fifo-depth - Transmitt FIFO depth- see dt-bindings/net/ti-dp83867.h
 		for applicable values
 
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/block/xen-blkback/blkback.c linux-libre-4.9.36-gnu/drivers/block/xen-blkback/blkback.c
--- linux-libre-4.9.35-gnu/drivers/block/xen-blkback/blkback.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/block/xen-blkback/blkback.c	2017-07-05 08:40:44.000000000 -0400
@@ -609,8 +609,6 @@ int xen_blkif_schedule(void *arg)
 	unsigned long timeout;
 	int ret;
 
-	xen_blkif_get(blkif);
-
 	set_freezable();
 	while (!kthread_should_stop()) {
 		if (try_to_freeze())
@@ -665,7 +663,6 @@ purge_gnt_list:
 		print_stats(ring);
 
 	ring->xenblkd = NULL;
-	xen_blkif_put(blkif);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/block/xen-blkback/xenbus.c linux-libre-4.9.36-gnu/drivers/block/xen-blkback/xenbus.c
--- linux-libre-4.9.35-gnu/drivers/block/xen-blkback/xenbus.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/block/xen-blkback/xenbus.c	2017-07-05 08:40:44.000000000 -0400
@@ -255,7 +255,6 @@ static int xen_blkif_disconnect(struct x
 		if (ring->xenblkd) {
 			kthread_stop(ring->xenblkd);
 			wake_up(&ring->shutdown_wq);
-			ring->xenblkd = NULL;
 		}
 
 		/* The above kthread_stop() guarantees that at this point we
@@ -316,8 +315,10 @@ static int xen_blkif_disconnect(struct x
 static void xen_blkif_free(struct xen_blkif *blkif)
 {
 
-	xen_blkif_disconnect(blkif);
+	WARN_ON(xen_blkif_disconnect(blkif));
 	xen_vbd_free(&blkif->vbd);
+	kfree(blkif->be->mode);
+	kfree(blkif->be);
 
 	/* Make sure everything is drained before shutting down */
 	kmem_cache_free(xen_blkif_cachep, blkif);
@@ -512,8 +513,6 @@ static int xen_blkbk_remove(struct xenbu
 
 	/* Put the reference we set in xen_blkif_alloc(). */
 	xen_blkif_put(be->blkif);
-	kfree(be->mode);
-	kfree(be);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/char/virtio_console.c linux-libre-4.9.36-gnu/drivers/char/virtio_console.c
--- linux-libre-4.9.35-gnu/drivers/char/virtio_console.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/char/virtio_console.c	2017-07-05 08:40:44.000000000 -0400
@@ -1870,7 +1870,7 @@ static void config_work_handler(struct w
 {
 	struct ports_device *portdev;
 
-	portdev = container_of(work, struct ports_device, control_work);
+	portdev = container_of(work, struct ports_device, config_work);
 	if (!use_multiport(portdev)) {
 		struct virtio_device *vdev;
 		struct port *port;
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/clk/clk-scpi.c linux-libre-4.9.36-gnu/drivers/clk/clk-scpi.c
--- linux-libre-4.9.35-gnu/drivers/clk/clk-scpi.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/clk/clk-scpi.c	2017-07-05 08:40:44.000000000 -0400
@@ -290,13 +290,15 @@ static int scpi_clocks_probe(struct plat
 			of_node_put(child);
 			return ret;
 		}
-	}
-	/* Add the virtual cpufreq device */
-	cpufreq_dev = platform_device_register_simple("scpi-cpufreq",
-						      -1, NULL, 0);
-	if (IS_ERR(cpufreq_dev))
-		pr_warn("unable to register cpufreq device");
 
+		if (match->data != &scpi_dvfs_ops)
+			continue;
+		/* Add the virtual cpufreq device if it's DVFS clock provider */
+		cpufreq_dev = platform_device_register_simple("scpi-cpufreq",
+							      -1, NULL, 0);
+		if (IS_ERR(cpufreq_dev))
+			pr_warn("unable to register cpufreq device");
+	}
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/cpufreq/s3c2416-cpufreq.c linux-libre-4.9.36-gnu/drivers/cpufreq/s3c2416-cpufreq.c
--- linux-libre-4.9.35-gnu/drivers/cpufreq/s3c2416-cpufreq.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/cpufreq/s3c2416-cpufreq.c	2017-07-05 08:40:44.000000000 -0400
@@ -400,7 +400,6 @@ static int s3c2416_cpufreq_driver_init(s
 	rate = clk_get_rate(s3c_freq->hclk);
 	if (rate < 133 * 1000 * 1000) {
 		pr_err("cpufreq: HCLK not at 133MHz\n");
-		clk_put(s3c_freq->hclk);
 		ret = -EINVAL;
 		goto err_armclk;
 	}
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/gpio/gpiolib.c linux-libre-4.9.36-gnu/drivers/gpio/gpiolib.c
--- linux-libre-4.9.35-gnu/drivers/gpio/gpiolib.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/gpio/gpiolib.c	2017-07-05 08:40:44.000000000 -0400
@@ -707,7 +707,8 @@ static irqreturn_t lineevent_irq_thread(
 
 	ge.timestamp = ktime_get_real_ns();
 
-	if (le->eflags & GPIOEVENT_REQUEST_BOTH_EDGES) {
+	if (le->eflags & GPIOEVENT_REQUEST_RISING_EDGE
+	    && le->eflags & GPIOEVENT_REQUEST_FALLING_EDGE) {
 		int level = gpiod_get_value_cansleep(le->desc);
 
 		if (level)
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c linux-libre-4.9.36-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
--- linux-libre-4.9.35-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c	2017-07-05 08:40:44.000000000 -0400
@@ -83,6 +83,13 @@ int amdgpu_cs_get_ring(struct amdgpu_dev
 		}
 		break;
 	}
+
+	if (!(*out_ring && (*out_ring)->adev)) {
+		DRM_ERROR("Ring %d is not initialized on IP %d\n",
+			  ring, ip_type);
+		return -EINVAL;
+	}
+
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/gpu/drm/amd/amdgpu/si_dpm.c linux-libre-4.9.36-gnu/drivers/gpu/drm/amd/amdgpu/si_dpm.c
--- linux-libre-4.9.35-gnu/drivers/gpu/drm/amd/amdgpu/si_dpm.c	2017-06-29 09:39:50.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/gpu/drm/amd/amdgpu/si_dpm.c	2017-07-05 14:59:42.000000000 -0400
@@ -7713,10 +7713,11 @@ static int si_dpm_init_microcode(struct
 			((adev->pdev->device == 0x6660) ||
 			(adev->pdev->device == 0x6663) ||
 			(adev->pdev->device == 0x6665) ||
-			(adev->pdev->device == 0x6667))) ||
-		    ((adev->pdev->revision == 0xc3) &&
-			(adev->pdev->device == 0x6665)))
+			 (adev->pdev->device == 0x6667))))
 			chip_name = "hainan_k";
+		else if ((adev->pdev->revision == 0xc3) &&
+			 (adev->pdev->device == 0x6665))
+			chip_name = "banks_k_2";
 		else
 			chip_name = "hainan";
 		break;
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c linux-libre-4.9.36-gnu/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
--- linux-libre-4.9.35-gnu/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c	2017-07-05 08:40:44.000000000 -0400
@@ -43,9 +43,13 @@
 
 #define GRBM_GFX_INDEX__VCE_INSTANCE__SHIFT	0x04
 #define GRBM_GFX_INDEX__VCE_INSTANCE_MASK	0x10
+#define GRBM_GFX_INDEX__VCE_ALL_PIPE		0x07
+
 #define mmVCE_LMI_VCPU_CACHE_40BIT_BAR0	0x8616
 #define mmVCE_LMI_VCPU_CACHE_40BIT_BAR1	0x8617
 #define mmVCE_LMI_VCPU_CACHE_40BIT_BAR2	0x8618
+#define mmGRBM_GFX_INDEX_DEFAULT 0xE0000000
+
 #define VCE_STATUS_VCPU_REPORT_FW_LOADED_MASK	0x02
 
 #define VCE_V3_0_FW_SIZE	(384 * 1024)
@@ -54,6 +58,9 @@
 
 #define FW_52_8_3	((52 << 24) | (8 << 16) | (3 << 8))
 
+#define GET_VCE_INSTANCE(i)  ((i) << GRBM_GFX_INDEX__VCE_INSTANCE__SHIFT \
+					| GRBM_GFX_INDEX__VCE_ALL_PIPE)
+
 static void vce_v3_0_mc_resume(struct amdgpu_device *adev, int idx);
 static void vce_v3_0_set_ring_funcs(struct amdgpu_device *adev);
 static void vce_v3_0_set_irq_funcs(struct amdgpu_device *adev);
@@ -249,7 +256,7 @@ static int vce_v3_0_start(struct amdgpu_
 		if (adev->vce.harvest_config & (1 << idx))
 			continue;
 
-		WREG32_FIELD(GRBM_GFX_INDEX, VCE_INSTANCE, idx);
+		WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(idx));
 		vce_v3_0_mc_resume(adev, idx);
 		WREG32_FIELD(VCE_STATUS, JOB_BUSY, 1);
 
@@ -273,7 +280,7 @@ static int vce_v3_0_start(struct amdgpu_
 		}
 	}
 
-	WREG32_FIELD(GRBM_GFX_INDEX, VCE_INSTANCE, 0);
+	WREG32(mmGRBM_GFX_INDEX, mmGRBM_GFX_INDEX_DEFAULT);
 	mutex_unlock(&adev->grbm_idx_mutex);
 
 	return 0;
@@ -288,7 +295,7 @@ static int vce_v3_0_stop(struct amdgpu_d
 		if (adev->vce.harvest_config & (1 << idx))
 			continue;
 
-		WREG32_FIELD(GRBM_GFX_INDEX, VCE_INSTANCE, idx);
+		WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(idx));
 
 		if (adev->asic_type >= CHIP_STONEY)
 			WREG32_P(mmVCE_VCPU_CNTL, 0, ~0x200001);
@@ -306,7 +313,7 @@ static int vce_v3_0_stop(struct amdgpu_d
 			vce_v3_0_set_vce_sw_clock_gating(adev, false);
 	}
 
-	WREG32_FIELD(GRBM_GFX_INDEX, VCE_INSTANCE, 0);
+	WREG32(mmGRBM_GFX_INDEX, mmGRBM_GFX_INDEX_DEFAULT);
 	mutex_unlock(&adev->grbm_idx_mutex);
 
 	return 0;
@@ -586,17 +593,17 @@ static bool vce_v3_0_check_soft_reset(vo
 	 * VCE team suggest use bit 3--bit 6 for busy status check
 	 */
 	mutex_lock(&adev->grbm_idx_mutex);
-	WREG32_FIELD(GRBM_GFX_INDEX, INSTANCE_INDEX, 0);
+	WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(0));
 	if (RREG32(mmVCE_STATUS) & AMDGPU_VCE_STATUS_BUSY_MASK) {
 		srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset, SRBM_SOFT_RESET, SOFT_RESET_VCE0, 1);
 		srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset, SRBM_SOFT_RESET, SOFT_RESET_VCE1, 1);
 	}
-	WREG32_FIELD(GRBM_GFX_INDEX, INSTANCE_INDEX, 0x10);
+	WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(1));
 	if (RREG32(mmVCE_STATUS) & AMDGPU_VCE_STATUS_BUSY_MASK) {
 		srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset, SRBM_SOFT_RESET, SOFT_RESET_VCE0, 1);
 		srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset, SRBM_SOFT_RESET, SOFT_RESET_VCE1, 1);
 	}
-	WREG32_FIELD(GRBM_GFX_INDEX, INSTANCE_INDEX, 0);
+	WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(0));
 	mutex_unlock(&adev->grbm_idx_mutex);
 
 	if (srbm_soft_reset) {
@@ -734,7 +741,7 @@ static int vce_v3_0_set_clockgating_stat
 		if (adev->vce.harvest_config & (1 << i))
 			continue;
 
-		WREG32_FIELD(GRBM_GFX_INDEX, VCE_INSTANCE, i);
+		WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(i));
 
 		if (enable) {
 			/* initialize VCE_CLOCK_GATING_A: Clock ON/OFF delay */
@@ -753,7 +760,7 @@ static int vce_v3_0_set_clockgating_stat
 		vce_v3_0_set_vce_sw_clock_gating(adev, enable);
 	}
 
-	WREG32_FIELD(GRBM_GFX_INDEX, VCE_INSTANCE, 0);
+	WREG32(mmGRBM_GFX_INDEX, mmGRBM_GFX_INDEX_DEFAULT);
 	mutex_unlock(&adev->grbm_idx_mutex);
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c linux-libre-4.9.36-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c
--- linux-libre-4.9.35-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c	2017-07-05 08:40:44.000000000 -0400
@@ -200,7 +200,7 @@ int cz_dpm_powergate_vce(struct pp_hwmgr
 				cgs_set_clockgating_state(
 							hwmgr->device,
 							AMD_IP_BLOCK_TYPE_VCE,
-							AMD_CG_STATE_UNGATE);
+							AMD_CG_STATE_GATE);
 				cgs_set_powergating_state(
 							hwmgr->device,
 							AMD_IP_BLOCK_TYPE_VCE,
@@ -218,7 +218,7 @@ int cz_dpm_powergate_vce(struct pp_hwmgr
 				cgs_set_clockgating_state(
 							hwmgr->device,
 							AMD_IP_BLOCK_TYPE_VCE,
-							AMD_PG_STATE_GATE);
+							AMD_PG_STATE_UNGATE);
 				cz_dpm_update_vce_dpm(hwmgr);
 				cz_enable_disable_vce_dpm(hwmgr, true);
 				return 0;
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c linux-libre-4.9.36-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c
--- linux-libre-4.9.35-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c	2017-07-05 08:40:44.000000000 -0400
@@ -1402,14 +1402,22 @@ int  cz_dpm_update_vce_dpm(struct pp_hwm
 					     cz_hwmgr->vce_dpm.hard_min_clk,
 						PPSMC_MSG_SetEclkHardMin));
 	} else {
-		/*EPR# 419220 -HW limitation to to */
-		cz_hwmgr->vce_dpm.hard_min_clk = hwmgr->vce_arbiter.ecclk;
-		smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
-					    PPSMC_MSG_SetEclkHardMin,
-					    cz_get_eclk_level(hwmgr,
-				     cz_hwmgr->vce_dpm.hard_min_clk,
-					  PPSMC_MSG_SetEclkHardMin));
-
+		/*Program HardMin based on the vce_arbiter.ecclk */
+		if (hwmgr->vce_arbiter.ecclk == 0) {
+			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+					    PPSMC_MSG_SetEclkHardMin, 0);
+		/* disable ECLK DPM 0. Otherwise VCE could hang if
+		 * switching SCLK from DPM 0 to 6/7 */
+			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+					PPSMC_MSG_SetEclkSoftMin, 1);
+		} else {
+			cz_hwmgr->vce_dpm.hard_min_clk = hwmgr->vce_arbiter.ecclk;
+			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+						PPSMC_MSG_SetEclkHardMin,
+						cz_get_eclk_level(hwmgr,
+						cz_hwmgr->vce_dpm.hard_min_clk,
+						PPSMC_MSG_SetEclkHardMin));
+		}
 	}
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/gpu/drm/ast/ast_drv.h linux-libre-4.9.36-gnu/drivers/gpu/drm/ast/ast_drv.h
--- linux-libre-4.9.35-gnu/drivers/gpu/drm/ast/ast_drv.h	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/gpu/drm/ast/ast_drv.h	2017-07-05 08:40:44.000000000 -0400
@@ -113,7 +113,11 @@ struct ast_private {
 	struct ttm_bo_kmap_obj cache_kmap;
 	int next_cursor;
 	bool support_wide_screen;
-	bool DisableP2A;
+	enum {
+		ast_use_p2a,
+		ast_use_dt,
+		ast_use_defaults
+	} config_mode;
 
 	enum ast_tx_chip tx_chip_type;
 	u8 dp501_maxclk;
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/gpu/drm/ast/ast_main.c linux-libre-4.9.36-gnu/drivers/gpu/drm/ast/ast_main.c
--- linux-libre-4.9.35-gnu/drivers/gpu/drm/ast/ast_main.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/gpu/drm/ast/ast_main.c	2017-07-05 08:40:44.000000000 -0400
@@ -62,13 +62,84 @@ uint8_t ast_get_index_reg_mask(struct as
 	return ret;
 }
 
+static void ast_detect_config_mode(struct drm_device *dev, u32 *scu_rev)
+{
+	struct device_node *np = dev->pdev->dev.of_node;
+	struct ast_private *ast = dev->dev_private;
+	uint32_t data, jregd0, jregd1;
+
+	/* Defaults */
+	ast->config_mode = ast_use_defaults;
+	*scu_rev = 0xffffffff;
+
+	/* Check if we have device-tree properties */
+	if (np && !of_property_read_u32(np, "aspeed,scu-revision-id",
+					scu_rev)) {
+		/* We do, disable P2A access */
+		ast->config_mode = ast_use_dt;
+		DRM_INFO("Using device-tree for configuration\n");
+		return;
+	}
+
+	/* Not all families have a P2A bridge */
+	if (dev->pdev->device != PCI_CHIP_AST2000)
+		return;
+
+	/*
+	 * The BMC will set SCU 0x40 D[12] to 1 if the P2 bridge
+	 * is disabled. We force using P2A if VGA only mode bit
+	 * is set D[7]
+	 */
+	jregd0 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
+	jregd1 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1, 0xff);
+	if (!(jregd0 & 0x80) || !(jregd1 & 0x10)) {
+		/* Double check it's actually working */
+		data = ast_read32(ast, 0xf004);
+		if (data != 0xFFFFFFFF) {
+			/* P2A works, grab silicon revision */
+			ast->config_mode = ast_use_p2a;
+
+			DRM_INFO("Using P2A bridge for configuration\n");
+
+			/* Read SCU7c (silicon revision register) */
+			ast_write32(ast, 0xf004, 0x1e6e0000);
+			ast_write32(ast, 0xf000, 0x1);
+			*scu_rev = ast_read32(ast, 0x1207c);
+			return;
+		}
+	}
+
+	/* We have a P2A bridge but it's disabled */
+	DRM_INFO("P2A bridge disabled, using default configuration\n");
+}
 
 static int ast_detect_chip(struct drm_device *dev, bool *need_post)
 {
 	struct ast_private *ast = dev->dev_private;
-	uint32_t data, jreg;
+	uint32_t jreg, scu_rev;
+
+	/*
+	 * If VGA isn't enabled, we need to enable now or subsequent
+	 * access to the scratch registers will fail. We also inform
+	 * our caller that it needs to POST the chip
+	 * (Assumption: VGA not enabled -> need to POST)
+	 */
+	if (!ast_is_vga_enabled(dev)) {
+		ast_enable_vga(dev);
+		DRM_INFO("VGA not enabled on entry, requesting chip POST\n");
+		*need_post = true;
+	} else
+		*need_post = false;
+
+
+	/* Enable extended register access */
+	ast_enable_mmio(dev);
 	ast_open_key(ast);
 
+	/* Find out whether P2A works or whether to use device-tree */
+	ast_detect_config_mode(dev, &scu_rev);
+
+	/* Identify chipset */
 	if (dev->pdev->device == PCI_CHIP_AST1180) {
 		ast->chip = AST1100;
 		DRM_INFO("AST 1180 detected\n");
@@ -80,12 +151,7 @@ static int ast_detect_chip(struct drm_de
 			ast->chip = AST2300;
 			DRM_INFO("AST 2300 detected\n");
 		} else if (dev->pdev->revision >= 0x10) {
-			uint32_t data;
-			ast_write32(ast, 0xf004, 0x1e6e0000);
-			ast_write32(ast, 0xf000, 0x1);
-
-			data = ast_read32(ast, 0x1207c);
-			switch (data & 0x0300) {
+			switch (scu_rev & 0x0300) {
 			case 0x0200:
 				ast->chip = AST1100;
 				DRM_INFO("AST 1100 detected\n");
@@ -110,26 +176,6 @@ static int ast_detect_chip(struct drm_de
 		}
 	}
 
-	/*
-	 * If VGA isn't enabled, we need to enable now or subsequent
-	 * access to the scratch registers will fail. We also inform
-	 * our caller that it needs to POST the chip
-	 * (Assumption: VGA not enabled -> need to POST)
-	 */
-	if (!ast_is_vga_enabled(dev)) {
-		ast_enable_vga(dev);
-		ast_enable_mmio(dev);
-		DRM_INFO("VGA not enabled on entry, requesting chip POST\n");
-		*need_post = true;
-	} else
-		*need_post = false;
-
-	/* Check P2A Access */
-	ast->DisableP2A = true;
-	data = ast_read32(ast, 0xf004);
-	if (data != 0xFFFFFFFF)
-		ast->DisableP2A = false;
-
 	/* Check if we support wide screen */
 	switch (ast->chip) {
 	case AST1180:
@@ -146,17 +192,12 @@ static int ast_detect_chip(struct drm_de
 			ast->support_wide_screen = true;
 		else {
 			ast->support_wide_screen = false;
-			if (ast->DisableP2A == false) {
-				/* Read SCU7c (silicon revision register) */
-				ast_write32(ast, 0xf004, 0x1e6e0000);
-				ast_write32(ast, 0xf000, 0x1);
-				data = ast_read32(ast, 0x1207c);
-				data &= 0x300;
-				if (ast->chip == AST2300 && data == 0x0) /* ast1300 */
-					ast->support_wide_screen = true;
-				if (ast->chip == AST2400 && data == 0x100) /* ast1400 */
-					ast->support_wide_screen = true;
-			}
+			if (ast->chip == AST2300 &&
+			    (scu_rev & 0x300) == 0x0) /* ast1300 */
+				ast->support_wide_screen = true;
+			if (ast->chip == AST2400 &&
+			    (scu_rev & 0x300) == 0x100) /* ast1400 */
+				ast->support_wide_screen = true;
 		}
 		break;
 	}
@@ -220,85 +261,102 @@ static int ast_detect_chip(struct drm_de
 
 static int ast_get_dram_info(struct drm_device *dev)
 {
+	struct device_node *np = dev->pdev->dev.of_node;
 	struct ast_private *ast = dev->dev_private;
-	uint32_t data, data2;
-	uint32_t denum, num, div, ref_pll;
+	uint32_t mcr_cfg, mcr_scu_mpll, mcr_scu_strap;
+	uint32_t denum, num, div, ref_pll, dsel;
 
-	if (ast->DisableP2A)
-	{
+	switch (ast->config_mode) {
+	case ast_use_dt:
+		/*
+		 * If some properties are missing, use reasonable
+		 * defaults for AST2400
+		 */
+		if (of_property_read_u32(np, "aspeed,mcr-configuration",
+					 &mcr_cfg))
+			mcr_cfg = 0x00000577;
+		if (of_property_read_u32(np, "aspeed,mcr-scu-mpll",
+					 &mcr_scu_mpll))
+			mcr_scu_mpll = 0x000050C0;
+		if (of_property_read_u32(np, "aspeed,mcr-scu-strap",
+					 &mcr_scu_strap))
+			mcr_scu_strap = 0;
+		break;
+	case ast_use_p2a:
+		ast_write32(ast, 0xf004, 0x1e6e0000);
+		ast_write32(ast, 0xf000, 0x1);
+		mcr_cfg = ast_read32(ast, 0x10004);
+		mcr_scu_mpll = ast_read32(ast, 0x10120);
+		mcr_scu_strap = ast_read32(ast, 0x10170);
+		break;
+	case ast_use_defaults:
+	default:
 		ast->dram_bus_width = 16;
 		ast->dram_type = AST_DRAM_1Gx16;
 		ast->mclk = 396;
+		return 0;
 	}
-	else
-	{
-		ast_write32(ast, 0xf004, 0x1e6e0000);
-		ast_write32(ast, 0xf000, 0x1);
-		data = ast_read32(ast, 0x10004);
-
-		if (data & 0x40)
-			ast->dram_bus_width = 16;
-		else
-			ast->dram_bus_width = 32;
-
-		if (ast->chip == AST2300 || ast->chip == AST2400) {
-			switch (data & 0x03) {
-			case 0:
-				ast->dram_type = AST_DRAM_512Mx16;
-				break;
-			default:
-			case 1:
-				ast->dram_type = AST_DRAM_1Gx16;
-				break;
-			case 2:
-				ast->dram_type = AST_DRAM_2Gx16;
-				break;
-			case 3:
-				ast->dram_type = AST_DRAM_4Gx16;
-				break;
-			}
-		} else {
-			switch (data & 0x0c) {
-			case 0:
-			case 4:
-				ast->dram_type = AST_DRAM_512Mx16;
-				break;
-			case 8:
-				if (data & 0x40)
-					ast->dram_type = AST_DRAM_1Gx16;
-				else
-					ast->dram_type = AST_DRAM_512Mx32;
-				break;
-			case 0xc:
-				ast->dram_type = AST_DRAM_1Gx32;
-				break;
-			}
-		}
 
-		data = ast_read32(ast, 0x10120);
-		data2 = ast_read32(ast, 0x10170);
-		if (data2 & 0x2000)
-			ref_pll = 14318;
-		else
-			ref_pll = 12000;
+	if (mcr_cfg & 0x40)
+		ast->dram_bus_width = 16;
+	else
+		ast->dram_bus_width = 32;
 
-		denum = data & 0x1f;
-		num = (data & 0x3fe0) >> 5;
-		data = (data & 0xc000) >> 14;
-		switch (data) {
-		case 3:
-			div = 0x4;
+	if (ast->chip == AST2300 || ast->chip == AST2400) {
+		switch (mcr_cfg & 0x03) {
+		case 0:
+			ast->dram_type = AST_DRAM_512Mx16;
 			break;
-		case 2:
+		default:
 		case 1:
-			div = 0x2;
+			ast->dram_type = AST_DRAM_1Gx16;
 			break;
-		default:
-			div = 0x1;
+		case 2:
+			ast->dram_type = AST_DRAM_2Gx16;
+			break;
+		case 3:
+			ast->dram_type = AST_DRAM_4Gx16;
+			break;
+		}
+	} else {
+		switch (mcr_cfg & 0x0c) {
+		case 0:
+		case 4:
+			ast->dram_type = AST_DRAM_512Mx16;
+			break;
+		case 8:
+			if (mcr_cfg & 0x40)
+				ast->dram_type = AST_DRAM_1Gx16;
+			else
+				ast->dram_type = AST_DRAM_512Mx32;
+			break;
+		case 0xc:
+			ast->dram_type = AST_DRAM_1Gx32;
 			break;
 		}
-		ast->mclk = ref_pll * (num + 2) / (denum + 2) * (div * 1000);
 	}
+
+	if (mcr_scu_strap & 0x2000)
+		ref_pll = 14318;
+	else
+		ref_pll = 12000;
+
+	denum = mcr_scu_mpll & 0x1f;
+	num = (mcr_scu_mpll & 0x3fe0) >> 5;
+	dsel = (mcr_scu_mpll & 0xc000) >> 14;
+	switch (dsel) {
+	case 3:
+		div = 0x4;
+		break;
+	case 2:
+	case 1:
+		div = 0x2;
+		break;
+	default:
+		div = 0x1;
+		break;
+	}
+	ast->mclk = ref_pll * (num + 2) / (denum + 2) * (div * 1000);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/gpu/drm/ast/ast_post.c linux-libre-4.9.36-gnu/drivers/gpu/drm/ast/ast_post.c
--- linux-libre-4.9.35-gnu/drivers/gpu/drm/ast/ast_post.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/gpu/drm/ast/ast_post.c	2017-07-05 08:40:44.000000000 -0400
@@ -375,17 +375,14 @@ void ast_post_gpu(struct drm_device *dev
 	ast_enable_mmio(dev);
 	ast_set_def_ext_reg(dev);
 
-	if (ast->DisableP2A == false)
-	{
+	if (ast->config_mode == ast_use_p2a) {
 		if (ast->chip == AST2300 || ast->chip == AST2400)
 			ast_init_dram_2300(dev);
 		else
 			ast_init_dram_reg(dev);
 
 		ast_init_3rdtx(dev);
-	}
-	else
-	{
+	} else {
 		if (ast->tx_chip_type != AST_TX_NONE)
 			ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xcf, 0x80);	/* Enable DVO */
 	}
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/gpu/drm/etnaviv/etnaviv_mmu.c linux-libre-4.9.36-gnu/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
--- linux-libre-4.9.35-gnu/drivers/gpu/drm/etnaviv/etnaviv_mmu.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/gpu/drm/etnaviv/etnaviv_mmu.c	2017-07-05 08:40:44.000000000 -0400
@@ -116,9 +116,14 @@ static int etnaviv_iommu_find_iova(struc
 		struct list_head list;
 		bool found;
 
+		/*
+		 * XXX: The DRM_MM_SEARCH_BELOW is really a hack to trick
+		 * drm_mm into giving out a low IOVA after address space
+		 * rollover. This needs a proper fix.
+		 */
 		ret = drm_mm_insert_node_in_range(&mmu->mm, node,
 			size, 0, mmu->last_iova, ~0UL,
-			DRM_MM_SEARCH_DEFAULT);
+			mmu->last_iova ? DRM_MM_SEARCH_DEFAULT : DRM_MM_SEARCH_BELOW);
 
 		if (ret != -ENOSPC)
 			break;
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/gpu/drm/radeon/si.c linux-libre-4.9.36-gnu/drivers/gpu/drm/radeon/si.c
--- linux-libre-4.9.35-gnu/drivers/gpu/drm/radeon/si.c	2017-06-29 09:42:29.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/gpu/drm/radeon/si.c	2017-07-05 15:01:13.000000000 -0400
@@ -1573,6 +1573,7 @@ static int si_init_microcode(struct rade
 	int err;
 	int new_fw = 0;
 	bool new_smc = false;
+	bool si58_fw = false;
 
 	DRM_DEBUG("\n");
 
@@ -1665,6 +1666,10 @@ static int si_init_microcode(struct rade
 	default: BUG();
 	}
 
+	/* this memory configuration requires special firmware */
+	if (((RREG32(MC_SEQ_MISC0) & 0xff000000) >> 24) == 0x58)
+		si58_fw = true;
+
 	DRM_INFO("Loading %s Microcode\n", new_chip_name);
 
 	snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", new_chip_name);
@@ -1768,7 +1773,10 @@ static int si_init_microcode(struct rade
 		}
 	}
 
-	snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", new_chip_name);
+	if (si58_fw)
+		snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/");
+	else
+		snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", new_chip_name);
 	err = reject_firmware(&rdev->mc_fw, fw_name, rdev->dev);
 	if (err) {
 		snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c linux-libre-4.9.36-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c
--- linux-libre-4.9.35-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c	2017-07-05 08:40:44.000000000 -0400
@@ -321,6 +321,7 @@ void vmw_cmdbuf_res_man_destroy(struct v
 	list_for_each_entry_safe(entry, next, &man->list, head)
 		vmw_cmdbuf_res_free(man, entry);
 
+	drm_ht_remove(&man->resources);
 	kfree(man);
 }
 
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/hid/i2c-hid/i2c-hid.c linux-libre-4.9.36-gnu/drivers/hid/i2c-hid/i2c-hid.c
--- linux-libre-4.9.35-gnu/drivers/hid/i2c-hid/i2c-hid.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/hid/i2c-hid/i2c-hid.c	2017-07-05 08:40:44.000000000 -0400
@@ -427,6 +427,15 @@ static int i2c_hid_hwreset(struct i2c_cl
 	if (ret)
 		goto out_unlock;
 
+	/*
+	 * The HID over I2C specification states that if a DEVICE needs time
+	 * after the PWR_ON request, it should utilise CLOCK stretching.
+	 * However, it has been observered that the Windows driver provides a
+	 * 1ms sleep between the PWR_ON and RESET requests and that some devices
+	 * rely on this.
+	 */
+	usleep_range(1000, 5000);
+
 	i2c_hid_dbg(ihid, "resetting...\n");
 
 	ret = i2c_hid_command(client, &hid_reset_cmd, NULL, 0);
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/i2c/busses/i2c-brcmstb.c linux-libre-4.9.36-gnu/drivers/i2c/busses/i2c-brcmstb.c
--- linux-libre-4.9.35-gnu/drivers/i2c/busses/i2c-brcmstb.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/i2c/busses/i2c-brcmstb.c	2017-07-05 08:40:44.000000000 -0400
@@ -465,6 +465,7 @@ static int brcmstb_i2c_xfer(struct i2c_a
 	u8 *tmp_buf;
 	int len = 0;
 	int xfersz = brcmstb_i2c_get_xfersz(dev);
+	u32 cond, cond_per_msg;
 
 	if (dev->is_suspended)
 		return -EBUSY;
@@ -481,10 +482,11 @@ static int brcmstb_i2c_xfer(struct i2c_a
 			pmsg->buf ? pmsg->buf[0] : '0', pmsg->len);
 
 		if (i < (num - 1) && (msgs[i + 1].flags & I2C_M_NOSTART))
-			brcmstb_set_i2c_start_stop(dev, ~(COND_START_STOP));
+			cond = ~COND_START_STOP;
 		else
-			brcmstb_set_i2c_start_stop(dev,
-						   COND_RESTART | COND_NOSTOP);
+			cond = COND_RESTART | COND_NOSTOP;
+
+		brcmstb_set_i2c_start_stop(dev, cond);
 
 		/* Send slave address */
 		if (!(pmsg->flags & I2C_M_NOSTART)) {
@@ -497,13 +499,24 @@ static int brcmstb_i2c_xfer(struct i2c_a
 			}
 		}
 
+		cond_per_msg = cond;
+
 		/* Perform data transfer */
 		while (len) {
 			bytes_to_xfer = min(len, xfersz);
 
-			if (len <= xfersz && i == (num - 1))
-				brcmstb_set_i2c_start_stop(dev,
-							   ~(COND_START_STOP));
+			if (len <= xfersz) {
+				if (i == (num - 1))
+					cond_per_msg = cond_per_msg &
+						~(COND_RESTART | COND_NOSTOP);
+				else
+					cond_per_msg = cond;
+			} else {
+				cond_per_msg = (cond_per_msg & ~COND_RESTART) |
+					COND_NOSTOP;
+			}
+
+			brcmstb_set_i2c_start_stop(dev, cond_per_msg);
 
 			rc = brcmstb_i2c_xfer_bsc_data(dev, tmp_buf,
 						       bytes_to_xfer, pmsg);
@@ -512,6 +525,8 @@ static int brcmstb_i2c_xfer(struct i2c_a
 
 			len -=  bytes_to_xfer;
 			tmp_buf += bytes_to_xfer;
+
+			cond_per_msg = COND_NOSTART | COND_NOSTOP;
 		}
 	}
 
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/infiniband/hw/hns/hns_roce_hw_v1.c linux-libre-4.9.36-gnu/drivers/infiniband/hw/hns/hns_roce_hw_v1.c
--- linux-libre-4.9.35-gnu/drivers/infiniband/hw/hns/hns_roce_hw_v1.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/infiniband/hw/hns/hns_roce_hw_v1.c	2017-07-05 08:40:44.000000000 -0400
@@ -1267,6 +1267,7 @@ void hns_roce_v1_cq_set_ci(struct hns_ro
 	u32 doorbell[2];
 
 	doorbell[0] = cons_index & ((hr_cq->cq_depth << 1) - 1);
+	doorbell[1] = 0;
 	roce_set_bit(doorbell[1], ROCEE_DB_OTHERS_H_ROCEE_DB_OTH_HW_SYNS_S, 1);
 	roce_set_field(doorbell[1], ROCEE_DB_OTHERS_H_ROCEE_DB_OTH_CMD_M,
 		       ROCEE_DB_OTHERS_H_ROCEE_DB_OTH_CMD_S, 3);
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/iommu/amd_iommu.c linux-libre-4.9.36-gnu/drivers/iommu/amd_iommu.c
--- linux-libre-4.9.35-gnu/drivers/iommu/amd_iommu.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/iommu/amd_iommu.c	2017-07-05 08:40:44.000000000 -0400
@@ -3857,11 +3857,9 @@ static void irte_ga_prepare(void *entry,
 			    u8 vector, u32 dest_apicid, int devid)
 {
 	struct irte_ga *irte = (struct irte_ga *) entry;
-	struct iommu_dev_data *dev_data = search_dev_data(devid);
 
 	irte->lo.val                      = 0;
 	irte->hi.val                      = 0;
-	irte->lo.fields_remap.guest_mode  = dev_data ? dev_data->use_vapic : 0;
 	irte->lo.fields_remap.int_type    = delivery_mode;
 	irte->lo.fields_remap.dm          = dest_mode;
 	irte->hi.fields.vector            = vector;
@@ -3917,10 +3915,10 @@ static void irte_ga_set_affinity(void *e
 	struct irte_ga *irte = (struct irte_ga *) entry;
 	struct iommu_dev_data *dev_data = search_dev_data(devid);
 
-	if (!dev_data || !dev_data->use_vapic) {
+	if (!dev_data || !dev_data->use_vapic ||
+	    !irte->lo.fields_remap.guest_mode) {
 		irte->hi.fields.vector = vector;
 		irte->lo.fields_remap.destination = dest_apicid;
-		irte->lo.fields_remap.guest_mode = 0;
 		modify_irte_ga(devid, index, irte, NULL);
 	}
 }
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/iommu/amd_iommu_v2.c linux-libre-4.9.36-gnu/drivers/iommu/amd_iommu_v2.c
--- linux-libre-4.9.35-gnu/drivers/iommu/amd_iommu_v2.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/iommu/amd_iommu_v2.c	2017-07-05 08:40:44.000000000 -0400
@@ -695,9 +695,9 @@ out_clear_state:
 
 out_unregister:
 	mmu_notifier_unregister(&pasid_state->mn, mm);
+	mmput(mm);
 
 out_free:
-	mmput(mm);
 	free_pasid_state(pasid_state);
 
 out:
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/iommu/dma-iommu.c linux-libre-4.9.36-gnu/drivers/iommu/dma-iommu.c
--- linux-libre-4.9.35-gnu/drivers/iommu/dma-iommu.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/iommu/dma-iommu.c	2017-07-05 08:40:44.000000000 -0400
@@ -112,8 +112,7 @@ static void iova_reserve_pci_windows(str
 	unsigned long lo, hi;
 
 	resource_list_for_each_entry(window, &bridge->windows) {
-		if (resource_type(window->res) != IORESOURCE_MEM &&
-		    resource_type(window->res) != IORESOURCE_IO)
+		if (resource_type(window->res) != IORESOURCE_MEM)
 			continue;
 
 		lo = iova_pfn(iovad, window->res->start - window->offset);
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/iommu/intel-iommu.c linux-libre-4.9.36-gnu/drivers/iommu/intel-iommu.c
--- linux-libre-4.9.35-gnu/drivers/iommu/intel-iommu.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/iommu/intel-iommu.c	2017-07-05 08:40:44.000000000 -0400
@@ -1144,7 +1144,7 @@ static void dma_pte_free_level(struct dm
 		if (!dma_pte_present(pte) || dma_pte_superpage(pte))
 			goto next;
 
-		level_pfn = pfn & level_mask(level - 1);
+		level_pfn = pfn & level_mask(level);
 		level_pte = phys_to_virt(dma_pte_addr(pte));
 
 		if (level > 2)
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/iommu/iommu.c linux-libre-4.9.36-gnu/drivers/iommu/iommu.c
--- linux-libre-4.9.35-gnu/drivers/iommu/iommu.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/iommu/iommu.c	2017-07-05 08:40:44.000000000 -0400
@@ -383,36 +383,30 @@ int iommu_group_add_device(struct iommu_
 	device->dev = dev;
 
 	ret = sysfs_create_link(&dev->kobj, &group->kobj, "iommu_group");
-	if (ret) {
-		kfree(device);
-		return ret;
-	}
+	if (ret)
+		goto err_free_device;
 
 	device->name = kasprintf(GFP_KERNEL, "%s", kobject_name(&dev->kobj));
 rename:
 	if (!device->name) {
-		sysfs_remove_link(&dev->kobj, "iommu_group");
-		kfree(device);
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto err_remove_link;
 	}
 
 	ret = sysfs_create_link_nowarn(group->devices_kobj,
 				       &dev->kobj, device->name);
 	if (ret) {
-		kfree(device->name);
 		if (ret == -EEXIST && i >= 0) {
 			/*
 			 * Account for the slim chance of collision
 			 * and append an instance to the name.
 			 */
+			kfree(device->name);
 			device->name = kasprintf(GFP_KERNEL, "%s.%d",
 						 kobject_name(&dev->kobj), i++);
 			goto rename;
 		}
-
-		sysfs_remove_link(&dev->kobj, "iommu_group");
-		kfree(device);
-		return ret;
+		goto err_free_name;
 	}
 
 	kobject_get(group->devices_kobj);
@@ -424,8 +418,10 @@ rename:
 	mutex_lock(&group->mutex);
 	list_add_tail(&device->list, &group->devices);
 	if (group->domain)
-		__iommu_attach_device(group->domain, dev);
+		ret = __iommu_attach_device(group->domain, dev);
 	mutex_unlock(&group->mutex);
+	if (ret)
+		goto err_put_group;
 
 	/* Notify any listeners about change to group. */
 	blocking_notifier_call_chain(&group->notifier,
@@ -436,6 +432,21 @@ rename:
 	pr_info("Adding device %s to group %d\n", dev_name(dev), group->id);
 
 	return 0;
+
+err_put_group:
+	mutex_lock(&group->mutex);
+	list_del(&device->list);
+	mutex_unlock(&group->mutex);
+	dev->iommu_group = NULL;
+	kobject_put(group->devices_kobj);
+err_free_name:
+	kfree(device->name);
+err_remove_link:
+	sysfs_remove_link(&dev->kobj, "iommu_group");
+err_free_device:
+	kfree(device);
+	pr_err("Failed to add device %s to group %d: %d\n", dev_name(dev), group->id, ret);
+	return ret;
 }
 EXPORT_SYMBOL_GPL(iommu_group_add_device);
 
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/md/dm-thin.c linux-libre-4.9.36-gnu/drivers/md/dm-thin.c
--- linux-libre-4.9.35-gnu/drivers/md/dm-thin.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/md/dm-thin.c	2017-07-05 08:40:44.000000000 -0400
@@ -1095,6 +1095,19 @@ static void process_prepared_discard_pas
 		return;
 	}
 
+	/*
+	 * Increment the unmapped blocks.  This prevents a race between the
+	 * passdown io and reallocation of freed blocks.
+	 */
+	r = dm_pool_inc_data_range(pool->pmd, m->data_block, data_end);
+	if (r) {
+		metadata_operation_failed(pool, "dm_pool_inc_data_range", r);
+		bio_io_error(m->bio);
+		cell_defer_no_holder(tc, m->cell);
+		mempool_free(m, pool->mapping_pool);
+		return;
+	}
+
 	discard_parent = bio_alloc(GFP_NOIO, 1);
 	if (!discard_parent) {
 		DMWARN("%s: unable to allocate top level discard bio for passdown. Skipping passdown.",
@@ -1115,19 +1128,6 @@ static void process_prepared_discard_pas
 			end_discard(&op, r);
 		}
 	}
-
-	/*
-	 * Increment the unmapped blocks.  This prevents a race between the
-	 * passdown io and reallocation of freed blocks.
-	 */
-	r = dm_pool_inc_data_range(pool->pmd, m->data_block, data_end);
-	if (r) {
-		metadata_operation_failed(pool, "dm_pool_inc_data_range", r);
-		bio_io_error(m->bio);
-		cell_defer_no_holder(tc, m->cell);
-		mempool_free(m, pool->mapping_pool);
-		return;
-	}
 }
 
 static void process_prepared_discard_passdown_pt2(struct dm_thin_new_mapping *m)
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/mtd/nand/brcmnand/brcmnand.c linux-libre-4.9.36-gnu/drivers/mtd/nand/brcmnand/brcmnand.c
--- linux-libre-4.9.35-gnu/drivers/mtd/nand/brcmnand/brcmnand.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/mtd/nand/brcmnand/brcmnand.c	2017-07-05 08:40:44.000000000 -0400
@@ -101,6 +101,9 @@ struct brcm_nand_dma_desc {
 #define BRCMNAND_MIN_BLOCKSIZE	(8 * 1024)
 #define BRCMNAND_MIN_DEVSIZE	(4ULL * 1024 * 1024)
 
+#define NAND_CTRL_RDY			(INTFC_CTLR_READY | INTFC_FLASH_READY)
+#define NAND_POLL_STATUS_TIMEOUT_MS	100
+
 /* Controller feature flags */
 enum {
 	BRCMNAND_HAS_1K_SECTORS			= BIT(0),
@@ -765,6 +768,31 @@ enum {
 	CS_SELECT_AUTO_DEVICE_ID_CFG		= BIT(30),
 };
 
+static int bcmnand_ctrl_poll_status(struct brcmnand_controller *ctrl,
+				    u32 mask, u32 expected_val,
+				    unsigned long timeout_ms)
+{
+	unsigned long limit;
+	u32 val;
+
+	if (!timeout_ms)
+		timeout_ms = NAND_POLL_STATUS_TIMEOUT_MS;
+
+	limit = jiffies + msecs_to_jiffies(timeout_ms);
+	do {
+		val = brcmnand_read_reg(ctrl, BRCMNAND_INTFC_STATUS);
+		if ((val & mask) == expected_val)
+			return 0;
+
+		cpu_relax();
+	} while (time_after(limit, jiffies));
+
+	dev_warn(ctrl->dev, "timeout on status poll (expected %x got %x)\n",
+		 expected_val, val & mask);
+
+	return -ETIMEDOUT;
+}
+
 static inline void brcmnand_set_wp(struct brcmnand_controller *ctrl, bool en)
 {
 	u32 val = en ? CS_SELECT_NAND_WP : 0;
@@ -1024,12 +1052,39 @@ static void brcmnand_wp(struct mtd_info
 
 	if ((ctrl->features & BRCMNAND_HAS_WP) && wp_on == 1) {
 		static int old_wp = -1;
+		int ret;
 
 		if (old_wp != wp) {
 			dev_dbg(ctrl->dev, "WP %s\n", wp ? "on" : "off");
 			old_wp = wp;
 		}
+
+		/*
+		 * make sure ctrl/flash ready before and after
+		 * changing state of #WP pin
+		 */
+		ret = bcmnand_ctrl_poll_status(ctrl, NAND_CTRL_RDY |
+					       NAND_STATUS_READY,
+					       NAND_CTRL_RDY |
+					       NAND_STATUS_READY, 0);
+		if (ret)
+			return;
+
 		brcmnand_set_wp(ctrl, wp);
+		chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
+		/* NAND_STATUS_WP 0x00 = protected, 0x80 = not protected */
+		ret = bcmnand_ctrl_poll_status(ctrl,
+					       NAND_CTRL_RDY |
+					       NAND_STATUS_READY |
+					       NAND_STATUS_WP,
+					       NAND_CTRL_RDY |
+					       NAND_STATUS_READY |
+					       (wp ? 0 : NAND_STATUS_WP), 0);
+
+		if (ret)
+			dev_err_ratelimited(&host->pdev->dev,
+					    "nand #WP expected %s\n",
+					    wp ? "on" : "off");
 	}
 }
 
@@ -1157,15 +1212,15 @@ static irqreturn_t brcmnand_dma_irq(int
 static void brcmnand_send_cmd(struct brcmnand_host *host, int cmd)
 {
 	struct brcmnand_controller *ctrl = host->ctrl;
-	u32 intfc;
+	int ret;
 
 	dev_dbg(ctrl->dev, "send native cmd %d addr_lo 0x%x\n", cmd,
 		brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS));
 	BUG_ON(ctrl->cmd_pending != 0);
 	ctrl->cmd_pending = cmd;
 
-	intfc = brcmnand_read_reg(ctrl, BRCMNAND_INTFC_STATUS);
-	WARN_ON(!(intfc & INTFC_CTLR_READY));
+	ret = bcmnand_ctrl_poll_status(ctrl, NAND_CTRL_RDY, NAND_CTRL_RDY, 0);
+	WARN_ON(ret);
 
 	mb(); /* flush previous writes */
 	brcmnand_write_reg(ctrl, BRCMNAND_CMD_START,
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/net/ethernet/amd/xgbe/xgbe-dev.c linux-libre-4.9.36-gnu/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
--- linux-libre-4.9.35-gnu/drivers/net/ethernet/amd/xgbe/xgbe-dev.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/net/ethernet/amd/xgbe/xgbe-dev.c	2017-07-05 08:40:44.000000000 -0400
@@ -2825,8 +2825,10 @@ static int xgbe_init(struct xgbe_prv_dat
 
 	/* Flush Tx queues */
 	ret = xgbe_flush_tx_queues(pdata);
-	if (ret)
+	if (ret) {
+		netdev_err(pdata->netdev, "error flushing TX queues\n");
 		return ret;
+	}
 
 	/*
 	 * Initialize DMA related features
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/net/ethernet/amd/xgbe/xgbe-drv.c linux-libre-4.9.36-gnu/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
--- linux-libre-4.9.35-gnu/drivers/net/ethernet/amd/xgbe/xgbe-drv.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/net/ethernet/amd/xgbe/xgbe-drv.c	2017-07-05 08:40:44.000000000 -0400
@@ -877,7 +877,9 @@ static int xgbe_start(struct xgbe_prv_da
 
 	DBGPR("-->xgbe_start\n");
 
-	hw_if->init(pdata);
+	ret = hw_if->init(pdata);
+	if (ret)
+		return ret;
 
 	ret = phy_if->phy_start(pdata);
 	if (ret)
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt.c linux-libre-4.9.36-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt.c
--- linux-libre-4.9.35-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt.c	2017-07-05 08:40:44.000000000 -0400
@@ -1097,7 +1097,7 @@ static struct sk_buff *bnxt_gro_func_573
 {
 #ifdef CONFIG_INET
 	struct tcphdr *th;
-	int len, nw_off, tcp_opt_len;
+	int len, nw_off, tcp_opt_len = 0;
 
 	if (tcp_ts)
 		tcp_opt_len = 12;
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/net/ethernet/cavium/thunder/thunder_bgx.c linux-libre-4.9.36-gnu/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
--- linux-libre-4.9.35-gnu/drivers/net/ethernet/cavium/thunder/thunder_bgx.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/net/ethernet/cavium/thunder/thunder_bgx.c	2017-07-05 08:40:44.000000000 -0400
@@ -48,8 +48,9 @@ struct lmac {
 struct bgx {
 	u8			bgx_id;
 	struct	lmac		lmac[MAX_LMAC_PER_BGX];
-	int			lmac_count;
+	u8			lmac_count;
 	u8			max_lmac;
+	u8                      acpi_lmac_idx;
 	void __iomem		*reg_base;
 	struct pci_dev		*pdev;
 	bool                    is_dlm;
@@ -1159,13 +1160,13 @@ static acpi_status bgx_acpi_register_phy
 	if (acpi_bus_get_device(handle, &adev))
 		goto out;
 
-	acpi_get_mac_address(dev, adev, bgx->lmac[bgx->lmac_count].mac);
+	acpi_get_mac_address(dev, adev, bgx->lmac[bgx->acpi_lmac_idx].mac);
 
-	SET_NETDEV_DEV(&bgx->lmac[bgx->lmac_count].netdev, dev);
+	SET_NETDEV_DEV(&bgx->lmac[bgx->acpi_lmac_idx].netdev, dev);
 
-	bgx->lmac[bgx->lmac_count].lmacid = bgx->lmac_count;
+	bgx->lmac[bgx->acpi_lmac_idx].lmacid = bgx->acpi_lmac_idx;
+	bgx->acpi_lmac_idx++; /* move to next LMAC */
 out:
-	bgx->lmac_count++;
 	return AE_OK;
 }
 
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/net/ethernet/emulex/benet/be_cmds.c linux-libre-4.9.36-gnu/drivers/net/ethernet/emulex/benet/be_cmds.c
--- linux-libre-4.9.35-gnu/drivers/net/ethernet/emulex/benet/be_cmds.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/net/ethernet/emulex/benet/be_cmds.c	2017-07-05 08:40:44.000000000 -0400
@@ -1118,7 +1118,7 @@ int be_cmd_pmac_add(struct be_adapter *a
 err:
 	mutex_unlock(&adapter->mcc_lock);
 
-	 if (status == MCC_STATUS_UNAUTHORIZED_REQUEST)
+	 if (base_status(status) == MCC_STATUS_UNAUTHORIZED_REQUEST)
 		status = -EPERM;
 
 	return status;
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/net/ethernet/emulex/benet/be_main.c linux-libre-4.9.36-gnu/drivers/net/ethernet/emulex/benet/be_main.c
--- linux-libre-4.9.35-gnu/drivers/net/ethernet/emulex/benet/be_main.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/net/ethernet/emulex/benet/be_main.c	2017-07-05 08:40:44.000000000 -0400
@@ -319,6 +319,13 @@ static int be_mac_addr_set(struct net_de
 	if (ether_addr_equal(addr->sa_data, adapter->dev_mac))
 		return 0;
 
+	/* BE3 VFs without FILTMGMT privilege are not allowed to set its MAC
+	 * address
+	 */
+	if (BEx_chip(adapter) && be_virtfn(adapter) &&
+	    !check_privilege(adapter, BE_PRIV_FILTMGMT))
+		return -EPERM;
+
 	/* if device is not running, copy MAC to netdev->dev_addr */
 	if (!netif_running(netdev))
 		goto done;
@@ -3630,7 +3637,11 @@ static void be_rx_qs_destroy(struct be_a
 
 static void be_disable_if_filters(struct be_adapter *adapter)
 {
-	be_dev_mac_del(adapter, adapter->pmac_id[0]);
+	/* Don't delete MAC on BE3 VFs without FILTMGMT privilege  */
+	if (!BEx_chip(adapter) || !be_virtfn(adapter) ||
+	    check_privilege(adapter, BE_PRIV_FILTMGMT))
+		be_dev_mac_del(adapter, adapter->pmac_id[0]);
+
 	be_clear_uc_list(adapter);
 	be_clear_mc_list(adapter);
 
@@ -3783,8 +3794,9 @@ static int be_enable_if_filters(struct b
 	if (status)
 		return status;
 
-	/* For BE3 VFs, the PF programs the initial MAC address */
-	if (!(BEx_chip(adapter) && be_virtfn(adapter))) {
+	/* Don't add MAC on BE3 VFs without FILTMGMT privilege */
+	if (!BEx_chip(adapter) || !be_virtfn(adapter) ||
+	    check_privilege(adapter, BE_PRIV_FILTMGMT)) {
 		status = be_dev_mac_add(adapter, adapter->netdev->dev_addr);
 		if (status)
 			return status;
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/net/ethernet/freescale/gianfar.c linux-libre-4.9.36-gnu/drivers/net/ethernet/freescale/gianfar.c
--- linux-libre-4.9.35-gnu/drivers/net/ethernet/freescale/gianfar.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/net/ethernet/freescale/gianfar.c	2017-07-05 08:40:44.000000000 -0400
@@ -2951,7 +2951,7 @@ static bool gfar_add_rx_frag(struct gfar
 	}
 
 	/* try reuse page */
-	if (unlikely(page_count(page) != 1))
+	if (unlikely(page_count(page) != 1 || page_is_pfmemalloc(page)))
 		return false;
 
 	/* change offset to the other half */
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/net/ethernet/ibm/ibmveth.c linux-libre-4.9.36-gnu/drivers/net/ethernet/ibm/ibmveth.c
--- linux-libre-4.9.35-gnu/drivers/net/ethernet/ibm/ibmveth.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/net/ethernet/ibm/ibmveth.c	2017-07-05 08:40:44.000000000 -0400
@@ -1604,8 +1604,11 @@ static int ibmveth_probe(struct vio_dev
 	netdev->netdev_ops = &ibmveth_netdev_ops;
 	netdev->ethtool_ops = &netdev_ethtool_ops;
 	SET_NETDEV_DEV(netdev, &dev->dev);
-	netdev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM |
-		NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+	netdev->hw_features = NETIF_F_SG;
+	if (vio_get_attribute(dev, "ibm,illan-options", NULL) != NULL) {
+		netdev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
+				       NETIF_F_RXCSUM;
+	}
 
 	netdev->features |= netdev->hw_features;
 
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/net/ethernet/korina.c linux-libre-4.9.36-gnu/drivers/net/ethernet/korina.c
--- linux-libre-4.9.35-gnu/drivers/net/ethernet/korina.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/net/ethernet/korina.c	2017-07-05 08:40:44.000000000 -0400
@@ -900,10 +900,10 @@ static void korina_restart_task(struct w
 				DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR,
 				&lp->rx_dma_regs->dmasm);
 
-	korina_free_ring(dev);
-
 	napi_disable(&lp->napi);
 
+	korina_free_ring(dev);
+
 	if (korina_init(dev) < 0) {
 		printk(KERN_ERR "%s: cannot restart device\n", dev->name);
 		return;
@@ -1064,12 +1064,12 @@ static int korina_close(struct net_devic
 	tmp = tmp | DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR;
 	writel(tmp, &lp->rx_dma_regs->dmasm);
 
-	korina_free_ring(dev);
-
 	napi_disable(&lp->napi);
 
 	cancel_work_sync(&lp->restart_task);
 
+	korina_free_ring(dev);
+
 	free_irq(lp->rx_irq, dev);
 	free_irq(lp->tx_irq, dev);
 	free_irq(lp->ovr_irq, dev);
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/net/ethernet/mellanox/mlx4/eq.c linux-libre-4.9.36-gnu/drivers/net/ethernet/mellanox/mlx4/eq.c
--- linux-libre-4.9.35-gnu/drivers/net/ethernet/mellanox/mlx4/eq.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/net/ethernet/mellanox/mlx4/eq.c	2017-07-05 08:40:44.000000000 -0400
@@ -554,8 +554,9 @@ static int mlx4_eq_int(struct mlx4_dev *
 			break;
 
 		case MLX4_EVENT_TYPE_SRQ_LIMIT:
-			mlx4_dbg(dev, "%s: MLX4_EVENT_TYPE_SRQ_LIMIT\n",
-				 __func__);
+			mlx4_dbg(dev, "%s: MLX4_EVENT_TYPE_SRQ_LIMIT. srq_no=0x%x, eq 0x%x\n",
+				 __func__, be32_to_cpu(eqe->event.srq.srqn),
+				 eq->eqn);
 		case MLX4_EVENT_TYPE_SRQ_CATAS_ERROR:
 			if (mlx4_is_master(dev)) {
 				/* forward only to slave owning the SRQ */
@@ -570,15 +571,19 @@ static int mlx4_eq_int(struct mlx4_dev *
 						  eq->eqn, eq->cons_index, ret);
 					break;
 				}
-				mlx4_warn(dev, "%s: slave:%d, srq_no:0x%x, event: %02x(%02x)\n",
-					  __func__, slave,
-					  be32_to_cpu(eqe->event.srq.srqn),
-					  eqe->type, eqe->subtype);
+				if (eqe->type ==
+				    MLX4_EVENT_TYPE_SRQ_CATAS_ERROR)
+					mlx4_warn(dev, "%s: slave:%d, srq_no:0x%x, event: %02x(%02x)\n",
+						  __func__, slave,
+						  be32_to_cpu(eqe->event.srq.srqn),
+						  eqe->type, eqe->subtype);
 
 				if (!ret && slave != dev->caps.function) {
-					mlx4_warn(dev, "%s: sending event %02x(%02x) to slave:%d\n",
-						  __func__, eqe->type,
-						  eqe->subtype, slave);
+					if (eqe->type ==
+					    MLX4_EVENT_TYPE_SRQ_CATAS_ERROR)
+						mlx4_warn(dev, "%s: sending event %02x(%02x) to slave:%d\n",
+							  __func__, eqe->type,
+							  eqe->subtype, slave);
 					mlx4_slave_event(dev, slave, eqe);
 					break;
 				}
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c linux-libre-4.9.36-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
--- linux-libre-4.9.35-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c	2017-07-05 08:40:44.000000000 -0400
@@ -1183,11 +1183,11 @@ static int mlx5e_get_ts_info(struct net_
 				 SOF_TIMESTAMPING_RX_HARDWARE |
 				 SOF_TIMESTAMPING_RAW_HARDWARE;
 
-	info->tx_types = (BIT(1) << HWTSTAMP_TX_OFF) |
-			 (BIT(1) << HWTSTAMP_TX_ON);
+	info->tx_types = BIT(HWTSTAMP_TX_OFF) |
+			 BIT(HWTSTAMP_TX_ON);
 
-	info->rx_filters = (BIT(1) << HWTSTAMP_FILTER_NONE) |
-			   (BIT(1) << HWTSTAMP_FILTER_ALL);
+	info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) |
+			   BIT(HWTSTAMP_FILTER_ALL);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/net/ethernet/mellanox/mlx5/core/en.h linux-libre-4.9.36-gnu/drivers/net/ethernet/mellanox/mlx5/core/en.h
--- linux-libre-4.9.35-gnu/drivers/net/ethernet/mellanox/mlx5/core/en.h	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/net/ethernet/mellanox/mlx5/core/en.h	2017-07-05 08:40:44.000000000 -0400
@@ -283,13 +283,15 @@ struct mlx5e_dma_info {
 
 struct mlx5e_rx_am_stats {
 	int ppms; /* packets per msec */
+	int bpms; /* bytes per msec */
 	int epms; /* events per msec */
 };
 
 struct mlx5e_rx_am_sample {
-	ktime_t		time;
-	unsigned int	pkt_ctr;
-	u16		event_ctr;
+	ktime_t	time;
+	u32	pkt_ctr;
+	u32	byte_ctr;
+	u16	event_ctr;
 };
 
 struct mlx5e_rx_am { /* Adaptive Moderation */
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_main.c linux-libre-4.9.36-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
--- linux-libre-4.9.35-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_main.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_main.c	2017-07-05 08:40:44.000000000 -0400
@@ -3846,7 +3846,8 @@ struct net_device *mlx5e_create_netdev(s
 	return netdev;
 
 err_cleanup_nic:
-	profile->cleanup(priv);
+	if (profile->cleanup)
+		profile->cleanup(priv);
 	free_netdev(netdev);
 
 	return NULL;
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c linux-libre-4.9.36-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c
--- linux-libre-4.9.35-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c	2017-07-05 08:40:44.000000000 -0400
@@ -183,28 +183,27 @@ static void mlx5e_am_exit_parking(struct
 	mlx5e_am_step(am);
 }
 
+#define IS_SIGNIFICANT_DIFF(val, ref) \
+	(((100 * abs((val) - (ref))) / (ref)) > 10) /* more than 10% difference */
+
 static int mlx5e_am_stats_compare(struct mlx5e_rx_am_stats *curr,
 				  struct mlx5e_rx_am_stats *prev)
 {
-	int diff;
-
-	if (!prev->ppms)
-		return curr->ppms ? MLX5E_AM_STATS_BETTER :
+	if (!prev->bpms)
+		return curr->bpms ? MLX5E_AM_STATS_BETTER :
 				    MLX5E_AM_STATS_SAME;
 
-	diff = curr->ppms - prev->ppms;
-	if (((100 * abs(diff)) / prev->ppms) > 10) /* more than 10% diff */
-		return (diff > 0) ? MLX5E_AM_STATS_BETTER :
-				    MLX5E_AM_STATS_WORSE;
+	if (IS_SIGNIFICANT_DIFF(curr->bpms, prev->bpms))
+		return (curr->bpms > prev->bpms) ? MLX5E_AM_STATS_BETTER :
+						   MLX5E_AM_STATS_WORSE;
 
-	if (!prev->epms)
-		return curr->epms ? MLX5E_AM_STATS_WORSE :
-				    MLX5E_AM_STATS_SAME;
+	if (IS_SIGNIFICANT_DIFF(curr->ppms, prev->ppms))
+		return (curr->ppms > prev->ppms) ? MLX5E_AM_STATS_BETTER :
+						   MLX5E_AM_STATS_WORSE;
 
-	diff = curr->epms - prev->epms;
-	if (((100 * abs(diff)) / prev->epms) > 10) /* more than 10% diff */
-		return (diff < 0) ? MLX5E_AM_STATS_BETTER :
-				    MLX5E_AM_STATS_WORSE;
+	if (IS_SIGNIFICANT_DIFF(curr->epms, prev->epms))
+		return (curr->epms < prev->epms) ? MLX5E_AM_STATS_BETTER :
+						   MLX5E_AM_STATS_WORSE;
 
 	return MLX5E_AM_STATS_SAME;
 }
@@ -266,10 +265,13 @@ static void mlx5e_am_sample(struct mlx5e
 {
 	s->time	     = ktime_get();
 	s->pkt_ctr   = rq->stats.packets;
+	s->byte_ctr  = rq->stats.bytes;
 	s->event_ctr = rq->cq.event_ctr;
 }
 
 #define MLX5E_AM_NEVENTS 64
+#define BITS_PER_TYPE(type) (sizeof(type) * BITS_PER_BYTE)
+#define BIT_GAP(bits, end, start) ((((end) - (start)) + BIT_ULL(bits)) & (BIT_ULL(bits) - 1))
 
 static void mlx5e_am_calc_stats(struct mlx5e_rx_am_sample *start,
 				struct mlx5e_rx_am_sample *end,
@@ -277,13 +279,17 @@ static void mlx5e_am_calc_stats(struct m
 {
 	/* u32 holds up to 71 minutes, should be enough */
 	u32 delta_us = ktime_us_delta(end->time, start->time);
-	unsigned int npkts = end->pkt_ctr - start->pkt_ctr;
+	u32 npkts = BIT_GAP(BITS_PER_TYPE(u32), end->pkt_ctr, start->pkt_ctr);
+	u32 nbytes = BIT_GAP(BITS_PER_TYPE(u32), end->byte_ctr,
+			     start->byte_ctr);
 
 	if (!delta_us)
 		return;
 
-	curr_stats->ppms =            (npkts * USEC_PER_MSEC) / delta_us;
-	curr_stats->epms = (MLX5E_AM_NEVENTS * USEC_PER_MSEC) / delta_us;
+	curr_stats->ppms = DIV_ROUND_UP(npkts * USEC_PER_MSEC, delta_us);
+	curr_stats->bpms = DIV_ROUND_UP(nbytes * USEC_PER_MSEC, delta_us);
+	curr_stats->epms = DIV_ROUND_UP(MLX5E_AM_NEVENTS * USEC_PER_MSEC,
+					delta_us);
 }
 
 void mlx5e_rx_am_work(struct work_struct *work)
@@ -308,7 +314,8 @@ void mlx5e_rx_am(struct mlx5e_rq *rq)
 
 	switch (am->state) {
 	case MLX5E_AM_MEASURE_IN_PROGRESS:
-		nevents = rq->cq.event_ctr - am->start_sample.event_ctr;
+		nevents = BIT_GAP(BITS_PER_TYPE(u16), rq->cq.event_ctr,
+				  am->start_sample.event_ctr);
 		if (nevents < MLX5E_AM_NEVENTS)
 			break;
 		mlx5e_am_sample(rq, &end_sample);
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/net/ethernet/mellanox/mlx5/core/main.c linux-libre-4.9.36-gnu/drivers/net/ethernet/mellanox/mlx5/core/main.c
--- linux-libre-4.9.35-gnu/drivers/net/ethernet/mellanox/mlx5/core/main.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/net/ethernet/mellanox/mlx5/core/main.c	2017-07-05 08:40:44.000000000 -0400
@@ -155,8 +155,9 @@ static struct mlx5_profile profile[] = {
 	},
 };
 
-#define FW_INIT_TIMEOUT_MILI	2000
-#define FW_INIT_WAIT_MS		2
+#define FW_INIT_TIMEOUT_MILI		2000
+#define FW_INIT_WAIT_MS			2
+#define FW_PRE_INIT_TIMEOUT_MILI	10000
 
 static int wait_fw_init(struct mlx5_core_dev *dev, u32 max_wait_mili)
 {
@@ -956,6 +957,15 @@ static int mlx5_load_one(struct mlx5_cor
 	 */
 	dev->state = MLX5_DEVICE_STATE_UP;
 
+	/* wait for firmware to accept initialization segments configurations
+	 */
+	err = wait_fw_init(dev, FW_PRE_INIT_TIMEOUT_MILI);
+	if (err) {
+		dev_err(&dev->pdev->dev, "Firmware over %d MS in pre-initializing state, aborting\n",
+			FW_PRE_INIT_TIMEOUT_MILI);
+		goto out;
+	}
+
 	err = mlx5_cmd_init(dev);
 	if (err) {
 		dev_err(&pdev->dev, "Failed initializing command interface, aborting\n");
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c linux-libre-4.9.36-gnu/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
--- linux-libre-4.9.35-gnu/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c	2017-07-05 08:40:44.000000000 -0400
@@ -1178,7 +1178,8 @@ static int mlxsw_sp_nexthop_mac_update(s
 
 static int
 mlxsw_sp_nexthop_group_mac_update(struct mlxsw_sp *mlxsw_sp,
-				  struct mlxsw_sp_nexthop_group *nh_grp)
+				  struct mlxsw_sp_nexthop_group *nh_grp,
+				  bool reallocate)
 {
 	u32 adj_index = nh_grp->adj_index; /* base */
 	struct mlxsw_sp_nexthop *nh;
@@ -1193,7 +1194,7 @@ mlxsw_sp_nexthop_group_mac_update(struct
 			continue;
 		}
 
-		if (nh->update) {
+		if (nh->update || reallocate) {
 			err = mlxsw_sp_nexthop_mac_update(mlxsw_sp,
 							  adj_index, nh);
 			if (err)
@@ -1254,7 +1255,8 @@ mlxsw_sp_nexthop_group_refresh(struct ml
 		/* Nothing was added or removed, so no need to reallocate. Just
 		 * update MAC on existing adjacency indexes.
 		 */
-		err = mlxsw_sp_nexthop_group_mac_update(mlxsw_sp, nh_grp);
+		err = mlxsw_sp_nexthop_group_mac_update(mlxsw_sp, nh_grp,
+							false);
 		if (err) {
 			dev_warn(mlxsw_sp->bus_info->dev, "Failed to update neigh MAC in adjacency table.\n");
 			goto set_trap;
@@ -1282,7 +1284,7 @@ mlxsw_sp_nexthop_group_refresh(struct ml
 	nh_grp->adj_index_valid = 1;
 	nh_grp->adj_index = adj_index;
 	nh_grp->ecmp_size = ecmp_size;
-	err = mlxsw_sp_nexthop_group_mac_update(mlxsw_sp, nh_grp);
+	err = mlxsw_sp_nexthop_group_mac_update(mlxsw_sp, nh_grp, true);
 	if (err) {
 		dev_warn(mlxsw_sp->bus_info->dev, "Failed to update neigh MAC in adjacency table.\n");
 		goto set_trap;
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/net/ethernet/renesas/ravb_main.c linux-libre-4.9.36-gnu/drivers/net/ethernet/renesas/ravb_main.c
--- linux-libre-4.9.35-gnu/drivers/net/ethernet/renesas/ravb_main.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/net/ethernet/renesas/ravb_main.c	2017-07-05 08:40:44.000000000 -0400
@@ -229,18 +229,6 @@ static void ravb_ring_free(struct net_de
 	int ring_size;
 	int i;
 
-	/* Free RX skb ringbuffer */
-	if (priv->rx_skb[q]) {
-		for (i = 0; i < priv->num_rx_ring[q]; i++)
-			dev_kfree_skb(priv->rx_skb[q][i]);
-	}
-	kfree(priv->rx_skb[q]);
-	priv->rx_skb[q] = NULL;
-
-	/* Free aligned TX buffers */
-	kfree(priv->tx_align[q]);
-	priv->tx_align[q] = NULL;
-
 	if (priv->rx_ring[q]) {
 		for (i = 0; i < priv->num_rx_ring[q]; i++) {
 			struct ravb_ex_rx_desc *desc = &priv->rx_ring[q][i];
@@ -269,6 +257,18 @@ static void ravb_ring_free(struct net_de
 		priv->tx_ring[q] = NULL;
 	}
 
+	/* Free RX skb ringbuffer */
+	if (priv->rx_skb[q]) {
+		for (i = 0; i < priv->num_rx_ring[q]; i++)
+			dev_kfree_skb(priv->rx_skb[q][i]);
+	}
+	kfree(priv->rx_skb[q]);
+	priv->rx_skb[q] = NULL;
+
+	/* Free aligned TX buffers */
+	kfree(priv->tx_align[q]);
+	priv->tx_align[q] = NULL;
+
 	/* Free TX skb ringbuffer.
 	 * SKBs are freed by ravb_tx_free() call above.
 	 */
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/net/ethernet/sfc/falcon.c linux-libre-4.9.36-gnu/drivers/net/ethernet/sfc/falcon.c
--- linux-libre-4.9.35-gnu/drivers/net/ethernet/sfc/falcon.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/net/ethernet/sfc/falcon.c	2017-07-05 08:40:44.000000000 -0400
@@ -2801,6 +2801,11 @@ const struct efx_nic_type falcon_a1_nic_
 	.timer_period_max =  1 << FRF_AB_TC_TIMER_VAL_WIDTH,
 	.offload_features = NETIF_F_IP_CSUM,
 	.mcdi_max_ver = -1,
+#ifdef CONFIG_SFC_SRIOV
+	.vswitching_probe = efx_port_dummy_op_int,
+	.vswitching_restore = efx_port_dummy_op_int,
+	.vswitching_remove = efx_port_dummy_op_void,
+#endif
 };
 
 const struct efx_nic_type falcon_b0_nic_type = {
@@ -2902,4 +2907,9 @@ const struct efx_nic_type falcon_b0_nic_
 	.offload_features = NETIF_F_IP_CSUM | NETIF_F_RXHASH | NETIF_F_NTUPLE,
 	.mcdi_max_ver = -1,
 	.max_rx_ip_filters = FR_BZ_RX_FILTER_TBL0_ROWS,
+#ifdef CONFIG_SFC_SRIOV
+	.vswitching_probe = efx_port_dummy_op_int,
+	.vswitching_restore = efx_port_dummy_op_int,
+	.vswitching_remove = efx_port_dummy_op_void,
+#endif
 };
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c linux-libre-4.9.36-gnu/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
--- linux-libre-4.9.35-gnu/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c	2017-07-05 08:40:44.000000000 -0400
@@ -346,6 +346,7 @@ void stmmac_remove_config_dt(struct plat
 	if (of_phy_is_fixed_link(np))
 		of_phy_deregister_fixed_link(np);
 	of_node_put(plat->phy_node);
+	of_node_put(plat->mdio_node);
 }
 #else
 struct plat_stmmacenet_data *
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/net/phy/dp83848.c linux-libre-4.9.36-gnu/drivers/net/phy/dp83848.c
--- linux-libre-4.9.35-gnu/drivers/net/phy/dp83848.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/net/phy/dp83848.c	2017-07-05 08:40:44.000000000 -0400
@@ -17,6 +17,7 @@
 #include <linux/phy.h>
 
 #define TI_DP83848C_PHY_ID		0x20005ca0
+#define TI_DP83620_PHY_ID		0x20005ce0
 #define NS_DP83848C_PHY_ID		0x20005c90
 #define TLK10X_PHY_ID			0x2000a210
 #define TI_DP83822_PHY_ID		0x2000a240
@@ -77,6 +78,7 @@ static int dp83848_config_intr(struct ph
 static struct mdio_device_id __maybe_unused dp83848_tbl[] = {
 	{ TI_DP83848C_PHY_ID, 0xfffffff0 },
 	{ NS_DP83848C_PHY_ID, 0xfffffff0 },
+	{ TI_DP83620_PHY_ID, 0xfffffff0 },
 	{ TLK10X_PHY_ID, 0xfffffff0 },
 	{ TI_DP83822_PHY_ID, 0xfffffff0 },
 	{ }
@@ -106,6 +108,7 @@ MODULE_DEVICE_TABLE(mdio, dp83848_tbl);
 static struct phy_driver dp83848_driver[] = {
 	DP83848_PHY_DRIVER(TI_DP83848C_PHY_ID, "TI DP83848C 10/100 Mbps PHY"),
 	DP83848_PHY_DRIVER(NS_DP83848C_PHY_ID, "NS DP83848C 10/100 Mbps PHY"),
+	DP83848_PHY_DRIVER(TI_DP83620_PHY_ID, "TI DP83620 10/100 Mbps PHY"),
 	DP83848_PHY_DRIVER(TLK10X_PHY_ID, "TI TLK10X 10/100 Mbps PHY"),
 	DP83848_PHY_DRIVER(TI_DP83822_PHY_ID, "TI DP83822 10/100 Mbps PHY"),
 };
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/net/phy/dp83867.c linux-libre-4.9.36-gnu/drivers/net/phy/dp83867.c
--- linux-libre-4.9.35-gnu/drivers/net/phy/dp83867.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/net/phy/dp83867.c	2017-07-05 08:40:44.000000000 -0400
@@ -113,12 +113,16 @@ static int dp83867_of_init(struct phy_de
 
 	ret = of_property_read_u32(of_node, "ti,rx-internal-delay",
 				   &dp83867->rx_id_delay);
-	if (ret)
+	if (ret &&
+	    (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
+	     phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID))
 		return ret;
 
 	ret = of_property_read_u32(of_node, "ti,tx-internal-delay",
 				   &dp83867->tx_id_delay);
-	if (ret)
+	if (ret &&
+	    (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
+	     phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID))
 		return ret;
 
 	return of_property_read_u32(of_node, "ti,fifo-depth",
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/net/phy/marvell.c linux-libre-4.9.36-gnu/drivers/net/phy/marvell.c
--- linux-libre-4.9.35-gnu/drivers/net/phy/marvell.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/net/phy/marvell.c	2017-07-05 08:40:44.000000000 -0400
@@ -1200,7 +1200,8 @@ static int marvell_read_status(struct ph
 	int err;
 
 	/* Check the fiber mode first */
-	if (phydev->supported & SUPPORTED_FIBRE) {
+	if (phydev->supported & SUPPORTED_FIBRE &&
+	    phydev->interface != PHY_INTERFACE_MODE_SGMII) {
 		err = phy_write(phydev, MII_MARVELL_PHY_PAGE, MII_M1111_FIBER);
 		if (err < 0)
 			goto error;
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/net/phy/phy.c linux-libre-4.9.36-gnu/drivers/net/phy/phy.c
--- linux-libre-4.9.35-gnu/drivers/net/phy/phy.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/net/phy/phy.c	2017-07-05 08:40:44.000000000 -0400
@@ -1384,6 +1384,9 @@ int phy_ethtool_set_eee(struct phy_devic
 {
 	int val = ethtool_adv_to_mmd_eee_adv_t(data->advertised);
 
+	/* Mask prohibited EEE modes */
+	val &= ~phydev->eee_broken_modes;
+
 	phy_write_mmd_indirect(phydev, MDIO_AN_EEE_ADV, MDIO_MMD_AN, val);
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/net/phy/phy_device.c linux-libre-4.9.36-gnu/drivers/net/phy/phy_device.c
--- linux-libre-4.9.35-gnu/drivers/net/phy/phy_device.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/net/phy/phy_device.c	2017-07-05 08:40:44.000000000 -0400
@@ -1146,6 +1146,43 @@ static int genphy_config_advert(struct p
 }
 
 /**
+ * genphy_config_eee_advert - disable unwanted eee mode advertisement
+ * @phydev: target phy_device struct
+ *
+ * Description: Writes MDIO_AN_EEE_ADV after disabling unsupported energy
+ *   efficent ethernet modes. Returns 0 if the PHY's advertisement hasn't
+ *   changed, and 1 if it has changed.
+ */
+static int genphy_config_eee_advert(struct phy_device *phydev)
+{
+	int broken = phydev->eee_broken_modes;
+	int old_adv, adv;
+
+	/* Nothing to disable */
+	if (!broken)
+		return 0;
+
+	/* If the following call fails, we assume that EEE is not
+	 * supported by the phy. If we read 0, EEE is not advertised
+	 * In both case, we don't need to continue
+	 */
+	adv = phy_read_mmd_indirect(phydev, MDIO_AN_EEE_ADV, MDIO_MMD_AN);
+	if (adv <= 0)
+		return 0;
+
+	old_adv = adv;
+	adv &= ~broken;
+
+	/* Advertising remains unchanged with the broken mask */
+	if (old_adv == adv)
+		return 0;
+
+	phy_write_mmd_indirect(phydev, MDIO_AN_EEE_ADV, MDIO_MMD_AN, adv);
+
+	return 1;
+}
+
+/**
  * genphy_setup_forced - configures/forces speed/duplex from @phydev
  * @phydev: target phy_device struct
  *
@@ -1203,15 +1240,20 @@ EXPORT_SYMBOL(genphy_restart_aneg);
  */
 int genphy_config_aneg(struct phy_device *phydev)
 {
-	int result;
+	int err, changed;
+
+	changed = genphy_config_eee_advert(phydev);
 
 	if (AUTONEG_ENABLE != phydev->autoneg)
 		return genphy_setup_forced(phydev);
 
-	result = genphy_config_advert(phydev);
-	if (result < 0) /* error */
-		return result;
-	if (result == 0) {
+	err = genphy_config_advert(phydev);
+	if (err < 0) /* error */
+		return err;
+
+	changed |= err;
+
+	if (changed == 0) {
 		/* Advertisement hasn't changed, but maybe aneg was never on to
 		 * begin with?  Or maybe phy was isolated?
 		 */
@@ -1221,16 +1263,16 @@ int genphy_config_aneg(struct phy_device
 			return ctl;
 
 		if (!(ctl & BMCR_ANENABLE) || (ctl & BMCR_ISOLATE))
-			result = 1; /* do restart aneg */
+			changed = 1; /* do restart aneg */
 	}
 
 	/* Only restart aneg if we are advertising something different
 	 * than we were before.
 	 */
-	if (result > 0)
-		result = genphy_restart_aneg(phydev);
+	if (changed > 0)
+		return genphy_restart_aneg(phydev);
 
-	return result;
+	return 0;
 }
 EXPORT_SYMBOL(genphy_config_aneg);
 
@@ -1588,6 +1630,33 @@ static void of_set_phy_supported(struct
 		__set_phy_supported(phydev, max_speed);
 }
 
+static void of_set_phy_eee_broken(struct phy_device *phydev)
+{
+	struct device_node *node = phydev->mdio.dev.of_node;
+	u32 broken = 0;
+
+	if (!IS_ENABLED(CONFIG_OF_MDIO))
+		return;
+
+	if (!node)
+		return;
+
+	if (of_property_read_bool(node, "eee-broken-100tx"))
+		broken |= MDIO_EEE_100TX;
+	if (of_property_read_bool(node, "eee-broken-1000t"))
+		broken |= MDIO_EEE_1000T;
+	if (of_property_read_bool(node, "eee-broken-10gt"))
+		broken |= MDIO_EEE_10GT;
+	if (of_property_read_bool(node, "eee-broken-1000kx"))
+		broken |= MDIO_EEE_1000KX;
+	if (of_property_read_bool(node, "eee-broken-10gkx4"))
+		broken |= MDIO_EEE_10GKX4;
+	if (of_property_read_bool(node, "eee-broken-10gkr"))
+		broken |= MDIO_EEE_10GKR;
+
+	phydev->eee_broken_modes = broken;
+}
+
 /**
  * phy_probe - probe and init a PHY device
  * @dev: device to probe and init
@@ -1625,6 +1694,11 @@ static int phy_probe(struct device *dev)
 	of_set_phy_supported(phydev);
 	phydev->advertising = phydev->supported;
 
+	/* Get the EEE modes we want to prohibit. We will ask
+	 * the PHY stop advertising these mode later on
+	 */
+	of_set_phy_eee_broken(phydev);
+
 	/* Set the state to READY by default */
 	phydev->state = PHY_READY;
 
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/net/virtio_net.c linux-libre-4.9.36-gnu/drivers/net/virtio_net.c
--- linux-libre-4.9.35-gnu/drivers/net/virtio_net.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/net/virtio_net.c	2017-07-05 08:40:44.000000000 -0400
@@ -47,8 +47,16 @@ module_param(gso, bool, 0444);
  */
 DECLARE_EWMA(pkt_len, 1, 64)
 
+/* With mergeable buffers we align buffer address and use the low bits to
+ * encode its true size. Buffer size is up to 1 page so we need to align to
+ * square root of page size to ensure we reserve enough bits to encode the true
+ * size.
+ */
+#define MERGEABLE_BUFFER_MIN_ALIGN_SHIFT ((PAGE_SHIFT + 1) / 2)
+
 /* Minimum alignment for mergeable packet buffers. */
-#define MERGEABLE_BUFFER_ALIGN max(L1_CACHE_BYTES, 256)
+#define MERGEABLE_BUFFER_ALIGN max(L1_CACHE_BYTES, \
+				   1 << MERGEABLE_BUFFER_MIN_ALIGN_SHIFT)
 
 #define VIRTNET_DRIVER_VERSION "1.0.0"
 
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/net/vrf.c linux-libre-4.9.36-gnu/drivers/net/vrf.c
--- linux-libre-4.9.35-gnu/drivers/net/vrf.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/net/vrf.c	2017-07-05 08:40:44.000000000 -0400
@@ -36,12 +36,14 @@
 #include <net/addrconf.h>
 #include <net/l3mdev.h>
 #include <net/fib_rules.h>
+#include <net/netns/generic.h>
 
 #define DRV_NAME	"vrf"
 #define DRV_VERSION	"1.0"
 
 #define FIB_RULE_PREF  1000       /* default preference for FIB rules */
-static bool add_fib_rules = true;
+
+static unsigned int vrf_net_id;
 
 struct net_vrf {
 	struct rtable __rcu	*rth;
@@ -1237,6 +1239,8 @@ static int vrf_newlink(struct net *src_n
 		       struct nlattr *tb[], struct nlattr *data[])
 {
 	struct net_vrf *vrf = netdev_priv(dev);
+	bool *add_fib_rules;
+	struct net *net;
 	int err;
 
 	if (!data || !data[IFLA_VRF_TABLE])
@@ -1252,13 +1256,15 @@ static int vrf_newlink(struct net *src_n
 	if (err)
 		goto out;
 
-	if (add_fib_rules) {
+	net = dev_net(dev);
+	add_fib_rules = net_generic(net, vrf_net_id);
+	if (*add_fib_rules) {
 		err = vrf_add_fib_rules(dev);
 		if (err) {
 			unregister_netdevice(dev);
 			goto out;
 		}
-		add_fib_rules = false;
+		*add_fib_rules = false;
 	}
 
 out:
@@ -1341,16 +1347,38 @@ static struct notifier_block vrf_notifie
 	.notifier_call = vrf_device_event,
 };
 
+/* Initialize per network namespace state */
+static int __net_init vrf_netns_init(struct net *net)
+{
+	bool *add_fib_rules = net_generic(net, vrf_net_id);
+
+	*add_fib_rules = true;
+
+	return 0;
+}
+
+static struct pernet_operations vrf_net_ops __net_initdata = {
+	.init = vrf_netns_init,
+	.id   = &vrf_net_id,
+	.size = sizeof(bool),
+};
+
 static int __init vrf_init_module(void)
 {
 	int rc;
 
 	register_netdevice_notifier(&vrf_notifier_block);
 
-	rc = rtnl_link_register(&vrf_link_ops);
+	rc = register_pernet_subsys(&vrf_net_ops);
 	if (rc < 0)
 		goto error;
 
+	rc = rtnl_link_register(&vrf_link_ops);
+	if (rc < 0) {
+		unregister_pernet_subsys(&vrf_net_ops);
+		goto error;
+	}
+
 	return 0;
 
 error:
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/net/vxlan.c linux-libre-4.9.36-gnu/drivers/net/vxlan.c
--- linux-libre-4.9.35-gnu/drivers/net/vxlan.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/net/vxlan.c	2017-07-05 08:40:44.000000000 -0400
@@ -2285,7 +2285,7 @@ static void vxlan_cleanup(unsigned long
 				= container_of(p, struct vxlan_fdb, hlist);
 			unsigned long timeout;
 
-			if (f->state & NUD_PERMANENT)
+			if (f->state & (NUD_PERMANENT | NUD_NOARP))
 				continue;
 
 			timeout = f->used + vxlan->cfg.age_interval * HZ;
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c linux-libre-4.9.36-gnu/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
--- linux-libre-4.9.35-gnu/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c	2017-07-05 08:40:44.000000000 -0400
@@ -5913,7 +5913,6 @@ static int brcmf_construct_chaninfo(stru
 	u32 i, j;
 	u32 total;
 	u32 chaninfo;
-	u32 index;
 
 	pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);
 
@@ -5961,33 +5960,36 @@ static int brcmf_construct_chaninfo(stru
 		    ch.bw == BRCMU_CHAN_BW_80)
 			continue;
 
-		channel = band->channels;
-		index = band->n_channels;
+		channel = NULL;
 		for (j = 0; j < band->n_channels; j++) {
-			if (channel[j].hw_value == ch.control_ch_num) {
-				index = j;
+			if (band->channels[j].hw_value == ch.control_ch_num) {
+				channel = &band->channels[j];
 				break;
 			}
 		}
-		channel[index].center_freq =
-			ieee80211_channel_to_frequency(ch.control_ch_num,
-						       band->band);
-		channel[index].hw_value = ch.control_ch_num;
+		if (!channel) {
+			/* It seems firmware supports some channel we never
+			 * considered. Something new in IEEE standard?
+			 */
+			brcmf_err("Ignoring unexpected firmware channel %d\n",
+				  ch.control_ch_num);
+			continue;
+		}
 
 		/* assuming the chanspecs order is HT20,
 		 * HT40 upper, HT40 lower, and VHT80.
 		 */
 		if (ch.bw == BRCMU_CHAN_BW_80) {
-			channel[index].flags &= ~IEEE80211_CHAN_NO_80MHZ;
+			channel->flags &= ~IEEE80211_CHAN_NO_80MHZ;
 		} else if (ch.bw == BRCMU_CHAN_BW_40) {
-			brcmf_update_bw40_channel_flag(&channel[index], &ch);
+			brcmf_update_bw40_channel_flag(channel, &ch);
 		} else {
 			/* enable the channel and disable other bandwidths
 			 * for now as mentioned order assure they are enabled
 			 * for subsequent chanspecs.
 			 */
-			channel[index].flags = IEEE80211_CHAN_NO_HT40 |
-					       IEEE80211_CHAN_NO_80MHZ;
+			channel->flags = IEEE80211_CHAN_NO_HT40 |
+					 IEEE80211_CHAN_NO_80MHZ;
 			ch.bw = BRCMU_CHAN_BW_20;
 			cfg->d11inf.encchspec(&ch);
 			chaninfo = ch.chspec;
@@ -5995,11 +5997,11 @@ static int brcmf_construct_chaninfo(stru
 						       &chaninfo);
 			if (!err) {
 				if (chaninfo & WL_CHAN_RADAR)
-					channel[index].flags |=
+					channel->flags |=
 						(IEEE80211_CHAN_RADAR |
 						 IEEE80211_CHAN_NO_IR);
 				if (chaninfo & WL_CHAN_PASSIVE)
-					channel[index].flags |=
+					channel->flags |=
 						IEEE80211_CHAN_NO_IR;
 			}
 		}
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/net/wireless/intel/iwlwifi/mvm/tt.c linux-libre-4.9.36-gnu/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
--- linux-libre-4.9.35-gnu/drivers/net/wireless/intel/iwlwifi/mvm/tt.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/net/wireless/intel/iwlwifi/mvm/tt.c	2017-07-05 08:40:44.000000000 -0400
@@ -843,8 +843,10 @@ static void iwl_mvm_thermal_zone_unregis
 		return;
 
 	IWL_DEBUG_TEMP(mvm, "Thermal zone device unregister\n");
-	thermal_zone_device_unregister(mvm->tz_device.tzone);
-	mvm->tz_device.tzone = NULL;
+	if (mvm->tz_device.tzone) {
+		thermal_zone_device_unregister(mvm->tz_device.tzone);
+		mvm->tz_device.tzone = NULL;
+	}
 }
 
 static void iwl_mvm_cooling_device_unregister(struct iwl_mvm *mvm)
@@ -853,8 +855,10 @@ static void iwl_mvm_cooling_device_unreg
 		return;
 
 	IWL_DEBUG_TEMP(mvm, "Cooling device unregister\n");
-	thermal_cooling_device_unregister(mvm->cooling_dev.cdev);
-	mvm->cooling_dev.cdev = NULL;
+	if (mvm->cooling_dev.cdev) {
+		thermal_cooling_device_unregister(mvm->cooling_dev.cdev);
+		mvm->cooling_dev.cdev = NULL;
+	}
 }
 #endif /* CONFIG_THERMAL */
 
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/net/xen-netback/interface.c linux-libre-4.9.36-gnu/drivers/net/xen-netback/interface.c
--- linux-libre-4.9.35-gnu/drivers/net/xen-netback/interface.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/net/xen-netback/interface.c	2017-07-05 08:40:44.000000000 -0400
@@ -221,18 +221,18 @@ static struct net_device_stats *xenvif_g
 {
 	struct xenvif *vif = netdev_priv(dev);
 	struct xenvif_queue *queue = NULL;
-	unsigned int num_queues = vif->num_queues;
 	unsigned long rx_bytes = 0;
 	unsigned long rx_packets = 0;
 	unsigned long tx_bytes = 0;
 	unsigned long tx_packets = 0;
 	unsigned int index;
 
+	spin_lock(&vif->lock);
 	if (vif->queues == NULL)
 		goto out;
 
 	/* Aggregate tx and rx stats from each queue */
-	for (index = 0; index < num_queues; ++index) {
+	for (index = 0; index < vif->num_queues; ++index) {
 		queue = &vif->queues[index];
 		rx_bytes += queue->stats.rx_bytes;
 		rx_packets += queue->stats.rx_packets;
@@ -241,6 +241,8 @@ static struct net_device_stats *xenvif_g
 	}
 
 out:
+	spin_unlock(&vif->lock);
+
 	vif->dev->stats.rx_bytes = rx_bytes;
 	vif->dev->stats.rx_packets = rx_packets;
 	vif->dev->stats.tx_bytes = tx_bytes;
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/net/xen-netback/xenbus.c linux-libre-4.9.36-gnu/drivers/net/xen-netback/xenbus.c
--- linux-libre-4.9.35-gnu/drivers/net/xen-netback/xenbus.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/net/xen-netback/xenbus.c	2017-07-05 08:40:44.000000000 -0400
@@ -493,11 +493,22 @@ static int backend_create_xenvif(struct
 static void backend_disconnect(struct backend_info *be)
 {
 	if (be->vif) {
+		unsigned int queue_index;
+
 		xen_unregister_watchers(be->vif);
 #ifdef CONFIG_DEBUG_FS
 		xenvif_debugfs_delif(be->vif);
 #endif /* CONFIG_DEBUG_FS */
 		xenvif_disconnect_data(be->vif);
+		for (queue_index = 0; queue_index < be->vif->num_queues; ++queue_index)
+			xenvif_deinit_queue(&be->vif->queues[queue_index]);
+
+		spin_lock(&be->vif->lock);
+		vfree(be->vif->queues);
+		be->vif->num_queues = 0;
+		be->vif->queues = NULL;
+		spin_unlock(&be->vif->lock);
+
 		xenvif_disconnect_ctrl(be->vif);
 	}
 }
@@ -1040,6 +1051,8 @@ static void connect(struct backend_info
 err:
 	if (be->vif->num_queues > 0)
 		xenvif_disconnect_data(be->vif); /* Clean up existing queues */
+	for (queue_index = 0; queue_index < be->vif->num_queues; ++queue_index)
+		xenvif_deinit_queue(&be->vif->queues[queue_index]);
 	vfree(be->vif->queues);
 	be->vif->queues = NULL;
 	be->vif->num_queues = 0;
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/net/xen-netfront.c linux-libre-4.9.36-gnu/drivers/net/xen-netfront.c
--- linux-libre-4.9.35-gnu/drivers/net/xen-netfront.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/net/xen-netfront.c	2017-07-05 08:40:44.000000000 -0400
@@ -321,7 +321,7 @@ static void xennet_alloc_rx_buffers(stru
 	queue->rx.req_prod_pvt = req_prod;
 
 	/* Not enough requests? Try again later. */
-	if (req_prod - queue->rx.rsp_cons < NET_RX_SLOTS_MIN) {
+	if (req_prod - queue->rx.sring->req_prod < NET_RX_SLOTS_MIN) {
 		mod_timer(&queue->rx_refill_timer, jiffies + (HZ/10));
 		return;
 	}
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/nvdimm/pmem.c linux-libre-4.9.36-gnu/drivers/nvdimm/pmem.c
--- linux-libre-4.9.35-gnu/drivers/nvdimm/pmem.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/nvdimm/pmem.c	2017-07-05 08:40:44.000000000 -0400
@@ -87,7 +87,9 @@ static int read_pmem(struct page *page,
 
 	rc = memcpy_from_pmem(mem + off, pmem_addr, len);
 	kunmap_atomic(mem);
-	return rc;
+	if (rc)
+		return -EIO;
+	return 0;
 }
 
 static int pmem_do_bvec(struct pmem_device *pmem, struct page *page,
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/pinctrl/intel/pinctrl-intel.c linux-libre-4.9.36-gnu/drivers/pinctrl/intel/pinctrl-intel.c
--- linux-libre-4.9.35-gnu/drivers/pinctrl/intel/pinctrl-intel.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/pinctrl/intel/pinctrl-intel.c	2017-07-05 08:40:44.000000000 -0400
@@ -353,6 +353,21 @@ static int intel_pinmux_set_mux(struct p
 	return 0;
 }
 
+static void __intel_gpio_set_direction(void __iomem *padcfg0, bool input)
+{
+	u32 value;
+
+	value = readl(padcfg0);
+	if (input) {
+		value &= ~PADCFG0_GPIORXDIS;
+		value |= PADCFG0_GPIOTXDIS;
+	} else {
+		value &= ~PADCFG0_GPIOTXDIS;
+		value |= PADCFG0_GPIORXDIS;
+	}
+	writel(value, padcfg0);
+}
+
 static int intel_gpio_request_enable(struct pinctrl_dev *pctldev,
 				     struct pinctrl_gpio_range *range,
 				     unsigned pin)
@@ -375,11 +390,11 @@ static int intel_gpio_request_enable(str
 	/* Disable SCI/SMI/NMI generation */
 	value &= ~(PADCFG0_GPIROUTIOXAPIC | PADCFG0_GPIROUTSCI);
 	value &= ~(PADCFG0_GPIROUTSMI | PADCFG0_GPIROUTNMI);
-	/* Disable TX buffer and enable RX (this will be input) */
-	value &= ~PADCFG0_GPIORXDIS;
-	value |= PADCFG0_GPIOTXDIS;
 	writel(value, padcfg0);
 
+	/* Disable TX buffer and enable RX (this will be input) */
+	__intel_gpio_set_direction(padcfg0, true);
+
 	raw_spin_unlock_irqrestore(&pctrl->lock, flags);
 
 	return 0;
@@ -392,18 +407,11 @@ static int intel_gpio_set_direction(stru
 	struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
 	void __iomem *padcfg0;
 	unsigned long flags;
-	u32 value;
 
 	raw_spin_lock_irqsave(&pctrl->lock, flags);
 
 	padcfg0 = intel_get_padcfg(pctrl, pin, PADCFG0);
-
-	value = readl(padcfg0);
-	if (input)
-		value |= PADCFG0_GPIOTXDIS;
-	else
-		value &= ~PADCFG0_GPIOTXDIS;
-	writel(value, padcfg0);
+	__intel_gpio_set_direction(padcfg0, input);
 
 	raw_spin_unlock_irqrestore(&pctrl->lock, flags);
 
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/platform/x86/ideapad-laptop.c linux-libre-4.9.36-gnu/drivers/platform/x86/ideapad-laptop.c
--- linux-libre-4.9.35-gnu/drivers/platform/x86/ideapad-laptop.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/platform/x86/ideapad-laptop.c	2017-07-05 08:40:44.000000000 -0400
@@ -813,6 +813,7 @@ static void ideapad_acpi_notify(acpi_han
 			case 8:
 			case 7:
 			case 6:
+			case 1:
 				ideapad_input_report(priv, vpc_bit);
 				break;
 			case 5:
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/regulator/tps65086-regulator.c linux-libre-4.9.36-gnu/drivers/regulator/tps65086-regulator.c
--- linux-libre-4.9.35-gnu/drivers/regulator/tps65086-regulator.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/regulator/tps65086-regulator.c	2017-07-05 08:40:44.000000000 -0400
@@ -156,19 +156,19 @@ static struct tps65086_regulator regulat
 			   VDOA23_VID_MASK, TPS65086_LDOA3CTRL, BIT(0),
 			   tps65086_ldoa23_ranges, 0, 0),
 	TPS65086_SWITCH("SWA1", "swa1", SWA1, TPS65086_SWVTT_EN, BIT(5)),
-	TPS65086_SWITCH("SWB1", "swa2", SWB1, TPS65086_SWVTT_EN, BIT(6)),
-	TPS65086_SWITCH("SWB2", "swa3", SWB2, TPS65086_SWVTT_EN, BIT(7)),
+	TPS65086_SWITCH("SWB1", "swb1", SWB1, TPS65086_SWVTT_EN, BIT(6)),
+	TPS65086_SWITCH("SWB2", "swb2", SWB2, TPS65086_SWVTT_EN, BIT(7)),
 	TPS65086_SWITCH("VTT", "vtt", VTT, TPS65086_SWVTT_EN, BIT(4)),
 };
 
-static int tps65086_of_parse_cb(struct device_node *dev,
+static int tps65086_of_parse_cb(struct device_node *node,
 				const struct regulator_desc *desc,
 				struct regulator_config *config)
 {
 	int ret;
 
 	/* Check for 25mV step mode */
-	if (of_property_read_bool(config->of_node, "ti,regulator-step-size-25mv")) {
+	if (of_property_read_bool(node, "ti,regulator-step-size-25mv")) {
 		switch (desc->id) {
 		case BUCK1:
 		case BUCK2:
@@ -192,7 +192,7 @@ static int tps65086_of_parse_cb(struct d
 	}
 
 	/* Check for decay mode */
-	if (desc->id <= BUCK6 && of_property_read_bool(config->of_node, "ti,regulator-decay")) {
+	if (desc->id <= BUCK6 && of_property_read_bool(node, "ti,regulator-decay")) {
 		ret = regmap_write_bits(config->regmap,
 					regulators[desc->id].decay_reg,
 					regulators[desc->id].decay_mask,
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/scsi/lpfc/lpfc_els.c linux-libre-4.9.36-gnu/drivers/scsi/lpfc/lpfc_els.c
--- linux-libre-4.9.35-gnu/drivers/scsi/lpfc/lpfc_els.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/scsi/lpfc/lpfc_els.c	2017-07-05 08:40:44.000000000 -0400
@@ -3590,12 +3590,14 @@ lpfc_els_free_iocb(struct lpfc_hba *phba
 		} else {
 			buf_ptr1 = (struct lpfc_dmabuf *) elsiocb->context2;
 			lpfc_els_free_data(phba, buf_ptr1);
+			elsiocb->context2 = NULL;
 		}
 	}
 
 	if (elsiocb->context3) {
 		buf_ptr = (struct lpfc_dmabuf *) elsiocb->context3;
 		lpfc_els_free_bpl(phba, buf_ptr);
+		elsiocb->context3 = NULL;
 	}
 	lpfc_sli_release_iocbq(phba, elsiocb);
 	return 0;
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/scsi/lpfc/lpfc_sli.c linux-libre-4.9.36-gnu/drivers/scsi/lpfc/lpfc_sli.c
--- linux-libre-4.9.35-gnu/drivers/scsi/lpfc/lpfc_sli.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/scsi/lpfc/lpfc_sli.c	2017-07-05 08:40:44.000000000 -0400
@@ -5951,18 +5951,25 @@ lpfc_sli4_alloc_resource_identifiers(str
 
  free_vfi_bmask:
 	kfree(phba->sli4_hba.vfi_bmask);
+	phba->sli4_hba.vfi_bmask = NULL;
  free_xri_ids:
 	kfree(phba->sli4_hba.xri_ids);
+	phba->sli4_hba.xri_ids = NULL;
  free_xri_bmask:
 	kfree(phba->sli4_hba.xri_bmask);
+	phba->sli4_hba.xri_bmask = NULL;
  free_vpi_ids:
 	kfree(phba->vpi_ids);
+	phba->vpi_ids = NULL;
  free_vpi_bmask:
 	kfree(phba->vpi_bmask);
+	phba->vpi_bmask = NULL;
  free_rpi_ids:
 	kfree(phba->sli4_hba.rpi_ids);
+	phba->sli4_hba.rpi_ids = NULL;
  free_rpi_bmask:
 	kfree(phba->sli4_hba.rpi_bmask);
+	phba->sli4_hba.rpi_bmask = NULL;
  err_exit:
 	return rc;
 }
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/scsi/qla2xxx/qla_def.h linux-libre-4.9.36-gnu/drivers/scsi/qla2xxx/qla_def.h
--- linux-libre-4.9.35-gnu/drivers/scsi/qla2xxx/qla_def.h	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/scsi/qla2xxx/qla_def.h	2017-07-05 08:40:44.000000000 -0400
@@ -1555,7 +1555,8 @@ typedef struct {
 struct atio {
 	uint8_t		entry_type;		/* Entry type. */
 	uint8_t		entry_count;		/* Entry count. */
-	uint8_t		data[58];
+	__le16		attr_n_length;
+	uint8_t		data[56];
 	uint32_t	signature;
 #define ATIO_PROCESSED 0xDEADDEAD		/* Signature */
 };
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/scsi/qla2xxx/qla_isr.c linux-libre-4.9.36-gnu/drivers/scsi/qla2xxx/qla_isr.c
--- linux-libre-4.9.35-gnu/drivers/scsi/qla2xxx/qla_isr.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/scsi/qla2xxx/qla_isr.c	2017-07-05 08:40:44.000000000 -0400
@@ -2487,6 +2487,10 @@ qla2x00_error_entry(scsi_qla_host_t *vha
 	if (pkt->entry_status & RF_BUSY)
 		res = DID_BUS_BUSY << 16;
 
+	if (pkt->entry_type == NOTIFY_ACK_TYPE &&
+	    pkt->handle == QLA_TGT_SKIP_HANDLE)
+		return;
+
 	sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
 	if (sp) {
 		sp->done(ha, sp, res);
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/scsi/qla2xxx/qla_target.c linux-libre-4.9.36-gnu/drivers/scsi/qla2xxx/qla_target.c
--- linux-libre-4.9.35-gnu/drivers/scsi/qla2xxx/qla_target.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/scsi/qla2xxx/qla_target.c	2017-07-05 08:40:44.000000000 -0400
@@ -3067,7 +3067,7 @@ static int __qlt_send_term_imm_notif(str
 
 	pkt->entry_type = NOTIFY_ACK_TYPE;
 	pkt->entry_count = 1;
-	pkt->handle = QLA_TGT_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK;
+	pkt->handle = QLA_TGT_SKIP_HANDLE;
 
 	nack = (struct nack_to_isp *)pkt;
 	nack->ox_id = ntfy->ox_id;
@@ -6463,12 +6463,29 @@ qlt_24xx_process_atio_queue(struct scsi_
 	if (!vha->flags.online)
 		return;
 
-	while (ha->tgt.atio_ring_ptr->signature != ATIO_PROCESSED) {
+	while ((ha->tgt.atio_ring_ptr->signature != ATIO_PROCESSED) ||
+	    fcpcmd_is_corrupted(ha->tgt.atio_ring_ptr)) {
 		pkt = (struct atio_from_isp *)ha->tgt.atio_ring_ptr;
 		cnt = pkt->u.raw.entry_count;
 
-		qlt_24xx_atio_pkt_all_vps(vha, (struct atio_from_isp *)pkt,
-		    ha_locked);
+		if (unlikely(fcpcmd_is_corrupted(ha->tgt.atio_ring_ptr))) {
+			/*
+			 * This packet is corrupted. The header + payload
+			 * can not be trusted. There is no point in passing
+			 * it further up.
+			 */
+			ql_log(ql_log_warn, vha, 0xffff,
+			    "corrupted fcp frame SID[%3phN] OXID[%04x] EXCG[%x] %64phN\n",
+			    pkt->u.isp24.fcp_hdr.s_id,
+			    be16_to_cpu(pkt->u.isp24.fcp_hdr.ox_id),
+			    le32_to_cpu(pkt->u.isp24.exchange_addr), pkt);
+
+			adjust_corrupted_atio(pkt);
+			qlt_send_term_exchange(vha, NULL, pkt, ha_locked, 0);
+		} else {
+			qlt_24xx_atio_pkt_all_vps(vha,
+			    (struct atio_from_isp *)pkt, ha_locked);
+		}
 
 		for (i = 0; i < cnt; i++) {
 			ha->tgt.atio_ring_index++;
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/scsi/qla2xxx/qla_target.h linux-libre-4.9.36-gnu/drivers/scsi/qla2xxx/qla_target.h
--- linux-libre-4.9.35-gnu/drivers/scsi/qla2xxx/qla_target.h	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/scsi/qla2xxx/qla_target.h	2017-07-05 08:40:44.000000000 -0400
@@ -427,13 +427,33 @@ struct atio_from_isp {
 		struct {
 			uint8_t  entry_type;	/* Entry type. */
 			uint8_t  entry_count;	/* Entry count. */
-			uint8_t  data[58];
+			__le16	 attr_n_length;
+#define FCP_CMD_LENGTH_MASK 0x0fff
+#define FCP_CMD_LENGTH_MIN  0x38
+			uint8_t  data[56];
 			uint32_t signature;
 #define ATIO_PROCESSED 0xDEADDEAD		/* Signature */
 		} raw;
 	} u;
 } __packed;
 
+static inline int fcpcmd_is_corrupted(struct atio *atio)
+{
+	if (atio->entry_type == ATIO_TYPE7 &&
+	    (le16_to_cpu(atio->attr_n_length & FCP_CMD_LENGTH_MASK) <
+	    FCP_CMD_LENGTH_MIN))
+		return 1;
+	else
+		return 0;
+}
+
+/* adjust corrupted atio so we won't trip over the same entry again. */
+static inline void adjust_corrupted_atio(struct atio_from_isp *atio)
+{
+	atio->u.raw.attr_n_length = cpu_to_le16(FCP_CMD_LENGTH_MIN);
+	atio->u.isp24.fcp_cmnd.add_cdb_len = 0;
+}
+
 #define CTIO_TYPE7 0x12 /* Continue target I/O entry (for 24xx) */
 
 /*
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/scsi/sd.c linux-libre-4.9.36-gnu/drivers/scsi/sd.c
--- linux-libre-4.9.35-gnu/drivers/scsi/sd.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/scsi/sd.c	2017-07-05 08:40:44.000000000 -0400
@@ -2572,7 +2572,8 @@ sd_read_cache_type(struct scsi_disk *sdk
 		if (sdp->broken_fua) {
 			sd_first_printk(KERN_NOTICE, sdkp, "Disabling FUA\n");
 			sdkp->DPOFUA = 0;
-		} else if (sdkp->DPOFUA && !sdkp->device->use_10_for_rw) {
+		} else if (sdkp->DPOFUA && !sdkp->device->use_10_for_rw &&
+			   !sdkp->device->use_16_for_rw) {
 			sd_first_printk(KERN_NOTICE, sdkp,
 				  "Uses READ/WRITE(6), disabling FUA\n");
 			sdkp->DPOFUA = 0;
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/scsi/virtio_scsi.c linux-libre-4.9.36-gnu/drivers/scsi/virtio_scsi.c
--- linux-libre-4.9.35-gnu/drivers/scsi/virtio_scsi.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/scsi/virtio_scsi.c	2017-07-05 08:40:44.000000000 -0400
@@ -534,7 +534,9 @@ static int virtscsi_queuecommand(struct
 {
 	struct Scsi_Host *shost = virtio_scsi_host(vscsi->vdev);
 	struct virtio_scsi_cmd *cmd = scsi_cmd_priv(sc);
+	unsigned long flags;
 	int req_size;
+	int ret;
 
 	BUG_ON(scsi_sg_count(sc) > shost->sg_tablesize);
 
@@ -562,8 +564,15 @@ static int virtscsi_queuecommand(struct
 		req_size = sizeof(cmd->req.cmd);
 	}
 
-	if (virtscsi_kick_cmd(req_vq, cmd, req_size, sizeof(cmd->resp.cmd)) != 0)
+	ret = virtscsi_kick_cmd(req_vq, cmd, req_size, sizeof(cmd->resp.cmd));
+	if (ret == -EIO) {
+		cmd->resp.cmd.response = VIRTIO_SCSI_S_BAD_TARGET;
+		spin_lock_irqsave(&req_vq->vq_lock, flags);
+		virtscsi_complete_cmd(vscsi, cmd);
+		spin_unlock_irqrestore(&req_vq->vq_lock, flags);
+	} else if (ret != 0) {
 		return SCSI_MLQUEUE_HOST_BUSY;
+	}
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/spi/spi.c linux-libre-4.9.36-gnu/drivers/spi/spi.c
--- linux-libre-4.9.35-gnu/drivers/spi/spi.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/spi/spi.c	2017-07-05 08:40:44.000000000 -0400
@@ -621,8 +621,10 @@ void spi_unregister_device(struct spi_de
 	if (!spi)
 		return;
 
-	if (spi->dev.of_node)
+	if (spi->dev.of_node) {
 		of_node_clear_flag(spi->dev.of_node, OF_POPULATED);
+		of_node_put(spi->dev.of_node);
+	}
 	if (ACPI_COMPANION(&spi->dev))
 		acpi_device_clear_enumerated(ACPI_COMPANION(&spi->dev));
 	device_unregister(&spi->dev);
@@ -797,12 +799,12 @@ static int __spi_map_msg(struct spi_mast
 	if (master->dma_tx)
 		tx_dev = master->dma_tx->device->dev;
 	else
-		tx_dev = &master->dev;
+		tx_dev = master->dev.parent;
 
 	if (master->dma_rx)
 		rx_dev = master->dma_rx->device->dev;
 	else
-		rx_dev = &master->dev;
+		rx_dev = master->dev.parent;
 
 	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
 		if (!master->can_dma(master, msg->spi, xfer))
@@ -844,12 +846,12 @@ static int __spi_unmap_msg(struct spi_ma
 	if (master->dma_tx)
 		tx_dev = master->dma_tx->device->dev;
 	else
-		tx_dev = &master->dev;
+		tx_dev = master->dev.parent;
 
 	if (master->dma_rx)
 		rx_dev = master->dma_rx->device->dev;
 	else
-		rx_dev = &master->dev;
+		rx_dev = master->dev.parent;
 
 	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
 		if (!master->can_dma(master, msg->spi, xfer))
@@ -1589,11 +1591,13 @@ of_register_spi_device(struct spi_master
 	if (rc) {
 		dev_err(&master->dev, "spi_device register error %s\n",
 			nc->full_name);
-		goto err_out;
+		goto err_of_node_put;
 	}
 
 	return spi;
 
+err_of_node_put:
+	of_node_put(nc);
 err_out:
 	spi_dev_put(spi);
 	return ERR_PTR(rc);
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/spi/spi-davinci.c linux-libre-4.9.36-gnu/drivers/spi/spi-davinci.c
--- linux-libre-4.9.35-gnu/drivers/spi/spi-davinci.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/spi/spi-davinci.c	2017-07-05 08:40:44.000000000 -0400
@@ -646,7 +646,7 @@ static int davinci_spi_bufs(struct spi_d
 			buf = t->rx_buf;
 		t->rx_dma = dma_map_single(&spi->dev, buf,
 				t->len, DMA_FROM_DEVICE);
-		if (!t->rx_dma) {
+		if (dma_mapping_error(&spi->dev, !t->rx_dma)) {
 			ret = -EFAULT;
 			goto err_rx_map;
 		}
@@ -660,7 +660,7 @@ static int davinci_spi_bufs(struct spi_d
 			buf = (void *)t->tx_buf;
 		t->tx_dma = dma_map_single(&spi->dev, buf,
 				t->len, DMA_TO_DEVICE);
-		if (!t->tx_dma) {
+		if (dma_mapping_error(&spi->dev, t->tx_dma)) {
 			ret = -EFAULT;
 			goto err_tx_map;
 		}
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/usb/dwc2/gadget.c linux-libre-4.9.36-gnu/drivers/usb/dwc2/gadget.c
--- linux-libre-4.9.35-gnu/drivers/usb/dwc2/gadget.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/usb/dwc2/gadget.c	2017-07-05 08:40:44.000000000 -0400
@@ -2532,7 +2532,7 @@ void dwc2_hsotg_core_init_disconnected(s
 	/* keep other bits untouched (so e.g. forced modes are not lost) */
 	usbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
 	usbcfg &= ~(GUSBCFG_TOUTCAL_MASK | GUSBCFG_PHYIF16 | GUSBCFG_SRPCAP |
-		GUSBCFG_HNPCAP);
+		GUSBCFG_HNPCAP | GUSBCFG_USBTRDTIM_MASK);
 
 	/* set the PLL on, remove the HNP/SRP and set the PHY */
 	val = (hsotg->phyif == GUSBCFG_PHYIF8) ? 9 : 5;
@@ -3403,7 +3403,7 @@ static void dwc2_hsotg_init(struct dwc2_
 	/* keep other bits untouched (so e.g. forced modes are not lost) */
 	usbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
 	usbcfg &= ~(GUSBCFG_TOUTCAL_MASK | GUSBCFG_PHYIF16 | GUSBCFG_SRPCAP |
-		GUSBCFG_HNPCAP);
+		GUSBCFG_HNPCAP | GUSBCFG_USBTRDTIM_MASK);
 
 	/* set the PLL on, remove the HNP/SRP and set the PHY */
 	trdtim = (hsotg->phyif == GUSBCFG_PHYIF8) ? 9 : 5;
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/usb/gadget/function/f_fs.c linux-libre-4.9.36-gnu/drivers/usb/gadget/function/f_fs.c
--- linux-libre-4.9.35-gnu/drivers/usb/gadget/function/f_fs.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/usb/gadget/function/f_fs.c	2017-07-05 08:40:44.000000000 -0400
@@ -3688,6 +3688,7 @@ static void ffs_closed(struct ffs_data *
 {
 	struct ffs_dev *ffs_obj;
 	struct f_fs_opts *opts;
+	struct config_item *ci;
 
 	ENTER();
 	ffs_dev_lock();
@@ -3711,8 +3712,11 @@ static void ffs_closed(struct ffs_data *
 	    || !atomic_read(&opts->func_inst.group.cg_item.ci_kref.refcount))
 		goto done;
 
-	unregister_gadget_item(ffs_obj->opts->
-			       func_inst.group.cg_item.ci_parent->ci_parent);
+	ci = opts->func_inst.group.cg_item.ci_parent->ci_parent;
+	ffs_dev_unlock();
+
+	unregister_gadget_item(ci);
+	return;
 done:
 	ffs_dev_unlock();
 }
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/vfio/vfio_iommu_spapr_tce.c linux-libre-4.9.36-gnu/drivers/vfio/vfio_iommu_spapr_tce.c
--- linux-libre-4.9.35-gnu/drivers/vfio/vfio_iommu_spapr_tce.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/vfio/vfio_iommu_spapr_tce.c	2017-07-05 08:40:44.000000000 -0400
@@ -1292,6 +1292,10 @@ static int tce_iommu_attach_group(void *
 	/* pr_debug("tce_vfio: Attaching group #%u to iommu %p\n",
 			iommu_group_id(iommu_group), iommu_group); */
 	table_group = iommu_group_get_iommudata(iommu_group);
+	if (!table_group) {
+		ret = -ENODEV;
+		goto unlock_exit;
+	}
 
 	if (tce_groups_attached(container) && (!table_group->ops ||
 			!table_group->ops->take_ownership ||
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/watchdog/bcm_kona_wdt.c linux-libre-4.9.36-gnu/drivers/watchdog/bcm_kona_wdt.c
--- linux-libre-4.9.35-gnu/drivers/watchdog/bcm_kona_wdt.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/watchdog/bcm_kona_wdt.c	2017-07-05 08:40:44.000000000 -0400
@@ -304,6 +304,8 @@ static int bcm_kona_wdt_probe(struct pla
 	if (!wdt)
 		return -ENOMEM;
 
+	spin_lock_init(&wdt->lock);
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	wdt->base = devm_ioremap_resource(dev, res);
 	if (IS_ERR(wdt->base))
@@ -316,7 +318,6 @@ static int bcm_kona_wdt_probe(struct pla
 		return ret;
 	}
 
-	spin_lock_init(&wdt->lock);
 	platform_set_drvdata(pdev, wdt);
 	watchdog_set_drvdata(&bcm_kona_wdt_wdd, wdt);
 	bcm_kona_wdt_wdd.parent = &pdev->dev;
diff -druNp --no-dereference linux-libre-4.9.35-gnu/drivers/xen/swiotlb-xen.c linux-libre-4.9.36-gnu/drivers/xen/swiotlb-xen.c
--- linux-libre-4.9.35-gnu/drivers/xen/swiotlb-xen.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/drivers/xen/swiotlb-xen.c	2017-07-05 08:40:44.000000000 -0400
@@ -409,9 +409,9 @@ dma_addr_t xen_swiotlb_map_page(struct d
 	if (map == SWIOTLB_MAP_ERROR)
 		return DMA_ERROR_CODE;
 
+	dev_addr = xen_phys_to_bus(map);
 	xen_dma_map_page(dev, pfn_to_page(map >> PAGE_SHIFT),
 					dev_addr, map & ~PAGE_MASK, size, dir, attrs);
-	dev_addr = xen_phys_to_bus(map);
 
 	/*
 	 * Ensure that the address returned is DMA'ble
@@ -567,13 +567,14 @@ xen_swiotlb_map_sg_attrs(struct device *
 				sg_dma_len(sgl) = 0;
 				return 0;
 			}
+			dev_addr = xen_phys_to_bus(map);
 			xen_dma_map_page(hwdev, pfn_to_page(map >> PAGE_SHIFT),
 						dev_addr,
 						map & ~PAGE_MASK,
 						sg->length,
 						dir,
 						attrs);
-			sg->dma_address = xen_phys_to_bus(map);
+			sg->dma_address = dev_addr;
 		} else {
 			/* we are not interested in the dma_addr returned by
 			 * xen_dma_map_page, only in the potential cache flushes executed
diff -druNp --no-dereference linux-libre-4.9.35-gnu/fs/aio.c linux-libre-4.9.36-gnu/fs/aio.c
--- linux-libre-4.9.35-gnu/fs/aio.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/fs/aio.c	2017-07-05 08:40:44.000000000 -0400
@@ -1085,7 +1085,8 @@ static void aio_complete(struct kiocb *k
 		 * Tell lockdep we inherited freeze protection from submission
 		 * thread.
 		 */
-		__sb_writers_acquired(file_inode(file)->i_sb, SB_FREEZE_WRITE);
+		if (S_ISREG(file_inode(file)->i_mode))
+			__sb_writers_acquired(file_inode(file)->i_sb, SB_FREEZE_WRITE);
 		file_end_write(file);
 	}
 
@@ -1492,7 +1493,8 @@ static ssize_t aio_write(struct kiocb *r
 		 * by telling it the lock got released so that it doesn't
 		 * complain about held lock when we return to userspace.
 		 */
-		__sb_writers_release(file_inode(file)->i_sb, SB_FREEZE_WRITE);
+		if (S_ISREG(file_inode(file)->i_mode))
+			__sb_writers_release(file_inode(file)->i_sb, SB_FREEZE_WRITE);
 	}
 	kfree(iovec);
 	return ret;
diff -druNp --no-dereference linux-libre-4.9.35-gnu/fs/binfmt_elf.c linux-libre-4.9.36-gnu/fs/binfmt_elf.c
--- linux-libre-4.9.35-gnu/fs/binfmt_elf.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/fs/binfmt_elf.c	2017-07-05 08:40:44.000000000 -0400
@@ -2296,6 +2296,7 @@ static int elf_core_dump(struct coredump
 				goto end_coredump;
 		}
 	}
+	dump_truncate(cprm);
 
 	if (!elf_core_write_extra_data(cprm))
 		goto end_coredump;
diff -druNp --no-dereference linux-libre-4.9.35-gnu/fs/btrfs/inode.c linux-libre-4.9.36-gnu/fs/btrfs/inode.c
--- linux-libre-4.9.35-gnu/fs/btrfs/inode.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/fs/btrfs/inode.c	2017-07-05 08:40:44.000000000 -0400
@@ -4480,8 +4480,19 @@ search_again:
 		if (found_type > min_type) {
 			del_item = 1;
 		} else {
-			if (item_end < new_size)
+			if (item_end < new_size) {
+				/*
+				 * With NO_HOLES mode, for the following mapping
+				 *
+				 * [0-4k][hole][8k-12k]
+				 *
+				 * if truncating isize down to 6k, it ends up
+				 * isize being 8k.
+				 */
+				if (btrfs_fs_incompat(root->fs_info, NO_HOLES))
+					last_size = new_size;
 				break;
+			}
 			if (found_key.offset >= new_size)
 				del_item = 1;
 			else
@@ -7235,7 +7246,6 @@ static struct extent_map *btrfs_create_d
 	struct extent_map *em = NULL;
 	int ret;
 
-	down_read(&BTRFS_I(inode)->dio_sem);
 	if (type != BTRFS_ORDERED_NOCOW) {
 		em = create_pinned_em(inode, start, len, orig_start,
 				      block_start, block_len, orig_block_len,
@@ -7254,7 +7264,6 @@ static struct extent_map *btrfs_create_d
 		em = ERR_PTR(ret);
 	}
  out:
-	up_read(&BTRFS_I(inode)->dio_sem);
 
 	return em;
 }
@@ -8707,6 +8716,7 @@ static ssize_t btrfs_direct_IO(struct ki
 		dio_data.unsubmitted_oe_range_start = (u64)offset;
 		dio_data.unsubmitted_oe_range_end = (u64)offset;
 		current->journal_info = &dio_data;
+		down_read(&BTRFS_I(inode)->dio_sem);
 	} else if (test_bit(BTRFS_INODE_READDIO_NEED_LOCK,
 				     &BTRFS_I(inode)->runtime_flags)) {
 		inode_dio_end(inode);
@@ -8719,6 +8729,7 @@ static ssize_t btrfs_direct_IO(struct ki
 				   iter, btrfs_get_blocks_direct, NULL,
 				   btrfs_submit_direct, flags);
 	if (iov_iter_rw(iter) == WRITE) {
+		up_read(&BTRFS_I(inode)->dio_sem);
 		current->journal_info = NULL;
 		if (ret < 0 && ret != -EIOCBQUEUED) {
 			if (dio_data.reserve)
diff -druNp --no-dereference linux-libre-4.9.35-gnu/fs/coredump.c linux-libre-4.9.36-gnu/fs/coredump.c
--- linux-libre-4.9.35-gnu/fs/coredump.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/fs/coredump.c	2017-07-05 08:40:44.000000000 -0400
@@ -833,3 +833,21 @@ int dump_align(struct coredump_params *c
 	return mod ? dump_skip(cprm, align - mod) : 1;
 }
 EXPORT_SYMBOL(dump_align);
+
+/*
+ * Ensures that file size is big enough to contain the current file
+ * postion. This prevents gdb from complaining about a truncated file
+ * if the last "write" to the file was dump_skip.
+ */
+void dump_truncate(struct coredump_params *cprm)
+{
+	struct file *file = cprm->file;
+	loff_t offset;
+
+	if (file->f_op->llseek && file->f_op->llseek != no_llseek) {
+		offset = file->f_op->llseek(file, 0, SEEK_CUR);
+		if (i_size_read(file->f_mapping->host) < offset)
+			do_truncate(file->f_path.dentry, offset, 0, file);
+	}
+}
+EXPORT_SYMBOL(dump_truncate);
diff -druNp --no-dereference linux-libre-4.9.35-gnu/fs/nfs/callback.c linux-libre-4.9.36-gnu/fs/nfs/callback.c
--- linux-libre-4.9.35-gnu/fs/nfs/callback.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/fs/nfs/callback.c	2017-07-05 08:40:44.000000000 -0400
@@ -279,7 +279,7 @@ static struct svc_serv *nfs_callback_cre
 		printk(KERN_WARNING "nfs_callback_create_svc: no kthread, %d users??\n",
 			cb_info->users);
 
-	serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, sv_ops);
+	serv = svc_create_pooled(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, sv_ops);
 	if (!serv) {
 		printk(KERN_ERR "nfs_callback_create_svc: create service failed\n");
 		return ERR_PTR(-ENOMEM);
diff -druNp --no-dereference linux-libre-4.9.35-gnu/fs/nfs/nfs4proc.c linux-libre-4.9.36-gnu/fs/nfs/nfs4proc.c
--- linux-libre-4.9.35-gnu/fs/nfs/nfs4proc.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/fs/nfs/nfs4proc.c	2017-07-05 08:40:44.000000000 -0400
@@ -2343,8 +2343,6 @@ static int nfs4_opendata_access(struct r
 	if ((mask & ~cache.mask & (MAY_READ | MAY_EXEC)) == 0)
 		return 0;
 
-	/* even though OPEN succeeded, access is denied. Close the file */
-	nfs4_close_state(state, fmode);
 	return -EACCES;
 }
 
@@ -8431,6 +8429,7 @@ static void nfs4_layoutget_release(void
 	size_t max_pages = max_response_pages(server);
 
 	dprintk("--> %s\n", __func__);
+	nfs4_sequence_free_slot(&lgp->res.seq_res);
 	nfs4_free_pages(lgp->args.layout.pages, max_pages);
 	pnfs_put_layout_hdr(NFS_I(inode)->layout);
 	put_nfs_open_context(lgp->args.ctx);
@@ -8505,7 +8504,6 @@ nfs4_proc_layoutget(struct nfs4_layoutge
 	/* if layoutp->len is 0, nfs4_layoutget_prepare called rpc_exit */
 	if (status == 0 && lgp->res.layoutp->len)
 		lseg = pnfs_layout_process(lgp);
-	nfs4_sequence_free_slot(&lgp->res.seq_res);
 	rpc_put_task(task);
 	dprintk("<-- %s status=%d\n", __func__, status);
 	if (status)
diff -druNp --no-dereference linux-libre-4.9.35-gnu/fs/ocfs2/cluster/heartbeat.c linux-libre-4.9.36-gnu/fs/ocfs2/cluster/heartbeat.c
--- linux-libre-4.9.35-gnu/fs/ocfs2/cluster/heartbeat.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/fs/ocfs2/cluster/heartbeat.c	2017-07-05 08:40:44.000000000 -0400
@@ -2242,13 +2242,13 @@ unlock:
 	spin_unlock(&o2hb_live_lock);
 }
 
-static ssize_t o2hb_heartbeat_group_threshold_show(struct config_item *item,
+static ssize_t o2hb_heartbeat_group_dead_threshold_show(struct config_item *item,
 		char *page)
 {
 	return sprintf(page, "%u\n", o2hb_dead_threshold);
 }
 
-static ssize_t o2hb_heartbeat_group_threshold_store(struct config_item *item,
+static ssize_t o2hb_heartbeat_group_dead_threshold_store(struct config_item *item,
 		const char *page, size_t count)
 {
 	unsigned long tmp;
@@ -2297,11 +2297,11 @@ static ssize_t o2hb_heartbeat_group_mode
 
 }
 
-CONFIGFS_ATTR(o2hb_heartbeat_group_, threshold);
+CONFIGFS_ATTR(o2hb_heartbeat_group_, dead_threshold);
 CONFIGFS_ATTR(o2hb_heartbeat_group_, mode);
 
 static struct configfs_attribute *o2hb_heartbeat_group_attrs[] = {
-	&o2hb_heartbeat_group_attr_threshold,
+	&o2hb_heartbeat_group_attr_dead_threshold,
 	&o2hb_heartbeat_group_attr_mode,
 	NULL,
 };
diff -druNp --no-dereference linux-libre-4.9.35-gnu/include/linux/bpf.h linux-libre-4.9.36-gnu/include/linux/bpf.h
--- linux-libre-4.9.35-gnu/include/linux/bpf.h	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/include/linux/bpf.h	2017-07-05 08:40:44.000000000 -0400
@@ -243,6 +243,8 @@ struct bpf_map *bpf_map_inc(struct bpf_m
 void bpf_map_put_with_uref(struct bpf_map *map);
 void bpf_map_put(struct bpf_map *map);
 int bpf_map_precharge_memlock(u32 pages);
+void *bpf_map_area_alloc(size_t size);
+void bpf_map_area_free(void *base);
 
 extern int sysctl_unprivileged_bpf_disabled;
 
diff -druNp --no-dereference linux-libre-4.9.35-gnu/include/linux/coredump.h linux-libre-4.9.36-gnu/include/linux/coredump.h
--- linux-libre-4.9.35-gnu/include/linux/coredump.h	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/include/linux/coredump.h	2017-07-05 08:40:44.000000000 -0400
@@ -14,6 +14,7 @@ struct coredump_params;
 extern int dump_skip(struct coredump_params *cprm, size_t nr);
 extern int dump_emit(struct coredump_params *cprm, const void *addr, int nr);
 extern int dump_align(struct coredump_params *cprm, int align);
+extern void dump_truncate(struct coredump_params *cprm);
 #ifdef CONFIG_COREDUMP
 extern void do_coredump(const siginfo_t *siginfo);
 #else
diff -druNp --no-dereference linux-libre-4.9.35-gnu/include/linux/phy.h linux-libre-4.9.36-gnu/include/linux/phy.h
--- linux-libre-4.9.35-gnu/include/linux/phy.h	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/include/linux/phy.h	2017-07-05 08:40:44.000000000 -0400
@@ -401,6 +401,9 @@ struct phy_device {
 	u32 advertising;
 	u32 lp_advertising;
 
+	/* Energy efficient ethernet modes which should be prohibited */
+	u32 eee_broken_modes;
+
 	int autoneg;
 
 	int link_timeout;
diff -druNp --no-dereference linux-libre-4.9.35-gnu/include/net/xfrm.h linux-libre-4.9.36-gnu/include/net/xfrm.h
--- linux-libre-4.9.35-gnu/include/net/xfrm.h	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/include/net/xfrm.h	2017-07-05 08:40:44.000000000 -0400
@@ -944,10 +944,6 @@ struct xfrm_dst {
 	struct flow_cache_object flo;
 	struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX];
 	int num_pols, num_xfrms;
-#ifdef CONFIG_XFRM_SUB_POLICY
-	struct flowi *origin;
-	struct xfrm_selector *partner;
-#endif
 	u32 xfrm_genid;
 	u32 policy_genid;
 	u32 route_mtu_cached;
@@ -963,12 +959,6 @@ static inline void xfrm_dst_destroy(stru
 	dst_release(xdst->route);
 	if (likely(xdst->u.dst.xfrm))
 		xfrm_state_put(xdst->u.dst.xfrm);
-#ifdef CONFIG_XFRM_SUB_POLICY
-	kfree(xdst->origin);
-	xdst->origin = NULL;
-	kfree(xdst->partner);
-	xdst->partner = NULL;
-#endif
 }
 #endif
 
diff -druNp --no-dereference linux-libre-4.9.35-gnu/include/uapi/linux/ethtool.h linux-libre-4.9.36-gnu/include/uapi/linux/ethtool.h
--- linux-libre-4.9.35-gnu/include/uapi/linux/ethtool.h	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/include/uapi/linux/ethtool.h	2017-07-05 08:40:44.000000000 -0400
@@ -1368,6 +1368,8 @@ enum ethtool_link_mode_bit_indices {
 	ETHTOOL_LINK_MODE_10000baseLR_Full_BIT	= 44,
 	ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT	= 45,
 	ETHTOOL_LINK_MODE_10000baseER_Full_BIT	= 46,
+	ETHTOOL_LINK_MODE_2500baseT_Full_BIT	= 47,
+	ETHTOOL_LINK_MODE_5000baseT_Full_BIT	= 48,
 
 
 	/* Last allowed bit for __ETHTOOL_LINK_MODE_LEGACY_MASK is bit
@@ -1377,7 +1379,7 @@ enum ethtool_link_mode_bit_indices {
 	 */
 
 	__ETHTOOL_LINK_MODE_LAST
-	  = ETHTOOL_LINK_MODE_10000baseER_Full_BIT,
+	  = ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
 };
 
 #define __ETHTOOL_LINK_MODE_LEGACY_MASK(base_name)	\
diff -druNp --no-dereference linux-libre-4.9.35-gnu/kernel/bpf/arraymap.c linux-libre-4.9.36-gnu/kernel/bpf/arraymap.c
--- linux-libre-4.9.35-gnu/kernel/bpf/arraymap.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/kernel/bpf/arraymap.c	2017-07-05 08:40:44.000000000 -0400
@@ -11,7 +11,6 @@
  */
 #include <linux/bpf.h>
 #include <linux/err.h>
-#include <linux/vmalloc.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/filter.h>
@@ -74,14 +73,10 @@ static struct bpf_map *array_map_alloc(u
 	if (array_size >= U32_MAX - PAGE_SIZE)
 		return ERR_PTR(-ENOMEM);
 
-
 	/* allocate all map elements and zero-initialize them */
-	array = kzalloc(array_size, GFP_USER | __GFP_NOWARN);
-	if (!array) {
-		array = vzalloc(array_size);
-		if (!array)
-			return ERR_PTR(-ENOMEM);
-	}
+	array = bpf_map_area_alloc(array_size);
+	if (!array)
+		return ERR_PTR(-ENOMEM);
 
 	/* copy mandatory map attributes */
 	array->map.map_type = attr->map_type;
@@ -97,7 +92,7 @@ static struct bpf_map *array_map_alloc(u
 
 	if (array_size >= U32_MAX - PAGE_SIZE ||
 	    elem_size > PCPU_MIN_UNIT_SIZE || bpf_array_alloc_percpu(array)) {
-		kvfree(array);
+		bpf_map_area_free(array);
 		return ERR_PTR(-ENOMEM);
 	}
 out:
@@ -262,7 +257,7 @@ static void array_map_free(struct bpf_ma
 	if (array->map.map_type == BPF_MAP_TYPE_PERCPU_ARRAY)
 		bpf_array_free_percpu(array);
 
-	kvfree(array);
+	bpf_map_area_free(array);
 }
 
 static const struct bpf_map_ops array_ops = {
@@ -319,7 +314,8 @@ static void fd_array_map_free(struct bpf
 	/* make sure it's empty */
 	for (i = 0; i < array->map.max_entries; i++)
 		BUG_ON(array->ptrs[i] != NULL);
-	kvfree(array);
+
+	bpf_map_area_free(array);
 }
 
 static void *fd_array_map_lookup_elem(struct bpf_map *map, void *key)
diff -druNp --no-dereference linux-libre-4.9.35-gnu/kernel/bpf/hashtab.c linux-libre-4.9.36-gnu/kernel/bpf/hashtab.c
--- linux-libre-4.9.35-gnu/kernel/bpf/hashtab.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/kernel/bpf/hashtab.c	2017-07-05 08:40:44.000000000 -0400
@@ -13,7 +13,6 @@
 #include <linux/bpf.h>
 #include <linux/jhash.h>
 #include <linux/filter.h>
-#include <linux/vmalloc.h>
 #include "percpu_freelist.h"
 
 struct bucket {
@@ -84,14 +83,15 @@ static void htab_free_elems(struct bpf_h
 		free_percpu(pptr);
 	}
 free_elems:
-	vfree(htab->elems);
+	bpf_map_area_free(htab->elems);
 }
 
 static int prealloc_elems_and_freelist(struct bpf_htab *htab)
 {
 	int err = -ENOMEM, i;
 
-	htab->elems = vzalloc(htab->elem_size * htab->map.max_entries);
+	htab->elems = bpf_map_area_alloc(htab->elem_size *
+					 htab->map.max_entries);
 	if (!htab->elems)
 		return -ENOMEM;
 
@@ -227,14 +227,10 @@ static struct bpf_map *htab_map_alloc(un
 		goto free_htab;
 
 	err = -ENOMEM;
-	htab->buckets = kmalloc_array(htab->n_buckets, sizeof(struct bucket),
-				      GFP_USER | __GFP_NOWARN);
-
-	if (!htab->buckets) {
-		htab->buckets = vmalloc(htab->n_buckets * sizeof(struct bucket));
-		if (!htab->buckets)
-			goto free_htab;
-	}
+	htab->buckets = bpf_map_area_alloc(htab->n_buckets *
+					   sizeof(struct bucket));
+	if (!htab->buckets)
+		goto free_htab;
 
 	for (i = 0; i < htab->n_buckets; i++) {
 		INIT_HLIST_HEAD(&htab->buckets[i].head);
@@ -258,7 +254,7 @@ static struct bpf_map *htab_map_alloc(un
 free_extra_elems:
 	free_percpu(htab->extra_elems);
 free_buckets:
-	kvfree(htab->buckets);
+	bpf_map_area_free(htab->buckets);
 free_htab:
 	kfree(htab);
 	return ERR_PTR(err);
@@ -715,7 +711,7 @@ static void htab_map_free(struct bpf_map
 		pcpu_freelist_destroy(&htab->freelist);
 	}
 	free_percpu(htab->extra_elems);
-	kvfree(htab->buckets);
+	bpf_map_area_free(htab->buckets);
 	kfree(htab);
 }
 
diff -druNp --no-dereference linux-libre-4.9.35-gnu/kernel/bpf/stackmap.c linux-libre-4.9.36-gnu/kernel/bpf/stackmap.c
--- linux-libre-4.9.35-gnu/kernel/bpf/stackmap.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/kernel/bpf/stackmap.c	2017-07-05 08:40:44.000000000 -0400
@@ -7,7 +7,6 @@
 #include <linux/bpf.h>
 #include <linux/jhash.h>
 #include <linux/filter.h>
-#include <linux/vmalloc.h>
 #include <linux/stacktrace.h>
 #include <linux/perf_event.h>
 #include "percpu_freelist.h"
@@ -32,7 +31,7 @@ static int prealloc_elems_and_freelist(s
 	u32 elem_size = sizeof(struct stack_map_bucket) + smap->map.value_size;
 	int err;
 
-	smap->elems = vzalloc(elem_size * smap->map.max_entries);
+	smap->elems = bpf_map_area_alloc(elem_size * smap->map.max_entries);
 	if (!smap->elems)
 		return -ENOMEM;
 
@@ -45,7 +44,7 @@ static int prealloc_elems_and_freelist(s
 	return 0;
 
 free_elems:
-	vfree(smap->elems);
+	bpf_map_area_free(smap->elems);
 	return err;
 }
 
@@ -76,12 +75,9 @@ static struct bpf_map *stack_map_alloc(u
 	if (cost >= U32_MAX - PAGE_SIZE)
 		return ERR_PTR(-E2BIG);
 
-	smap = kzalloc(cost, GFP_USER | __GFP_NOWARN);
-	if (!smap) {
-		smap = vzalloc(cost);
-		if (!smap)
-			return ERR_PTR(-ENOMEM);
-	}
+	smap = bpf_map_area_alloc(cost);
+	if (!smap)
+		return ERR_PTR(-ENOMEM);
 
 	err = -E2BIG;
 	cost += n_buckets * (value_size + sizeof(struct stack_map_bucket));
@@ -112,7 +108,7 @@ static struct bpf_map *stack_map_alloc(u
 put_buffers:
 	put_callchain_buffers();
 free_smap:
-	kvfree(smap);
+	bpf_map_area_free(smap);
 	return ERR_PTR(err);
 }
 
@@ -262,9 +258,9 @@ static void stack_map_free(struct bpf_ma
 	/* wait for bpf programs to complete before freeing stack map */
 	synchronize_rcu();
 
-	vfree(smap->elems);
+	bpf_map_area_free(smap->elems);
 	pcpu_freelist_destroy(&smap->freelist);
-	kvfree(smap);
+	bpf_map_area_free(smap);
 	put_callchain_buffers();
 }
 
diff -druNp --no-dereference linux-libre-4.9.35-gnu/kernel/bpf/syscall.c linux-libre-4.9.36-gnu/kernel/bpf/syscall.c
--- linux-libre-4.9.35-gnu/kernel/bpf/syscall.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/kernel/bpf/syscall.c	2017-07-05 08:40:44.000000000 -0400
@@ -12,6 +12,8 @@
 #include <linux/bpf.h>
 #include <linux/syscalls.h>
 #include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/mmzone.h>
 #include <linux/anon_inodes.h>
 #include <linux/file.h>
 #include <linux/license.h>
@@ -48,6 +50,30 @@ void bpf_register_map_type(struct bpf_ma
 	list_add(&tl->list_node, &bpf_map_types);
 }
 
+void *bpf_map_area_alloc(size_t size)
+{
+	/* We definitely need __GFP_NORETRY, so OOM killer doesn't
+	 * trigger under memory pressure as we really just want to
+	 * fail instead.
+	 */
+	const gfp_t flags = __GFP_NOWARN | __GFP_NORETRY | __GFP_ZERO;
+	void *area;
+
+	if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) {
+		area = kmalloc(size, GFP_USER | flags);
+		if (area != NULL)
+			return area;
+	}
+
+	return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM | flags,
+			 PAGE_KERNEL);
+}
+
+void bpf_map_area_free(void *area)
+{
+	kvfree(area);
+}
+
 int bpf_map_precharge_memlock(u32 pages)
 {
 	struct user_struct *user = get_current_user();
diff -druNp --no-dereference linux-libre-4.9.35-gnu/kernel/events/core.c linux-libre-4.9.36-gnu/kernel/events/core.c
--- linux-libre-4.9.35-gnu/kernel/events/core.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/kernel/events/core.c	2017-07-05 08:40:44.000000000 -0400
@@ -2272,7 +2272,7 @@ static int  __perf_install_in_context(vo
 	struct perf_event_context *ctx = event->ctx;
 	struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
 	struct perf_event_context *task_ctx = cpuctx->task_ctx;
-	bool activate = true;
+	bool reprogram = true;
 	int ret = 0;
 
 	raw_spin_lock(&cpuctx->ctx.lock);
@@ -2280,27 +2280,26 @@ static int  __perf_install_in_context(vo
 		raw_spin_lock(&ctx->lock);
 		task_ctx = ctx;
 
-		/* If we're on the wrong CPU, try again */
-		if (task_cpu(ctx->task) != smp_processor_id()) {
-			ret = -ESRCH;
-			goto unlock;
-		}
+		reprogram = (ctx->task == current);
 
 		/*
-		 * If we're on the right CPU, see if the task we target is
-		 * current, if not we don't have to activate the ctx, a future
-		 * context switch will do that for us.
+		 * If the task is running, it must be running on this CPU,
+		 * otherwise we cannot reprogram things.
+		 *
+		 * If its not running, we don't care, ctx->lock will
+		 * serialize against it becoming runnable.
 		 */
-		if (ctx->task != current)
-			activate = false;
-		else
-			WARN_ON_ONCE(cpuctx->task_ctx && cpuctx->task_ctx != ctx);
+		if (task_curr(ctx->task) && !reprogram) {
+			ret = -ESRCH;
+			goto unlock;
+		}
 
+		WARN_ON_ONCE(reprogram && cpuctx->task_ctx && cpuctx->task_ctx != ctx);
 	} else if (task_ctx) {
 		raw_spin_lock(&task_ctx->lock);
 	}
 
-	if (activate) {
+	if (reprogram) {
 		ctx_sched_out(ctx, cpuctx, EVENT_TIME);
 		add_event_to_ctx(event, ctx);
 		ctx_resched(cpuctx, task_ctx);
@@ -2351,13 +2350,36 @@ perf_install_in_context(struct perf_even
 	/*
 	 * Installing events is tricky because we cannot rely on ctx->is_active
 	 * to be set in case this is the nr_events 0 -> 1 transition.
+	 *
+	 * Instead we use task_curr(), which tells us if the task is running.
+	 * However, since we use task_curr() outside of rq::lock, we can race
+	 * against the actual state. This means the result can be wrong.
+	 *
+	 * If we get a false positive, we retry, this is harmless.
+	 *
+	 * If we get a false negative, things are complicated. If we are after
+	 * perf_event_context_sched_in() ctx::lock will serialize us, and the
+	 * value must be correct. If we're before, it doesn't matter since
+	 * perf_event_context_sched_in() will program the counter.
+	 *
+	 * However, this hinges on the remote context switch having observed
+	 * our task->perf_event_ctxp[] store, such that it will in fact take
+	 * ctx::lock in perf_event_context_sched_in().
+	 *
+	 * We do this by task_function_call(), if the IPI fails to hit the task
+	 * we know any future context switch of task must see the
+	 * perf_event_ctpx[] store.
 	 */
-again:
+
 	/*
-	 * Cannot use task_function_call() because we need to run on the task's
-	 * CPU regardless of whether its current or not.
+	 * This smp_mb() orders the task->perf_event_ctxp[] store with the
+	 * task_cpu() load, such that if the IPI then does not find the task
+	 * running, a future context switch of that task must observe the
+	 * store.
 	 */
-	if (!cpu_function_call(task_cpu(task), __perf_install_in_context, event))
+	smp_mb();
+again:
+	if (!task_function_call(task, __perf_install_in_context, event))
 		return;
 
 	raw_spin_lock_irq(&ctx->lock);
@@ -2371,12 +2393,16 @@ again:
 		raw_spin_unlock_irq(&ctx->lock);
 		return;
 	}
-	raw_spin_unlock_irq(&ctx->lock);
 	/*
-	 * Since !ctx->is_active doesn't mean anything, we must IPI
-	 * unconditionally.
+	 * If the task is not running, ctx->lock will avoid it becoming so,
+	 * thus we can safely install the event.
 	 */
-	goto again;
+	if (task_curr(task)) {
+		raw_spin_unlock_irq(&ctx->lock);
+		goto again;
+	}
+	add_event_to_ctx(event, ctx);
+	raw_spin_unlock_irq(&ctx->lock);
 }
 
 /*
diff -druNp --no-dereference linux-libre-4.9.35-gnu/kernel/panic.c linux-libre-4.9.36-gnu/kernel/panic.c
--- linux-libre-4.9.35-gnu/kernel/panic.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/kernel/panic.c	2017-07-05 08:40:44.000000000 -0400
@@ -249,7 +249,7 @@ void panic(const char *fmt, ...)
 		 * Delay timeout seconds before rebooting the machine.
 		 * We can't use the "normal" timers since we just panicked.
 		 */
-		pr_emerg("Rebooting in %d seconds..", panic_timeout);
+		pr_emerg("Rebooting in %d seconds..\n", panic_timeout);
 
 		for (i = 0; i < panic_timeout * 1000; i += PANIC_TIMER_STEP) {
 			touch_nmi_watchdog();
diff -druNp --no-dereference linux-libre-4.9.35-gnu/kernel/sched/loadavg.c linux-libre-4.9.36-gnu/kernel/sched/loadavg.c
--- linux-libre-4.9.35-gnu/kernel/sched/loadavg.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/kernel/sched/loadavg.c	2017-07-05 08:40:44.000000000 -0400
@@ -201,8 +201,9 @@ void calc_load_exit_idle(void)
 	struct rq *this_rq = this_rq();
 
 	/*
-	 * If we're still before the sample window, we're done.
+	 * If we're still before the pending sample window, we're done.
 	 */
+	this_rq->calc_load_update = calc_load_update;
 	if (time_before(jiffies, this_rq->calc_load_update))
 		return;
 
@@ -211,7 +212,6 @@ void calc_load_exit_idle(void)
 	 * accounted through the nohz accounting, so skip the entire deal and
 	 * sync up for the next window.
 	 */
-	this_rq->calc_load_update = calc_load_update;
 	if (time_before(jiffies, this_rq->calc_load_update + 10))
 		this_rq->calc_load_update += LOAD_FREQ;
 }
diff -druNp --no-dereference linux-libre-4.9.35-gnu/lib/swiotlb.c linux-libre-4.9.36-gnu/lib/swiotlb.c
--- linux-libre-4.9.35-gnu/lib/swiotlb.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/lib/swiotlb.c	2017-07-05 08:40:44.000000000 -0400
@@ -456,11 +456,11 @@ phys_addr_t swiotlb_tbl_map_single(struc
 		    : 1UL << (BITS_PER_LONG - IO_TLB_SHIFT);
 
 	/*
-	 * For mappings greater than a page, we limit the stride (and
-	 * hence alignment) to a page size.
+	 * For mappings greater than or equal to a page, we limit the stride
+	 * (and hence alignment) to a page size.
 	 */
 	nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
-	if (size > PAGE_SIZE)
+	if (size >= PAGE_SIZE)
 		stride = (1 << (PAGE_SHIFT - IO_TLB_SHIFT));
 	else
 		stride = 1;
diff -druNp --no-dereference linux-libre-4.9.35-gnu/Makefile linux-libre-4.9.36-gnu/Makefile
--- linux-libre-4.9.35-gnu/Makefile	2017-06-29 09:32:56.000000000 -0400
+++ linux-libre-4.9.36-gnu/Makefile	2017-07-05 14:55:30.000000000 -0400
@@ -1,6 +1,6 @@
 VERSION = 4
 PATCHLEVEL = 9
-SUBLEVEL = 35
+SUBLEVEL = 36
 EXTRAVERSION = -gnu
 NAME = Roaring Lionus
 
diff -druNp --no-dereference linux-libre-4.9.35-gnu/mm/huge_memory.c linux-libre-4.9.36-gnu/mm/huge_memory.c
--- linux-libre-4.9.35-gnu/mm/huge_memory.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/mm/huge_memory.c	2017-07-05 08:40:44.000000000 -0400
@@ -1227,8 +1227,11 @@ int do_huge_pmd_numa_page(struct fault_e
 	 */
 	if (unlikely(pmd_trans_migrating(*fe->pmd))) {
 		page = pmd_page(*fe->pmd);
+		if (!get_page_unless_zero(page))
+			goto out_unlock;
 		spin_unlock(fe->ptl);
 		wait_on_page_locked(page);
+		put_page(page);
 		goto out;
 	}
 
@@ -1260,8 +1263,11 @@ int do_huge_pmd_numa_page(struct fault_e
 
 	/* Migration could have started since the pmd_trans_migrating check */
 	if (!page_locked) {
+		if (!get_page_unless_zero(page))
+			goto out_unlock;
 		spin_unlock(fe->ptl);
 		wait_on_page_locked(page);
+		put_page(page);
 		page_nid = -1;
 		goto out;
 	}
diff -druNp --no-dereference linux-libre-4.9.35-gnu/mm/swap_cgroup.c linux-libre-4.9.36-gnu/mm/swap_cgroup.c
--- linux-libre-4.9.35-gnu/mm/swap_cgroup.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/mm/swap_cgroup.c	2017-07-05 08:40:44.000000000 -0400
@@ -204,6 +204,8 @@ void swap_cgroup_swapoff(int type)
 			struct page *page = map[i];
 			if (page)
 				__free_page(page);
+			if (!(i % SWAP_CLUSTER_MAX))
+				cond_resched();
 		}
 		vfree(map);
 	}
diff -druNp --no-dereference linux-libre-4.9.35-gnu/mm/vmalloc.c linux-libre-4.9.36-gnu/mm/vmalloc.c
--- linux-libre-4.9.35-gnu/mm/vmalloc.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/mm/vmalloc.c	2017-07-05 08:40:44.000000000 -0400
@@ -244,11 +244,21 @@ struct page *vmalloc_to_page(const void
 	 */
 	VIRTUAL_BUG_ON(!is_vmalloc_or_module_addr(vmalloc_addr));
 
+	/*
+	 * Don't dereference bad PUD or PMD (below) entries. This will also
+	 * identify huge mappings, which we may encounter on architectures
+	 * that define CONFIG_HAVE_ARCH_HUGE_VMAP=y. Such regions will be
+	 * identified as vmalloc addresses by is_vmalloc_addr(), but are
+	 * not [unambiguously] associated with a struct page, so there is
+	 * no correct value to return for them.
+	 */
 	if (!pgd_none(*pgd)) {
 		pud_t *pud = pud_offset(pgd, addr);
-		if (!pud_none(*pud)) {
+		WARN_ON_ONCE(pud_bad(*pud));
+		if (!pud_none(*pud) && !pud_bad(*pud)) {
 			pmd_t *pmd = pmd_offset(pud, addr);
-			if (!pmd_none(*pmd)) {
+			WARN_ON_ONCE(pmd_bad(*pmd));
+			if (!pmd_none(*pmd) && !pmd_bad(*pmd)) {
 				pte_t *ptep, pte;
 
 				ptep = pte_offset_map(pmd, addr);
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/8021q/vlan.c linux-libre-4.9.36-gnu/net/8021q/vlan.c
--- linux-libre-4.9.35-gnu/net/8021q/vlan.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/8021q/vlan.c	2017-07-05 08:40:44.000000000 -0400
@@ -277,7 +277,8 @@ static int register_vlan_device(struct n
 	return 0;
 
 out_free_newdev:
-	free_netdev(new_dev);
+	if (new_dev->reg_state == NETREG_UNINITIALIZED)
+		free_netdev(new_dev);
 	return err;
 }
 
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/caif/cfpkt_skbuff.c linux-libre-4.9.36-gnu/net/caif/cfpkt_skbuff.c
--- linux-libre-4.9.35-gnu/net/caif/cfpkt_skbuff.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/caif/cfpkt_skbuff.c	2017-07-05 08:40:44.000000000 -0400
@@ -81,11 +81,7 @@ static struct cfpkt *cfpkt_create_pfx(u1
 {
 	struct sk_buff *skb;
 
-	if (likely(in_interrupt()))
-		skb = alloc_skb(len + pfx, GFP_ATOMIC);
-	else
-		skb = alloc_skb(len + pfx, GFP_KERNEL);
-
+	skb = alloc_skb(len + pfx, GFP_ATOMIC);
 	if (unlikely(skb == NULL))
 		return NULL;
 
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/core/dev.c linux-libre-4.9.36-gnu/net/core/dev.c
--- linux-libre-4.9.35-gnu/net/core/dev.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/core/dev.c	2017-07-05 08:40:44.000000000 -0400
@@ -1250,8 +1250,9 @@ int dev_set_alias(struct net_device *dev
 	if (!new_ifalias)
 		return -ENOMEM;
 	dev->ifalias = new_ifalias;
+	memcpy(dev->ifalias, alias, len);
+	dev->ifalias[len] = 0;
 
-	strlcpy(dev->ifalias, alias, len+1);
 	return len;
 }
 
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/core/dst.c linux-libre-4.9.36-gnu/net/core/dst.c
--- linux-libre-4.9.35-gnu/net/core/dst.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/core/dst.c	2017-07-05 08:40:44.000000000 -0400
@@ -470,6 +470,20 @@ static int dst_dev_event(struct notifier
 		spin_lock_bh(&dst_garbage.lock);
 		dst = dst_garbage.list;
 		dst_garbage.list = NULL;
+		/* The code in dst_ifdown places a hold on the loopback device.
+		 * If the gc entry processing is set to expire after a lengthy
+		 * interval, this hold can cause netdev_wait_allrefs() to hang
+		 * out and wait for a long time -- until the the loopback
+		 * interface is released.  If we're really unlucky, it'll emit
+		 * pr_emerg messages to console too.  Reset the interval here,
+		 * so dst cleanups occur in a more timely fashion.
+		 */
+		if (dst_garbage.timer_inc > DST_GC_INC) {
+			dst_garbage.timer_inc = DST_GC_INC;
+			dst_garbage.timer_expires = DST_GC_MIN;
+			mod_delayed_work(system_wq, &dst_gc_work,
+					 dst_garbage.timer_expires);
+		}
 		spin_unlock_bh(&dst_garbage.lock);
 
 		if (last)
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/core/ethtool.c linux-libre-4.9.36-gnu/net/core/ethtool.c
--- linux-libre-4.9.35-gnu/net/core/ethtool.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/core/ethtool.c	2017-07-05 08:40:44.000000000 -0400
@@ -1704,7 +1704,7 @@ static noinline_for_stack int ethtool_ge
 static noinline_for_stack int ethtool_set_channels(struct net_device *dev,
 						   void __user *useraddr)
 {
-	struct ethtool_channels channels, max;
+	struct ethtool_channels channels, max = { .cmd = ETHTOOL_GCHANNELS };
 	u32 max_rx_in_use = 0;
 
 	if (!dev->ethtool_ops->set_channels || !dev->ethtool_ops->get_channels)
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/core/rtnetlink.c linux-libre-4.9.36-gnu/net/core/rtnetlink.c
--- linux-libre-4.9.35-gnu/net/core/rtnetlink.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/core/rtnetlink.c	2017-07-05 08:40:44.000000000 -0400
@@ -937,6 +937,7 @@ static noinline size_t if_nlmsg_size(con
 	       + nla_total_size(1) /* IFLA_LINKMODE */
 	       + nla_total_size(4) /* IFLA_CARRIER_CHANGES */
 	       + nla_total_size(4) /* IFLA_LINK_NETNSID */
+	       + nla_total_size(4) /* IFLA_GROUP */
 	       + nla_total_size(ext_filter_mask
 			        & RTEXT_FILTER_VF ? 4 : 0) /* IFLA_NUM_VF */
 	       + rtnl_vfinfo_size(dev, ext_filter_mask) /* IFLA_VFINFO_LIST */
@@ -1130,6 +1131,8 @@ static noinline_for_stack int rtnl_fill_
 	struct ifla_vf_mac vf_mac;
 	struct ifla_vf_info ivi;
 
+	memset(&ivi, 0, sizeof(ivi));
+
 	/* Not all SR-IOV capable drivers support the
 	 * spoofcheck and "RSS query enable" query.  Preset to
 	 * -1 so the user space tool can detect that the driver
@@ -1138,7 +1141,6 @@ static noinline_for_stack int rtnl_fill_
 	ivi.spoofchk = -1;
 	ivi.rss_query_en = -1;
 	ivi.trusted = -1;
-	memset(ivi.mac, 0, sizeof(ivi.mac));
 	/* The default value for VF link state is "auto"
 	 * IFLA_VF_LINK_STATE_AUTO which equals zero
 	 */
@@ -1464,6 +1466,7 @@ static const struct nla_policy ifla_poli
 	[IFLA_LINK_NETNSID]	= { .type = NLA_S32 },
 	[IFLA_PROTO_DOWN]	= { .type = NLA_U8 },
 	[IFLA_XDP]		= { .type = NLA_NESTED },
+	[IFLA_GROUP]		= { .type = NLA_U32 },
 };
 
 static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/decnet/dn_route.c linux-libre-4.9.36-gnu/net/decnet/dn_route.c
--- linux-libre-4.9.35-gnu/net/decnet/dn_route.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/decnet/dn_route.c	2017-07-05 08:40:44.000000000 -0400
@@ -188,12 +188,6 @@ static inline void dnrt_free(struct dn_r
 	call_rcu_bh(&rt->dst.rcu_head, dst_rcu_free);
 }
 
-static inline void dnrt_drop(struct dn_route *rt)
-{
-	dst_release(&rt->dst);
-	call_rcu_bh(&rt->dst.rcu_head, dst_rcu_free);
-}
-
 static void dn_dst_check_expire(unsigned long dummy)
 {
 	int i;
@@ -248,7 +242,7 @@ static int dn_dst_gc(struct dst_ops *ops
 			}
 			*rtp = rt->dst.dn_next;
 			rt->dst.dn_next = NULL;
-			dnrt_drop(rt);
+			dnrt_free(rt);
 			break;
 		}
 		spin_unlock_bh(&dn_rt_hash_table[i].lock);
@@ -350,7 +344,7 @@ static int dn_insert_route(struct dn_rou
 			dst_use(&rth->dst, now);
 			spin_unlock_bh(&dn_rt_hash_table[hash].lock);
 
-			dnrt_drop(rt);
+			dst_free(&rt->dst);
 			*rp = rth;
 			return 0;
 		}
@@ -380,7 +374,7 @@ static void dn_run_flush(unsigned long d
 		for(; rt; rt = next) {
 			next = rcu_dereference_raw(rt->dst.dn_next);
 			RCU_INIT_POINTER(rt->dst.dn_next, NULL);
-			dst_free((struct dst_entry *)rt);
+			dnrt_free(rt);
 		}
 
 nothing_to_declare:
@@ -1187,7 +1181,7 @@ make_route:
 	if (dev_out->flags & IFF_LOOPBACK)
 		flags |= RTCF_LOCAL;
 
-	rt = dst_alloc(&dn_dst_ops, dev_out, 1, DST_OBSOLETE_NONE, DST_HOST);
+	rt = dst_alloc(&dn_dst_ops, dev_out, 0, DST_OBSOLETE_NONE, DST_HOST);
 	if (rt == NULL)
 		goto e_nobufs;
 
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/decnet/netfilter/dn_rtmsg.c linux-libre-4.9.36-gnu/net/decnet/netfilter/dn_rtmsg.c
--- linux-libre-4.9.35-gnu/net/decnet/netfilter/dn_rtmsg.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/decnet/netfilter/dn_rtmsg.c	2017-07-05 08:40:44.000000000 -0400
@@ -102,7 +102,9 @@ static inline void dnrmg_receive_user_sk
 {
 	struct nlmsghdr *nlh = nlmsg_hdr(skb);
 
-	if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len)
+	if (skb->len < sizeof(*nlh) ||
+	    nlh->nlmsg_len < sizeof(*nlh) ||
+	    skb->len < nlh->nlmsg_len)
 		return;
 
 	if (!netlink_capable(skb, CAP_NET_ADMIN))
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/dsa/slave.c linux-libre-4.9.36-gnu/net/dsa/slave.c
--- linux-libre-4.9.35-gnu/net/dsa/slave.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/dsa/slave.c	2017-07-05 08:40:44.000000000 -0400
@@ -1103,10 +1103,8 @@ static int dsa_slave_phy_connect(struct
 	/* Use already configured phy mode */
 	if (p->phy_interface == PHY_INTERFACE_MODE_NA)
 		p->phy_interface = p->phy->interface;
-	phy_connect_direct(slave_dev, p->phy, dsa_slave_adjust_link,
-			   p->phy_interface);
-
-	return 0;
+	return phy_connect_direct(slave_dev, p->phy, dsa_slave_adjust_link,
+				  p->phy_interface);
 }
 
 static int dsa_slave_phy_setup(struct dsa_slave_priv *p,
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/ipv4/igmp.c linux-libre-4.9.36-gnu/net/ipv4/igmp.c
--- linux-libre-4.9.35-gnu/net/ipv4/igmp.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/ipv4/igmp.c	2017-07-05 08:40:44.000000000 -0400
@@ -1112,6 +1112,7 @@ static void igmpv3_add_delrec(struct in_
 	pmc = kzalloc(sizeof(*pmc), GFP_KERNEL);
 	if (!pmc)
 		return;
+	spin_lock_init(&pmc->lock);
 	spin_lock_bh(&im->lock);
 	pmc->interface = im->interface;
 	in_dev_hold(in_dev);
@@ -2071,21 +2072,26 @@ static int ip_mc_add_src(struct in_devic
 
 static void ip_mc_clear_src(struct ip_mc_list *pmc)
 {
-	struct ip_sf_list *psf, *nextpsf;
+	struct ip_sf_list *psf, *nextpsf, *tomb, *sources;
 
-	for (psf = pmc->tomb; psf; psf = nextpsf) {
+	spin_lock_bh(&pmc->lock);
+	tomb = pmc->tomb;
+	pmc->tomb = NULL;
+	sources = pmc->sources;
+	pmc->sources = NULL;
+	pmc->sfmode = MCAST_EXCLUDE;
+	pmc->sfcount[MCAST_INCLUDE] = 0;
+	pmc->sfcount[MCAST_EXCLUDE] = 1;
+	spin_unlock_bh(&pmc->lock);
+
+	for (psf = tomb; psf; psf = nextpsf) {
 		nextpsf = psf->sf_next;
 		kfree(psf);
 	}
-	pmc->tomb = NULL;
-	for (psf = pmc->sources; psf; psf = nextpsf) {
+	for (psf = sources; psf; psf = nextpsf) {
 		nextpsf = psf->sf_next;
 		kfree(psf);
 	}
-	pmc->sources = NULL;
-	pmc->sfmode = MCAST_EXCLUDE;
-	pmc->sfcount[MCAST_INCLUDE] = 0;
-	pmc->sfcount[MCAST_EXCLUDE] = 1;
 }
 
 /* Join a multicast group
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/ipv4/netfilter.c linux-libre-4.9.36-gnu/net/ipv4/netfilter.c
--- linux-libre-4.9.35-gnu/net/ipv4/netfilter.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/ipv4/netfilter.c	2017-07-05 08:40:44.000000000 -0400
@@ -23,7 +23,8 @@ int ip_route_me_harder(struct net *net,
 	struct rtable *rt;
 	struct flowi4 fl4 = {};
 	__be32 saddr = iph->saddr;
-	__u8 flags = skb->sk ? inet_sk_flowi_flags(skb->sk) : 0;
+	const struct sock *sk = skb_to_full_sk(skb);
+	__u8 flags = sk ? inet_sk_flowi_flags(sk) : 0;
 	struct net_device *dev = skb_dst(skb)->dev;
 	unsigned int hh_len;
 
@@ -40,7 +41,7 @@ int ip_route_me_harder(struct net *net,
 	fl4.daddr = iph->daddr;
 	fl4.saddr = saddr;
 	fl4.flowi4_tos = RT_TOS(iph->tos);
-	fl4.flowi4_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0;
+	fl4.flowi4_oif = sk ? sk->sk_bound_dev_if : 0;
 	if (!fl4.flowi4_oif)
 		fl4.flowi4_oif = l3mdev_master_ifindex(dev);
 	fl4.flowi4_mark = skb->mark;
@@ -61,7 +62,7 @@ int ip_route_me_harder(struct net *net,
 	    xfrm_decode_session(skb, flowi4_to_flowi(&fl4), AF_INET) == 0) {
 		struct dst_entry *dst = skb_dst(skb);
 		skb_dst_set(skb, NULL);
-		dst = xfrm_lookup(net, dst, flowi4_to_flowi(&fl4), skb->sk, 0);
+		dst = xfrm_lookup(net, dst, flowi4_to_flowi(&fl4), sk, 0);
 		if (IS_ERR(dst))
 			return PTR_ERR(dst);
 		skb_dst_set(skb, dst);
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/ipv6/addrconf.c linux-libre-4.9.36-gnu/net/ipv6/addrconf.c
--- linux-libre-4.9.35-gnu/net/ipv6/addrconf.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/ipv6/addrconf.c	2017-07-05 08:40:44.000000000 -0400
@@ -315,9 +315,9 @@ static void addrconf_mod_rs_timer(struct
 static void addrconf_mod_dad_work(struct inet6_ifaddr *ifp,
 				   unsigned long delay)
 {
-	if (!delayed_work_pending(&ifp->dad_work))
-		in6_ifa_hold(ifp);
-	mod_delayed_work(addrconf_wq, &ifp->dad_work, delay);
+	in6_ifa_hold(ifp);
+	if (mod_delayed_work(addrconf_wq, &ifp->dad_work, delay))
+		in6_ifa_put(ifp);
 }
 
 static int snmp6_alloc_dev(struct inet6_dev *idev)
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/ipv6/fib6_rules.c linux-libre-4.9.36-gnu/net/ipv6/fib6_rules.c
--- linux-libre-4.9.35-gnu/net/ipv6/fib6_rules.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/ipv6/fib6_rules.c	2017-07-05 08:40:44.000000000 -0400
@@ -32,7 +32,6 @@ struct fib6_rule {
 struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
 				   int flags, pol_lookup_t lookup)
 {
-	struct rt6_info *rt;
 	struct fib_lookup_arg arg = {
 		.lookup_ptr = lookup,
 		.flags = FIB_LOOKUP_NOREF,
@@ -44,21 +43,11 @@ struct dst_entry *fib6_rule_lookup(struc
 	fib_rules_lookup(net->ipv6.fib6_rules_ops,
 			 flowi6_to_flowi(fl6), flags, &arg);
 
-	rt = arg.result;
-
-	if (!rt) {
-		dst_hold(&net->ipv6.ip6_null_entry->dst);
-		return &net->ipv6.ip6_null_entry->dst;
-	}
-
-	if (rt->rt6i_flags & RTF_REJECT &&
-	    rt->dst.error == -EAGAIN) {
-		ip6_rt_put(rt);
-		rt = net->ipv6.ip6_null_entry;
-		dst_hold(&rt->dst);
-	}
+	if (arg.result)
+		return arg.result;
 
-	return &rt->dst;
+	dst_hold(&net->ipv6.ip6_null_entry->dst);
+	return &net->ipv6.ip6_null_entry->dst;
 }
 
 static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
@@ -121,7 +110,8 @@ static int fib6_rule_action(struct fib_r
 			flp6->saddr = saddr;
 		}
 		err = rt->dst.error;
-		goto out;
+		if (err != -EAGAIN)
+			goto out;
 	}
 again:
 	ip6_rt_put(rt);
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/ipv6/ip6_fib.c linux-libre-4.9.36-gnu/net/ipv6/ip6_fib.c
--- linux-libre-4.9.35-gnu/net/ipv6/ip6_fib.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/ipv6/ip6_fib.c	2017-07-05 08:40:44.000000000 -0400
@@ -289,8 +289,7 @@ struct dst_entry *fib6_rule_lookup(struc
 	struct rt6_info *rt;
 
 	rt = lookup(net, net->ipv6.fib6_main_tbl, fl6, flags);
-	if (rt->rt6i_flags & RTF_REJECT &&
-	    rt->dst.error == -EAGAIN) {
+	if (rt->dst.error == -EAGAIN) {
 		ip6_rt_put(rt);
 		rt = net->ipv6.ip6_null_entry;
 		dst_hold(&rt->dst);
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/ipv6/ip6_gre.c linux-libre-4.9.36-gnu/net/ipv6/ip6_gre.c
--- linux-libre-4.9.35-gnu/net/ipv6/ip6_gre.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/ipv6/ip6_gre.c	2017-07-05 08:40:44.000000000 -0400
@@ -542,11 +542,10 @@ static inline int ip6gre_xmit_ipv4(struc
 
 	memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6));
 
-	dsfield = ipv4_get_dsfield(iph);
-
 	if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)
-		fl6.flowlabel |= htonl((__u32)iph->tos << IPV6_TCLASS_SHIFT)
-					  & IPV6_TCLASS_MASK;
+		dsfield = ipv4_get_dsfield(iph);
+	else
+		dsfield = ip6_tclass(t->parms.flowinfo);
 	if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
 		fl6.flowi6_mark = skb->mark;
 
@@ -582,6 +581,9 @@ static inline int ip6gre_xmit_ipv6(struc
 		return -1;
 
 	offset = ip6_tnl_parse_tlv_enc_lim(skb, skb_network_header(skb));
+	/* ip6_tnl_parse_tlv_enc_lim() might have reallocated skb->head */
+	ipv6h = ipv6_hdr(skb);
+
 	if (offset > 0) {
 		struct ipv6_tlv_tnl_enc_lim *tel;
 		tel = (struct ipv6_tlv_tnl_enc_lim *)&skb_network_header(skb)[offset];
@@ -596,9 +598,11 @@ static inline int ip6gre_xmit_ipv6(struc
 
 	memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6));
 
-	dsfield = ipv6_get_dsfield(ipv6h);
 	if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)
-		fl6.flowlabel |= (*(__be32 *) ipv6h & IPV6_TCLASS_MASK);
+		dsfield = ipv6_get_dsfield(ipv6h);
+	else
+		dsfield = ip6_tclass(t->parms.flowinfo);
+
 	if (t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL)
 		fl6.flowlabel |= ip6_flowlabel(ipv6h);
 	if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/ipv6/ip6_output.c linux-libre-4.9.36-gnu/net/ipv6/ip6_output.c
--- linux-libre-4.9.35-gnu/net/ipv6/ip6_output.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/ipv6/ip6_output.c	2017-07-05 08:40:44.000000000 -0400
@@ -1020,8 +1020,10 @@ static int ip6_dst_lookup_tail(struct ne
 	}
 #endif
 	if (ipv6_addr_v4mapped(&fl6->saddr) &&
-	    !(ipv6_addr_v4mapped(&fl6->daddr) || ipv6_addr_any(&fl6->daddr)))
-		return -EAFNOSUPPORT;
+	    !(ipv6_addr_v4mapped(&fl6->daddr) || ipv6_addr_any(&fl6->daddr))) {
+		err = -EAFNOSUPPORT;
+		goto out_err_release;
+	}
 
 	return 0;
 
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/ipv6/ip6_tunnel.c linux-libre-4.9.36-gnu/net/ipv6/ip6_tunnel.c
--- linux-libre-4.9.35-gnu/net/ipv6/ip6_tunnel.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/ipv6/ip6_tunnel.c	2017-07-05 08:40:44.000000000 -0400
@@ -1196,7 +1196,7 @@ route_lookup:
 	skb_push(skb, sizeof(struct ipv6hdr));
 	skb_reset_network_header(skb);
 	ipv6h = ipv6_hdr(skb);
-	ip6_flow_hdr(ipv6h, INET_ECN_encapsulate(0, dsfield),
+	ip6_flow_hdr(ipv6h, dsfield,
 		     ip6_make_flowlabel(net, skb, fl6->flowlabel, true, fl6));
 	ipv6h->hop_limit = hop_limit;
 	ipv6h->nexthdr = proto;
@@ -1231,8 +1231,6 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, str
 	if (tproto != IPPROTO_IPIP && tproto != 0)
 		return -1;
 
-	dsfield = ipv4_get_dsfield(iph);
-
 	if (t->parms.collect_md) {
 		struct ip_tunnel_info *tun_info;
 		const struct ip_tunnel_key *key;
@@ -1246,6 +1244,7 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, str
 		fl6.flowi6_proto = IPPROTO_IPIP;
 		fl6.daddr = key->u.ipv6.dst;
 		fl6.flowlabel = key->label;
+		dsfield = ip6_tclass(key->label);
 	} else {
 		if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
 			encap_limit = t->parms.encap_limit;
@@ -1254,8 +1253,9 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, str
 		fl6.flowi6_proto = IPPROTO_IPIP;
 
 		if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)
-			fl6.flowlabel |= htonl((__u32)iph->tos << IPV6_TCLASS_SHIFT)
-					 & IPV6_TCLASS_MASK;
+			dsfield = ipv4_get_dsfield(iph);
+		else
+			dsfield = ip6_tclass(t->parms.flowinfo);
 		if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
 			fl6.flowi6_mark = skb->mark;
 	}
@@ -1263,6 +1263,8 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, str
 	if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6))
 		return -1;
 
+	dsfield = INET_ECN_encapsulate(dsfield, ipv4_get_dsfield(iph));
+
 	skb_set_inner_ipproto(skb, IPPROTO_IPIP);
 
 	err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu,
@@ -1296,8 +1298,6 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, str
 	    ip6_tnl_addr_conflict(t, ipv6h))
 		return -1;
 
-	dsfield = ipv6_get_dsfield(ipv6h);
-
 	if (t->parms.collect_md) {
 		struct ip_tunnel_info *tun_info;
 		const struct ip_tunnel_key *key;
@@ -1311,8 +1311,11 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, str
 		fl6.flowi6_proto = IPPROTO_IPV6;
 		fl6.daddr = key->u.ipv6.dst;
 		fl6.flowlabel = key->label;
+		dsfield = ip6_tclass(key->label);
 	} else {
 		offset = ip6_tnl_parse_tlv_enc_lim(skb, skb_network_header(skb));
+		/* ip6_tnl_parse_tlv_enc_lim() might have reallocated skb->head */
+		ipv6h = ipv6_hdr(skb);
 		if (offset > 0) {
 			struct ipv6_tlv_tnl_enc_lim *tel;
 
@@ -1331,7 +1334,9 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, str
 		fl6.flowi6_proto = IPPROTO_IPV6;
 
 		if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)
-			fl6.flowlabel |= (*(__be32 *)ipv6h & IPV6_TCLASS_MASK);
+			dsfield = ipv6_get_dsfield(ipv6h);
+		else
+			dsfield = ip6_tclass(t->parms.flowinfo);
 		if (t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL)
 			fl6.flowlabel |= ip6_flowlabel(ipv6h);
 		if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
@@ -1341,6 +1346,8 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, str
 	if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6))
 		return -1;
 
+	dsfield = INET_ECN_encapsulate(dsfield, ipv6_get_dsfield(ipv6h));
+
 	skb_set_inner_ipproto(skb, IPPROTO_IPV6);
 
 	err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu,
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/ipv6/proc.c linux-libre-4.9.36-gnu/net/ipv6/proc.c
--- linux-libre-4.9.35-gnu/net/ipv6/proc.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/ipv6/proc.c	2017-07-05 08:40:44.000000000 -0400
@@ -219,7 +219,7 @@ static void snmp6_seq_show_item64(struct
 	u64 buff64[SNMP_MIB_MAX];
 	int i;
 
-	memset(buff64, 0, sizeof(unsigned long) * SNMP_MIB_MAX);
+	memset(buff64, 0, sizeof(u64) * SNMP_MIB_MAX);
 
 	snmp_get_cpu_field64_batch(buff64, itemlist, mib, syncpoff);
 	for (i = 0; itemlist[i].name; i++)
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/key/af_key.c linux-libre-4.9.36-gnu/net/key/af_key.c
--- linux-libre-4.9.35-gnu/net/key/af_key.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/key/af_key.c	2017-07-05 08:40:44.000000000 -0400
@@ -1135,6 +1135,7 @@ static struct xfrm_state * pfkey_msg2xfr
 			goto out;
 	}
 
+	err = -ENOBUFS;
 	key = ext_hdrs[SADB_EXT_KEY_AUTH - 1];
 	if (sa->sadb_sa_auth) {
 		int keysize = 0;
@@ -1146,8 +1147,10 @@ static struct xfrm_state * pfkey_msg2xfr
 		if (key)
 			keysize = (key->sadb_key_bits + 7) / 8;
 		x->aalg = kmalloc(sizeof(*x->aalg) + keysize, GFP_KERNEL);
-		if (!x->aalg)
+		if (!x->aalg) {
+			err = -ENOMEM;
 			goto out;
+		}
 		strcpy(x->aalg->alg_name, a->name);
 		x->aalg->alg_key_len = 0;
 		if (key) {
@@ -1166,8 +1169,10 @@ static struct xfrm_state * pfkey_msg2xfr
 				goto out;
 			}
 			x->calg = kmalloc(sizeof(*x->calg), GFP_KERNEL);
-			if (!x->calg)
+			if (!x->calg) {
+				err = -ENOMEM;
 				goto out;
+			}
 			strcpy(x->calg->alg_name, a->name);
 			x->props.calgo = sa->sadb_sa_encrypt;
 		} else {
@@ -1181,8 +1186,10 @@ static struct xfrm_state * pfkey_msg2xfr
 			if (key)
 				keysize = (key->sadb_key_bits + 7) / 8;
 			x->ealg = kmalloc(sizeof(*x->ealg) + keysize, GFP_KERNEL);
-			if (!x->ealg)
+			if (!x->ealg) {
+				err = -ENOMEM;
 				goto out;
+			}
 			strcpy(x->ealg->alg_name, a->name);
 			x->ealg->alg_key_len = 0;
 			if (key) {
@@ -1227,8 +1234,10 @@ static struct xfrm_state * pfkey_msg2xfr
 		struct xfrm_encap_tmpl *natt;
 
 		x->encap = kmalloc(sizeof(*x->encap), GFP_KERNEL);
-		if (!x->encap)
+		if (!x->encap) {
+			err = -ENOMEM;
 			goto out;
+		}
 
 		natt = x->encap;
 		n_type = ext_hdrs[SADB_X_EXT_NAT_T_TYPE-1];
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/l2tp/l2tp_core.c linux-libre-4.9.36-gnu/net/l2tp/l2tp_core.c
--- linux-libre-4.9.35-gnu/net/l2tp/l2tp_core.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/l2tp/l2tp_core.c	2017-07-05 08:40:44.000000000 -0400
@@ -278,6 +278,55 @@ struct l2tp_session *l2tp_session_find(s
 }
 EXPORT_SYMBOL_GPL(l2tp_session_find);
 
+/* Like l2tp_session_find() but takes a reference on the returned session.
+ * Optionally calls session->ref() too if do_ref is true.
+ */
+struct l2tp_session *l2tp_session_get(struct net *net,
+				      struct l2tp_tunnel *tunnel,
+				      u32 session_id, bool do_ref)
+{
+	struct hlist_head *session_list;
+	struct l2tp_session *session;
+
+	if (!tunnel) {
+		struct l2tp_net *pn = l2tp_pernet(net);
+
+		session_list = l2tp_session_id_hash_2(pn, session_id);
+
+		rcu_read_lock_bh();
+		hlist_for_each_entry_rcu(session, session_list, global_hlist) {
+			if (session->session_id == session_id) {
+				l2tp_session_inc_refcount(session);
+				if (do_ref && session->ref)
+					session->ref(session);
+				rcu_read_unlock_bh();
+
+				return session;
+			}
+		}
+		rcu_read_unlock_bh();
+
+		return NULL;
+	}
+
+	session_list = l2tp_session_id_hash(tunnel, session_id);
+	read_lock_bh(&tunnel->hlist_lock);
+	hlist_for_each_entry(session, session_list, hlist) {
+		if (session->session_id == session_id) {
+			l2tp_session_inc_refcount(session);
+			if (do_ref && session->ref)
+				session->ref(session);
+			read_unlock_bh(&tunnel->hlist_lock);
+
+			return session;
+		}
+	}
+	read_unlock_bh(&tunnel->hlist_lock);
+
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(l2tp_session_get);
+
 struct l2tp_session *l2tp_session_get_nth(struct l2tp_tunnel *tunnel, int nth,
 					  bool do_ref)
 {
@@ -307,7 +356,8 @@ EXPORT_SYMBOL_GPL(l2tp_session_get_nth);
 /* Lookup a session by interface name.
  * This is very inefficient but is only used by management interfaces.
  */
-struct l2tp_session *l2tp_session_find_by_ifname(struct net *net, char *ifname)
+struct l2tp_session *l2tp_session_get_by_ifname(struct net *net, char *ifname,
+						bool do_ref)
 {
 	struct l2tp_net *pn = l2tp_pernet(net);
 	int hash;
@@ -317,7 +367,11 @@ struct l2tp_session *l2tp_session_find_b
 	for (hash = 0; hash < L2TP_HASH_SIZE_2; hash++) {
 		hlist_for_each_entry_rcu(session, &pn->l2tp_session_hlist[hash], global_hlist) {
 			if (!strcmp(session->ifname, ifname)) {
+				l2tp_session_inc_refcount(session);
+				if (do_ref && session->ref)
+					session->ref(session);
 				rcu_read_unlock_bh();
+
 				return session;
 			}
 		}
@@ -327,7 +381,49 @@ struct l2tp_session *l2tp_session_find_b
 
 	return NULL;
 }
-EXPORT_SYMBOL_GPL(l2tp_session_find_by_ifname);
+EXPORT_SYMBOL_GPL(l2tp_session_get_by_ifname);
+
+static int l2tp_session_add_to_tunnel(struct l2tp_tunnel *tunnel,
+				      struct l2tp_session *session)
+{
+	struct l2tp_session *session_walk;
+	struct hlist_head *g_head;
+	struct hlist_head *head;
+	struct l2tp_net *pn;
+
+	head = l2tp_session_id_hash(tunnel, session->session_id);
+
+	write_lock_bh(&tunnel->hlist_lock);
+	hlist_for_each_entry(session_walk, head, hlist)
+		if (session_walk->session_id == session->session_id)
+			goto exist;
+
+	if (tunnel->version == L2TP_HDR_VER_3) {
+		pn = l2tp_pernet(tunnel->l2tp_net);
+		g_head = l2tp_session_id_hash_2(l2tp_pernet(tunnel->l2tp_net),
+						session->session_id);
+
+		spin_lock_bh(&pn->l2tp_session_hlist_lock);
+		hlist_for_each_entry(session_walk, g_head, global_hlist)
+			if (session_walk->session_id == session->session_id)
+				goto exist_glob;
+
+		hlist_add_head_rcu(&session->global_hlist, g_head);
+		spin_unlock_bh(&pn->l2tp_session_hlist_lock);
+	}
+
+	hlist_add_head(&session->hlist, head);
+	write_unlock_bh(&tunnel->hlist_lock);
+
+	return 0;
+
+exist_glob:
+	spin_unlock_bh(&pn->l2tp_session_hlist_lock);
+exist:
+	write_unlock_bh(&tunnel->hlist_lock);
+
+	return -EEXIST;
+}
 
 /* Lookup a tunnel by id
  */
@@ -637,6 +733,9 @@ discard:
  * a data (not control) frame before coming here. Fields up to the
  * session-id have already been parsed and ptr points to the data
  * after the session-id.
+ *
+ * session->ref() must have been called prior to l2tp_recv_common().
+ * session->deref() will be called automatically after skb is processed.
  */
 void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
 		      unsigned char *ptr, unsigned char *optr, u16 hdrflags,
@@ -646,14 +745,6 @@ void l2tp_recv_common(struct l2tp_sessio
 	int offset;
 	u32 ns, nr;
 
-	/* The ref count is increased since we now hold a pointer to
-	 * the session. Take care to decrement the refcnt when exiting
-	 * this function from now on...
-	 */
-	l2tp_session_inc_refcount(session);
-	if (session->ref)
-		(*session->ref)(session);
-
 	/* Parse and check optional cookie */
 	if (session->peer_cookie_len > 0) {
 		if (memcmp(ptr, &session->peer_cookie[0], session->peer_cookie_len)) {
@@ -806,8 +897,6 @@ void l2tp_recv_common(struct l2tp_sessio
 	/* Try to dequeue as many skbs from reorder_q as we can. */
 	l2tp_recv_dequeue(session);
 
-	l2tp_session_dec_refcount(session);
-
 	return;
 
 discard:
@@ -816,8 +905,6 @@ discard:
 
 	if (session->deref)
 		(*session->deref)(session);
-
-	l2tp_session_dec_refcount(session);
 }
 EXPORT_SYMBOL(l2tp_recv_common);
 
@@ -924,8 +1011,14 @@ static int l2tp_udp_recv_core(struct l2t
 	}
 
 	/* Find the session context */
-	session = l2tp_session_find(tunnel->l2tp_net, tunnel, session_id);
+	session = l2tp_session_get(tunnel->l2tp_net, tunnel, session_id, true);
 	if (!session || !session->recv_skb) {
+		if (session) {
+			if (session->deref)
+				session->deref(session);
+			l2tp_session_dec_refcount(session);
+		}
+
 		/* Not found? Pass to userspace to deal with */
 		l2tp_info(tunnel, L2TP_MSG_DATA,
 			  "%s: no session found (%u/%u). Passing up.\n",
@@ -934,6 +1027,7 @@ static int l2tp_udp_recv_core(struct l2t
 	}
 
 	l2tp_recv_common(session, skb, ptr, optr, hdrflags, length, payload_hook);
+	l2tp_session_dec_refcount(session);
 
 	return 0;
 
@@ -1740,6 +1834,7 @@ EXPORT_SYMBOL_GPL(l2tp_session_set_heade
 struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunnel, u32 session_id, u32 peer_session_id, struct l2tp_session_cfg *cfg)
 {
 	struct l2tp_session *session;
+	int err;
 
 	session = kzalloc(sizeof(struct l2tp_session) + priv_size, GFP_KERNEL);
 	if (session != NULL) {
@@ -1795,6 +1890,13 @@ struct l2tp_session *l2tp_session_create
 
 		l2tp_session_set_header_len(session, tunnel->version);
 
+		err = l2tp_session_add_to_tunnel(tunnel, session);
+		if (err) {
+			kfree(session);
+
+			return ERR_PTR(err);
+		}
+
 		/* Bump the reference count. The session context is deleted
 		 * only when this drops to zero.
 		 */
@@ -1804,28 +1906,14 @@ struct l2tp_session *l2tp_session_create
 		/* Ensure tunnel socket isn't deleted */
 		sock_hold(tunnel->sock);
 
-		/* Add session to the tunnel's hash list */
-		write_lock_bh(&tunnel->hlist_lock);
-		hlist_add_head(&session->hlist,
-			       l2tp_session_id_hash(tunnel, session_id));
-		write_unlock_bh(&tunnel->hlist_lock);
-
-		/* And to the global session list if L2TPv3 */
-		if (tunnel->version != L2TP_HDR_VER_2) {
-			struct l2tp_net *pn = l2tp_pernet(tunnel->l2tp_net);
-
-			spin_lock_bh(&pn->l2tp_session_hlist_lock);
-			hlist_add_head_rcu(&session->global_hlist,
-					   l2tp_session_id_hash_2(pn, session_id));
-			spin_unlock_bh(&pn->l2tp_session_hlist_lock);
-		}
-
 		/* Ignore management session in session count value */
 		if (session->session_id != 0)
 			atomic_inc(&l2tp_session_count);
+
+		return session;
 	}
 
-	return session;
+	return ERR_PTR(-ENOMEM);
 }
 EXPORT_SYMBOL_GPL(l2tp_session_create);
 
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/l2tp/l2tp_core.h linux-libre-4.9.36-gnu/net/l2tp/l2tp_core.h
--- linux-libre-4.9.35-gnu/net/l2tp/l2tp_core.h	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/l2tp/l2tp_core.h	2017-07-05 08:40:44.000000000 -0400
@@ -240,12 +240,16 @@ out:
 	return tunnel;
 }
 
+struct l2tp_session *l2tp_session_get(struct net *net,
+				      struct l2tp_tunnel *tunnel,
+				      u32 session_id, bool do_ref);
 struct l2tp_session *l2tp_session_find(struct net *net,
 				       struct l2tp_tunnel *tunnel,
 				       u32 session_id);
 struct l2tp_session *l2tp_session_get_nth(struct l2tp_tunnel *tunnel, int nth,
 					  bool do_ref);
-struct l2tp_session *l2tp_session_find_by_ifname(struct net *net, char *ifname);
+struct l2tp_session *l2tp_session_get_by_ifname(struct net *net, char *ifname,
+						bool do_ref);
 struct l2tp_tunnel *l2tp_tunnel_find(struct net *net, u32 tunnel_id);
 struct l2tp_tunnel *l2tp_tunnel_find_nth(struct net *net, int nth);
 
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/l2tp/l2tp_eth.c linux-libre-4.9.36-gnu/net/l2tp/l2tp_eth.c
--- linux-libre-4.9.35-gnu/net/l2tp/l2tp_eth.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/l2tp/l2tp_eth.c	2017-07-05 08:40:44.000000000 -0400
@@ -223,12 +223,6 @@ static int l2tp_eth_create(struct net *n
 		goto out;
 	}
 
-	session = l2tp_session_find(net, tunnel, session_id);
-	if (session) {
-		rc = -EEXIST;
-		goto out;
-	}
-
 	if (cfg->ifname) {
 		dev = dev_get_by_name(net, cfg->ifname);
 		if (dev) {
@@ -242,8 +236,8 @@ static int l2tp_eth_create(struct net *n
 
 	session = l2tp_session_create(sizeof(*spriv), tunnel, session_id,
 				      peer_session_id, cfg);
-	if (!session) {
-		rc = -ENOMEM;
+	if (IS_ERR(session)) {
+		rc = PTR_ERR(session);
 		goto out;
 	}
 
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/l2tp/l2tp_ip6.c linux-libre-4.9.36-gnu/net/l2tp/l2tp_ip6.c
--- linux-libre-4.9.35-gnu/net/l2tp/l2tp_ip6.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/l2tp/l2tp_ip6.c	2017-07-05 08:40:44.000000000 -0400
@@ -156,19 +156,19 @@ static int l2tp_ip6_recv(struct sk_buff
 	}
 
 	/* Ok, this is a data packet. Lookup the session. */
-	session = l2tp_session_find(net, NULL, session_id);
-	if (session == NULL)
+	session = l2tp_session_get(net, NULL, session_id, true);
+	if (!session)
 		goto discard;
 
 	tunnel = session->tunnel;
-	if (tunnel == NULL)
-		goto discard;
+	if (!tunnel)
+		goto discard_sess;
 
 	/* Trace packet contents, if enabled */
 	if (tunnel->debug & L2TP_MSG_DATA) {
 		length = min(32u, skb->len);
 		if (!pskb_may_pull(skb, length))
-			goto discard;
+			goto discard_sess;
 
 		/* Point to L2TP header */
 		optr = ptr = skb->data;
@@ -179,6 +179,8 @@ static int l2tp_ip6_recv(struct sk_buff
 
 	l2tp_recv_common(session, skb, ptr, optr, 0, skb->len,
 			 tunnel->recv_payload_hook);
+	l2tp_session_dec_refcount(session);
+
 	return 0;
 
 pass_up:
@@ -216,6 +218,12 @@ pass_up:
 
 	return sk_receive_skb(sk, skb, 1);
 
+discard_sess:
+	if (session->deref)
+		session->deref(session);
+	l2tp_session_dec_refcount(session);
+	goto discard;
+
 discard_put:
 	sock_put(sk);
 
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/l2tp/l2tp_ip.c linux-libre-4.9.36-gnu/net/l2tp/l2tp_ip.c
--- linux-libre-4.9.35-gnu/net/l2tp/l2tp_ip.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/l2tp/l2tp_ip.c	2017-07-05 08:40:44.000000000 -0400
@@ -143,19 +143,19 @@ static int l2tp_ip_recv(struct sk_buff *
 	}
 
 	/* Ok, this is a data packet. Lookup the session. */
-	session = l2tp_session_find(net, NULL, session_id);
-	if (session == NULL)
+	session = l2tp_session_get(net, NULL, session_id, true);
+	if (!session)
 		goto discard;
 
 	tunnel = session->tunnel;
-	if (tunnel == NULL)
-		goto discard;
+	if (!tunnel)
+		goto discard_sess;
 
 	/* Trace packet contents, if enabled */
 	if (tunnel->debug & L2TP_MSG_DATA) {
 		length = min(32u, skb->len);
 		if (!pskb_may_pull(skb, length))
-			goto discard;
+			goto discard_sess;
 
 		/* Point to L2TP header */
 		optr = ptr = skb->data;
@@ -165,6 +165,7 @@ static int l2tp_ip_recv(struct sk_buff *
 	}
 
 	l2tp_recv_common(session, skb, ptr, optr, 0, skb->len, tunnel->recv_payload_hook);
+	l2tp_session_dec_refcount(session);
 
 	return 0;
 
@@ -203,6 +204,12 @@ pass_up:
 
 	return sk_receive_skb(sk, skb, 1);
 
+discard_sess:
+	if (session->deref)
+		session->deref(session);
+	l2tp_session_dec_refcount(session);
+	goto discard;
+
 discard_put:
 	sock_put(sk);
 
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/l2tp/l2tp_netlink.c linux-libre-4.9.36-gnu/net/l2tp/l2tp_netlink.c
--- linux-libre-4.9.35-gnu/net/l2tp/l2tp_netlink.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/l2tp/l2tp_netlink.c	2017-07-05 08:40:44.000000000 -0400
@@ -55,7 +55,8 @@ static int l2tp_nl_session_send(struct s
 /* Accessed under genl lock */
 static const struct l2tp_nl_cmd_ops *l2tp_nl_cmd_ops[__L2TP_PWTYPE_MAX];
 
-static struct l2tp_session *l2tp_nl_session_find(struct genl_info *info)
+static struct l2tp_session *l2tp_nl_session_get(struct genl_info *info,
+						bool do_ref)
 {
 	u32 tunnel_id;
 	u32 session_id;
@@ -66,14 +67,15 @@ static struct l2tp_session *l2tp_nl_sess
 
 	if (info->attrs[L2TP_ATTR_IFNAME]) {
 		ifname = nla_data(info->attrs[L2TP_ATTR_IFNAME]);
-		session = l2tp_session_find_by_ifname(net, ifname);
+		session = l2tp_session_get_by_ifname(net, ifname, do_ref);
 	} else if ((info->attrs[L2TP_ATTR_SESSION_ID]) &&
 		   (info->attrs[L2TP_ATTR_CONN_ID])) {
 		tunnel_id = nla_get_u32(info->attrs[L2TP_ATTR_CONN_ID]);
 		session_id = nla_get_u32(info->attrs[L2TP_ATTR_SESSION_ID]);
 		tunnel = l2tp_tunnel_find(net, tunnel_id);
 		if (tunnel)
-			session = l2tp_session_find(net, tunnel, session_id);
+			session = l2tp_session_get(net, tunnel, session_id,
+						   do_ref);
 	}
 
 	return session;
@@ -634,10 +636,12 @@ static int l2tp_nl_cmd_session_create(st
 			session_id, peer_session_id, &cfg);
 
 	if (ret >= 0) {
-		session = l2tp_session_find(net, tunnel, session_id);
-		if (session)
+		session = l2tp_session_get(net, tunnel, session_id, false);
+		if (session) {
 			ret = l2tp_session_notify(&l2tp_nl_family, info, session,
 						  L2TP_CMD_SESSION_CREATE);
+			l2tp_session_dec_refcount(session);
+		}
 	}
 
 out:
@@ -650,7 +654,7 @@ static int l2tp_nl_cmd_session_delete(st
 	struct l2tp_session *session;
 	u16 pw_type;
 
-	session = l2tp_nl_session_find(info);
+	session = l2tp_nl_session_get(info, true);
 	if (session == NULL) {
 		ret = -ENODEV;
 		goto out;
@@ -664,6 +668,10 @@ static int l2tp_nl_cmd_session_delete(st
 		if (l2tp_nl_cmd_ops[pw_type] && l2tp_nl_cmd_ops[pw_type]->session_delete)
 			ret = (*l2tp_nl_cmd_ops[pw_type]->session_delete)(session);
 
+	if (session->deref)
+		session->deref(session);
+	l2tp_session_dec_refcount(session);
+
 out:
 	return ret;
 }
@@ -673,7 +681,7 @@ static int l2tp_nl_cmd_session_modify(st
 	int ret = 0;
 	struct l2tp_session *session;
 
-	session = l2tp_nl_session_find(info);
+	session = l2tp_nl_session_get(info, false);
 	if (session == NULL) {
 		ret = -ENODEV;
 		goto out;
@@ -708,6 +716,8 @@ static int l2tp_nl_cmd_session_modify(st
 	ret = l2tp_session_notify(&l2tp_nl_family, info,
 				  session, L2TP_CMD_SESSION_MODIFY);
 
+	l2tp_session_dec_refcount(session);
+
 out:
 	return ret;
 }
@@ -803,29 +813,34 @@ static int l2tp_nl_cmd_session_get(struc
 	struct sk_buff *msg;
 	int ret;
 
-	session = l2tp_nl_session_find(info);
+	session = l2tp_nl_session_get(info, false);
 	if (session == NULL) {
 		ret = -ENODEV;
-		goto out;
+		goto err;
 	}
 
 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
 	if (!msg) {
 		ret = -ENOMEM;
-		goto out;
+		goto err_ref;
 	}
 
 	ret = l2tp_nl_session_send(msg, info->snd_portid, info->snd_seq,
 				   0, session, L2TP_CMD_SESSION_GET);
 	if (ret < 0)
-		goto err_out;
+		goto err_ref_msg;
 
-	return genlmsg_unicast(genl_info_net(info), msg, info->snd_portid);
+	ret = genlmsg_unicast(genl_info_net(info), msg, info->snd_portid);
 
-err_out:
-	nlmsg_free(msg);
+	l2tp_session_dec_refcount(session);
 
-out:
+	return ret;
+
+err_ref_msg:
+	nlmsg_free(msg);
+err_ref:
+	l2tp_session_dec_refcount(session);
+err:
 	return ret;
 }
 
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/l2tp/l2tp_ppp.c linux-libre-4.9.36-gnu/net/l2tp/l2tp_ppp.c
--- linux-libre-4.9.35-gnu/net/l2tp/l2tp_ppp.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/l2tp/l2tp_ppp.c	2017-07-05 08:40:44.000000000 -0400
@@ -583,6 +583,7 @@ static int pppol2tp_connect(struct socke
 	int error = 0;
 	u32 tunnel_id, peer_tunnel_id;
 	u32 session_id, peer_session_id;
+	bool drop_refcnt = false;
 	int ver = 2;
 	int fd;
 
@@ -684,36 +685,36 @@ static int pppol2tp_connect(struct socke
 	if (tunnel->peer_tunnel_id == 0)
 		tunnel->peer_tunnel_id = peer_tunnel_id;
 
-	/* Create session if it doesn't already exist. We handle the
-	 * case where a session was previously created by the netlink
-	 * interface by checking that the session doesn't already have
-	 * a socket and its tunnel socket are what we expect. If any
-	 * of those checks fail, return EEXIST to the caller.
-	 */
-	session = l2tp_session_find(sock_net(sk), tunnel, session_id);
-	if (session == NULL) {
-		/* Default MTU must allow space for UDP/L2TP/PPP
-		 * headers.
+	session = l2tp_session_get(sock_net(sk), tunnel, session_id, false);
+	if (session) {
+		drop_refcnt = true;
+		ps = l2tp_session_priv(session);
+
+		/* Using a pre-existing session is fine as long as it hasn't
+		 * been connected yet.
 		 */
-		cfg.mtu = cfg.mru = 1500 - PPPOL2TP_HEADER_OVERHEAD;
+		if (ps->sock) {
+			error = -EEXIST;
+			goto end;
+		}
 
-		/* Allocate and initialize a new session context. */
-		session = l2tp_session_create(sizeof(struct pppol2tp_session),
-					      tunnel, session_id,
-					      peer_session_id, &cfg);
-		if (session == NULL) {
-			error = -ENOMEM;
+		/* consistency checks */
+		if (ps->tunnel_sock != tunnel->sock) {
+			error = -EEXIST;
 			goto end;
 		}
 	} else {
-		ps = l2tp_session_priv(session);
-		error = -EEXIST;
-		if (ps->sock != NULL)
-			goto end;
+		/* Default MTU must allow space for UDP/L2TP/PPP headers */
+		cfg.mtu = 1500 - PPPOL2TP_HEADER_OVERHEAD;
+		cfg.mru = cfg.mtu;
 
-		/* consistency checks */
-		if (ps->tunnel_sock != tunnel->sock)
+		session = l2tp_session_create(sizeof(struct pppol2tp_session),
+					      tunnel, session_id,
+					      peer_session_id, &cfg);
+		if (IS_ERR(session)) {
+			error = PTR_ERR(session);
 			goto end;
+		}
 	}
 
 	/* Associate session with its PPPoL2TP socket */
@@ -778,6 +779,8 @@ out_no_ppp:
 		  session->name);
 
 end:
+	if (drop_refcnt)
+		l2tp_session_dec_refcount(session);
 	release_sock(sk);
 
 	return error;
@@ -805,12 +808,6 @@ static int pppol2tp_session_create(struc
 	if (tunnel->sock == NULL)
 		goto out;
 
-	/* Check that this session doesn't already exist */
-	error = -EEXIST;
-	session = l2tp_session_find(net, tunnel, session_id);
-	if (session != NULL)
-		goto out;
-
 	/* Default MTU values. */
 	if (cfg->mtu == 0)
 		cfg->mtu = 1500 - PPPOL2TP_HEADER_OVERHEAD;
@@ -818,12 +815,13 @@ static int pppol2tp_session_create(struc
 		cfg->mru = cfg->mtu;
 
 	/* Allocate and initialize a new session context. */
-	error = -ENOMEM;
 	session = l2tp_session_create(sizeof(struct pppol2tp_session),
 				      tunnel, session_id,
 				      peer_session_id, cfg);
-	if (session == NULL)
+	if (IS_ERR(session)) {
+		error = PTR_ERR(session);
 		goto out;
+	}
 
 	ps = l2tp_session_priv(session);
 	ps->tunnel_sock = tunnel->sock;
@@ -1141,11 +1139,18 @@ static int pppol2tp_tunnel_ioctl(struct
 		if (stats.session_id != 0) {
 			/* resend to session ioctl handler */
 			struct l2tp_session *session =
-				l2tp_session_find(sock_net(sk), tunnel, stats.session_id);
-			if (session != NULL)
-				err = pppol2tp_session_ioctl(session, cmd, arg);
-			else
+				l2tp_session_get(sock_net(sk), tunnel,
+						 stats.session_id, true);
+
+			if (session) {
+				err = pppol2tp_session_ioctl(session, cmd,
+							     arg);
+				if (session->deref)
+					session->deref(session);
+				l2tp_session_dec_refcount(session);
+			} else {
 				err = -EBADR;
+			}
 			break;
 		}
 #ifdef CONFIG_XFRM
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/mac80211/iface.c linux-libre-4.9.36-gnu/net/mac80211/iface.c
--- linux-libre-4.9.35-gnu/net/mac80211/iface.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/mac80211/iface.c	2017-07-05 08:40:44.000000000 -0400
@@ -6,6 +6,7 @@
  * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
  * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
+ * Copyright (c) 2016        Intel Deutschland GmbH
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -1307,6 +1308,26 @@ static void ieee80211_iface_work(struct
 		} else if (ieee80211_is_action(mgmt->frame_control) &&
 			   mgmt->u.action.category == WLAN_CATEGORY_VHT) {
 			switch (mgmt->u.action.u.vht_group_notif.action_code) {
+			case WLAN_VHT_ACTION_OPMODE_NOTIF: {
+				struct ieee80211_rx_status *status;
+				enum nl80211_band band;
+				u8 opmode;
+
+				status = IEEE80211_SKB_RXCB(skb);
+				band = status->band;
+				opmode = mgmt->u.action.u.vht_opmode_notif.operating_mode;
+
+				mutex_lock(&local->sta_mtx);
+				sta = sta_info_get_bss(sdata, mgmt->sa);
+
+				if (sta)
+					ieee80211_vht_handle_opmode(sdata, sta,
+								    opmode,
+								    band);
+
+				mutex_unlock(&local->sta_mtx);
+				break;
+			}
 			case WLAN_VHT_ACTION_GROUPID_MGMT:
 				ieee80211_process_mu_groups(sdata, mgmt);
 				break;
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/mac80211/main.c linux-libre-4.9.36-gnu/net/mac80211/main.c
--- linux-libre-4.9.35-gnu/net/mac80211/main.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/mac80211/main.c	2017-07-05 08:40:44.000000000 -0400
@@ -908,12 +908,17 @@ int ieee80211_register_hw(struct ieee802
 		supp_ht = supp_ht || sband->ht_cap.ht_supported;
 		supp_vht = supp_vht || sband->vht_cap.vht_supported;
 
-		if (sband->ht_cap.ht_supported)
-			local->rx_chains =
-				max(ieee80211_mcs_to_chains(&sband->ht_cap.mcs),
-				    local->rx_chains);
+		if (!sband->ht_cap.ht_supported)
+			continue;
 
 		/* TODO: consider VHT for RX chains, hopefully it's the same */
+		local->rx_chains =
+			max(ieee80211_mcs_to_chains(&sband->ht_cap.mcs),
+			    local->rx_chains);
+
+		/* no need to mask, SM_PS_DISABLED has all bits set */
+		sband->ht_cap.cap |= WLAN_HT_CAP_SM_PS_DISABLED <<
+			             IEEE80211_HT_CAP_SM_PS_SHIFT;
 	}
 
 	/* if low-level driver supports AP, we also support VLAN */
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/mac80211/rx.c linux-libre-4.9.36-gnu/net/mac80211/rx.c
--- linux-libre-4.9.35-gnu/net/mac80211/rx.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/mac80211/rx.c	2017-07-05 08:40:44.000000000 -0400
@@ -2923,17 +2923,10 @@ ieee80211_rx_h_action(struct ieee80211_r
 
 		switch (mgmt->u.action.u.vht_opmode_notif.action_code) {
 		case WLAN_VHT_ACTION_OPMODE_NOTIF: {
-			u8 opmode;
-
 			/* verify opmode is present */
 			if (len < IEEE80211_MIN_ACTION_SIZE + 2)
 				goto invalid;
-
-			opmode = mgmt->u.action.u.vht_opmode_notif.operating_mode;
-
-			ieee80211_vht_handle_opmode(rx->sdata, rx->sta,
-						    opmode, status->band);
-			goto handled;
+			goto queue;
 		}
 		case WLAN_VHT_ACTION_GROUPID_MGMT: {
 			if (len < IEEE80211_MIN_ACTION_SIZE + 25)
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/mac80211/vht.c linux-libre-4.9.36-gnu/net/mac80211/vht.c
--- linux-libre-4.9.35-gnu/net/mac80211/vht.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/mac80211/vht.c	2017-07-05 08:40:44.000000000 -0400
@@ -527,8 +527,10 @@ void ieee80211_vht_handle_opmode(struct
 
 	u32 changed = __ieee80211_vht_handle_opmode(sdata, sta, opmode, band);
 
-	if (changed > 0)
+	if (changed > 0) {
+		ieee80211_recalc_min_chandef(sdata);
 		rate_control_rate_update(local, sband, sta, changed);
+	}
 }
 
 void ieee80211_get_vht_mask_from_cap(__le16 vht_cap,
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/netfilter/nf_conntrack_netlink.c linux-libre-4.9.36-gnu/net/netfilter/nf_conntrack_netlink.c
--- linux-libre-4.9.35-gnu/net/netfilter/nf_conntrack_netlink.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/netfilter/nf_conntrack_netlink.c	2017-07-05 08:40:44.000000000 -0400
@@ -45,6 +45,8 @@
 #include <net/netfilter/nf_conntrack_zones.h>
 #include <net/netfilter/nf_conntrack_timestamp.h>
 #include <net/netfilter/nf_conntrack_labels.h>
+#include <net/netfilter/nf_conntrack_seqadj.h>
+#include <net/netfilter/nf_conntrack_synproxy.h>
 #ifdef CONFIG_NF_NAT_NEEDED
 #include <net/netfilter/nf_nat_core.h>
 #include <net/netfilter/nf_nat_l4proto.h>
@@ -1800,6 +1802,8 @@ ctnetlink_create_conntrack(struct net *n
 	nf_ct_tstamp_ext_add(ct, GFP_ATOMIC);
 	nf_ct_ecache_ext_add(ct, 0, 0, GFP_ATOMIC);
 	nf_ct_labels_ext_add(ct);
+	nfct_seqadj_ext_add(ct);
+	nfct_synproxy_ext_add(ct);
 
 	/* we must add conntrack extensions before confirmation. */
 	ct->status |= IPS_CONFIRMED;
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/netfilter/xt_TCPMSS.c linux-libre-4.9.36-gnu/net/netfilter/xt_TCPMSS.c
--- linux-libre-4.9.35-gnu/net/netfilter/xt_TCPMSS.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/netfilter/xt_TCPMSS.c	2017-07-05 08:40:44.000000000 -0400
@@ -104,7 +104,7 @@ tcpmss_mangle_packet(struct sk_buff *skb
 	tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff);
 	tcp_hdrlen = tcph->doff * 4;
 
-	if (len < tcp_hdrlen)
+	if (len < tcp_hdrlen || tcp_hdrlen < sizeof(struct tcphdr))
 		return -1;
 
 	if (info->mss == XT_TCPMSS_CLAMP_PMTU) {
@@ -152,6 +152,10 @@ tcpmss_mangle_packet(struct sk_buff *skb
 	if (len > tcp_hdrlen)
 		return 0;
 
+	/* tcph->doff has 4 bits, do not wrap it to 0 */
+	if (tcp_hdrlen >= 15 * 4)
+		return 0;
+
 	/*
 	 * MSS Option not found ?! add it..
 	 */
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/sctp/socket.c linux-libre-4.9.36-gnu/net/sctp/socket.c
--- linux-libre-4.9.35-gnu/net/sctp/socket.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/sctp/socket.c	2017-07-05 08:40:44.000000000 -0400
@@ -239,7 +239,7 @@ static struct sctp_transport *sctp_addr_
 	union sctp_addr *laddr = (union sctp_addr *)addr;
 	struct sctp_transport *transport;
 
-	if (sctp_verify_addr(sk, laddr, af->sockaddr_len))
+	if (!af || sctp_verify_addr(sk, laddr, af->sockaddr_len))
 		return NULL;
 
 	addr_asoc = sctp_endpoint_lookup_assoc(sctp_sk(sk)->ep,
@@ -4460,13 +4460,13 @@ int sctp_for_each_endpoint(int (*cb)(str
 
 	for (head = sctp_ep_hashtable; hash < sctp_ep_hashsize;
 	     hash++, head++) {
-		read_lock(&head->lock);
+		read_lock_bh(&head->lock);
 		sctp_for_each_hentry(epb, &head->chain) {
 			err = cb(sctp_ep(epb), p);
 			if (err)
 				break;
 		}
-		read_unlock(&head->lock);
+		read_unlock_bh(&head->lock);
 	}
 
 	return err;
@@ -4506,9 +4506,8 @@ int sctp_for_each_transport(int (*cb)(st
 	if (err)
 		return err;
 
-	sctp_transport_get_idx(net, &hti, pos);
-	obj = sctp_transport_get_next(net, &hti);
-	for (; obj && !IS_ERR(obj); obj = sctp_transport_get_next(net, &hti)) {
+	obj = sctp_transport_get_idx(net, &hti, pos + 1);
+	for (; !IS_ERR_OR_NULL(obj); obj = sctp_transport_get_next(net, &hti)) {
 		struct sctp_transport *transport = obj;
 
 		if (!sctp_transport_hold(transport))
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/tipc/discover.c linux-libre-4.9.36-gnu/net/tipc/discover.c
--- linux-libre-4.9.35-gnu/net/tipc/discover.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/tipc/discover.c	2017-07-05 08:40:44.000000000 -0400
@@ -169,7 +169,7 @@ void tipc_disc_rcv(struct net *net, stru
 
 	/* Send response, if necessary */
 	if (respond && (mtyp == DSC_REQ_MSG)) {
-		rskb = tipc_buf_acquire(MAX_H_SIZE);
+		rskb = tipc_buf_acquire(MAX_H_SIZE, GFP_ATOMIC);
 		if (!rskb)
 			return;
 		tipc_disc_init_msg(net, rskb, DSC_RESP_MSG, bearer);
@@ -278,7 +278,7 @@ int tipc_disc_create(struct net *net, st
 	req = kmalloc(sizeof(*req), GFP_ATOMIC);
 	if (!req)
 		return -ENOMEM;
-	req->buf = tipc_buf_acquire(MAX_H_SIZE);
+	req->buf = tipc_buf_acquire(MAX_H_SIZE, GFP_ATOMIC);
 	if (!req->buf) {
 		kfree(req);
 		return -ENOMEM;
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/tipc/link.c linux-libre-4.9.36-gnu/net/tipc/link.c
--- linux-libre-4.9.35-gnu/net/tipc/link.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/tipc/link.c	2017-07-05 08:40:44.000000000 -0400
@@ -1395,7 +1395,7 @@ tnl:
 			msg_set_seqno(hdr, seqno++);
 		pktlen = msg_size(hdr);
 		msg_set_size(&tnlhdr, pktlen + INT_H_SIZE);
-		tnlskb = tipc_buf_acquire(pktlen + INT_H_SIZE);
+		tnlskb = tipc_buf_acquire(pktlen + INT_H_SIZE, GFP_ATOMIC);
 		if (!tnlskb) {
 			pr_warn("%sunable to send packet\n", link_co_err);
 			return;
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/tipc/msg.c linux-libre-4.9.36-gnu/net/tipc/msg.c
--- linux-libre-4.9.35-gnu/net/tipc/msg.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/tipc/msg.c	2017-07-05 08:40:44.000000000 -0400
@@ -58,12 +58,12 @@ static unsigned int align(unsigned int i
  * NOTE: Headroom is reserved to allow prepending of a data link header.
  *       There may also be unrequested tailroom present at the buffer's end.
  */
-struct sk_buff *tipc_buf_acquire(u32 size)
+struct sk_buff *tipc_buf_acquire(u32 size, gfp_t gfp)
 {
 	struct sk_buff *skb;
 	unsigned int buf_size = (BUF_HEADROOM + size + 3) & ~3u;
 
-	skb = alloc_skb_fclone(buf_size, GFP_ATOMIC);
+	skb = alloc_skb_fclone(buf_size, gfp);
 	if (skb) {
 		skb_reserve(skb, BUF_HEADROOM);
 		skb_put(skb, size);
@@ -95,7 +95,7 @@ struct sk_buff *tipc_msg_create(uint use
 	struct tipc_msg *msg;
 	struct sk_buff *buf;
 
-	buf = tipc_buf_acquire(hdr_sz + data_sz);
+	buf = tipc_buf_acquire(hdr_sz + data_sz, GFP_ATOMIC);
 	if (unlikely(!buf))
 		return NULL;
 
@@ -261,7 +261,7 @@ int tipc_msg_build(struct tipc_msg *mhdr
 
 	/* No fragmentation needed? */
 	if (likely(msz <= pktmax)) {
-		skb = tipc_buf_acquire(msz);
+		skb = tipc_buf_acquire(msz, GFP_KERNEL);
 		if (unlikely(!skb))
 			return -ENOMEM;
 		skb_orphan(skb);
@@ -282,7 +282,7 @@ int tipc_msg_build(struct tipc_msg *mhdr
 	msg_set_importance(&pkthdr, msg_importance(mhdr));
 
 	/* Prepare first fragment */
-	skb = tipc_buf_acquire(pktmax);
+	skb = tipc_buf_acquire(pktmax, GFP_KERNEL);
 	if (!skb)
 		return -ENOMEM;
 	skb_orphan(skb);
@@ -313,7 +313,7 @@ int tipc_msg_build(struct tipc_msg *mhdr
 			pktsz = drem + INT_H_SIZE;
 		else
 			pktsz = pktmax;
-		skb = tipc_buf_acquire(pktsz);
+		skb = tipc_buf_acquire(pktsz, GFP_KERNEL);
 		if (!skb) {
 			rc = -ENOMEM;
 			goto error;
@@ -448,7 +448,7 @@ bool tipc_msg_make_bundle(struct sk_buff
 	if (msz > (max / 2))
 		return false;
 
-	_skb = tipc_buf_acquire(max);
+	_skb = tipc_buf_acquire(max, GFP_ATOMIC);
 	if (!_skb)
 		return false;
 
@@ -496,7 +496,7 @@ bool tipc_msg_reverse(u32 own_node,  str
 
 	/* Never return SHORT header; expand by replacing buffer if necessary */
 	if (msg_short(hdr)) {
-		*skb = tipc_buf_acquire(BASIC_H_SIZE + dlen);
+		*skb = tipc_buf_acquire(BASIC_H_SIZE + dlen, GFP_ATOMIC);
 		if (!*skb)
 			goto exit;
 		memcpy((*skb)->data + BASIC_H_SIZE, msg_data(hdr), dlen);
@@ -508,7 +508,7 @@ bool tipc_msg_reverse(u32 own_node,  str
 	}
 
 	if (skb_cloned(_skb) &&
-	    pskb_expand_head(_skb, BUF_HEADROOM, BUF_TAILROOM, GFP_KERNEL))
+	    pskb_expand_head(_skb, BUF_HEADROOM, BUF_TAILROOM, GFP_ATOMIC))
 		goto exit;
 
 	/* Now reverse the concerned fields */
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/tipc/msg.h linux-libre-4.9.36-gnu/net/tipc/msg.h
--- linux-libre-4.9.35-gnu/net/tipc/msg.h	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/tipc/msg.h	2017-07-05 08:40:44.000000000 -0400
@@ -820,7 +820,7 @@ static inline bool msg_is_reset(struct t
 	return (msg_user(hdr) == LINK_PROTOCOL) && (msg_type(hdr) == RESET_MSG);
 }
 
-struct sk_buff *tipc_buf_acquire(u32 size);
+struct sk_buff *tipc_buf_acquire(u32 size, gfp_t gfp);
 bool tipc_msg_validate(struct sk_buff *skb);
 bool tipc_msg_reverse(u32 own_addr, struct sk_buff **skb, int err);
 void tipc_msg_init(u32 own_addr, struct tipc_msg *m, u32 user, u32 type,
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/tipc/name_distr.c linux-libre-4.9.36-gnu/net/tipc/name_distr.c
--- linux-libre-4.9.35-gnu/net/tipc/name_distr.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/tipc/name_distr.c	2017-07-05 08:40:44.000000000 -0400
@@ -69,7 +69,7 @@ static struct sk_buff *named_prepare_buf
 					 u32 dest)
 {
 	struct tipc_net *tn = net_generic(net, tipc_net_id);
-	struct sk_buff *buf = tipc_buf_acquire(INT_H_SIZE + size);
+	struct sk_buff *buf = tipc_buf_acquire(INT_H_SIZE + size, GFP_ATOMIC);
 	struct tipc_msg *msg;
 
 	if (buf != NULL) {
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/unix/af_unix.c linux-libre-4.9.36-gnu/net/unix/af_unix.c
--- linux-libre-4.9.35-gnu/net/unix/af_unix.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/unix/af_unix.c	2017-07-05 08:40:44.000000000 -0400
@@ -998,7 +998,8 @@ static int unix_bind(struct socket *sock
 	struct path path = { NULL, NULL };
 
 	err = -EINVAL;
-	if (sunaddr->sun_family != AF_UNIX)
+	if (addr_len < offsetofend(struct sockaddr_un, sun_family) ||
+	    sunaddr->sun_family != AF_UNIX)
 		goto out;
 
 	if (addr_len == sizeof(short)) {
@@ -1109,6 +1110,10 @@ static int unix_dgram_connect(struct soc
 	unsigned int hash;
 	int err;
 
+	err = -EINVAL;
+	if (alen < offsetofend(struct sockaddr, sa_family))
+		goto out;
+
 	if (addr->sa_family != AF_UNSPEC) {
 		err = unix_mkname(sunaddr, alen, &hash);
 		if (err < 0)
diff -druNp --no-dereference linux-libre-4.9.35-gnu/net/xfrm/xfrm_policy.c linux-libre-4.9.36-gnu/net/xfrm/xfrm_policy.c
--- linux-libre-4.9.35-gnu/net/xfrm/xfrm_policy.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/net/xfrm/xfrm_policy.c	2017-07-05 08:40:44.000000000 -0400
@@ -1808,43 +1808,6 @@ free_dst:
 	goto out;
 }
 
-#ifdef CONFIG_XFRM_SUB_POLICY
-static int xfrm_dst_alloc_copy(void **target, const void *src, int size)
-{
-	if (!*target) {
-		*target = kmalloc(size, GFP_ATOMIC);
-		if (!*target)
-			return -ENOMEM;
-	}
-
-	memcpy(*target, src, size);
-	return 0;
-}
-#endif
-
-static int xfrm_dst_update_parent(struct dst_entry *dst,
-				  const struct xfrm_selector *sel)
-{
-#ifdef CONFIG_XFRM_SUB_POLICY
-	struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
-	return xfrm_dst_alloc_copy((void **)&(xdst->partner),
-				   sel, sizeof(*sel));
-#else
-	return 0;
-#endif
-}
-
-static int xfrm_dst_update_origin(struct dst_entry *dst,
-				  const struct flowi *fl)
-{
-#ifdef CONFIG_XFRM_SUB_POLICY
-	struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
-	return xfrm_dst_alloc_copy((void **)&(xdst->origin), fl, sizeof(*fl));
-#else
-	return 0;
-#endif
-}
-
 static int xfrm_expand_policies(const struct flowi *fl, u16 family,
 				struct xfrm_policy **pols,
 				int *num_pols, int *num_xfrms)
@@ -1916,16 +1879,6 @@ xfrm_resolve_and_create_bundle(struct xf
 
 	xdst = (struct xfrm_dst *)dst;
 	xdst->num_xfrms = err;
-	if (num_pols > 1)
-		err = xfrm_dst_update_parent(dst, &pols[1]->selector);
-	else
-		err = xfrm_dst_update_origin(dst, fl);
-	if (unlikely(err)) {
-		dst_free(dst);
-		XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTBUNDLECHECKERROR);
-		return ERR_PTR(err);
-	}
-
 	xdst->num_pols = num_pols;
 	memcpy(xdst->pols, pols, sizeof(struct xfrm_policy *) * num_pols);
 	xdst->policy_genid = atomic_read(&pols[0]->genid);
diff -druNp --no-dereference linux-libre-4.9.35-gnu/sound/pci/hda/hda_codec.h linux-libre-4.9.36-gnu/sound/pci/hda/hda_codec.h
--- linux-libre-4.9.35-gnu/sound/pci/hda/hda_codec.h	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/sound/pci/hda/hda_codec.h	2017-07-05 08:40:44.000000000 -0400
@@ -294,6 +294,8 @@ struct hda_codec {
 
 #define list_for_each_codec(c, bus) \
 	list_for_each_entry(c, &(bus)->core.codec_list, core.list)
+#define list_for_each_codec_safe(c, n, bus)				\
+	list_for_each_entry_safe(c, n, &(bus)->core.codec_list, core.list)
 
 /* snd_hda_codec_read/write optional flags */
 #define HDA_RW_NO_RESPONSE_FALLBACK	(1 << 0)
diff -druNp --no-dereference linux-libre-4.9.35-gnu/sound/pci/hda/hda_controller.c linux-libre-4.9.36-gnu/sound/pci/hda/hda_controller.c
--- linux-libre-4.9.35-gnu/sound/pci/hda/hda_controller.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/sound/pci/hda/hda_controller.c	2017-07-05 08:40:44.000000000 -0400
@@ -1333,8 +1333,12 @@ EXPORT_SYMBOL_GPL(azx_probe_codecs);
 /* configure each codec instance */
 int azx_codec_configure(struct azx *chip)
 {
-	struct hda_codec *codec;
-	list_for_each_codec(codec, &chip->bus) {
+	struct hda_codec *codec, *next;
+
+	/* use _safe version here since snd_hda_codec_configure() deregisters
+	 * the device upon error and deletes itself from the bus list.
+	 */
+	list_for_each_codec_safe(codec, next, &chip->bus) {
 		snd_hda_codec_configure(codec);
 	}
 	return 0;
diff -druNp --no-dereference linux-libre-4.9.35-gnu/sound/pci/hda/hda_generic.c linux-libre-4.9.36-gnu/sound/pci/hda/hda_generic.c
--- linux-libre-4.9.35-gnu/sound/pci/hda/hda_generic.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/sound/pci/hda/hda_generic.c	2017-07-05 08:40:44.000000000 -0400
@@ -3169,6 +3169,7 @@ static int check_dyn_adc_switch(struct h
 						spec->input_paths[i][nums]);
 					spec->input_paths[i][nums] =
 						spec->input_paths[i][n];
+					spec->input_paths[i][n] = 0;
 				}
 			}
 			nums++;
diff -druNp --no-dereference linux-libre-4.9.35-gnu/tools/arch/x86/lib/memcpy_64.S linux-libre-4.9.36-gnu/tools/arch/x86/lib/memcpy_64.S
--- linux-libre-4.9.35-gnu/tools/arch/x86/lib/memcpy_64.S	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/tools/arch/x86/lib/memcpy_64.S	2017-07-05 08:40:44.000000000 -0400
@@ -286,7 +286,7 @@ ENDPROC(memcpy_mcsafe_unrolled)
 	_ASM_EXTABLE_FAULT(.L_copy_leading_bytes, .L_memcpy_mcsafe_fail)
 	_ASM_EXTABLE_FAULT(.L_cache_w0, .L_memcpy_mcsafe_fail)
 	_ASM_EXTABLE_FAULT(.L_cache_w1, .L_memcpy_mcsafe_fail)
-	_ASM_EXTABLE_FAULT(.L_cache_w3, .L_memcpy_mcsafe_fail)
+	_ASM_EXTABLE_FAULT(.L_cache_w2, .L_memcpy_mcsafe_fail)
 	_ASM_EXTABLE_FAULT(.L_cache_w3, .L_memcpy_mcsafe_fail)
 	_ASM_EXTABLE_FAULT(.L_cache_w4, .L_memcpy_mcsafe_fail)
 	_ASM_EXTABLE_FAULT(.L_cache_w5, .L_memcpy_mcsafe_fail)
diff -druNp --no-dereference linux-libre-4.9.35-gnu/tools/objtool/arch/x86/decode.c linux-libre-4.9.36-gnu/tools/objtool/arch/x86/decode.c
--- linux-libre-4.9.35-gnu/tools/objtool/arch/x86/decode.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/tools/objtool/arch/x86/decode.c	2017-07-05 08:40:44.000000000 -0400
@@ -150,9 +150,9 @@ int arch_decode_instruction(struct elf *
 		*type = INSN_RETURN;
 		break;
 
-	case 0xc5: /* iret */
 	case 0xca: /* retf */
 	case 0xcb: /* retf */
+	case 0xcf: /* iret */
 		*type = INSN_CONTEXT_SWITCH;
 		break;
 
diff -druNp --no-dereference linux-libre-4.9.35-gnu/tools/objtool/builtin-check.c linux-libre-4.9.36-gnu/tools/objtool/builtin-check.c
--- linux-libre-4.9.35-gnu/tools/objtool/builtin-check.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/tools/objtool/builtin-check.c	2017-07-05 08:40:44.000000000 -0400
@@ -757,11 +757,20 @@ static struct rela *find_switch_table(st
 		     insn->jump_dest->offset > orig_insn->offset))
 		    break;
 
+		/* look for a relocation which references .rodata */
 		text_rela = find_rela_by_dest_range(insn->sec, insn->offset,
 						    insn->len);
-		if (text_rela && text_rela->sym == file->rodata->sym)
-			return find_rela_by_dest(file->rodata,
-						 text_rela->addend);
+		if (!text_rela || text_rela->sym != file->rodata->sym)
+			continue;
+
+		/*
+		 * Make sure the .rodata address isn't associated with a
+		 * symbol.  gcc jump tables are anonymous data.
+		 */
+		if (find_symbol_containing(file->rodata, text_rela->addend))
+			continue;
+
+		return find_rela_by_dest(file->rodata, text_rela->addend);
 	}
 
 	return NULL;
diff -druNp --no-dereference linux-libre-4.9.35-gnu/tools/objtool/elf.c linux-libre-4.9.36-gnu/tools/objtool/elf.c
--- linux-libre-4.9.35-gnu/tools/objtool/elf.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/tools/objtool/elf.c	2017-07-05 08:40:44.000000000 -0400
@@ -85,6 +85,18 @@ struct symbol *find_symbol_by_offset(str
 	return NULL;
 }
 
+struct symbol *find_symbol_containing(struct section *sec, unsigned long offset)
+{
+	struct symbol *sym;
+
+	list_for_each_entry(sym, &sec->symbol_list, list)
+		if (sym->type != STT_SECTION &&
+		    offset >= sym->offset && offset < sym->offset + sym->len)
+			return sym;
+
+	return NULL;
+}
+
 struct rela *find_rela_by_dest_range(struct section *sec, unsigned long offset,
 				     unsigned int len)
 {
diff -druNp --no-dereference linux-libre-4.9.35-gnu/tools/objtool/elf.h linux-libre-4.9.36-gnu/tools/objtool/elf.h
--- linux-libre-4.9.35-gnu/tools/objtool/elf.h	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/tools/objtool/elf.h	2017-07-05 08:40:44.000000000 -0400
@@ -79,6 +79,7 @@ struct elf {
 struct elf *elf_open(const char *name);
 struct section *find_section_by_name(struct elf *elf, const char *name);
 struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset);
+struct symbol *find_symbol_containing(struct section *sec, unsigned long offset);
 struct rela *find_rela_by_dest(struct section *sec, unsigned long offset);
 struct rela *find_rela_by_dest_range(struct section *sec, unsigned long offset,
 				     unsigned int len);
diff -druNp --no-dereference linux-libre-4.9.35-gnu/tools/perf/util/probe-event.c linux-libre-4.9.36-gnu/tools/perf/util/probe-event.c
--- linux-libre-4.9.35-gnu/tools/perf/util/probe-event.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/tools/perf/util/probe-event.c	2017-07-05 08:40:44.000000000 -0400
@@ -645,18 +645,31 @@ static int add_exec_to_probe_trace_event
 	return ret;
 }
 
-static int add_module_to_probe_trace_events(struct probe_trace_event *tevs,
-					    int ntevs, const char *module)
+static int
+post_process_module_probe_trace_events(struct probe_trace_event *tevs,
+				       int ntevs, const char *module,
+				       struct debuginfo *dinfo)
 {
+	Dwarf_Addr text_offs = 0;
 	int i, ret = 0;
 	char *mod_name = NULL;
+	struct map *map;
 
 	if (!module)
 		return 0;
 
-	mod_name = find_module_name(module);
+	map = get_target_map(module, false);
+	if (!map || debuginfo__get_text_offset(dinfo, &text_offs, true) < 0) {
+		pr_warning("Failed to get ELF symbols for %s\n", module);
+		return -EINVAL;
+	}
 
+	mod_name = find_module_name(module);
 	for (i = 0; i < ntevs; i++) {
+		ret = post_process_probe_trace_point(&tevs[i].point,
+						map, (unsigned long)text_offs);
+		if (ret < 0)
+			break;
 		tevs[i].point.module =
 			strdup(mod_name ? mod_name : module);
 		if (!tevs[i].point.module) {
@@ -666,6 +679,8 @@ static int add_module_to_probe_trace_eve
 	}
 
 	free(mod_name);
+	map__put(map);
+
 	return ret;
 }
 
@@ -722,7 +737,7 @@ arch__post_process_probe_trace_events(st
 static int post_process_probe_trace_events(struct perf_probe_event *pev,
 					   struct probe_trace_event *tevs,
 					   int ntevs, const char *module,
-					   bool uprobe)
+					   bool uprobe, struct debuginfo *dinfo)
 {
 	int ret;
 
@@ -730,7 +745,8 @@ static int post_process_probe_trace_even
 		ret = add_exec_to_probe_trace_events(tevs, ntevs, module);
 	else if (module)
 		/* Currently ref_reloc_sym based probe is not for drivers */
-		ret = add_module_to_probe_trace_events(tevs, ntevs, module);
+		ret = post_process_module_probe_trace_events(tevs, ntevs,
+							     module, dinfo);
 	else
 		ret = post_process_kernel_probe_trace_events(tevs, ntevs);
 
@@ -774,30 +790,27 @@ static int try_to_find_probe_trace_event
 		}
 	}
 
-	debuginfo__delete(dinfo);
-
 	if (ntevs > 0) {	/* Succeeded to find trace events */
 		pr_debug("Found %d probe_trace_events.\n", ntevs);
 		ret = post_process_probe_trace_events(pev, *tevs, ntevs,
-						pev->target, pev->uprobes);
+					pev->target, pev->uprobes, dinfo);
 		if (ret < 0 || ret == ntevs) {
+			pr_debug("Post processing failed or all events are skipped. (%d)\n", ret);
 			clear_probe_trace_events(*tevs, ntevs);
 			zfree(tevs);
+			ntevs = 0;
 		}
-		if (ret != ntevs)
-			return ret < 0 ? ret : ntevs;
-		ntevs = 0;
-		/* Fall through */
 	}
 
+	debuginfo__delete(dinfo);
+
 	if (ntevs == 0)	{	/* No error but failed to find probe point. */
 		pr_warning("Probe point '%s' not found.\n",
 			   synthesize_perf_probe_point(&pev->point));
 		return -ENOENT;
-	}
-	/* Error path : ntevs < 0 */
-	pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs);
-	if (ntevs < 0) {
+	} else if (ntevs < 0) {
+		/* Error path : ntevs < 0 */
+		pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs);
 		if (ntevs == -EBADF)
 			pr_warning("Warning: No dwarf info found in the vmlinux - "
 				"please rebuild kernel with CONFIG_DEBUG_INFO=y.\n");
diff -druNp --no-dereference linux-libre-4.9.35-gnu/tools/perf/util/probe-finder.c linux-libre-4.9.36-gnu/tools/perf/util/probe-finder.c
--- linux-libre-4.9.35-gnu/tools/perf/util/probe-finder.c	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/tools/perf/util/probe-finder.c	2017-07-05 08:40:44.000000000 -0400
@@ -1501,7 +1501,8 @@ int debuginfo__find_available_vars_at(st
 }
 
 /* For the kernel module, we need a special code to get a DIE */
-static int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs)
+int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs,
+				bool adjust_offset)
 {
 	int n, i;
 	Elf32_Word shndx;
@@ -1530,6 +1531,8 @@ static int debuginfo__get_text_offset(st
 			if (!shdr)
 				return -ENOENT;
 			*offs = shdr->sh_addr;
+			if (adjust_offset)
+				*offs -= shdr->sh_offset;
 		}
 	}
 	return 0;
@@ -1543,16 +1546,12 @@ int debuginfo__find_probe_point(struct d
 	Dwarf_Addr _addr = 0, baseaddr = 0;
 	const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp;
 	int baseline = 0, lineno = 0, ret = 0;
-	bool reloc = false;
 
-retry:
+	/* We always need to relocate the address for aranges */
+	if (debuginfo__get_text_offset(dbg, &baseaddr, false) == 0)
+		addr += baseaddr;
 	/* Find cu die */
 	if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr, &cudie)) {
-		if (!reloc && debuginfo__get_text_offset(dbg, &baseaddr) == 0) {
-			addr += baseaddr;
-			reloc = true;
-			goto retry;
-		}
 		pr_warning("Failed to find debug information for address %lx\n",
 			   addr);
 		ret = -EINVAL;
diff -druNp --no-dereference linux-libre-4.9.35-gnu/tools/perf/util/probe-finder.h linux-libre-4.9.36-gnu/tools/perf/util/probe-finder.h
--- linux-libre-4.9.35-gnu/tools/perf/util/probe-finder.h	2017-06-29 07:00:49.000000000 -0400
+++ linux-libre-4.9.36-gnu/tools/perf/util/probe-finder.h	2017-07-05 08:40:44.000000000 -0400
@@ -46,6 +46,9 @@ int debuginfo__find_trace_events(struct
 int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr,
 				struct perf_probe_point *ppt);
 
+int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs,
+			       bool adjust_offset);
+
 /* Find a line range */
 int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr);
 
