diff -druNp --no-dereference linux-libre-4.9.27-gnu/arch/arm/boot/dts/bcm958522er.dts linux-libre-4.9.28-gnu/arch/arm/boot/dts/bcm958522er.dts
--- linux-libre-4.9.27-gnu/arch/arm/boot/dts/bcm958522er.dts	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/arch/arm/boot/dts/bcm958522er.dts	2017-05-14 08:00:37.000000000 -0400
@@ -55,6 +55,7 @@
 	gpio-restart {
 		compatible = "gpio-restart";
 		gpios = <&gpioa 15 GPIO_ACTIVE_LOW>;
+		open-source;
 		priority = <200>;
 	};
 };
diff -druNp --no-dereference linux-libre-4.9.27-gnu/arch/arm/boot/dts/bcm958525er.dts linux-libre-4.9.28-gnu/arch/arm/boot/dts/bcm958525er.dts
--- linux-libre-4.9.27-gnu/arch/arm/boot/dts/bcm958525er.dts	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/arch/arm/boot/dts/bcm958525er.dts	2017-05-14 08:00:37.000000000 -0400
@@ -55,6 +55,7 @@
 	gpio-restart {
 		compatible = "gpio-restart";
 		gpios = <&gpioa 15 GPIO_ACTIVE_LOW>;
+		open-source;
 		priority = <200>;
 	};
 };
diff -druNp --no-dereference linux-libre-4.9.27-gnu/arch/arm/boot/dts/bcm958525xmc.dts linux-libre-4.9.28-gnu/arch/arm/boot/dts/bcm958525xmc.dts
--- linux-libre-4.9.27-gnu/arch/arm/boot/dts/bcm958525xmc.dts	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/arch/arm/boot/dts/bcm958525xmc.dts	2017-05-14 08:00:37.000000000 -0400
@@ -55,6 +55,7 @@
 	gpio-restart {
 		compatible = "gpio-restart";
 		gpios = <&gpioa 31 GPIO_ACTIVE_LOW>;
+		open-source;
 		priority = <200>;
 	};
 };
diff -druNp --no-dereference linux-libre-4.9.27-gnu/arch/arm/boot/dts/bcm958622hr.dts linux-libre-4.9.28-gnu/arch/arm/boot/dts/bcm958622hr.dts
--- linux-libre-4.9.27-gnu/arch/arm/boot/dts/bcm958622hr.dts	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/arch/arm/boot/dts/bcm958622hr.dts	2017-05-14 08:00:37.000000000 -0400
@@ -55,6 +55,7 @@
 	gpio-restart {
 		compatible = "gpio-restart";
 		gpios = <&gpioa 15 GPIO_ACTIVE_LOW>;
+		open-source;
 		priority = <200>;
 	};
 };
diff -druNp --no-dereference linux-libre-4.9.27-gnu/arch/arm/boot/dts/bcm958623hr.dts linux-libre-4.9.28-gnu/arch/arm/boot/dts/bcm958623hr.dts
--- linux-libre-4.9.27-gnu/arch/arm/boot/dts/bcm958623hr.dts	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/arch/arm/boot/dts/bcm958623hr.dts	2017-05-14 08:00:37.000000000 -0400
@@ -55,6 +55,7 @@
 	gpio-restart {
 		compatible = "gpio-restart";
 		gpios = <&gpioa 15 GPIO_ACTIVE_LOW>;
+		open-source;
 		priority = <200>;
 	};
 };
diff -druNp --no-dereference linux-libre-4.9.27-gnu/arch/arm/boot/dts/bcm958625hr.dts linux-libre-4.9.28-gnu/arch/arm/boot/dts/bcm958625hr.dts
--- linux-libre-4.9.27-gnu/arch/arm/boot/dts/bcm958625hr.dts	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/arch/arm/boot/dts/bcm958625hr.dts	2017-05-14 08:00:37.000000000 -0400
@@ -55,6 +55,7 @@
 	gpio-restart {
 		compatible = "gpio-restart";
 		gpios = <&gpioa 15 GPIO_ACTIVE_LOW>;
+		open-source;
 		priority = <200>;
 	};
 };
diff -druNp --no-dereference linux-libre-4.9.27-gnu/arch/arm/boot/dts/bcm988312hr.dts linux-libre-4.9.28-gnu/arch/arm/boot/dts/bcm988312hr.dts
--- linux-libre-4.9.27-gnu/arch/arm/boot/dts/bcm988312hr.dts	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/arch/arm/boot/dts/bcm988312hr.dts	2017-05-14 08:00:37.000000000 -0400
@@ -55,6 +55,7 @@
 	gpio-restart {
 		compatible = "gpio-restart";
 		gpios = <&gpioa 15 GPIO_ACTIVE_LOW>;
+		open-source;
 		priority = <200>;
 	};
 };
diff -druNp --no-dereference linux-libre-4.9.27-gnu/arch/arm/boot/dts/qcom-ipq8064.dtsi linux-libre-4.9.28-gnu/arch/arm/boot/dts/qcom-ipq8064.dtsi
--- linux-libre-4.9.27-gnu/arch/arm/boot/dts/qcom-ipq8064.dtsi	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/arch/arm/boot/dts/qcom-ipq8064.dtsi	2017-05-14 08:00:37.000000000 -0400
@@ -65,13 +65,13 @@
 		cxo_board {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
-			clock-frequency = <19200000>;
+			clock-frequency = <25000000>;
 		};
 
 		pxo_board {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
-			clock-frequency = <27000000>;
+			clock-frequency = <25000000>;
 		};
 
 		sleep_clk: sleep_clk {
diff -druNp --no-dereference linux-libre-4.9.27-gnu/arch/arm/boot/dts/sun7i-a20-lamobo-r1.dts linux-libre-4.9.28-gnu/arch/arm/boot/dts/sun7i-a20-lamobo-r1.dts
--- linux-libre-4.9.27-gnu/arch/arm/boot/dts/sun7i-a20-lamobo-r1.dts	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/arch/arm/boot/dts/sun7i-a20-lamobo-r1.dts	2017-05-14 08:00:37.000000000 -0400
@@ -167,7 +167,7 @@
 					reg = <8>;
 					label = "cpu";
 					ethernet = <&gmac>;
-					phy-mode = "rgmii";
+					phy-mode = "rgmii-txid";
 					fixed-link {
 						speed = <1000>;
 						full-duplex;
diff -druNp --no-dereference linux-libre-4.9.27-gnu/arch/arm/mach-omap2/omap-headsmp.S linux-libre-4.9.28-gnu/arch/arm/mach-omap2/omap-headsmp.S
--- linux-libre-4.9.27-gnu/arch/arm/mach-omap2/omap-headsmp.S	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/arch/arm/mach-omap2/omap-headsmp.S	2017-05-14 08:00:37.000000000 -0400
@@ -17,6 +17,7 @@
 
 #include <linux/linkage.h>
 #include <linux/init.h>
+#include <asm/assembler.h>
 
 #include "omap44xx.h"
 
@@ -66,7 +67,7 @@ wait_2:	ldr	r2, =AUX_CORE_BOOT0_PA	@ rea
 	cmp	r0, r4
 	bne	wait_2
 	ldr	r12, =API_HYP_ENTRY
-	adr	r0, hyp_boot
+	badr	r0, hyp_boot
 	smc	#0
 hyp_boot:
 	b	omap_secondary_startup
diff -druNp --no-dereference linux-libre-4.9.27-gnu/arch/arm64/boot/dts/renesas/r8a7795.dtsi linux-libre-4.9.28-gnu/arch/arm64/boot/dts/renesas/r8a7795.dtsi
--- linux-libre-4.9.27-gnu/arch/arm64/boot/dts/renesas/r8a7795.dtsi	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/arch/arm64/boot/dts/renesas/r8a7795.dtsi	2017-05-14 08:00:37.000000000 -0400
@@ -553,6 +553,7 @@
 			phy-mode = "rgmii-id";
 			#address-cells = <1>;
 			#size-cells = <0>;
+			status = "disabled";
 		};
 
 		can0: can@e6c30000 {
diff -druNp --no-dereference linux-libre-4.9.27-gnu/arch/arm64/include/asm/pgtable.h linux-libre-4.9.28-gnu/arch/arm64/include/asm/pgtable.h
--- linux-libre-4.9.27-gnu/arch/arm64/include/asm/pgtable.h	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/arch/arm64/include/asm/pgtable.h	2017-05-14 08:00:37.000000000 -0400
@@ -71,9 +71,8 @@ extern unsigned long empty_zero_page[PAG
 #define pte_young(pte)		(!!(pte_val(pte) & PTE_AF))
 #define pte_special(pte)	(!!(pte_val(pte) & PTE_SPECIAL))
 #define pte_write(pte)		(!!(pte_val(pte) & PTE_WRITE))
-#define pte_exec(pte)		(!(pte_val(pte) & PTE_UXN))
+#define pte_user_exec(pte)	(!(pte_val(pte) & PTE_UXN))
 #define pte_cont(pte)		(!!(pte_val(pte) & PTE_CONT))
-#define pte_ng(pte)		(!!(pte_val(pte) & PTE_NG))
 
 #ifdef CONFIG_ARM64_HW_AFDBM
 #define pte_hw_dirty(pte)	(pte_write(pte) && !(pte_val(pte) & PTE_RDONLY))
@@ -84,8 +83,12 @@ extern unsigned long empty_zero_page[PAG
 #define pte_dirty(pte)		(pte_sw_dirty(pte) || pte_hw_dirty(pte))
 
 #define pte_valid(pte)		(!!(pte_val(pte) & PTE_VALID))
-#define pte_valid_global(pte) \
-	((pte_val(pte) & (PTE_VALID | PTE_NG)) == PTE_VALID)
+/*
+ * Execute-only user mappings do not have the PTE_USER bit set. All valid
+ * kernel mappings have the PTE_UXN bit set.
+ */
+#define pte_valid_not_user(pte) \
+	((pte_val(pte) & (PTE_VALID | PTE_USER | PTE_UXN)) == (PTE_VALID | PTE_UXN))
 #define pte_valid_young(pte) \
 	((pte_val(pte) & (PTE_VALID | PTE_AF)) == (PTE_VALID | PTE_AF))
 
@@ -178,7 +181,7 @@ static inline void set_pte(pte_t *ptep,
 	 * Only if the new pte is valid and kernel, otherwise TLB maintenance
 	 * or update_mmu_cache() have the necessary barriers.
 	 */
-	if (pte_valid_global(pte)) {
+	if (pte_valid_not_user(pte)) {
 		dsb(ishst);
 		isb();
 	}
@@ -212,7 +215,7 @@ static inline void set_pte_at(struct mm_
 			pte_val(pte) &= ~PTE_RDONLY;
 		else
 			pte_val(pte) |= PTE_RDONLY;
-		if (pte_ng(pte) && pte_exec(pte) && !pte_special(pte))
+		if (pte_user_exec(pte) && !pte_special(pte))
 			__sync_icache_dcache(pte, addr);
 	}
 
diff -druNp --no-dereference linux-libre-4.9.27-gnu/arch/arm64/net/bpf_jit_comp.c linux-libre-4.9.28-gnu/arch/arm64/net/bpf_jit_comp.c
--- linux-libre-4.9.27-gnu/arch/arm64/net/bpf_jit_comp.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/arch/arm64/net/bpf_jit_comp.c	2017-05-14 08:00:37.000000000 -0400
@@ -779,14 +779,14 @@ static int build_body(struct jit_ctx *ct
 		int ret;
 
 		ret = build_insn(insn, ctx);
-
-		if (ctx->image == NULL)
-			ctx->offset[i] = ctx->idx;
-
 		if (ret > 0) {
 			i++;
+			if (ctx->image == NULL)
+				ctx->offset[i] = ctx->idx;
 			continue;
 		}
+		if (ctx->image == NULL)
+			ctx->offset[i] = ctx->idx;
 		if (ret)
 			return ret;
 	}
diff -druNp --no-dereference linux-libre-4.9.27-gnu/arch/mips/kernel/mips-r2-to-r6-emul.c linux-libre-4.9.28-gnu/arch/mips/kernel/mips-r2-to-r6-emul.c
--- linux-libre-4.9.27-gnu/arch/mips/kernel/mips-r2-to-r6-emul.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/arch/mips/kernel/mips-r2-to-r6-emul.c	2017-05-14 08:00:37.000000000 -0400
@@ -433,8 +433,8 @@ static int multu_func(struct pt_regs *re
 	rs = regs->regs[MIPSInst_RS(ir)];
 	res = (u64)rt * (u64)rs;
 	rt = res;
-	regs->lo = (s64)rt;
-	regs->hi = (s64)(res >> 32);
+	regs->lo = (s64)(s32)rt;
+	regs->hi = (s64)(s32)(res >> 32);
 
 	MIPS_R2_STATS(muls);
 
@@ -670,9 +670,9 @@ static int maddu_func(struct pt_regs *re
 	res += ((((s64)rt) << 32) | (u32)rs);
 
 	rt = res;
-	regs->lo = (s64)rt;
+	regs->lo = (s64)(s32)rt;
 	rs = res >> 32;
-	regs->hi = (s64)rs;
+	regs->hi = (s64)(s32)rs;
 
 	MIPS_R2_STATS(dsps);
 
@@ -728,9 +728,9 @@ static int msubu_func(struct pt_regs *re
 	res = ((((s64)rt) << 32) | (u32)rs) - res;
 
 	rt = res;
-	regs->lo = (s64)rt;
+	regs->lo = (s64)(s32)rt;
 	rs = res >> 32;
-	regs->hi = (s64)rs;
+	regs->hi = (s64)(s32)rs;
 
 	MIPS_R2_STATS(dsps);
 
diff -druNp --no-dereference linux-libre-4.9.27-gnu/arch/powerpc/include/asm/reg.h linux-libre-4.9.28-gnu/arch/powerpc/include/asm/reg.h
--- linux-libre-4.9.27-gnu/arch/powerpc/include/asm/reg.h	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/arch/powerpc/include/asm/reg.h	2017-05-14 08:00:37.000000000 -0400
@@ -337,7 +337,7 @@
 #define   LPCR_DPFD_SH		52
 #define   LPCR_DPFD		(ASM_CONST(7) << LPCR_DPFD_SH)
 #define   LPCR_VRMASD_SH	47
-#define   LPCR_VRMASD		(ASM_CONST(1) << LPCR_VRMASD_SH)
+#define   LPCR_VRMASD		(ASM_CONST(0x1f) << LPCR_VRMASD_SH)
 #define   LPCR_VRMA_L		ASM_CONST(0x0008000000000000)
 #define   LPCR_VRMA_LP0		ASM_CONST(0x0001000000000000)
 #define   LPCR_VRMA_LP1		ASM_CONST(0x0000800000000000)
diff -druNp --no-dereference linux-libre-4.9.27-gnu/arch/powerpc/Kconfig linux-libre-4.9.28-gnu/arch/powerpc/Kconfig
--- linux-libre-4.9.27-gnu/arch/powerpc/Kconfig	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/arch/powerpc/Kconfig	2017-05-14 08:00:37.000000000 -0400
@@ -388,8 +388,8 @@ config DISABLE_MPROFILE_KERNEL
 	  be disabled also.
 
 	  If you have a toolchain which supports mprofile-kernel, then you can
-	  enable this. Otherwise leave it disabled. If you're not sure, say
-	  "N".
+	  disable this. Otherwise leave it enabled. If you're not sure, say
+	  "Y".
 
 config MPROFILE_KERNEL
 	depends on PPC64 && CPU_LITTLE_ENDIAN
diff -druNp --no-dereference linux-libre-4.9.27-gnu/arch/powerpc/kernel/Makefile linux-libre-4.9.28-gnu/arch/powerpc/kernel/Makefile
--- linux-libre-4.9.27-gnu/arch/powerpc/kernel/Makefile	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/arch/powerpc/kernel/Makefile	2017-05-14 08:00:37.000000000 -0400
@@ -15,7 +15,7 @@ CFLAGS_btext.o		+= -fPIC
 endif
 
 CFLAGS_cputable.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
-CFLAGS_init.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
+CFLAGS_prom_init.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
 CFLAGS_btext.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
 CFLAGS_prom.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
 
diff -druNp --no-dereference linux-libre-4.9.27-gnu/arch/powerpc/platforms/powernv/opal-wrappers.S linux-libre-4.9.28-gnu/arch/powerpc/platforms/powernv/opal-wrappers.S
--- linux-libre-4.9.27-gnu/arch/powerpc/platforms/powernv/opal-wrappers.S	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/arch/powerpc/platforms/powernv/opal-wrappers.S	2017-05-14 08:00:37.000000000 -0400
@@ -146,7 +146,7 @@ opal_tracepoint_entry:
 opal_tracepoint_return:
 	std	r3,STK_REG(R31)(r1)
 	mr	r4,r3
-	ld	r0,STK_REG(R23)(r1)
+	ld	r3,STK_REG(R23)(r1)
 	bl	__trace_opal_exit
 	ld	r3,STK_REG(R31)(r1)
 	addi	r1,r1,STACKFRAMESIZE
diff -druNp --no-dereference linux-libre-4.9.27-gnu/arch/sparc/kernel/head_64.S linux-libre-4.9.28-gnu/arch/sparc/kernel/head_64.S
--- linux-libre-4.9.27-gnu/arch/sparc/kernel/head_64.S	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/arch/sparc/kernel/head_64.S	2017-05-14 08:00:37.000000000 -0400
@@ -935,3 +935,9 @@ ENTRY(__retl_o1)
 	retl
 	 mov	%o1, %o0
 ENDPROC(__retl_o1)
+
+ENTRY(__retl_o1_asi)
+	wr      %o5, 0x0, %asi
+	retl
+	 mov    %o1, %o0
+ENDPROC(__retl_o1_asi)
diff -druNp --no-dereference linux-libre-4.9.27-gnu/arch/sparc/lib/GENbzero.S linux-libre-4.9.28-gnu/arch/sparc/lib/GENbzero.S
--- linux-libre-4.9.27-gnu/arch/sparc/lib/GENbzero.S	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/arch/sparc/lib/GENbzero.S	2017-05-14 08:00:37.000000000 -0400
@@ -8,7 +8,7 @@
 98:	x,y;			\
 	.section __ex_table,"a";\
 	.align 4;		\
-	.word 98b, __retl_o1;	\
+	.word 98b, __retl_o1_asi;\
 	.text;			\
 	.align 4;
 
diff -druNp --no-dereference linux-libre-4.9.27-gnu/arch/sparc/lib/NGbzero.S linux-libre-4.9.28-gnu/arch/sparc/lib/NGbzero.S
--- linux-libre-4.9.27-gnu/arch/sparc/lib/NGbzero.S	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/arch/sparc/lib/NGbzero.S	2017-05-14 08:00:37.000000000 -0400
@@ -8,7 +8,7 @@
 98:	x,y;			\
 	.section __ex_table,"a";\
 	.align 4;		\
-	.word 98b, __retl_o1;	\
+	.word 98b, __retl_o1_asi;\
 	.text;			\
 	.align 4;
 
diff -druNp --no-dereference linux-libre-4.9.27-gnu/arch/x86/events/intel/pt.c linux-libre-4.9.28-gnu/arch/x86/events/intel/pt.c
--- linux-libre-4.9.27-gnu/arch/x86/events/intel/pt.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/arch/x86/events/intel/pt.c	2017-05-14 08:00:37.000000000 -0400
@@ -106,18 +106,24 @@ static struct attribute_group pt_cap_gro
 };
 
 PMU_FORMAT_ATTR(cyc,		"config:1"	);
+PMU_FORMAT_ATTR(pwr_evt,	"config:4"	);
+PMU_FORMAT_ATTR(fup_on_ptw,	"config:5"	);
 PMU_FORMAT_ATTR(mtc,		"config:9"	);
 PMU_FORMAT_ATTR(tsc,		"config:10"	);
 PMU_FORMAT_ATTR(noretcomp,	"config:11"	);
+PMU_FORMAT_ATTR(ptw,		"config:12"	);
 PMU_FORMAT_ATTR(mtc_period,	"config:14-17"	);
 PMU_FORMAT_ATTR(cyc_thresh,	"config:19-22"	);
 PMU_FORMAT_ATTR(psb_period,	"config:24-27"	);
 
 static struct attribute *pt_formats_attr[] = {
 	&format_attr_cyc.attr,
+	&format_attr_pwr_evt.attr,
+	&format_attr_fup_on_ptw.attr,
 	&format_attr_mtc.attr,
 	&format_attr_tsc.attr,
 	&format_attr_noretcomp.attr,
+	&format_attr_ptw.attr,
 	&format_attr_mtc_period.attr,
 	&format_attr_cyc_thresh.attr,
 	&format_attr_psb_period.attr,
diff -druNp --no-dereference linux-libre-4.9.27-gnu/arch/x86/include/asm/xen/events.h linux-libre-4.9.28-gnu/arch/x86/include/asm/xen/events.h
--- linux-libre-4.9.27-gnu/arch/x86/include/asm/xen/events.h	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/arch/x86/include/asm/xen/events.h	2017-05-14 08:00:37.000000000 -0400
@@ -20,4 +20,15 @@ static inline int xen_irqs_disabled(stru
 /* No need for a barrier -- XCHG is a barrier on x86. */
 #define xchg_xen_ulong(ptr, val) xchg((ptr), (val))
 
+extern int xen_have_vector_callback;
+
+/*
+ * Events delivered via platform PCI interrupts are always
+ * routed to vcpu 0 and hence cannot be rebound.
+ */
+static inline bool xen_support_evtchn_rebind(void)
+{
+	return (!xen_hvm_domain() || xen_have_vector_callback);
+}
+
 #endif /* _ASM_X86_XEN_EVENTS_H */
diff -druNp --no-dereference linux-libre-4.9.27-gnu/arch/x86/kernel/apic/io_apic.c linux-libre-4.9.28-gnu/arch/x86/kernel/apic/io_apic.c
--- linux-libre-4.9.27-gnu/arch/x86/kernel/apic/io_apic.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/arch/x86/kernel/apic/io_apic.c	2017-05-14 08:00:37.000000000 -0400
@@ -1876,6 +1876,7 @@ static struct irq_chip ioapic_chip __rea
 	.irq_ack		= irq_chip_ack_parent,
 	.irq_eoi		= ioapic_ack_level,
 	.irq_set_affinity	= ioapic_set_affinity,
+	.irq_retrigger		= irq_chip_retrigger_hierarchy,
 	.flags			= IRQCHIP_SKIP_SET_WAKE,
 };
 
@@ -1887,6 +1888,7 @@ static struct irq_chip ioapic_ir_chip __
 	.irq_ack		= irq_chip_ack_parent,
 	.irq_eoi		= ioapic_ir_ack_level,
 	.irq_set_affinity	= ioapic_set_affinity,
+	.irq_retrigger		= irq_chip_retrigger_hierarchy,
 	.flags			= IRQCHIP_SKIP_SET_WAKE,
 };
 
diff -druNp --no-dereference linux-libre-4.9.27-gnu/arch/x86/kernel/kprobes/common.h linux-libre-4.9.28-gnu/arch/x86/kernel/kprobes/common.h
--- linux-libre-4.9.27-gnu/arch/x86/kernel/kprobes/common.h	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/arch/x86/kernel/kprobes/common.h	2017-05-14 08:00:37.000000000 -0400
@@ -67,7 +67,7 @@
 #endif
 
 /* Ensure if the instruction can be boostable */
-extern int can_boost(kprobe_opcode_t *instruction);
+extern int can_boost(kprobe_opcode_t *instruction, void *addr);
 /* Recover instruction if given address is probed */
 extern unsigned long recover_probed_instruction(kprobe_opcode_t *buf,
 					 unsigned long addr);
diff -druNp --no-dereference linux-libre-4.9.27-gnu/arch/x86/kernel/kprobes/core.c linux-libre-4.9.28-gnu/arch/x86/kernel/kprobes/core.c
--- linux-libre-4.9.27-gnu/arch/x86/kernel/kprobes/core.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/arch/x86/kernel/kprobes/core.c	2017-05-14 08:00:37.000000000 -0400
@@ -166,12 +166,12 @@ NOKPROBE_SYMBOL(skip_prefixes);
  * Returns non-zero if opcode is boostable.
  * RIP relative instructions are adjusted at copying time in 64 bits mode
  */
-int can_boost(kprobe_opcode_t *opcodes)
+int can_boost(kprobe_opcode_t *opcodes, void *addr)
 {
 	kprobe_opcode_t opcode;
 	kprobe_opcode_t *orig_opcodes = opcodes;
 
-	if (search_exception_tables((unsigned long)opcodes))
+	if (search_exception_tables((unsigned long)addr))
 		return 0;	/* Page fault may occur on this address. */
 
 retry:
@@ -416,7 +416,7 @@ static int arch_copy_kprobe(struct kprob
 	 * __copy_instruction can modify the displacement of the instruction,
 	 * but it doesn't affect boostable check.
 	 */
-	if (can_boost(p->ainsn.insn))
+	if (can_boost(p->ainsn.insn, p->addr))
 		p->ainsn.boostable = 0;
 	else
 		p->ainsn.boostable = -1;
diff -druNp --no-dereference linux-libre-4.9.27-gnu/arch/x86/kernel/kprobes/opt.c linux-libre-4.9.28-gnu/arch/x86/kernel/kprobes/opt.c
--- linux-libre-4.9.27-gnu/arch/x86/kernel/kprobes/opt.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/arch/x86/kernel/kprobes/opt.c	2017-05-14 08:00:37.000000000 -0400
@@ -178,7 +178,7 @@ static int copy_optimized_instructions(u
 
 	while (len < RELATIVEJUMP_SIZE) {
 		ret = __copy_instruction(dest + len, src + len);
-		if (!ret || !can_boost(dest + len))
+		if (!ret || !can_boost(dest + len, src + len))
 			return -EINVAL;
 		len += ret;
 	}
diff -druNp --no-dereference linux-libre-4.9.27-gnu/arch/x86/kernel/pci-calgary_64.c linux-libre-4.9.28-gnu/arch/x86/kernel/pci-calgary_64.c
--- linux-libre-4.9.27-gnu/arch/x86/kernel/pci-calgary_64.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/arch/x86/kernel/pci-calgary_64.c	2017-05-14 08:00:37.000000000 -0400
@@ -296,7 +296,7 @@ static void iommu_free(struct iommu_tabl
 
 	/* were we called with bad_dma_address? */
 	badend = DMA_ERROR_CODE + (EMERGENCY_PAGES * PAGE_SIZE);
-	if (unlikely((dma_addr >= DMA_ERROR_CODE) && (dma_addr < badend))) {
+	if (unlikely(dma_addr < badend)) {
 		WARN(1, KERN_ERR "Calgary: driver tried unmapping bad DMA "
 		       "address 0x%Lx\n", dma_addr);
 		return;
diff -druNp --no-dereference linux-libre-4.9.27-gnu/arch/x86/kvm/cpuid.c linux-libre-4.9.28-gnu/arch/x86/kvm/cpuid.c
--- linux-libre-4.9.27-gnu/arch/x86/kvm/cpuid.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/arch/x86/kvm/cpuid.c	2017-05-14 08:00:37.000000000 -0400
@@ -846,12 +846,6 @@ void kvm_cpuid(struct kvm_vcpu *vcpu, u3
 	if (!best)
 		best = check_cpuid_limit(vcpu, function, index);
 
-	/*
-	 * Perfmon not yet supported for L2 guest.
-	 */
-	if (is_guest_mode(vcpu) && function == 0xa)
-		best = NULL;
-
 	if (best) {
 		*eax = best->eax;
 		*ebx = best->ebx;
diff -druNp --no-dereference linux-libre-4.9.27-gnu/arch/x86/kvm/vmx.c linux-libre-4.9.28-gnu/arch/x86/kvm/vmx.c
--- linux-libre-4.9.27-gnu/arch/x86/kvm/vmx.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/arch/x86/kvm/vmx.c	2017-05-14 08:00:37.000000000 -0400
@@ -8051,8 +8051,6 @@ static bool nested_vmx_exit_handled(stru
 	case EXIT_REASON_TASK_SWITCH:
 		return true;
 	case EXIT_REASON_CPUID:
-		if (kvm_register_read(vcpu, VCPU_REGS_RAX) == 0xa)
-			return false;
 		return true;
 	case EXIT_REASON_HLT:
 		return nested_cpu_has(vmcs12, CPU_BASED_HLT_EXITING);
@@ -8137,6 +8135,9 @@ static bool nested_vmx_exit_handled(stru
 		return nested_cpu_has2(vmcs12, SECONDARY_EXEC_XSAVES);
 	case EXIT_REASON_PREEMPTION_TIMER:
 		return false;
+	case EXIT_REASON_PML_FULL:
+		/* We don't expose PML support to L1. */
+		return false;
 	default:
 		return true;
 	}
@@ -10073,6 +10074,18 @@ static void prepare_vmcs02(struct kvm_vc
 
 	}
 
+	if (enable_pml) {
+		/*
+		 * Conceptually we want to copy the PML address and index from
+		 * vmcs01 here, and then back to vmcs01 on nested vmexit. But,
+		 * since we always flush the log on each vmexit, this happens
+		 * to be equivalent to simply resetting the fields in vmcs02.
+		 */
+		ASSERT(vmx->pml_pg);
+		vmcs_write64(PML_ADDRESS, page_to_phys(vmx->pml_pg));
+		vmcs_write16(GUEST_PML_INDEX, PML_ENTITY_NUM - 1);
+	}
+
 	if (nested_cpu_has_ept(vmcs12)) {
 		kvm_mmu_unload(vcpu);
 		nested_ept_init_mmu_context(vcpu);
diff -druNp --no-dereference linux-libre-4.9.27-gnu/arch/x86/pci/xen.c linux-libre-4.9.28-gnu/arch/x86/pci/xen.c
--- linux-libre-4.9.27-gnu/arch/x86/pci/xen.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/arch/x86/pci/xen.c	2017-05-14 08:00:37.000000000 -0400
@@ -447,7 +447,7 @@ void __init xen_msi_init(void)
 
 int __init pci_xen_hvm_init(void)
 {
-	if (!xen_feature(XENFEAT_hvm_pirqs))
+	if (!xen_have_vector_callback || !xen_feature(XENFEAT_hvm_pirqs))
 		return 0;
 
 #ifdef CONFIG_ACPI
diff -druNp --no-dereference linux-libre-4.9.27-gnu/arch/x86/platform/intel-mid/device_libs/platform_mrfld_wdt.c linux-libre-4.9.28-gnu/arch/x86/platform/intel-mid/device_libs/platform_mrfld_wdt.c
--- linux-libre-4.9.27-gnu/arch/x86/platform/intel-mid/device_libs/platform_mrfld_wdt.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/arch/x86/platform/intel-mid/device_libs/platform_mrfld_wdt.c	2017-05-14 08:00:37.000000000 -0400
@@ -19,7 +19,7 @@
 #include <asm/intel_scu_ipc.h>
 #include <asm/io_apic.h>
 
-#define TANGIER_EXT_TIMER0_MSI 15
+#define TANGIER_EXT_TIMER0_MSI 12
 
 static struct platform_device wdt_dev = {
 	.name = "intel_mid_wdt",
diff -druNp --no-dereference linux-libre-4.9.27-gnu/arch/x86/xen/enlighten.c linux-libre-4.9.28-gnu/arch/x86/xen/enlighten.c
--- linux-libre-4.9.27-gnu/arch/x86/xen/enlighten.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/arch/x86/xen/enlighten.c	2017-05-14 08:00:37.000000000 -0400
@@ -137,6 +137,8 @@ struct shared_info xen_dummy_shared_info
 void *xen_initial_gdt;
 
 RESERVE_BRK(shared_info_page_brk, PAGE_SIZE);
+__read_mostly int xen_have_vector_callback;
+EXPORT_SYMBOL_GPL(xen_have_vector_callback);
 
 static int xen_cpu_up_prepare(unsigned int cpu);
 static int xen_cpu_up_online(unsigned int cpu);
@@ -1521,7 +1523,10 @@ static void __init xen_pvh_early_guest_i
 	if (!xen_feature(XENFEAT_auto_translated_physmap))
 		return;
 
-	BUG_ON(!xen_feature(XENFEAT_hvm_callback_vector));
+	if (!xen_feature(XENFEAT_hvm_callback_vector))
+		return;
+
+	xen_have_vector_callback = 1;
 
 	xen_pvh_early_cpu_init(0, false);
 	xen_pvh_set_cr_flags(0);
@@ -1860,7 +1865,9 @@ static int xen_cpu_up_prepare(unsigned i
 		xen_vcpu_setup(cpu);
 	}
 
-	if (xen_pv_domain() || xen_feature(XENFEAT_hvm_safe_pvclock))
+	if (xen_pv_domain() ||
+	    (xen_have_vector_callback &&
+	     xen_feature(XENFEAT_hvm_safe_pvclock)))
 		xen_setup_timer(cpu);
 
 	rc = xen_smp_intr_init(cpu);
@@ -1876,7 +1883,9 @@ static int xen_cpu_dead(unsigned int cpu
 {
 	xen_smp_intr_free(cpu);
 
-	if (xen_pv_domain() || xen_feature(XENFEAT_hvm_safe_pvclock))
+	if (xen_pv_domain() ||
+	    (xen_have_vector_callback &&
+	     xen_feature(XENFEAT_hvm_safe_pvclock)))
 		xen_teardown_timer(cpu);
 
 	return 0;
@@ -1915,8 +1924,8 @@ static void __init xen_hvm_guest_init(vo
 
 	xen_panic_handler_init();
 
-	BUG_ON(!xen_feature(XENFEAT_hvm_callback_vector));
-
+	if (xen_feature(XENFEAT_hvm_callback_vector))
+		xen_have_vector_callback = 1;
 	xen_hvm_smp_init();
 	WARN_ON(xen_cpuhp_setup());
 	xen_unplug_emulated_devices();
@@ -1954,7 +1963,7 @@ bool xen_hvm_need_lapic(void)
 		return false;
 	if (!xen_hvm_domain())
 		return false;
-	if (xen_feature(XENFEAT_hvm_pirqs))
+	if (xen_feature(XENFEAT_hvm_pirqs) && xen_have_vector_callback)
 		return false;
 	return true;
 }
diff -druNp --no-dereference linux-libre-4.9.27-gnu/arch/x86/xen/smp.c linux-libre-4.9.28-gnu/arch/x86/xen/smp.c
--- linux-libre-4.9.27-gnu/arch/x86/xen/smp.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/arch/x86/xen/smp.c	2017-05-14 08:00:37.000000000 -0400
@@ -765,6 +765,8 @@ static void __init xen_hvm_smp_prepare_c
 
 void __init xen_hvm_smp_init(void)
 {
+	if (!xen_have_vector_callback)
+		return;
 	smp_ops.smp_prepare_cpus = xen_hvm_smp_prepare_cpus;
 	smp_ops.smp_send_reschedule = xen_smp_send_reschedule;
 	smp_ops.cpu_die = xen_cpu_die;
diff -druNp --no-dereference linux-libre-4.9.27-gnu/arch/x86/xen/time.c linux-libre-4.9.28-gnu/arch/x86/xen/time.c
--- linux-libre-4.9.27-gnu/arch/x86/xen/time.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/arch/x86/xen/time.c	2017-05-14 08:00:37.000000000 -0400
@@ -432,6 +432,11 @@ static void xen_hvm_setup_cpu_clockevent
 
 void __init xen_hvm_init_time_ops(void)
 {
+	/* vector callback is needed otherwise we cannot receive interrupts
+	 * on cpu > 0 and at this point we don't know how many cpus are
+	 * available */
+	if (!xen_have_vector_callback)
+		return;
 	if (!xen_feature(XENFEAT_hvm_safe_pvclock)) {
 		printk(KERN_INFO "Xen doesn't support pvclock on HVM,"
 				"disable pv timer\n");
diff -druNp --no-dereference linux-libre-4.9.27-gnu/block/blk-integrity.c linux-libre-4.9.28-gnu/block/blk-integrity.c
--- linux-libre-4.9.27-gnu/block/blk-integrity.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/block/blk-integrity.c	2017-05-14 08:00:37.000000000 -0400
@@ -417,7 +417,7 @@ void blk_integrity_register(struct gendi
 	bi->tuple_size = template->tuple_size;
 	bi->tag_size = template->tag_size;
 
-	blk_integrity_revalidate(disk);
+	disk->queue->backing_dev_info.capabilities |= BDI_CAP_STABLE_WRITES;
 }
 EXPORT_SYMBOL(blk_integrity_register);
 
@@ -430,26 +430,11 @@ EXPORT_SYMBOL(blk_integrity_register);
  */
 void blk_integrity_unregister(struct gendisk *disk)
 {
-	blk_integrity_revalidate(disk);
+	disk->queue->backing_dev_info.capabilities &= ~BDI_CAP_STABLE_WRITES;
 	memset(&disk->queue->integrity, 0, sizeof(struct blk_integrity));
 }
 EXPORT_SYMBOL(blk_integrity_unregister);
 
-void blk_integrity_revalidate(struct gendisk *disk)
-{
-	struct blk_integrity *bi = &disk->queue->integrity;
-
-	if (!(disk->flags & GENHD_FL_UP))
-		return;
-
-	if (bi->profile)
-		disk->queue->backing_dev_info.capabilities |=
-			BDI_CAP_STABLE_WRITES;
-	else
-		disk->queue->backing_dev_info.capabilities &=
-			~BDI_CAP_STABLE_WRITES;
-}
-
 void blk_integrity_add(struct gendisk *disk)
 {
 	if (kobject_init_and_add(&disk->integrity_kobj, &integrity_ktype,
diff -druNp --no-dereference linux-libre-4.9.27-gnu/block/partition-generic.c linux-libre-4.9.28-gnu/block/partition-generic.c
--- linux-libre-4.9.27-gnu/block/partition-generic.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/block/partition-generic.c	2017-05-14 08:00:37.000000000 -0400
@@ -447,7 +447,6 @@ rescan:
 
 	if (disk->fops->revalidate_disk)
 		disk->fops->revalidate_disk(disk);
-	blk_integrity_revalidate(disk);
 	check_disk_size_change(disk, bdev);
 	bdev->bd_invalidated = 0;
 	if (!get_capacity(disk) || !(state = check_partition(disk, bdev)))
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/char/tpm/tpm2-cmd.c linux-libre-4.9.28-gnu/drivers/char/tpm/tpm2-cmd.c
--- linux-libre-4.9.27-gnu/drivers/char/tpm/tpm2-cmd.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/char/tpm/tpm2-cmd.c	2017-05-14 08:00:37.000000000 -0400
@@ -529,7 +529,7 @@ out:
 	tpm_buf_destroy(&buf);
 
 	if (rc > 0) {
-		if ((rc & TPM2_RC_HASH) == TPM2_RC_HASH)
+		if (tpm2_rc_value(rc) == TPM2_RC_HASH)
 			rc = -EINVAL;
 		else
 			rc = -EPERM;
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/char/tpm/tpm-chip.c linux-libre-4.9.28-gnu/drivers/char/tpm/tpm-chip.c
--- linux-libre-4.9.27-gnu/drivers/char/tpm/tpm-chip.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/char/tpm/tpm-chip.c	2017-05-14 08:00:37.000000000 -0400
@@ -140,7 +140,7 @@ static void tpm_dev_release(struct devic
  * Allocates a new struct tpm_chip instance and assigns a free
  * device number for it. Must be paired with put_device(&chip->dev).
  */
-struct tpm_chip *tpm_chip_alloc(struct device *dev,
+struct tpm_chip *tpm_chip_alloc(struct device *pdev,
 				const struct tpm_class_ops *ops)
 {
 	struct tpm_chip *chip;
@@ -159,7 +159,7 @@ struct tpm_chip *tpm_chip_alloc(struct d
 	rc = idr_alloc(&dev_nums_idr, NULL, 0, TPM_NUM_DEVICES, GFP_KERNEL);
 	mutex_unlock(&idr_lock);
 	if (rc < 0) {
-		dev_err(dev, "No available tpm device numbers\n");
+		dev_err(pdev, "No available tpm device numbers\n");
 		kfree(chip);
 		return ERR_PTR(rc);
 	}
@@ -169,7 +169,7 @@ struct tpm_chip *tpm_chip_alloc(struct d
 
 	chip->dev.class = tpm_class;
 	chip->dev.release = tpm_dev_release;
-	chip->dev.parent = dev;
+	chip->dev.parent = pdev;
 	chip->dev.groups = chip->groups;
 
 	if (chip->dev_num == 0)
@@ -181,7 +181,7 @@ struct tpm_chip *tpm_chip_alloc(struct d
 	if (rc)
 		goto out;
 
-	if (!dev)
+	if (!pdev)
 		chip->flags |= TPM_CHIP_FLAG_VIRTUAL;
 
 	cdev_init(&chip->cdev, &tpm_fops);
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/char/tpm/tpm.h linux-libre-4.9.28-gnu/drivers/char/tpm/tpm.h
--- linux-libre-4.9.27-gnu/drivers/char/tpm/tpm.h	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/char/tpm/tpm.h	2017-05-14 08:00:37.000000000 -0400
@@ -518,6 +518,11 @@ static inline void tpm_add_ppi(struct tp
 }
 #endif
 
+static inline inline u32 tpm2_rc_value(u32 rc)
+{
+	return (rc & BIT(7)) ? rc & 0xff : rc;
+}
+
 int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf);
 int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash);
 int tpm2_get_random(struct tpm_chip *chip, u8 *out, size_t max);
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/clk/Makefile linux-libre-4.9.28-gnu/drivers/clk/Makefile
--- linux-libre-4.9.27-gnu/drivers/clk/Makefile	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/clk/Makefile	2017-05-14 08:00:37.000000000 -0400
@@ -87,6 +87,8 @@ obj-y					+= ti/
 obj-$(CONFIG_CLK_UNIPHIER)		+= uniphier/
 obj-$(CONFIG_ARCH_U8500)		+= ux500/
 obj-$(CONFIG_COMMON_CLK_VERSATILE)	+= versatile/
+ifeq ($(CONFIG_COMMON_CLK), y)
 obj-$(CONFIG_X86)			+= x86/
+endif
 obj-$(CONFIG_ARCH_ZX)			+= zte/
 obj-$(CONFIG_ARCH_ZYNQ)			+= zynq/
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/clk/rockchip/clk-rk3036.c linux-libre-4.9.28-gnu/drivers/clk/rockchip/clk-rk3036.c
--- linux-libre-4.9.27-gnu/drivers/clk/rockchip/clk-rk3036.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/clk/rockchip/clk-rk3036.c	2017-05-14 08:00:37.000000000 -0400
@@ -127,7 +127,7 @@ PNAME(mux_ddrphy_p)		= { "dpll_ddr", "gp
 PNAME(mux_pll_src_3plls_p)	= { "apll", "dpll", "gpll" };
 PNAME(mux_timer_p)		= { "xin24m", "pclk_peri_src" };
 
-PNAME(mux_pll_src_apll_dpll_gpll_usb480m_p)	= { "apll", "dpll", "gpll" "usb480m" };
+PNAME(mux_pll_src_apll_dpll_gpll_usb480m_p)	= { "apll", "dpll", "gpll", "usb480m" };
 
 PNAME(mux_mmc_src_p)	= { "apll", "dpll", "gpll", "xin24m" };
 PNAME(mux_i2s_pre_p)	= { "i2s_src", "i2s_frac", "ext_i2s", "xin12m" };
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/crypto/caam/caamhash.c linux-libre-4.9.28-gnu/drivers/crypto/caam/caamhash.c
--- linux-libre-4.9.27-gnu/drivers/crypto/caam/caamhash.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/crypto/caam/caamhash.c	2017-05-14 08:00:37.000000000 -0400
@@ -154,6 +154,7 @@ static inline int map_seq_out_ptr_ctx(u3
 					ctx_len, DMA_FROM_DEVICE);
 	if (dma_mapping_error(jrdev, state->ctx_dma)) {
 		dev_err(jrdev, "unable to map ctx\n");
+		state->ctx_dma = 0;
 		return -ENOMEM;
 	}
 
@@ -214,6 +215,7 @@ static inline int ctx_map_to_sec4_sg(u32
 	state->ctx_dma = dma_map_single(jrdev, state->caam_ctx, ctx_len, flag);
 	if (dma_mapping_error(jrdev, state->ctx_dma)) {
 		dev_err(jrdev, "unable to map ctx\n");
+		state->ctx_dma = 0;
 		return -ENOMEM;
 	}
 
@@ -620,8 +622,10 @@ static inline void ahash_unmap_ctx(struc
 	struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
 	struct caam_hash_state *state = ahash_request_ctx(req);
 
-	if (state->ctx_dma)
+	if (state->ctx_dma) {
 		dma_unmap_single(dev, state->ctx_dma, ctx->ctx_len, flag);
+		state->ctx_dma = 0;
+	}
 	ahash_unmap(dev, edesc, req, dst_len);
 }
 
@@ -1605,6 +1609,7 @@ static int ahash_init(struct ahash_reque
 	state->finup = ahash_finup_first;
 	state->final = ahash_final_no_ctx;
 
+	state->ctx_dma = 0;
 	state->current_buf = 0;
 	state->buf_dma = 0;
 	state->buflen_0 = 0;
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/gpu/drm/sti/sti_gdp.c linux-libre-4.9.28-gnu/drivers/gpu/drm/sti/sti_gdp.c
--- linux-libre-4.9.27-gnu/drivers/gpu/drm/sti/sti_gdp.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/gpu/drm/sti/sti_gdp.c	2017-05-14 08:00:37.000000000 -0400
@@ -66,7 +66,9 @@ static struct gdp_format_to_str {
 #define GAM_GDP_ALPHARANGE_255  BIT(5)
 #define GAM_GDP_AGC_FULL_RANGE  0x00808080
 #define GAM_GDP_PPT_IGNORE      (BIT(1) | BIT(0))
-#define GAM_GDP_SIZE_MAX        0x7FF
+
+#define GAM_GDP_SIZE_MAX_WIDTH  3840
+#define GAM_GDP_SIZE_MAX_HEIGHT 2160
 
 #define GDP_NODE_NB_BANK        2
 #define GDP_NODE_PER_FIELD      2
@@ -633,8 +635,8 @@ static int sti_gdp_atomic_check(struct d
 	/* src_x are in 16.16 format */
 	src_x = state->src_x >> 16;
 	src_y = state->src_y >> 16;
-	src_w = clamp_val(state->src_w >> 16, 0, GAM_GDP_SIZE_MAX);
-	src_h = clamp_val(state->src_h >> 16, 0, GAM_GDP_SIZE_MAX);
+	src_w = clamp_val(state->src_w >> 16, 0, GAM_GDP_SIZE_MAX_WIDTH);
+	src_h = clamp_val(state->src_h >> 16, 0, GAM_GDP_SIZE_MAX_HEIGHT);
 
 	format = sti_gdp_fourcc2format(fb->pixel_format);
 	if (format == -1) {
@@ -732,8 +734,8 @@ static void sti_gdp_atomic_update(struct
 	/* src_x are in 16.16 format */
 	src_x = state->src_x >> 16;
 	src_y = state->src_y >> 16;
-	src_w = clamp_val(state->src_w >> 16, 0, GAM_GDP_SIZE_MAX);
-	src_h = clamp_val(state->src_h >> 16, 0, GAM_GDP_SIZE_MAX);
+	src_w = clamp_val(state->src_w >> 16, 0, GAM_GDP_SIZE_MAX_WIDTH);
+	src_h = clamp_val(state->src_h >> 16, 0, GAM_GDP_SIZE_MAX_HEIGHT);
 
 	list = sti_gdp_get_free_nodes(gdp);
 	top_field = list->top_field;
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/gpu/drm/ttm/ttm_bo_vm.c linux-libre-4.9.28-gnu/drivers/gpu/drm/ttm/ttm_bo_vm.c
--- linux-libre-4.9.27-gnu/drivers/gpu/drm/ttm/ttm_bo_vm.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/gpu/drm/ttm/ttm_bo_vm.c	2017-05-14 08:00:37.000000000 -0400
@@ -66,8 +66,11 @@ static int ttm_bo_vm_fault_idle(struct t
 		if (vmf->flags & FAULT_FLAG_RETRY_NOWAIT)
 			goto out_unlock;
 
+		ttm_bo_reference(bo);
 		up_read(&vma->vm_mm->mmap_sem);
 		(void) fence_wait(bo->moving, true);
+		ttm_bo_unreserve(bo);
+		ttm_bo_unref(&bo);
 		goto out_unlock;
 	}
 
@@ -120,8 +123,10 @@ static int ttm_bo_vm_fault(struct vm_are
 
 		if (vmf->flags & FAULT_FLAG_ALLOW_RETRY) {
 			if (!(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) {
+				ttm_bo_reference(bo);
 				up_read(&vma->vm_mm->mmap_sem);
 				(void) ttm_bo_wait_unreserved(bo);
+				ttm_bo_unref(&bo);
 			}
 
 			return VM_FAULT_RETRY;
@@ -166,6 +171,13 @@ static int ttm_bo_vm_fault(struct vm_are
 	ret = ttm_bo_vm_fault_idle(bo, vma, vmf);
 	if (unlikely(ret != 0)) {
 		retval = ret;
+
+		if (retval == VM_FAULT_RETRY &&
+		    !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) {
+			/* The BO has already been unreserved. */
+			return retval;
+		}
+
 		goto out_unlock;
 	}
 
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/hwmon/it87.c linux-libre-4.9.28-gnu/drivers/hwmon/it87.c
--- linux-libre-4.9.27-gnu/drivers/hwmon/it87.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/hwmon/it87.c	2017-05-14 08:00:37.000000000 -0400
@@ -2600,7 +2600,7 @@ static int __init it87_find(int sioaddr,
 
 		/* Check for pwm4 */
 		reg = superio_inb(sioaddr, IT87_SIO_GPIO4_REG);
-		if (!(reg & BIT(2)))
+		if (reg & BIT(2))
 			sio_data->skip_pwm |= BIT(3);
 
 		/* Check for pwm2, fan2 */
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/leds/leds-ktd2692.c linux-libre-4.9.28-gnu/drivers/leds/leds-ktd2692.c
--- linux-libre-4.9.27-gnu/drivers/leds/leds-ktd2692.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/leds/leds-ktd2692.c	2017-05-14 08:00:37.000000000 -0400
@@ -270,15 +270,15 @@ static int ktd2692_parse_dt(struct ktd26
 		return -ENXIO;
 
 	led->ctrl_gpio = devm_gpiod_get(dev, "ctrl", GPIOD_ASIS);
-	if (IS_ERR(led->ctrl_gpio)) {
-		ret = PTR_ERR(led->ctrl_gpio);
+	ret = PTR_ERR_OR_ZERO(led->ctrl_gpio);
+	if (ret) {
 		dev_err(dev, "cannot get ctrl-gpios %d\n", ret);
 		return ret;
 	}
 
 	led->aux_gpio = devm_gpiod_get(dev, "aux", GPIOD_ASIS);
-	if (IS_ERR(led->aux_gpio)) {
-		ret = PTR_ERR(led->aux_gpio);
+	ret = PTR_ERR_OR_ZERO(led->aux_gpio);
+	if (ret) {
 		dev_err(dev, "cannot get aux-gpios %d\n", ret);
 		return ret;
 	}
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt.c linux-libre-4.9.28-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt.c
--- linux-libre-4.9.27-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt.c	2017-05-14 08:00:37.000000000 -0400
@@ -2867,7 +2867,8 @@ static int bnxt_alloc_ntp_fltrs(struct b
 		INIT_HLIST_HEAD(&bp->ntp_fltr_hash_tbl[i]);
 
 	bp->ntp_fltr_count = 0;
-	bp->ntp_fltr_bmap = kzalloc(BITS_TO_LONGS(BNXT_NTP_FLTR_MAX_FLTR),
+	bp->ntp_fltr_bmap = kcalloc(BITS_TO_LONGS(BNXT_NTP_FLTR_MAX_FLTR),
+				    sizeof(long),
 				    GFP_KERNEL);
 
 	if (!bp->ntp_fltr_bmap)
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/net/macsec.c linux-libre-4.9.28-gnu/drivers/net/macsec.c
--- linux-libre-4.9.27-gnu/drivers/net/macsec.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/net/macsec.c	2017-05-14 08:00:37.000000000 -0400
@@ -617,7 +617,8 @@ static void macsec_encrypt_done(struct c
 
 static struct aead_request *macsec_alloc_req(struct crypto_aead *tfm,
 					     unsigned char **iv,
-					     struct scatterlist **sg)
+					     struct scatterlist **sg,
+					     int num_frags)
 {
 	size_t size, iv_offset, sg_offset;
 	struct aead_request *req;
@@ -629,7 +630,7 @@ static struct aead_request *macsec_alloc
 
 	size = ALIGN(size, __alignof__(struct scatterlist));
 	sg_offset = size;
-	size += sizeof(struct scatterlist) * (MAX_SKB_FRAGS + 1);
+	size += sizeof(struct scatterlist) * num_frags;
 
 	tmp = kmalloc(size, GFP_ATOMIC);
 	if (!tmp)
@@ -649,6 +650,7 @@ static struct sk_buff *macsec_encrypt(st
 {
 	int ret;
 	struct scatterlist *sg;
+	struct sk_buff *trailer;
 	unsigned char *iv;
 	struct ethhdr *eth;
 	struct macsec_eth_header *hh;
@@ -723,7 +725,14 @@ static struct sk_buff *macsec_encrypt(st
 		return ERR_PTR(-EINVAL);
 	}
 
-	req = macsec_alloc_req(tx_sa->key.tfm, &iv, &sg);
+	ret = skb_cow_data(skb, 0, &trailer);
+	if (unlikely(ret < 0)) {
+		macsec_txsa_put(tx_sa);
+		kfree_skb(skb);
+		return ERR_PTR(ret);
+	}
+
+	req = macsec_alloc_req(tx_sa->key.tfm, &iv, &sg, ret);
 	if (!req) {
 		macsec_txsa_put(tx_sa);
 		kfree_skb(skb);
@@ -732,7 +741,7 @@ static struct sk_buff *macsec_encrypt(st
 
 	macsec_fill_iv(iv, secy->sci, pn);
 
-	sg_init_table(sg, MAX_SKB_FRAGS + 1);
+	sg_init_table(sg, ret);
 	skb_to_sgvec(skb, sg, 0, skb->len);
 
 	if (tx_sc->encrypt) {
@@ -914,6 +923,7 @@ static struct sk_buff *macsec_decrypt(st
 {
 	int ret;
 	struct scatterlist *sg;
+	struct sk_buff *trailer;
 	unsigned char *iv;
 	struct aead_request *req;
 	struct macsec_eth_header *hdr;
@@ -924,7 +934,12 @@ static struct sk_buff *macsec_decrypt(st
 	if (!skb)
 		return ERR_PTR(-ENOMEM);
 
-	req = macsec_alloc_req(rx_sa->key.tfm, &iv, &sg);
+	ret = skb_cow_data(skb, 0, &trailer);
+	if (unlikely(ret < 0)) {
+		kfree_skb(skb);
+		return ERR_PTR(ret);
+	}
+	req = macsec_alloc_req(rx_sa->key.tfm, &iv, &sg, ret);
 	if (!req) {
 		kfree_skb(skb);
 		return ERR_PTR(-ENOMEM);
@@ -933,7 +948,7 @@ static struct sk_buff *macsec_decrypt(st
 	hdr = (struct macsec_eth_header *)skb->data;
 	macsec_fill_iv(iv, sci, ntohl(hdr->packet_number));
 
-	sg_init_table(sg, MAX_SKB_FRAGS + 1);
+	sg_init_table(sg, ret);
 	skb_to_sgvec(skb, sg, 0, skb->len);
 
 	if (hdr->tci_an & MACSEC_TCI_E) {
@@ -2709,7 +2724,7 @@ static netdev_tx_t macsec_start_xmit(str
 }
 
 #define MACSEC_FEATURES \
-	(NETIF_F_SG | NETIF_F_HIGHDMA)
+	(NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST)
 static struct lock_class_key macsec_netdev_addr_lock_key;
 
 static int macsec_dev_init(struct net_device *dev)
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/net/phy/mdio-mux-bcm-iproc.c linux-libre-4.9.28-gnu/drivers/net/phy/mdio-mux-bcm-iproc.c
--- linux-libre-4.9.27-gnu/drivers/net/phy/mdio-mux-bcm-iproc.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/net/phy/mdio-mux-bcm-iproc.c	2017-05-14 08:00:37.000000000 -0400
@@ -203,11 +203,14 @@ static int mdio_mux_iproc_probe(struct p
 			   &md->mux_handle, md, md->mii_bus);
 	if (rc) {
 		dev_info(md->dev, "mdiomux initialization failed\n");
-		goto out;
+		goto out_register;
 	}
 
 	dev_info(md->dev, "iProc mdiomux registered\n");
 	return 0;
+
+out_register:
+	mdiobus_unregister(bus);
 out:
 	mdiobus_free(bus);
 	return rc;
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/net/usb/qmi_wwan.c linux-libre-4.9.28-gnu/drivers/net/usb/qmi_wwan.c
--- linux-libre-4.9.27-gnu/drivers/net/usb/qmi_wwan.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/net/usb/qmi_wwan.c	2017-05-14 08:00:37.000000000 -0400
@@ -902,6 +902,7 @@ static const struct usb_device_id produc
 	{QMI_FIXED_INTF(0x2357, 0x0201, 4)},	/* TP-LINK HSUPA Modem MA180 */
 	{QMI_FIXED_INTF(0x2357, 0x9000, 4)},	/* TP-LINK MA260 */
 	{QMI_QUIRK_SET_DTR(0x1bc7, 0x1040, 2)},	/* Telit LE922A */
+	{QMI_FIXED_INTF(0x1bc7, 0x1100, 3)},	/* Telit ME910 */
 	{QMI_FIXED_INTF(0x1bc7, 0x1200, 5)},	/* Telit LE920 */
 	{QMI_FIXED_INTF(0x1bc7, 0x1201, 2)},	/* Telit LE920 */
 	{QMI_FIXED_INTF(0x1c9e, 0x9b01, 3)},	/* XS Stick W100-2 from 4G Systems */
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c linux-libre-4.9.28-gnu/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
--- linux-libre-4.9.27-gnu/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c	2017-05-14 08:00:37.000000000 -0400
@@ -198,7 +198,7 @@ static netdev_tx_t brcmf_netdev_start_xm
 	int ret;
 	struct brcmf_if *ifp = netdev_priv(ndev);
 	struct brcmf_pub *drvr = ifp->drvr;
-	struct ethhdr *eh = (struct ethhdr *)(skb->data);
+	struct ethhdr *eh;
 
 	brcmf_dbg(DATA, "Enter, bsscfgidx=%d\n", ifp->bsscfgidx);
 
@@ -211,22 +211,13 @@ static netdev_tx_t brcmf_netdev_start_xm
 		goto done;
 	}
 
-	/* Make sure there's enough room for any header */
-	if (skb_headroom(skb) < drvr->hdrlen) {
-		struct sk_buff *skb2;
-
-		brcmf_dbg(INFO, "%s: insufficient headroom\n",
+	/* Make sure there's enough writable headroom*/
+	ret = skb_cow_head(skb, drvr->hdrlen);
+	if (ret < 0) {
+		brcmf_err("%s: skb_cow_head failed\n",
 			  brcmf_ifname(ifp));
-		drvr->bus_if->tx_realloc++;
-		skb2 = skb_realloc_headroom(skb, drvr->hdrlen);
 		dev_kfree_skb(skb);
-		skb = skb2;
-		if (skb == NULL) {
-			brcmf_err("%s: skb_realloc_headroom failed\n",
-				  brcmf_ifname(ifp));
-			ret = -ENOMEM;
-			goto done;
-		}
+		goto done;
 	}
 
 	/* validate length for ether packet */
@@ -236,6 +227,8 @@ static netdev_tx_t brcmf_netdev_start_xm
 		goto done;
 	}
 
+	eh = (struct ethhdr *)(skb->data);
+
 	if (eh->h_proto == htons(ETH_P_PAE))
 		atomic_inc(&ifp->pend_8021x_cnt);
 
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/net/wireless/intel/iwlwifi/mvm/d3.c linux-libre-4.9.28-gnu/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
--- linux-libre-4.9.27-gnu/drivers/net/wireless/intel/iwlwifi/mvm/d3.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/net/wireless/intel/iwlwifi/mvm/d3.c	2017-05-14 08:00:37.000000000 -0400
@@ -1262,12 +1262,15 @@ static int __iwl_mvm_suspend(struct ieee
 	iwl_trans_d3_suspend(mvm->trans, test, !unified_image);
  out:
 	if (ret < 0) {
-		iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN);
-		if (mvm->restart_fw > 0) {
-			mvm->restart_fw--;
-			ieee80211_restart_hw(mvm->hw);
-		}
 		iwl_mvm_free_nd(mvm);
+
+		if (!unified_image) {
+			iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN);
+			if (mvm->restart_fw > 0) {
+				mvm->restart_fw--;
+				ieee80211_restart_hw(mvm->hw);
+			}
+		}
 	}
  out_noreset:
 	mutex_unlock(&mvm->mutex);
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c linux-libre-4.9.28-gnu/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
--- linux-libre-4.9.27-gnu/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c	2017-05-14 08:00:37.000000000 -0400
@@ -1056,6 +1056,8 @@ static ssize_t iwl_dbgfs_fw_dbg_collect_
 
 	if (ret)
 		return ret;
+	if (count == 0)
+		return 0;
 
 	iwl_mvm_fw_dbg_collect(mvm, FW_DBG_TRIGGER_USER, buf,
 			       (count - 1), NULL);
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/net/wireless/intel/iwlwifi/mvm/fw.c linux-libre-4.9.28-gnu/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
--- linux-libre-4.9.27-gnu/drivers/net/wireless/intel/iwlwifi/mvm/fw.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/net/wireless/intel/iwlwifi/mvm/fw.c	2017-05-14 08:00:37.000000000 -0400
@@ -214,6 +214,10 @@ static int iwl_fill_paging_mem(struct iw
 	memcpy(page_address(mvm->fw_paging_db[0].fw_paging_block),
 	       image->sec[sec_idx].data,
 	       mvm->fw_paging_db[0].fw_paging_size);
+	dma_sync_single_for_device(mvm->trans->dev,
+				   mvm->fw_paging_db[0].fw_paging_phys,
+				   mvm->fw_paging_db[0].fw_paging_size,
+				   DMA_BIDIRECTIONAL);
 
 	IWL_DEBUG_FW(mvm,
 		     "Paging: copied %d CSS bytes to first block\n",
@@ -228,9 +232,16 @@ static int iwl_fill_paging_mem(struct iw
 	 * loop stop at num_of_paging_blk since that last block is not full.
 	 */
 	for (idx = 1; idx < mvm->num_of_paging_blk; idx++) {
-		memcpy(page_address(mvm->fw_paging_db[idx].fw_paging_block),
+		struct iwl_fw_paging *block = &mvm->fw_paging_db[idx];
+
+		memcpy(page_address(block->fw_paging_block),
 		       image->sec[sec_idx].data + offset,
-		       mvm->fw_paging_db[idx].fw_paging_size);
+		       block->fw_paging_size);
+		dma_sync_single_for_device(mvm->trans->dev,
+					   block->fw_paging_phys,
+					   block->fw_paging_size,
+					   DMA_BIDIRECTIONAL);
+
 
 		IWL_DEBUG_FW(mvm,
 			     "Paging: copied %d paging bytes to block %d\n",
@@ -242,9 +253,15 @@ static int iwl_fill_paging_mem(struct iw
 
 	/* copy the last paging block */
 	if (mvm->num_of_pages_in_last_blk > 0) {
-		memcpy(page_address(mvm->fw_paging_db[idx].fw_paging_block),
+		struct iwl_fw_paging *block = &mvm->fw_paging_db[idx];
+
+		memcpy(page_address(block->fw_paging_block),
 		       image->sec[sec_idx].data + offset,
 		       FW_PAGING_SIZE * mvm->num_of_pages_in_last_blk);
+		dma_sync_single_for_device(mvm->trans->dev,
+					   block->fw_paging_phys,
+					   block->fw_paging_size,
+					   DMA_BIDIRECTIONAL);
 
 		IWL_DEBUG_FW(mvm,
 			     "Paging: copied %d pages in the last block %d\n",
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c linux-libre-4.9.28-gnu/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c
--- linux-libre-4.9.27-gnu/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c	2017-05-14 08:00:37.000000000 -0400
@@ -784,12 +784,16 @@ void iwl_mvm_fw_error_dump(struct iwl_mv
 			struct iwl_fw_error_dump_paging *paging;
 			struct page *pages =
 				mvm->fw_paging_db[i].fw_paging_block;
+			dma_addr_t addr = mvm->fw_paging_db[i].fw_paging_phys;
 
 			dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PAGING);
 			dump_data->len = cpu_to_le32(sizeof(*paging) +
 						     PAGING_BLOCK_SIZE);
 			paging = (void *)dump_data->data;
 			paging->index = cpu_to_le32(i);
+			dma_sync_single_for_cpu(mvm->trans->dev, addr,
+						PAGING_BLOCK_SIZE,
+						DMA_BIDIRECTIONAL);
 			memcpy(paging->data, page_address(pages),
 			       PAGING_BLOCK_SIZE);
 			dump_data = iwl_fw_error_next_data(dump_data);
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c linux-libre-4.9.28-gnu/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
--- linux-libre-4.9.27-gnu/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c	2017-05-14 08:00:37.000000000 -0400
@@ -409,7 +409,7 @@ static void iwl_mvm_release_frames(struc
 
 	/* ignore nssn smaller than head sn - this can happen due to timeout */
 	if (iwl_mvm_is_sn_less(nssn, ssn, reorder_buf->buf_size))
-		return;
+		goto set_timer;
 
 	while (iwl_mvm_is_sn_less(ssn, nssn, reorder_buf->buf_size)) {
 		int index = ssn % reorder_buf->buf_size;
@@ -432,6 +432,7 @@ static void iwl_mvm_release_frames(struc
 	}
 	reorder_buf->head_sn = nssn;
 
+set_timer:
 	if (reorder_buf->num_stored && !reorder_buf->removed) {
 		u16 index = reorder_buf->head_sn % reorder_buf->buf_size;
 
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/net/wireless/intel/iwlwifi/mvm/sta.c linux-libre-4.9.28-gnu/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
--- linux-libre-4.9.27-gnu/drivers/net/wireless/intel/iwlwifi/mvm/sta.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/net/wireless/intel/iwlwifi/mvm/sta.c	2017-05-14 08:00:37.000000000 -0400
@@ -1466,6 +1466,7 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
 {
 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 	struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
+	u8 sta_id = mvm_sta->sta_id;
 	int ret;
 
 	lockdep_assert_held(&mvm->mutex);
@@ -1474,7 +1475,7 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
 		kfree(mvm_sta->dup_data);
 
 	if ((vif->type == NL80211_IFTYPE_STATION &&
-	     mvmvif->ap_sta_id == mvm_sta->sta_id) ||
+	     mvmvif->ap_sta_id == sta_id) ||
 	    iwl_mvm_is_dqa_supported(mvm)){
 		ret = iwl_mvm_drain_sta(mvm, mvm_sta, true);
 		if (ret)
@@ -1497,6 +1498,15 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
 			iwl_mvm_disable_sta_queues(mvm, vif, mvm_sta);
 
 			/*
+			 * If pending_frames is set at this point - it must be
+			 * driver internal logic error, since queues are empty
+			 * and removed successuly.
+			 * warn on it but set it to 0 anyway to avoid station
+			 * not being removed later in the function
+			 */
+			WARN_ON(atomic_xchg(&mvm->pending_frames[sta_id], 0));
+
+			/*
 			 * If no traffic has gone through the reserved TXQ - it
 			 * is still marked as IWL_MVM_QUEUE_RESERVED, and
 			 * should be manually marked as free again
@@ -1506,7 +1516,7 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
 			if (WARN((*status != IWL_MVM_QUEUE_RESERVED) &&
 				 (*status != IWL_MVM_QUEUE_FREE),
 				 "sta_id %d reserved txq %d status %d",
-				 mvm_sta->sta_id, reserved_txq, *status)) {
+				 sta_id, reserved_txq, *status)) {
 				spin_unlock_bh(&mvm->queue_info_lock);
 				return -EINVAL;
 			}
@@ -1516,7 +1526,7 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
 		}
 
 		if (vif->type == NL80211_IFTYPE_STATION &&
-		    mvmvif->ap_sta_id == mvm_sta->sta_id) {
+		    mvmvif->ap_sta_id == sta_id) {
 			/* if associated - we can't remove the AP STA now */
 			if (vif->bss_conf.assoc)
 				return ret;
@@ -1525,7 +1535,7 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
 			mvmvif->ap_sta_id = IWL_MVM_STATION_COUNT;
 
 			/* clear d0i3_ap_sta_id if no longer relevant */
-			if (mvm->d0i3_ap_sta_id == mvm_sta->sta_id)
+			if (mvm->d0i3_ap_sta_id == sta_id)
 				mvm->d0i3_ap_sta_id = IWL_MVM_STATION_COUNT;
 		}
 	}
@@ -1534,7 +1544,7 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
 	 * This shouldn't happen - the TDLS channel switch should be canceled
 	 * before the STA is removed.
 	 */
-	if (WARN_ON_ONCE(mvm->tdls_cs.peer.sta_id == mvm_sta->sta_id)) {
+	if (WARN_ON_ONCE(mvm->tdls_cs.peer.sta_id == sta_id)) {
 		mvm->tdls_cs.peer.sta_id = IWL_MVM_STATION_COUNT;
 		cancel_delayed_work(&mvm->tdls_cs.dwork);
 	}
@@ -1544,21 +1554,20 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
 	 * calls the drain worker.
 	 */
 	spin_lock_bh(&mvm_sta->lock);
+
 	/*
 	 * There are frames pending on the AC queues for this station.
 	 * We need to wait until all the frames are drained...
 	 */
-	if (atomic_read(&mvm->pending_frames[mvm_sta->sta_id])) {
-		rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id],
+	if (atomic_read(&mvm->pending_frames[sta_id])) {
+		rcu_assign_pointer(mvm->fw_id_to_mac_id[sta_id],
 				   ERR_PTR(-EBUSY));
 		spin_unlock_bh(&mvm_sta->lock);
 
 		/* disable TDLS sta queues on drain complete */
 		if (sta->tdls) {
-			mvm->tfd_drained[mvm_sta->sta_id] =
-							mvm_sta->tfd_queue_msk;
-			IWL_DEBUG_TDLS(mvm, "Draining TDLS sta %d\n",
-				       mvm_sta->sta_id);
+			mvm->tfd_drained[sta_id] = mvm_sta->tfd_queue_msk;
+			IWL_DEBUG_TDLS(mvm, "Draining TDLS sta %d\n", sta_id);
 		}
 
 		ret = iwl_mvm_drain_sta(mvm, mvm_sta, true);
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/net/wireless/intel/iwlwifi/mvm/tx.c linux-libre-4.9.28-gnu/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
--- linux-libre-4.9.27-gnu/drivers/net/wireless/intel/iwlwifi/mvm/tx.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/net/wireless/intel/iwlwifi/mvm/tx.c	2017-05-14 08:00:37.000000000 -0400
@@ -202,7 +202,6 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *
 			struct iwl_tx_cmd *tx_cmd,
 			struct ieee80211_tx_info *info, u8 sta_id)
 {
-	struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb);
 	struct ieee80211_hdr *hdr = (void *)skb->data;
 	__le16 fc = hdr->frame_control;
 	u32 tx_flags = le32_to_cpu(tx_cmd->tx_flags);
@@ -284,9 +283,8 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *
 		tx_flags |= TX_CMD_FLG_WRITE_TX_POWER;
 
 	tx_cmd->tx_flags = cpu_to_le32(tx_flags);
-	/* Total # bytes to be transmitted */
-	tx_cmd->len = cpu_to_le16((u16)skb->len +
-		(uintptr_t)skb_info->driver_data[0]);
+	/* Total # bytes to be transmitted - PCIe code will adjust for A-MSDU */
+	tx_cmd->len = cpu_to_le16((u16)skb->len);
 	tx_cmd->life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE);
 	tx_cmd->sta_id = sta_id;
 
@@ -459,7 +457,6 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mv
 		      struct ieee80211_sta *sta, u8 sta_id)
 {
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-	struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb);
 	struct iwl_device_cmd *dev_cmd;
 	struct iwl_tx_cmd *tx_cmd;
 
@@ -479,12 +476,18 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mv
 
 	iwl_mvm_set_tx_cmd_rate(mvm, tx_cmd, info, sta, hdr->frame_control);
 
+	return dev_cmd;
+}
+
+static void iwl_mvm_skb_prepare_status(struct sk_buff *skb,
+				       struct iwl_device_cmd *cmd)
+{
+	struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb);
+
 	memset(&skb_info->status, 0, sizeof(skb_info->status));
 	memset(skb_info->driver_data, 0, sizeof(skb_info->driver_data));
 
-	skb_info->driver_data[1] = dev_cmd;
-
-	return dev_cmd;
+	skb_info->driver_data[1] = cmd;
 }
 
 static int iwl_mvm_get_ctrl_vif_queue(struct iwl_mvm *mvm,
@@ -550,9 +553,6 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mv
 			  info.hw_queue != info.control.vif->cab_queue)))
 		return -1;
 
-	/* This holds the amsdu headers length */
-	skb_info->driver_data[0] = (void *)(uintptr_t)0;
-
 	queue = info.hw_queue;
 
 	/*
@@ -563,9 +563,10 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mv
 	 * (this is not possible for unicast packets as a TLDS discovery
 	 * response are sent without a station entry); otherwise use the
 	 * AUX station.
-	 * In DQA mode, if vif is of type STATION and frames are not multicast,
-	 * they should be sent from the BSS queue. For example, TDLS setup
-	 * frames should be sent on this queue, as they go through the AP.
+	 * In DQA mode, if vif is of type STATION and frames are not multicast
+	 * or offchannel, they should be sent from the BSS queue.
+	 * For example, TDLS setup frames should be sent on this queue,
+	 * as they go through the AP.
 	 */
 	sta_id = mvm->aux_sta.sta_id;
 	if (info.control.vif) {
@@ -587,7 +588,8 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mv
 			if (ap_sta_id != IWL_MVM_STATION_COUNT)
 				sta_id = ap_sta_id;
 		} else if (iwl_mvm_is_dqa_supported(mvm) &&
-			   info.control.vif->type == NL80211_IFTYPE_STATION) {
+			   info.control.vif->type == NL80211_IFTYPE_STATION &&
+			   queue != mvm->aux_queue) {
 			queue = IWL_MVM_DQA_BSS_CLIENT_QUEUE;
 		}
 	}
@@ -598,6 +600,9 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mv
 	if (!dev_cmd)
 		return -1;
 
+	/* From now on, we cannot access info->control */
+	iwl_mvm_skb_prepare_status(skb, dev_cmd);
+
 	tx_cmd = (struct iwl_tx_cmd *)dev_cmd->payload;
 
 	/* Copy MAC header from skb into command buffer */
@@ -634,7 +639,7 @@ static int iwl_mvm_tx_tso(struct iwl_mvm
 	unsigned int num_subframes, tcp_payload_len, subf_len, max_amsdu_len;
 	bool ipv4 = (skb->protocol == htons(ETH_P_IP));
 	u16 ip_base_id = ipv4 ? ntohs(ip_hdr(skb)->id) : 0;
-	u16 amsdu_add, snap_ip_tcp, pad, i = 0;
+	u16 snap_ip_tcp, pad, i = 0;
 	unsigned int dbg_max_amsdu_len;
 	netdev_features_t netdev_features = NETIF_F_CSUM_MASK | NETIF_F_SG;
 	u8 *qc, tid, txf;
@@ -736,21 +741,6 @@ static int iwl_mvm_tx_tso(struct iwl_mvm
 
 	/* This skb fits in one single A-MSDU */
 	if (num_subframes * mss >= tcp_payload_len) {
-		struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb);
-
-		/*
-		 * Compute the length of all the data added for the A-MSDU.
-		 * This will be used to compute the length to write in the TX
-		 * command. We have: SNAP + IP + TCP for n -1 subframes and
-		 * ETH header for n subframes. Note that the original skb
-		 * already had one set of SNAP / IP / TCP headers.
-		 */
-		num_subframes = DIV_ROUND_UP(tcp_payload_len, mss);
-		amsdu_add = num_subframes * sizeof(struct ethhdr) +
-			(num_subframes - 1) * (snap_ip_tcp + pad);
-		/* This holds the amsdu headers length */
-		skb_info->driver_data[0] = (void *)(uintptr_t)amsdu_add;
-
 		__skb_queue_tail(mpdus_skb, skb);
 		return 0;
 	}
@@ -789,14 +779,6 @@ segment:
 			ip_hdr(tmp)->id = htons(ip_base_id + i * num_subframes);
 
 		if (tcp_payload_len > mss) {
-			struct ieee80211_tx_info *skb_info =
-				IEEE80211_SKB_CB(tmp);
-
-			num_subframes = DIV_ROUND_UP(tcp_payload_len, mss);
-			amsdu_add = num_subframes * sizeof(struct ethhdr) +
-				(num_subframes - 1) * (snap_ip_tcp + pad);
-			skb_info->driver_data[0] =
-				(void *)(uintptr_t)amsdu_add;
 			skb_shinfo(tmp)->gso_size = mss;
 		} else {
 			qc = ieee80211_get_qos_ctl((void *)tmp->data);
@@ -908,7 +890,6 @@ static int iwl_mvm_tx_mpdu(struct iwl_mv
 		goto drop;
 
 	tx_cmd = (struct iwl_tx_cmd *)dev_cmd->payload;
-	/* From now on, we cannot access info->control */
 
 	/*
 	 * we handle that entirely ourselves -- for uAPSD the firmware
@@ -1015,6 +996,9 @@ static int iwl_mvm_tx_mpdu(struct iwl_mv
 	IWL_DEBUG_TX(mvm, "TX to [%d|%d] Q:%d - seq: 0x%x\n", mvmsta->sta_id,
 		     tid, txq_id, IEEE80211_SEQ_TO_SN(seq_number));
 
+	/* From now on, we cannot access info->control */
+	iwl_mvm_skb_prepare_status(skb, dev_cmd);
+
 	if (iwl_trans_tx(mvm->trans, skb, dev_cmd, txq_id))
 		goto drop_unlock_sta;
 
@@ -1024,7 +1008,10 @@ static int iwl_mvm_tx_mpdu(struct iwl_mv
 	spin_unlock(&mvmsta->lock);
 
 	/* Increase pending frames count if this isn't AMPDU */
-	if (!is_ampdu)
+	if ((iwl_mvm_is_dqa_supported(mvm) &&
+	     mvmsta->tid_data[tx_cmd->tid_tspec].state != IWL_AGG_ON &&
+	     mvmsta->tid_data[tx_cmd->tid_tspec].state != IWL_AGG_STARTING) ||
+	    (!iwl_mvm_is_dqa_supported(mvm) && !is_ampdu))
 		atomic_inc(&mvm->pending_frames[mvmsta->sta_id]);
 
 	return 0;
@@ -1040,7 +1027,6 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm,
 		   struct ieee80211_sta *sta)
 {
 	struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
-	struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb);
 	struct ieee80211_tx_info info;
 	struct sk_buff_head mpdus_skbs;
 	unsigned int payload_len;
@@ -1054,9 +1040,6 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm,
 
 	memcpy(&info, skb->cb, sizeof(info));
 
-	/* This holds the amsdu headers length */
-	skb_info->driver_data[0] = (void *)(uintptr_t)0;
-
 	if (!skb_is_gso(skb))
 		return iwl_mvm_tx_mpdu(mvm, skb, &info, sta);
 
@@ -1295,8 +1278,6 @@ static void iwl_mvm_rx_tx_cmd_single(str
 
 		memset(&info->status, 0, sizeof(info->status));
 
-		info->flags &= ~IEEE80211_TX_CTL_AMPDU;
-
 		/* inform mac80211 about what happened with the frame */
 		switch (status & TX_STATUS_MSK) {
 		case TX_STATUS_SUCCESS:
@@ -1319,10 +1300,11 @@ static void iwl_mvm_rx_tx_cmd_single(str
 			(void *)(uintptr_t)le32_to_cpu(tx_resp->initial_rate);
 
 		/* Single frame failure in an AMPDU queue => send BAR */
-		if (txq_id >= mvm->first_agg_queue &&
+		if (info->flags & IEEE80211_TX_CTL_AMPDU &&
 		    !(info->flags & IEEE80211_TX_STAT_ACK) &&
 		    !(info->flags & IEEE80211_TX_STAT_TX_FILTERED))
 			info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
+		info->flags &= ~IEEE80211_TX_CTL_AMPDU;
 
 		/* W/A FW bug: seq_ctl is wrong when the status isn't success */
 		if (status != TX_STATUS_SUCCESS) {
@@ -1357,7 +1339,7 @@ static void iwl_mvm_rx_tx_cmd_single(str
 		ieee80211_tx_status(mvm->hw, skb);
 	}
 
-	if (txq_id >= mvm->first_agg_queue) {
+	if (iwl_mvm_is_dqa_supported(mvm) || txq_id >= mvm->first_agg_queue) {
 		/* If this is an aggregation queue, we use the ssn since:
 		 * ssn = wifi seq_num % 256.
 		 * The seq_ctl is the sequence control of the packet to which
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/net/wireless/intel/iwlwifi/pcie/internal.h linux-libre-4.9.28-gnu/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
--- linux-libre-4.9.27-gnu/drivers/net/wireless/intel/iwlwifi/pcie/internal.h	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/net/wireless/intel/iwlwifi/pcie/internal.h	2017-05-14 08:00:37.000000000 -0400
@@ -279,7 +279,7 @@ struct iwl_txq {
 	bool frozen;
 	u8 active;
 	bool ampdu;
-	bool block;
+	int block;
 	unsigned long wd_timeout;
 	struct sk_buff_head overflow_q;
 
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/net/wireless/intel/iwlwifi/pcie/trans.c linux-libre-4.9.28-gnu/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
--- linux-libre-4.9.27-gnu/drivers/net/wireless/intel/iwlwifi/pcie/trans.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/net/wireless/intel/iwlwifi/pcie/trans.c	2017-05-14 08:00:37.000000000 -0400
@@ -868,17 +868,13 @@ static int iwl_pcie_load_cpu_sections(st
 				      int cpu,
 				      int *first_ucode_section)
 {
-	int shift_param;
 	int i, ret = 0;
 	u32 last_read_idx = 0;
 
-	if (cpu == 1) {
-		shift_param = 0;
+	if (cpu == 1)
 		*first_ucode_section = 0;
-	} else {
-		shift_param = 16;
+	else
 		(*first_ucode_section)++;
-	}
 
 	for (i = *first_ucode_section; i < IWL_UCODE_SECTION_MAX; i++) {
 		last_read_idx = i;
@@ -2933,16 +2929,12 @@ struct iwl_trans *iwl_trans_pcie_alloc(s
 				       PCIE_LINK_STATE_CLKPM);
 	}
 
-	if (cfg->mq_rx_supported)
-		addr_size = 64;
-	else
-		addr_size = 36;
-
 	if (cfg->use_tfh) {
+		addr_size = 64;
 		trans_pcie->max_tbs = IWL_TFH_NUM_TBS;
 		trans_pcie->tfd_size = sizeof(struct iwl_tfh_tfd);
-
 	} else {
+		addr_size = 36;
 		trans_pcie->max_tbs = IWL_NUM_OF_TBS;
 		trans_pcie->tfd_size = sizeof(struct iwl_tfd);
 	}
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/net/wireless/intel/iwlwifi/pcie/tx.c linux-libre-4.9.28-gnu/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
--- linux-libre-4.9.27-gnu/drivers/net/wireless/intel/iwlwifi/pcie/tx.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/net/wireless/intel/iwlwifi/pcie/tx.c	2017-05-14 08:00:37.000000000 -0400
@@ -2096,6 +2096,7 @@ static int iwl_fill_data_tbs_amsdu(struc
 				   struct iwl_cmd_meta *out_meta,
 				   struct iwl_device_cmd *dev_cmd, u16 tb1_len)
 {
+	struct iwl_tx_cmd *tx_cmd = (void *)dev_cmd->payload;
 	struct iwl_trans_pcie *trans_pcie = txq->trans_pcie;
 	struct ieee80211_hdr *hdr = (void *)skb->data;
 	unsigned int snap_ip_tcp_hdrlen, ip_hdrlen, total_len, hdr_room;
@@ -2145,6 +2146,13 @@ static int iwl_fill_data_tbs_amsdu(struc
 	 */
 	skb_pull(skb, hdr_len + iv_len);
 
+	/*
+	 * Remove the length of all the headers that we don't actually
+	 * have in the MPDU by themselves, but that we duplicate into
+	 * all the different MSDUs inside the A-MSDU.
+	 */
+	le16_add_cpu(&tx_cmd->len, -snap_ip_tcp_hdrlen);
+
 	tso_start(skb, &tso);
 
 	while (total_len) {
@@ -2155,7 +2163,7 @@ static int iwl_fill_data_tbs_amsdu(struc
 		unsigned int hdr_tb_len;
 		dma_addr_t hdr_tb_phys;
 		struct tcphdr *tcph;
-		u8 *iph;
+		u8 *iph, *subf_hdrs_start = hdr_page->pos;
 
 		total_len -= data_left;
 
@@ -2216,6 +2224,8 @@ static int iwl_fill_data_tbs_amsdu(struc
 				       hdr_tb_len, false);
 		trace_iwlwifi_dev_tx_tso_chunk(trans->dev, start_hdr,
 					       hdr_tb_len);
+		/* add this subframe's headers' length to the tx_cmd */
+		le16_add_cpu(&tx_cmd->len, hdr_page->pos - subf_hdrs_start);
 
 		/* prepare the start_hdr for the next subframe */
 		start_hdr = hdr_page->pos;
@@ -2408,9 +2418,10 @@ int iwl_trans_pcie_tx(struct iwl_trans *
 		tb1_len = len;
 	}
 
-	/* The first TB points to bi-directional DMA data */
-	memcpy(&txq->first_tb_bufs[txq->write_ptr], &dev_cmd->hdr,
-	       IWL_FIRST_TB_SIZE);
+	/*
+	 * The first TB points to bi-directional DMA data, we'll
+	 * memcpy the data into it later.
+	 */
 	iwl_pcie_txq_build_tfd(trans, txq, tb0_phys,
 			       IWL_FIRST_TB_SIZE, true);
 
@@ -2434,6 +2445,10 @@ int iwl_trans_pcie_tx(struct iwl_trans *
 		goto out_err;
 	}
 
+	/* building the A-MSDU might have changed this data, so memcpy it now */
+	memcpy(&txq->first_tb_bufs[txq->write_ptr], &dev_cmd->hdr,
+	       IWL_FIRST_TB_SIZE);
+
 	tfd = iwl_pcie_get_tfd(trans_pcie, txq, txq->write_ptr);
 	/* Set up entry for this TFD in Tx byte-count array */
 	iwl_pcie_txq_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->len),
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/net/wireless/marvell/mwifiex/11n_aggr.c linux-libre-4.9.28-gnu/drivers/net/wireless/marvell/mwifiex/11n_aggr.c
--- linux-libre-4.9.27-gnu/drivers/net/wireless/marvell/mwifiex/11n_aggr.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/net/wireless/marvell/mwifiex/11n_aggr.c	2017-05-14 08:00:37.000000000 -0400
@@ -101,13 +101,6 @@ mwifiex_11n_form_amsdu_txpd(struct mwifi
 {
 	struct txpd *local_tx_pd;
 	struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb);
-	unsigned int pad;
-	int headroom = (priv->adapter->iface_type ==
-			MWIFIEX_USB) ? 0 : INTF_HEADER_LEN;
-
-	pad = ((void *)skb->data - sizeof(*local_tx_pd) -
-		headroom - NULL) & (MWIFIEX_DMA_ALIGN_SZ - 1);
-	skb_push(skb, pad);
 
 	skb_push(skb, sizeof(*local_tx_pd));
 
@@ -121,12 +114,10 @@ mwifiex_11n_form_amsdu_txpd(struct mwifi
 	local_tx_pd->bss_num = priv->bss_num;
 	local_tx_pd->bss_type = priv->bss_type;
 	/* Always zero as the data is followed by struct txpd */
-	local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd) +
-						 pad);
+	local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd));
 	local_tx_pd->tx_pkt_type = cpu_to_le16(PKT_TYPE_AMSDU);
 	local_tx_pd->tx_pkt_length = cpu_to_le16(skb->len -
-						 sizeof(*local_tx_pd) -
-						 pad);
+						 sizeof(*local_tx_pd));
 
 	if (tx_info->flags & MWIFIEX_BUF_FLAG_TDLS_PKT)
 		local_tx_pd->flags |= MWIFIEX_TXPD_FLAGS_TDLS_PACKET;
@@ -190,7 +181,11 @@ mwifiex_11n_aggregate_pkt(struct mwifiex
 				       ra_list_flags);
 		return -1;
 	}
-	skb_reserve(skb_aggr, MWIFIEX_MIN_DATA_HEADER_LEN);
+
+	/* skb_aggr->data already 64 byte align, just reserve bus interface
+	 * header and txpd.
+	 */
+	skb_reserve(skb_aggr, headroom + sizeof(struct txpd));
 	tx_info_aggr =  MWIFIEX_SKB_TXCB(skb_aggr);
 
 	memset(tx_info_aggr, 0, sizeof(*tx_info_aggr));
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/net/wireless/marvell/mwifiex/debugfs.c linux-libre-4.9.28-gnu/drivers/net/wireless/marvell/mwifiex/debugfs.c
--- linux-libre-4.9.27-gnu/drivers/net/wireless/marvell/mwifiex/debugfs.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/net/wireless/marvell/mwifiex/debugfs.c	2017-05-14 08:00:37.000000000 -0400
@@ -114,7 +114,8 @@ mwifiex_info_read(struct file *file, cha
 	if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) {
 		p += sprintf(p, "multicast_count=\"%d\"\n",
 			     netdev_mc_count(netdev));
-		p += sprintf(p, "essid=\"%s\"\n", info.ssid.ssid);
+		p += sprintf(p, "essid=\"%.*s\"\n", info.ssid.ssid_len,
+			     info.ssid.ssid);
 		p += sprintf(p, "bssid=\"%pM\"\n", info.bssid);
 		p += sprintf(p, "channel=\"%d\"\n", (int) info.bss_chan);
 		p += sprintf(p, "country_code = \"%s\"\n", info.country_code);
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c linux-libre-4.9.28-gnu/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c
--- linux-libre-4.9.27-gnu/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c	2017-05-14 08:00:37.000000000 -0400
@@ -1159,8 +1159,6 @@ int mwifiex_set_encode(struct mwifiex_pr
 			encrypt_key.is_rx_seq_valid = true;
 		}
 	} else {
-		if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP)
-			return 0;
 		encrypt_key.key_disable = true;
 		if (mac_addr)
 			memcpy(encrypt_key.mac_addr, mac_addr, ETH_ALEN);
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/net/wireless/ti/wl18xx/event.c linux-libre-4.9.28-gnu/drivers/net/wireless/ti/wl18xx/event.c
--- linux-libre-4.9.27-gnu/drivers/net/wireless/ti/wl18xx/event.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/net/wireless/ti/wl18xx/event.c	2017-05-14 08:00:37.000000000 -0400
@@ -218,5 +218,33 @@ int wl18xx_process_mailbox_events(struct
 	if (vector & FW_LOGGER_INDICATION)
 		wlcore_event_fw_logger(wl);
 
+	if (vector & RX_BA_WIN_SIZE_CHANGE_EVENT_ID) {
+		struct wl12xx_vif *wlvif;
+		struct ieee80211_vif *vif;
+		struct ieee80211_sta *sta;
+		u8 link_id = mbox->rx_ba_link_id;
+		u8 win_size = mbox->rx_ba_win_size;
+		const u8 *addr;
+
+		wlvif = wl->links[link_id].wlvif;
+		vif = wl12xx_wlvif_to_vif(wlvif);
+
+		/* Update RX aggregation window size and call
+		 * MAC routine to stop active RX aggregations for this link
+		 */
+		if (wlvif->bss_type != BSS_TYPE_AP_BSS)
+			addr = vif->bss_conf.bssid;
+		else
+			addr = wl->links[link_id].addr;
+
+		sta = ieee80211_find_sta(vif, addr);
+		if (sta) {
+			sta->max_rx_aggregation_subframes = win_size;
+			ieee80211_stop_rx_ba_session(vif,
+						wl->links[link_id].ba_bitmap,
+						addr);
+		}
+	}
+
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/net/wireless/ti/wl18xx/event.h linux-libre-4.9.28-gnu/drivers/net/wireless/ti/wl18xx/event.h
--- linux-libre-4.9.27-gnu/drivers/net/wireless/ti/wl18xx/event.h	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/net/wireless/ti/wl18xx/event.h	2017-05-14 08:00:37.000000000 -0400
@@ -38,6 +38,7 @@ enum {
 	REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID      = BIT(18),
 	DFS_CHANNELS_CONFIG_COMPLETE_EVENT       = BIT(19),
 	PERIODIC_SCAN_REPORT_EVENT_ID            = BIT(20),
+	RX_BA_WIN_SIZE_CHANGE_EVENT_ID           = BIT(21),
 	SMART_CONFIG_SYNC_EVENT_ID               = BIT(22),
 	SMART_CONFIG_DECODE_EVENT_ID             = BIT(23),
 	TIME_SYNC_EVENT_ID                       = BIT(24),
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/net/wireless/ti/wl18xx/main.c linux-libre-4.9.28-gnu/drivers/net/wireless/ti/wl18xx/main.c
--- linux-libre-4.9.27-gnu/drivers/net/wireless/ti/wl18xx/main.c	2017-05-08 04:24:21.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/net/wireless/ti/wl18xx/main.c	2017-05-14 16:58:38.000000000 -0400
@@ -1041,7 +1041,8 @@ static int wl18xx_boot(struct wl1271 *wl
 		SMART_CONFIG_SYNC_EVENT_ID |
 		SMART_CONFIG_DECODE_EVENT_ID |
 		TIME_SYNC_EVENT_ID |
-		FW_LOGGER_INDICATION;
+		FW_LOGGER_INDICATION |
+		RX_BA_WIN_SIZE_CHANGE_EVENT_ID;
 
 	wl->ap_event_mask = MAX_TX_FAILURE_EVENT_ID;
 
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/net/wireless/ti/wlcore/acx.c linux-libre-4.9.28-gnu/drivers/net/wireless/ti/wlcore/acx.c
--- linux-libre-4.9.27-gnu/drivers/net/wireless/ti/wlcore/acx.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/net/wireless/ti/wlcore/acx.c	2017-05-14 08:00:37.000000000 -0400
@@ -1419,7 +1419,8 @@ out:
 
 /* setup BA session receiver setting in the FW. */
 int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index,
-				       u16 ssn, bool enable, u8 peer_hlid)
+				       u16 ssn, bool enable, u8 peer_hlid,
+				       u8 win_size)
 {
 	struct wl1271_acx_ba_receiver_setup *acx;
 	int ret;
@@ -1435,7 +1436,7 @@ int wl12xx_acx_set_ba_receiver_session(s
 	acx->hlid = peer_hlid;
 	acx->tid = tid_index;
 	acx->enable = enable;
-	acx->win_size = wl->conf.ht.rx_ba_win_size;
+	acx->win_size =	win_size;
 	acx->ssn = ssn;
 
 	ret = wlcore_cmd_configure_failsafe(wl, ACX_BA_SESSION_RX_SETUP, acx,
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/net/wireless/ti/wlcore/acx.h linux-libre-4.9.28-gnu/drivers/net/wireless/ti/wlcore/acx.h
--- linux-libre-4.9.27-gnu/drivers/net/wireless/ti/wlcore/acx.h	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/net/wireless/ti/wlcore/acx.h	2017-05-14 08:00:37.000000000 -0400
@@ -1113,7 +1113,8 @@ int wl1271_acx_set_ht_information(struct
 int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl,
 				       struct wl12xx_vif *wlvif);
 int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index,
-				       u16 ssn, bool enable, u8 peer_hlid);
+				       u16 ssn, bool enable, u8 peer_hlid,
+				       u8 win_size);
 int wl12xx_acx_tsf_info(struct wl1271 *wl, struct wl12xx_vif *wlvif,
 			u64 *mactime);
 int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif,
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/net/wireless/ti/wlcore/main.c linux-libre-4.9.28-gnu/drivers/net/wireless/ti/wlcore/main.c
--- linux-libre-4.9.27-gnu/drivers/net/wireless/ti/wlcore/main.c	2017-05-08 04:24:23.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/net/wireless/ti/wlcore/main.c	2017-05-14 16:58:40.000000000 -0400
@@ -5285,7 +5285,9 @@ static int wl1271_op_ampdu_action(struct
 		}
 
 		ret = wl12xx_acx_set_ba_receiver_session(wl, tid, *ssn, true,
-							 hlid);
+				hlid,
+				params->buf_size);
+
 		if (!ret) {
 			*ba_bitmap |= BIT(tid);
 			wl->ba_rx_session_count++;
@@ -5306,7 +5308,7 @@ static int wl1271_op_ampdu_action(struct
 		}
 
 		ret = wl12xx_acx_set_ba_receiver_session(wl, tid, 0, false,
-							 hlid);
+							 hlid, 0);
 		if (!ret) {
 			*ba_bitmap &= ~BIT(tid);
 			wl->ba_rx_session_count--;
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/phy/Kconfig linux-libre-4.9.28-gnu/drivers/phy/Kconfig
--- linux-libre-4.9.27-gnu/drivers/phy/Kconfig	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/phy/Kconfig	2017-05-14 08:00:37.000000000 -0400
@@ -456,6 +456,7 @@ config PHY_QCOM_UFS
 config PHY_TUSB1210
 	tristate "TI TUSB1210 ULPI PHY module"
 	depends on USB_ULPI_BUS
+	depends on EXTCON || !EXTCON # if EXTCON=m, this cannot be built-in
 	select GENERIC_PHY
 	help
 	  Support for TI TUSB1210 USB ULPI PHY.
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/power/supply/bq24190_charger.c linux-libre-4.9.28-gnu/drivers/power/supply/bq24190_charger.c
--- linux-libre-4.9.27-gnu/drivers/power/supply/bq24190_charger.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/power/supply/bq24190_charger.c	2017-05-14 08:00:37.000000000 -0400
@@ -144,10 +144,7 @@
  * so the first read after a fault returns the latched value and subsequent
  * reads return the current value.  In order to return the fault status
  * to the user, have the interrupt handler save the reg's value and retrieve
- * it in the appropriate health/status routine.  Each routine has its own
- * flag indicating whether it should use the value stored by the last run
- * of the interrupt handler or do an actual reg read.  That way each routine
- * can report back whatever fault may have occured.
+ * it in the appropriate health/status routine.
  */
 struct bq24190_dev_info {
 	struct i2c_client		*client;
@@ -159,10 +156,6 @@ struct bq24190_dev_info {
 	unsigned int			gpio_int;
 	unsigned int			irq;
 	struct mutex			f_reg_lock;
-	bool				first_time;
-	bool				charger_health_valid;
-	bool				battery_health_valid;
-	bool				battery_status_valid;
 	u8				f_reg;
 	u8				ss_reg;
 	u8				watchdog;
@@ -636,21 +629,11 @@ static int bq24190_charger_get_health(st
 		union power_supply_propval *val)
 {
 	u8 v;
-	int health, ret;
+	int health;
 
 	mutex_lock(&bdi->f_reg_lock);
-
-	if (bdi->charger_health_valid) {
-		v = bdi->f_reg;
-		bdi->charger_health_valid = false;
-		mutex_unlock(&bdi->f_reg_lock);
-	} else {
-		mutex_unlock(&bdi->f_reg_lock);
-
-		ret = bq24190_read(bdi, BQ24190_REG_F, &v);
-		if (ret < 0)
-			return ret;
-	}
+	v = bdi->f_reg;
+	mutex_unlock(&bdi->f_reg_lock);
 
 	if (v & BQ24190_REG_F_BOOST_FAULT_MASK) {
 		/*
@@ -937,18 +920,8 @@ static int bq24190_battery_get_status(st
 	int status, ret;
 
 	mutex_lock(&bdi->f_reg_lock);
-
-	if (bdi->battery_status_valid) {
-		chrg_fault = bdi->f_reg;
-		bdi->battery_status_valid = false;
-		mutex_unlock(&bdi->f_reg_lock);
-	} else {
-		mutex_unlock(&bdi->f_reg_lock);
-
-		ret = bq24190_read(bdi, BQ24190_REG_F, &chrg_fault);
-		if (ret < 0)
-			return ret;
-	}
+	chrg_fault = bdi->f_reg;
+	mutex_unlock(&bdi->f_reg_lock);
 
 	chrg_fault &= BQ24190_REG_F_CHRG_FAULT_MASK;
 	chrg_fault >>= BQ24190_REG_F_CHRG_FAULT_SHIFT;
@@ -996,21 +969,11 @@ static int bq24190_battery_get_health(st
 		union power_supply_propval *val)
 {
 	u8 v;
-	int health, ret;
+	int health;
 
 	mutex_lock(&bdi->f_reg_lock);
-
-	if (bdi->battery_health_valid) {
-		v = bdi->f_reg;
-		bdi->battery_health_valid = false;
-		mutex_unlock(&bdi->f_reg_lock);
-	} else {
-		mutex_unlock(&bdi->f_reg_lock);
-
-		ret = bq24190_read(bdi, BQ24190_REG_F, &v);
-		if (ret < 0)
-			return ret;
-	}
+	v = bdi->f_reg;
+	mutex_unlock(&bdi->f_reg_lock);
 
 	if (v & BQ24190_REG_F_BAT_FAULT_MASK) {
 		health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
@@ -1197,9 +1160,12 @@ static const struct power_supply_desc bq
 static irqreturn_t bq24190_irq_handler_thread(int irq, void *data)
 {
 	struct bq24190_dev_info *bdi = data;
-	bool alert_userspace = false;
+	const u8 battery_mask_ss = BQ24190_REG_SS_CHRG_STAT_MASK;
+	const u8 battery_mask_f = BQ24190_REG_F_BAT_FAULT_MASK
+				| BQ24190_REG_F_NTC_FAULT_MASK;
+	bool alert_charger = false, alert_battery = false;
 	u8 ss_reg = 0, f_reg = 0;
-	int ret;
+	int i, ret;
 
 	pm_runtime_get_sync(bdi->dev);
 
@@ -1209,6 +1175,32 @@ static irqreturn_t bq24190_irq_handler_t
 		goto out;
 	}
 
+	i = 0;
+	do {
+		ret = bq24190_read(bdi, BQ24190_REG_F, &f_reg);
+		if (ret < 0) {
+			dev_err(bdi->dev, "Can't read F reg: %d\n", ret);
+			goto out;
+		}
+	} while (f_reg && ++i < 2);
+
+	if (f_reg != bdi->f_reg) {
+		dev_info(bdi->dev,
+			"Fault: boost %d, charge %d, battery %d, ntc %d\n",
+			!!(f_reg & BQ24190_REG_F_BOOST_FAULT_MASK),
+			!!(f_reg & BQ24190_REG_F_CHRG_FAULT_MASK),
+			!!(f_reg & BQ24190_REG_F_BAT_FAULT_MASK),
+			!!(f_reg & BQ24190_REG_F_NTC_FAULT_MASK));
+
+		mutex_lock(&bdi->f_reg_lock);
+		if ((bdi->f_reg & battery_mask_f) != (f_reg & battery_mask_f))
+			alert_battery = true;
+		if ((bdi->f_reg & ~battery_mask_f) != (f_reg & ~battery_mask_f))
+			alert_charger = true;
+		bdi->f_reg = f_reg;
+		mutex_unlock(&bdi->f_reg_lock);
+	}
+
 	if (ss_reg != bdi->ss_reg) {
 		/*
 		 * The device is in host mode so when PG_STAT goes from 1->0
@@ -1225,47 +1217,17 @@ static irqreturn_t bq24190_irq_handler_t
 					ret);
 		}
 
+		if ((bdi->ss_reg & battery_mask_ss) != (ss_reg & battery_mask_ss))
+			alert_battery = true;
+		if ((bdi->ss_reg & ~battery_mask_ss) != (ss_reg & ~battery_mask_ss))
+			alert_charger = true;
 		bdi->ss_reg = ss_reg;
-		alert_userspace = true;
-	}
-
-	mutex_lock(&bdi->f_reg_lock);
-
-	ret = bq24190_read(bdi, BQ24190_REG_F, &f_reg);
-	if (ret < 0) {
-		mutex_unlock(&bdi->f_reg_lock);
-		dev_err(bdi->dev, "Can't read F reg: %d\n", ret);
-		goto out;
 	}
 
-	if (f_reg != bdi->f_reg) {
-		bdi->f_reg = f_reg;
-		bdi->charger_health_valid = true;
-		bdi->battery_health_valid = true;
-		bdi->battery_status_valid = true;
-
-		alert_userspace = true;
-	}
-
-	mutex_unlock(&bdi->f_reg_lock);
-
-	/*
-	 * Sometimes bq24190 gives a steady trickle of interrupts even
-	 * though the watchdog timer is turned off and neither the STATUS
-	 * nor FAULT registers have changed.  Weed out these sprurious
-	 * interrupts so userspace isn't alerted for no reason.
-	 * In addition, the chip always generates an interrupt after
-	 * register reset so we should ignore that one (the very first
-	 * interrupt received).
-	 */
-	if (alert_userspace) {
-		if (!bdi->first_time) {
-			power_supply_changed(bdi->charger);
-			power_supply_changed(bdi->battery);
-		} else {
-			bdi->first_time = false;
-		}
-	}
+	if (alert_charger)
+		power_supply_changed(bdi->charger);
+	if (alert_battery)
+		power_supply_changed(bdi->battery);
 
 out:
 	pm_runtime_put_sync(bdi->dev);
@@ -1300,6 +1262,10 @@ static int bq24190_hw_init(struct bq2419
 		goto out;
 
 	ret = bq24190_set_mode_host(bdi);
+	if (ret < 0)
+		goto out;
+
+	ret = bq24190_read(bdi, BQ24190_REG_SS, &bdi->ss_reg);
 out:
 	pm_runtime_put_sync(bdi->dev);
 	return ret;
@@ -1375,10 +1341,8 @@ static int bq24190_probe(struct i2c_clie
 	bdi->model = id->driver_data;
 	strncpy(bdi->model_name, id->name, I2C_NAME_SIZE);
 	mutex_init(&bdi->f_reg_lock);
-	bdi->first_time = true;
-	bdi->charger_health_valid = false;
-	bdi->battery_health_valid = false;
-	bdi->battery_status_valid = false;
+	bdi->f_reg = 0;
+	bdi->ss_reg = BQ24190_REG_SS_VBUS_STAT_MASK; /* impossible state */
 
 	i2c_set_clientdata(client, bdi);
 
@@ -1392,22 +1356,13 @@ static int bq24190_probe(struct i2c_clie
 		return -EINVAL;
 	}
 
-	ret = devm_request_threaded_irq(dev, bdi->irq, NULL,
-			bq24190_irq_handler_thread,
-			IRQF_TRIGGER_RISING | IRQF_ONESHOT,
-			"bq24190-charger", bdi);
-	if (ret < 0) {
-		dev_err(dev, "Can't set up irq handler\n");
-		goto out1;
-	}
-
 	pm_runtime_enable(dev);
 	pm_runtime_resume(dev);
 
 	ret = bq24190_hw_init(bdi);
 	if (ret < 0) {
 		dev_err(dev, "Hardware init failed\n");
-		goto out2;
+		goto out1;
 	}
 
 	charger_cfg.drv_data = bdi;
@@ -1418,7 +1373,7 @@ static int bq24190_probe(struct i2c_clie
 	if (IS_ERR(bdi->charger)) {
 		dev_err(dev, "Can't register charger\n");
 		ret = PTR_ERR(bdi->charger);
-		goto out2;
+		goto out1;
 	}
 
 	battery_cfg.drv_data = bdi;
@@ -1427,24 +1382,34 @@ static int bq24190_probe(struct i2c_clie
 	if (IS_ERR(bdi->battery)) {
 		dev_err(dev, "Can't register battery\n");
 		ret = PTR_ERR(bdi->battery);
-		goto out3;
+		goto out2;
 	}
 
 	ret = bq24190_sysfs_create_group(bdi);
 	if (ret) {
 		dev_err(dev, "Can't create sysfs entries\n");
+		goto out3;
+	}
+
+	ret = devm_request_threaded_irq(dev, bdi->irq, NULL,
+			bq24190_irq_handler_thread,
+			IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+			"bq24190-charger", bdi);
+	if (ret < 0) {
+		dev_err(dev, "Can't set up irq handler\n");
 		goto out4;
 	}
 
 	return 0;
 
 out4:
-	power_supply_unregister(bdi->battery);
+	bq24190_sysfs_remove_group(bdi);
 out3:
-	power_supply_unregister(bdi->charger);
+	power_supply_unregister(bdi->battery);
 out2:
-	pm_runtime_disable(dev);
+	power_supply_unregister(bdi->charger);
 out1:
+	pm_runtime_disable(dev);
 	if (bdi->gpio_int)
 		gpio_free(bdi->gpio_int);
 
@@ -1488,12 +1453,13 @@ static int bq24190_pm_resume(struct devi
 	struct i2c_client *client = to_i2c_client(dev);
 	struct bq24190_dev_info *bdi = i2c_get_clientdata(client);
 
-	bdi->charger_health_valid = false;
-	bdi->battery_health_valid = false;
-	bdi->battery_status_valid = false;
+	bdi->f_reg = 0;
+	bdi->ss_reg = BQ24190_REG_SS_VBUS_STAT_MASK; /* impossible state */
 
 	pm_runtime_get_sync(bdi->dev);
 	bq24190_register_reset(bdi);
+	bq24190_set_mode_host(bdi);
+	bq24190_read(bdi, BQ24190_REG_SS, &bdi->ss_reg);
 	pm_runtime_put_sync(bdi->dev);
 
 	/* Things may have changed while suspended so alert upper layer */
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/power/supply/lp8788-charger.c linux-libre-4.9.28-gnu/drivers/power/supply/lp8788-charger.c
--- linux-libre-4.9.27-gnu/drivers/power/supply/lp8788-charger.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/power/supply/lp8788-charger.c	2017-05-14 08:00:37.000000000 -0400
@@ -654,7 +654,7 @@ static ssize_t lp8788_show_eoc_time(stru
 {
 	struct lp8788_charger *pchg = dev_get_drvdata(dev);
 	char *stime[] = { "400ms", "5min", "10min", "15min",
-			"20min", "25min", "30min" "No timeout" };
+			"20min", "25min", "30min", "No timeout" };
 	u8 val;
 
 	lp8788_read_byte(pchg->lp, LP8788_CHG_EOC, &val);
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/scsi/Kconfig linux-libre-4.9.28-gnu/drivers/scsi/Kconfig
--- linux-libre-4.9.27-gnu/drivers/scsi/Kconfig	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/scsi/Kconfig	2017-05-14 08:00:37.000000000 -0400
@@ -1497,7 +1497,7 @@ config ATARI_SCSI
 
 config MAC_SCSI
 	tristate "Macintosh NCR5380 SCSI"
-	depends on MAC && SCSI=y
+	depends on MAC && SCSI
 	select SCSI_SPI_ATTRS
 	help
 	  This is the NCR 5380 SCSI controller included on most of the 68030
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/scsi/qla2xxx/qla_os.c linux-libre-4.9.28-gnu/drivers/scsi/qla2xxx/qla_os.c
--- linux-libre-4.9.27-gnu/drivers/scsi/qla2xxx/qla_os.c	2017-05-08 04:32:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/scsi/qla2xxx/qla_os.c	2017-05-14 17:06:10.000000000 -0400
@@ -1464,7 +1464,8 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *
 				/* Don't abort commands in adapter during EEH
 				 * recovery as it's not accessible/responding.
 				 */
-				if (GET_CMD_SP(sp) && !ha->flags.eeh_busy) {
+				if (GET_CMD_SP(sp) && !ha->flags.eeh_busy &&
+				    (sp->type == SRB_SCSI_CMD)) {
 					/* Get a reference to the sp and drop the lock.
 					 * The reference ensures this sp->done() call
 					 * - and not the call in qla2xxx_eh_abort() -
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/scsi/smartpqi/smartpqi_init.c linux-libre-4.9.28-gnu/drivers/scsi/smartpqi/smartpqi_init.c
--- linux-libre-4.9.27-gnu/drivers/scsi/smartpqi/smartpqi_init.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/scsi/smartpqi/smartpqi_init.c	2017-05-14 08:00:37.000000000 -0400
@@ -533,8 +533,7 @@ static int pqi_write_current_time_to_hos
 	size_t buffer_length;
 	time64_t local_time;
 	unsigned int year;
-	struct timeval time;
-	struct rtc_time tm;
+	struct tm tm;
 
 	buffer_length = sizeof(*buffer);
 
@@ -551,9 +550,8 @@ static int pqi_write_current_time_to_hos
 	put_unaligned_le16(sizeof(buffer->time),
 		&buffer->time_length);
 
-	do_gettimeofday(&time);
-	local_time = time.tv_sec - (sys_tz.tz_minuteswest * 60);
-	rtc_time64_to_tm(local_time, &tm);
+	local_time = ktime_get_real_seconds();
+	time64_to_tm(local_time, -sys_tz.tz_minuteswest * 60, &tm);
 	year = tm.tm_year + 1900;
 
 	buffer->time[0] = bin2bcd(tm.tm_hour);
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/staging/emxx_udc/emxx_udc.c linux-libre-4.9.28-gnu/drivers/staging/emxx_udc/emxx_udc.c
--- linux-libre-4.9.27-gnu/drivers/staging/emxx_udc/emxx_udc.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/staging/emxx_udc/emxx_udc.c	2017-05-14 08:00:37.000000000 -0400
@@ -3160,7 +3160,7 @@ static const struct {
 };
 
 /*-------------------------------------------------------------------------*/
-static void __init nbu2ss_drv_ep_init(struct nbu2ss_udc *udc)
+static void nbu2ss_drv_ep_init(struct nbu2ss_udc *udc)
 {
 	int	i;
 
@@ -3191,7 +3191,7 @@ static void __init nbu2ss_drv_ep_init(st
 
 /*-------------------------------------------------------------------------*/
 /* platform_driver */
-static int __init nbu2ss_drv_contest_init(
+static int nbu2ss_drv_contest_init(
 	struct platform_device *pdev,
 	struct nbu2ss_udc *udc)
 {
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/staging/lustre/lustre/llite/lproc_llite.c linux-libre-4.9.28-gnu/drivers/staging/lustre/lustre/llite/lproc_llite.c
--- linux-libre-4.9.27-gnu/drivers/staging/lustre/lustre/llite/lproc_llite.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/staging/lustre/lustre/llite/lproc_llite.c	2017-05-14 08:00:37.000000000 -0400
@@ -924,27 +924,29 @@ static ssize_t ll_unstable_stats_seq_wri
 }
 LPROC_SEQ_FOPS(ll_unstable_stats);
 
-static ssize_t root_squash_show(struct kobject *kobj, struct attribute *attr,
-				char *buf)
+static int ll_root_squash_seq_show(struct seq_file *m, void *v)
 {
-	struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
-					      ll_kobj);
+	struct super_block *sb = m->private;
+	struct ll_sb_info *sbi = ll_s2sbi(sb);
 	struct root_squash_info *squash = &sbi->ll_squash;
 
-	return sprintf(buf, "%u:%u\n", squash->rsi_uid, squash->rsi_gid);
+	seq_printf(m, "%u:%u\n", squash->rsi_uid, squash->rsi_gid);
+	return 0;
 }
 
-static ssize_t root_squash_store(struct kobject *kobj, struct attribute *attr,
-				 const char *buffer, size_t count)
+static ssize_t ll_root_squash_seq_write(struct file *file,
+					const char __user *buffer,
+					size_t count, loff_t *off)
 {
-	struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
-					      ll_kobj);
+	struct seq_file *m = file->private_data;
+	struct super_block *sb = m->private;
+	struct ll_sb_info *sbi = ll_s2sbi(sb);
 	struct root_squash_info *squash = &sbi->ll_squash;
 
 	return lprocfs_wr_root_squash(buffer, count, squash,
-				      ll_get_fsname(sbi->ll_sb, NULL, 0));
+				      ll_get_fsname(sb, NULL, 0));
 }
-LUSTRE_RW_ATTR(root_squash);
+LPROC_SEQ_FOPS(ll_root_squash);
 
 static int ll_nosquash_nids_seq_show(struct seq_file *m, void *v)
 {
@@ -997,6 +999,8 @@ static struct lprocfs_vars lprocfs_llite
 	{ "statahead_stats",  &ll_statahead_stats_fops, NULL, 0 },
 	{ "unstable_stats",   &ll_unstable_stats_fops, NULL },
 	{ "sbi_flags",	      &ll_sbi_flags_fops, NULL, 0 },
+	{ .name =       "root_squash",
+	  .fops =       &ll_root_squash_fops			},
 	{ .name =		"nosquash_nids",
 	  .fops =		&ll_nosquash_nids_fops		},
 	{ NULL }
@@ -1027,7 +1031,6 @@ static struct attribute *llite_attrs[] =
 	&lustre_attr_max_easize.attr,
 	&lustre_attr_default_easize.attr,
 	&lustre_attr_xattr_cache.attr,
-	&lustre_attr_root_squash.attr,
 	NULL,
 };
 
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/staging/wlan-ng/p80211netdev.c linux-libre-4.9.28-gnu/drivers/staging/wlan-ng/p80211netdev.c
--- linux-libre-4.9.27-gnu/drivers/staging/wlan-ng/p80211netdev.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/staging/wlan-ng/p80211netdev.c	2017-05-14 08:00:37.000000000 -0400
@@ -232,7 +232,7 @@ static int p80211_convert_to_ether(struc
 	struct p80211_hdr_a3 *hdr;
 
 	hdr = (struct p80211_hdr_a3 *)skb->data;
-	if (p80211_rx_typedrop(wlandev, hdr->fc))
+	if (p80211_rx_typedrop(wlandev, le16_to_cpu(hdr->fc)))
 		return CONV_TO_ETHER_SKIPPED;
 
 	/* perform mcast filtering: allow my local address through but reject
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/tty/serial/8250/8250_omap.c linux-libre-4.9.28-gnu/drivers/tty/serial/8250/8250_omap.c
--- linux-libre-4.9.27-gnu/drivers/tty/serial/8250/8250_omap.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/tty/serial/8250/8250_omap.c	2017-05-14 08:00:37.000000000 -0400
@@ -1237,7 +1237,8 @@ static int omap8250_probe(struct platfor
 	pm_runtime_put_autosuspend(&pdev->dev);
 	return 0;
 err:
-	pm_runtime_put(&pdev->dev);
+	pm_runtime_dont_use_autosuspend(&pdev->dev);
+	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 	return ret;
 }
@@ -1246,6 +1247,7 @@ static int omap8250_remove(struct platfo
 {
 	struct omap8250_priv *priv = platform_get_drvdata(pdev);
 
+	pm_runtime_dont_use_autosuspend(&pdev->dev);
 	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 	serial8250_unregister_port(priv->line);
@@ -1345,6 +1347,10 @@ static int omap8250_runtime_suspend(stru
 	struct omap8250_priv *priv = dev_get_drvdata(dev);
 	struct uart_8250_port *up;
 
+	/* In case runtime-pm tries this before we are setup */
+	if (!priv)
+		return 0;
+
 	up = serial8250_get_port(priv->line);
 	/*
 	 * When using 'no_console_suspend', the console UART must not be
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/usb/chipidea/ci.h linux-libre-4.9.28-gnu/drivers/usb/chipidea/ci.h
--- linux-libre-4.9.27-gnu/drivers/usb/chipidea/ci.h	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/usb/chipidea/ci.h	2017-05-14 08:00:37.000000000 -0400
@@ -428,9 +428,6 @@ int hw_port_test_set(struct ci_hdrc *ci,
 
 u8 hw_port_test_get(struct ci_hdrc *ci);
 
-int hw_wait_reg(struct ci_hdrc *ci, enum ci_hw_regs reg, u32 mask,
-				u32 value, unsigned int timeout_ms);
-
 void ci_platform_configure(struct ci_hdrc *ci);
 
 int dbg_create_files(struct ci_hdrc *ci);
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/usb/chipidea/core.c linux-libre-4.9.28-gnu/drivers/usb/chipidea/core.c
--- linux-libre-4.9.27-gnu/drivers/usb/chipidea/core.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/usb/chipidea/core.c	2017-05-14 08:00:37.000000000 -0400
@@ -516,38 +516,6 @@ int hw_device_reset(struct ci_hdrc *ci)
 	return 0;
 }
 
-/**
- * hw_wait_reg: wait the register value
- *
- * Sometimes, it needs to wait register value before going on.
- * Eg, when switch to device mode, the vbus value should be lower
- * than OTGSC_BSV before connects to host.
- *
- * @ci: the controller
- * @reg: register index
- * @mask: mast bit
- * @value: the bit value to wait
- * @timeout_ms: timeout in millisecond
- *
- * This function returns an error code if timeout
- */
-int hw_wait_reg(struct ci_hdrc *ci, enum ci_hw_regs reg, u32 mask,
-				u32 value, unsigned int timeout_ms)
-{
-	unsigned long elapse = jiffies + msecs_to_jiffies(timeout_ms);
-
-	while (hw_read(ci, reg, mask) != value) {
-		if (time_after(jiffies, elapse)) {
-			dev_err(ci->dev, "timeout waiting for %08x in %d\n",
-					mask, reg);
-			return -ETIMEDOUT;
-		}
-		msleep(20);
-	}
-
-	return 0;
-}
-
 static irqreturn_t ci_irq(int irq, void *data)
 {
 	struct ci_hdrc *ci = data;
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/usb/chipidea/otg.c linux-libre-4.9.28-gnu/drivers/usb/chipidea/otg.c
--- linux-libre-4.9.27-gnu/drivers/usb/chipidea/otg.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/usb/chipidea/otg.c	2017-05-14 08:00:37.000000000 -0400
@@ -44,12 +44,15 @@ u32 hw_read_otgsc(struct ci_hdrc *ci, u3
 		else
 			val &= ~OTGSC_BSVIS;
 
-		cable->changed = false;
-
 		if (cable->state)
 			val |= OTGSC_BSV;
 		else
 			val &= ~OTGSC_BSV;
+
+		if (cable->enabled)
+			val |= OTGSC_BSVIE;
+		else
+			val &= ~OTGSC_BSVIE;
 	}
 
 	cable = &ci->platdata->id_extcon;
@@ -59,15 +62,18 @@ u32 hw_read_otgsc(struct ci_hdrc *ci, u3
 		else
 			val &= ~OTGSC_IDIS;
 
-		cable->changed = false;
-
 		if (cable->state)
 			val |= OTGSC_ID;
 		else
 			val &= ~OTGSC_ID;
+
+		if (cable->enabled)
+			val |= OTGSC_IDIE;
+		else
+			val &= ~OTGSC_IDIE;
 	}
 
-	return val;
+	return val & mask;
 }
 
 /**
@@ -77,6 +83,36 @@ u32 hw_read_otgsc(struct ci_hdrc *ci, u3
  */
 void hw_write_otgsc(struct ci_hdrc *ci, u32 mask, u32 data)
 {
+	struct ci_hdrc_cable *cable;
+
+	cable = &ci->platdata->vbus_extcon;
+	if (!IS_ERR(cable->edev)) {
+		if (data & mask & OTGSC_BSVIS)
+			cable->changed = false;
+
+		/* Don't enable vbus interrupt if using external notifier */
+		if (data & mask & OTGSC_BSVIE) {
+			cable->enabled = true;
+			data &= ~OTGSC_BSVIE;
+		} else if (mask & OTGSC_BSVIE) {
+			cable->enabled = false;
+		}
+	}
+
+	cable = &ci->platdata->id_extcon;
+	if (!IS_ERR(cable->edev)) {
+		if (data & mask & OTGSC_IDIS)
+			cable->changed = false;
+
+		/* Don't enable id interrupt if using external notifier */
+		if (data & mask & OTGSC_IDIE) {
+			cable->enabled = true;
+			data &= ~OTGSC_IDIE;
+		} else if (mask & OTGSC_IDIE) {
+			cable->enabled = false;
+		}
+	}
+
 	hw_write(ci, OP_OTGSC, mask | OTGSC_INT_STATUS_BITS, data);
 }
 
@@ -104,7 +140,31 @@ void ci_handle_vbus_change(struct ci_hdr
 		usb_gadget_vbus_disconnect(&ci->gadget);
 }
 
-#define CI_VBUS_STABLE_TIMEOUT_MS 5000
+/**
+ * When we switch to device mode, the vbus value should be lower
+ * than OTGSC_BSV before connecting to host.
+ *
+ * @ci: the controller
+ *
+ * This function returns an error code if timeout
+ */
+static int hw_wait_vbus_lower_bsv(struct ci_hdrc *ci)
+{
+	unsigned long elapse = jiffies + msecs_to_jiffies(5000);
+	u32 mask = OTGSC_BSV;
+
+	while (hw_read_otgsc(ci, mask)) {
+		if (time_after(jiffies, elapse)) {
+			dev_err(ci->dev, "timeout waiting for %08x in OTGSC\n",
+					mask);
+			return -ETIMEDOUT;
+		}
+		msleep(20);
+	}
+
+	return 0;
+}
+
 static void ci_handle_id_switch(struct ci_hdrc *ci)
 {
 	enum ci_role role = ci_otg_role(ci);
@@ -116,9 +176,11 @@ static void ci_handle_id_switch(struct c
 		ci_role_stop(ci);
 
 		if (role == CI_ROLE_GADGET)
-			/* wait vbus lower than OTGSC_BSV */
-			hw_wait_reg(ci, OP_OTGSC, OTGSC_BSV, 0,
-					CI_VBUS_STABLE_TIMEOUT_MS);
+			/*
+			 * wait vbus lower than OTGSC_BSV before connecting
+			 * to host
+			 */
+			hw_wait_vbus_lower_bsv(ci);
 
 		ci_role_start(ci, role);
 	}
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/usb/dwc2/core.c linux-libre-4.9.28-gnu/drivers/usb/dwc2/core.c
--- linux-libre-4.9.27-gnu/drivers/usb/dwc2/core.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/usb/dwc2/core.c	2017-05-14 08:00:37.000000000 -0400
@@ -455,7 +455,7 @@ static void dwc2_clear_force_mode(struct
 	dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG);
 
 	if (dwc2_iddig_filter_enabled(hsotg))
-		usleep_range(100000, 110000);
+		msleep(100);
 }
 
 /*
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/usb/host/ehci-exynos.c linux-libre-4.9.28-gnu/drivers/usb/host/ehci-exynos.c
--- linux-libre-4.9.27-gnu/drivers/usb/host/ehci-exynos.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/usb/host/ehci-exynos.c	2017-05-14 08:00:37.000000000 -0400
@@ -77,10 +77,12 @@ static int exynos_ehci_get_phy(struct de
 		if (IS_ERR(phy)) {
 			ret = PTR_ERR(phy);
 			if (ret == -EPROBE_DEFER) {
+				of_node_put(child);
 				return ret;
 			} else if (ret != -ENOSYS && ret != -ENODEV) {
 				dev_err(dev,
 					"Error retrieving usb2 phy: %d\n", ret);
+				of_node_put(child);
 				return ret;
 			}
 		}
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/usb/host/ohci-exynos.c linux-libre-4.9.28-gnu/drivers/usb/host/ohci-exynos.c
--- linux-libre-4.9.27-gnu/drivers/usb/host/ohci-exynos.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/usb/host/ohci-exynos.c	2017-05-14 08:00:37.000000000 -0400
@@ -66,10 +66,12 @@ static int exynos_ohci_get_phy(struct de
 		if (IS_ERR(phy)) {
 			ret = PTR_ERR(phy);
 			if (ret == -EPROBE_DEFER) {
+				of_node_put(child);
 				return ret;
 			} else if (ret != -ENOSYS && ret != -ENODEV) {
 				dev_err(dev,
 					"Error retrieving usb2 phy: %d\n", ret);
+				of_node_put(child);
 				return ret;
 			}
 		}
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/usb/serial/ark3116.c linux-libre-4.9.28-gnu/drivers/usb/serial/ark3116.c
--- linux-libre-4.9.27-gnu/drivers/usb/serial/ark3116.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/usb/serial/ark3116.c	2017-05-14 08:00:37.000000000 -0400
@@ -373,23 +373,29 @@ static int ark3116_open(struct tty_struc
 		dev_dbg(&port->dev,
 			"%s - usb_serial_generic_open failed: %d\n",
 			__func__, result);
-		goto err_out;
+		goto err_free;
 	}
 
 	/* remove any data still left: also clears error state */
 	ark3116_read_reg(serial, UART_RX, buf);
 
 	/* read modem status */
-	priv->msr = ark3116_read_reg(serial, UART_MSR, buf);
+	result = ark3116_read_reg(serial, UART_MSR, buf);
+	if (result < 0)
+		goto err_close;
+	priv->msr = *buf;
+
 	/* read line status */
-	priv->lsr = ark3116_read_reg(serial, UART_LSR, buf);
+	result = ark3116_read_reg(serial, UART_LSR, buf);
+	if (result < 0)
+		goto err_close;
+	priv->lsr = *buf;
 
 	result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
 	if (result) {
 		dev_err(&port->dev, "submit irq_in urb failed %d\n",
 			result);
-		ark3116_close(port);
-		goto err_out;
+		goto err_close;
 	}
 
 	/* activate interrupts */
@@ -402,8 +408,15 @@ static int ark3116_open(struct tty_struc
 	if (tty)
 		ark3116_set_termios(tty, port, NULL);
 
-err_out:
 	kfree(buf);
+
+	return 0;
+
+err_close:
+	usb_serial_generic_close(port);
+err_free:
+	kfree(buf);
+
 	return result;
 }
 
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/usb/serial/digi_acceleport.c linux-libre-4.9.28-gnu/drivers/usb/serial/digi_acceleport.c
--- linux-libre-4.9.27-gnu/drivers/usb/serial/digi_acceleport.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/usb/serial/digi_acceleport.c	2017-05-14 08:00:37.000000000 -0400
@@ -1398,25 +1398,30 @@ static int digi_read_inb_callback(struct
 {
 	struct usb_serial_port *port = urb->context;
 	struct digi_port *priv = usb_get_serial_port_data(port);
-	int opcode = ((unsigned char *)urb->transfer_buffer)[0];
-	int len = ((unsigned char *)urb->transfer_buffer)[1];
-	int port_status = ((unsigned char *)urb->transfer_buffer)[2];
-	unsigned char *data = ((unsigned char *)urb->transfer_buffer) + 3;
+	unsigned char *buf = urb->transfer_buffer;
+	int opcode;
+	int len;
+	int port_status;
+	unsigned char *data;
 	int flag, throttled;
-	int status = urb->status;
-
-	/* do not process callbacks on closed ports */
-	/* but do continue the read chain */
-	if (urb->status == -ENOENT)
-		return 0;
 
 	/* short/multiple packet check */
+	if (urb->actual_length < 2) {
+		dev_warn(&port->dev, "short packet received\n");
+		return -1;
+	}
+
+	opcode = buf[0];
+	len = buf[1];
+
 	if (urb->actual_length != len + 2) {
-		dev_err(&port->dev, "%s: INCOMPLETE OR MULTIPLE PACKET, "
-			"status=%d, port=%d, opcode=%d, len=%d, "
-			"actual_length=%d, status=%d\n", __func__, status,
-			priv->dp_port_num, opcode, len, urb->actual_length,
-			port_status);
+		dev_err(&port->dev, "malformed packet received: port=%d, opcode=%d, len=%d, actual_length=%u\n",
+			priv->dp_port_num, opcode, len, urb->actual_length);
+		return -1;
+	}
+
+	if (opcode == DIGI_CMD_RECEIVE_DATA && len < 1) {
+		dev_err(&port->dev, "malformed data packet received\n");
 		return -1;
 	}
 
@@ -1430,6 +1435,9 @@ static int digi_read_inb_callback(struct
 
 	/* receive data */
 	if (opcode == DIGI_CMD_RECEIVE_DATA) {
+		port_status = buf[2];
+		data = &buf[3];
+
 		/* get flag from port_status */
 		flag = 0;
 
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/usb/serial/ftdi_sio.c linux-libre-4.9.28-gnu/drivers/usb/serial/ftdi_sio.c
--- linux-libre-4.9.27-gnu/drivers/usb/serial/ftdi_sio.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/usb/serial/ftdi_sio.c	2017-05-14 08:00:37.000000000 -0400
@@ -1439,10 +1439,13 @@ static int read_latency_timer(struct usb
 			     FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE,
 			     0, priv->interface,
 			     buf, 1, WDR_TIMEOUT);
-	if (rv < 0)
+	if (rv < 1) {
 		dev_err(&port->dev, "Unable to read latency timer: %i\n", rv);
-	else
+		if (rv >= 0)
+			rv = -EIO;
+	} else {
 		priv->latency = buf[0];
+	}
 
 	kfree(buf);
 
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/usb/serial/io_edgeport.c linux-libre-4.9.28-gnu/drivers/usb/serial/io_edgeport.c
--- linux-libre-4.9.27-gnu/drivers/usb/serial/io_edgeport.c	2017-05-08 04:34:26.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/usb/serial/io_edgeport.c	2017-05-14 17:08:08.000000000 -0400
@@ -492,20 +492,24 @@ static int get_epic_descriptor(struct ed
 	int result;
 	struct usb_serial *serial = ep->serial;
 	struct edgeport_product_info *product_info = &ep->product_info;
-	struct edge_compatibility_descriptor *epic = &ep->epic_descriptor;
+	struct edge_compatibility_descriptor *epic;
 	struct edge_compatibility_bits *bits;
 	struct device *dev = &serial->dev->dev;
 
 	ep->is_epic = 0;
+
+	epic = kmalloc(sizeof(*epic), GFP_KERNEL);
+	if (!epic)
+		return -ENOMEM;
+
 	result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
 				 USB_REQUEST_ION_GET_EPIC_DESC,
 				 0xC0, 0x00, 0x00,
-				 &ep->epic_descriptor,
-				 sizeof(struct edge_compatibility_descriptor),
+				 epic, sizeof(*epic),
 				 300);
-
-	if (result > 0) {
+	if (result == sizeof(*epic)) {
 		ep->is_epic = 1;
+		memcpy(&ep->epic_descriptor, epic, sizeof(*epic));
 		memset(product_info, 0, sizeof(struct edgeport_product_info));
 
 		product_info->NumPorts = epic->NumPorts;
@@ -534,8 +538,16 @@ static int get_epic_descriptor(struct ed
 		dev_dbg(dev, "  IOSPWriteLCR     : %s\n", bits->IOSPWriteLCR	? "TRUE": "FALSE");
 		dev_dbg(dev, "  IOSPSetBaudRate  : %s\n", bits->IOSPSetBaudRate	? "TRUE": "FALSE");
 		dev_dbg(dev, "  TrueEdgeport     : %s\n", bits->TrueEdgeport	? "TRUE": "FALSE");
+
+		result = 0;
+	} else if (result >= 0) {
+		dev_warn(&serial->interface->dev, "short epic descriptor received: %d\n",
+			 result);
+		result = -EIO;
 	}
 
+	kfree(epic);
+
 	return result;
 }
 
@@ -2093,8 +2105,7 @@ static int rom_write(struct usb_serial *
  * rom_read
  *	reads a number of bytes from the Edgeport device starting at the given
  *	address.
- *	If successful returns the number of bytes read, otherwise it returns
- *	a negative error number of the problem.
+ *	Returns zero on success or a negative error number.
  ****************************************************************************/
 static int rom_read(struct usb_serial *serial, __u16 extAddr,
 					__u16 addr, __u16 length, __u8 *data)
@@ -2119,12 +2130,17 @@ static int rom_read(struct usb_serial *s
 					USB_REQUEST_ION_READ_ROM,
 					0xC0, addr, extAddr, transfer_buffer,
 					current_length, 300);
-		if (result < 0)
+		if (result < current_length) {
+			if (result >= 0)
+				result = -EIO;
 			break;
+		}
 		memcpy(data, transfer_buffer, current_length);
 		length -= current_length;
 		addr += current_length;
 		data += current_length;
+
+		result = 0;
 	}
 
 	kfree(transfer_buffer);
@@ -2578,9 +2594,10 @@ static void get_manufacturing_desc(struc
 				EDGE_MANUF_DESC_LEN,
 				(__u8 *)(&edge_serial->manuf_descriptor));
 
-	if (response < 1)
-		dev_err(dev, "error in getting manufacturer descriptor\n");
-	else {
+	if (response < 0) {
+		dev_err(dev, "error in getting manufacturer descriptor: %d\n",
+				response);
+	} else {
 		char string[30];
 		dev_dbg(dev, "**Manufacturer Descriptor\n");
 		dev_dbg(dev, "  RomSize:        %dK\n",
@@ -2637,9 +2654,10 @@ static void get_boot_desc(struct edgepor
 				EDGE_BOOT_DESC_LEN,
 				(__u8 *)(&edge_serial->boot_descriptor));
 
-	if (response < 1)
-		dev_err(dev, "error in getting boot descriptor\n");
-	else {
+	if (response < 0) {
+		dev_err(dev, "error in getting boot descriptor: %d\n",
+				response);
+	} else {
 		dev_dbg(dev, "**Boot Descriptor:\n");
 		dev_dbg(dev, "  BootCodeLength: %d\n",
 			le16_to_cpu(edge_serial->boot_descriptor.BootCodeLength));
@@ -2782,7 +2800,7 @@ static int edge_startup(struct usb_seria
 	dev_info(&serial->dev->dev, "%s detected\n", edge_serial->name);
 
 	/* Read the epic descriptor */
-	if (get_epic_descriptor(edge_serial) <= 0) {
+	if (get_epic_descriptor(edge_serial) < 0) {
 		/* memcpy descriptor to Supports structures */
 		memcpy(&edge_serial->epic_descriptor.Supports, descriptor,
 		       sizeof(struct edge_compatibility_bits));
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/usb/serial/keyspan_pda.c linux-libre-4.9.28-gnu/drivers/usb/serial/keyspan_pda.c
--- linux-libre-4.9.27-gnu/drivers/usb/serial/keyspan_pda.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/usb/serial/keyspan_pda.c	2017-05-14 08:00:37.000000000 -0400
@@ -139,6 +139,7 @@ static void keyspan_pda_rx_interrupt(str
 {
 	struct usb_serial_port *port = urb->context;
 	unsigned char *data = urb->transfer_buffer;
+	unsigned int len = urb->actual_length;
 	int retval;
 	int status = urb->status;
 	struct keyspan_pda_private *priv;
@@ -159,18 +160,26 @@ static void keyspan_pda_rx_interrupt(str
 		goto exit;
 	}
 
+	if (len < 1) {
+		dev_warn(&port->dev, "short message received\n");
+		goto exit;
+	}
+
 	/* see if the message is data or a status interrupt */
 	switch (data[0]) {
 	case 0:
 		 /* rest of message is rx data */
-		if (urb->actual_length) {
-			tty_insert_flip_string(&port->port, data + 1,
-						urb->actual_length - 1);
-			tty_flip_buffer_push(&port->port);
-		}
+		if (len < 2)
+			break;
+		tty_insert_flip_string(&port->port, data + 1, len - 1);
+		tty_flip_buffer_push(&port->port);
 		break;
 	case 1:
 		/* status interrupt */
+		if (len < 3) {
+			dev_warn(&port->dev, "short interrupt message received\n");
+			break;
+		}
 		dev_dbg(&port->dev, "rx int, d1=%d, d2=%d\n", data[1], data[2]);
 		switch (data[1]) {
 		case 1: /* modemline change */
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/usb/serial/mct_u232.c linux-libre-4.9.28-gnu/drivers/usb/serial/mct_u232.c
--- linux-libre-4.9.27-gnu/drivers/usb/serial/mct_u232.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/usb/serial/mct_u232.c	2017-05-14 08:00:37.000000000 -0400
@@ -322,8 +322,12 @@ static int mct_u232_get_modem_stat(struc
 			MCT_U232_GET_REQUEST_TYPE,
 			0, 0, buf, MCT_U232_GET_MODEM_STAT_SIZE,
 			WDR_TIMEOUT);
-	if (rc < 0) {
+	if (rc < MCT_U232_GET_MODEM_STAT_SIZE) {
 		dev_err(&port->dev, "Get MODEM STATus failed (error = %d)\n", rc);
+
+		if (rc >= 0)
+			rc = -EIO;
+
 		*msr = 0;
 	} else {
 		*msr = buf[0];
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/usb/serial/quatech2.c linux-libre-4.9.28-gnu/drivers/usb/serial/quatech2.c
--- linux-libre-4.9.27-gnu/drivers/usb/serial/quatech2.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/usb/serial/quatech2.c	2017-05-14 08:00:37.000000000 -0400
@@ -188,22 +188,22 @@ static inline int qt2_setdevice(struct u
 }
 
 
-static inline int qt2_getdevice(struct usb_device *dev, u8 *data)
-{
-	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-			       QT_SET_GET_DEVICE, 0xc0, 0, 0,
-			       data, 3, QT2_USB_TIMEOUT);
-}
-
 static inline int qt2_getregister(struct usb_device *dev,
 				  u8 uart,
 				  u8 reg,
 				  u8 *data)
 {
-	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-			       QT_SET_GET_REGISTER, 0xc0, reg,
-			       uart, data, sizeof(*data), QT2_USB_TIMEOUT);
+	int ret;
+
+	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+			      QT_SET_GET_REGISTER, 0xc0, reg,
+			      uart, data, sizeof(*data), QT2_USB_TIMEOUT);
+	if (ret < sizeof(*data)) {
+		if (ret >= 0)
+			ret = -EIO;
+	}
 
+	return ret;
 }
 
 static inline int qt2_setregister(struct usb_device *dev,
@@ -372,9 +372,11 @@ static int qt2_open(struct tty_struct *t
 				 0xc0, 0,
 				 device_port, data, 2, QT2_USB_TIMEOUT);
 
-	if (status < 0) {
+	if (status < 2) {
 		dev_err(&port->dev, "%s - open port failed %i\n", __func__,
 			status);
+		if (status >= 0)
+			status = -EIO;
 		kfree(data);
 		return status;
 	}
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/usb/serial/ssu100.c linux-libre-4.9.28-gnu/drivers/usb/serial/ssu100.c
--- linux-libre-4.9.27-gnu/drivers/usb/serial/ssu100.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/usb/serial/ssu100.c	2017-05-14 08:00:37.000000000 -0400
@@ -80,9 +80,17 @@ static inline int ssu100_setdevice(struc
 
 static inline int ssu100_getdevice(struct usb_device *dev, u8 *data)
 {
-	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-			       QT_SET_GET_DEVICE, 0xc0, 0, 0,
-			       data, 3, 300);
+	int ret;
+
+	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+			      QT_SET_GET_DEVICE, 0xc0, 0, 0,
+			      data, 3, 300);
+	if (ret < 3) {
+		if (ret >= 0)
+			ret = -EIO;
+	}
+
+	return ret;
 }
 
 static inline int ssu100_getregister(struct usb_device *dev,
@@ -90,10 +98,17 @@ static inline int ssu100_getregister(str
 				     unsigned short reg,
 				     u8 *data)
 {
-	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-			       QT_SET_GET_REGISTER, 0xc0, reg,
-			       uart, data, sizeof(*data), 300);
+	int ret;
 
+	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+			      QT_SET_GET_REGISTER, 0xc0, reg,
+			      uart, data, sizeof(*data), 300);
+	if (ret < sizeof(*data)) {
+		if (ret >= 0)
+			ret = -EIO;
+	}
+
+	return ret;
 }
 
 
@@ -289,8 +304,10 @@ static int ssu100_open(struct tty_struct
 				 QT_OPEN_CLOSE_CHANNEL,
 				 QT_TRANSFER_IN, 0x01,
 				 0, data, 2, 300);
-	if (result < 0) {
+	if (result < 2) {
 		dev_dbg(&port->dev, "%s - open failed %i\n", __func__, result);
+		if (result >= 0)
+			result = -EIO;
 		kfree(data);
 		return result;
 	}
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/usb/serial/ti_usb_3410_5052.c linux-libre-4.9.28-gnu/drivers/usb/serial/ti_usb_3410_5052.c
--- linux-libre-4.9.27-gnu/drivers/usb/serial/ti_usb_3410_5052.c	2017-05-08 04:34:50.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/usb/serial/ti_usb_3410_5052.c	2017-05-14 17:08:30.000000000 -0400
@@ -1545,13 +1545,10 @@ static int ti_command_out_sync(struct ti
 		(USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT),
 		value, moduleid, data, size, 1000);
 
-	if (status == size)
-		status = 0;
-
-	if (status > 0)
-		status = -ECOMM;
+	if (status < 0)
+		return status;
 
-	return status;
+	return 0;
 }
 
 
@@ -1567,8 +1564,7 @@ static int ti_command_in_sync(struct ti_
 
 	if (status == size)
 		status = 0;
-
-	if (status > 0)
+	else if (status >= 0)
 		status = -ECOMM;
 
 	return status;
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/xen/events/events_base.c linux-libre-4.9.28-gnu/drivers/xen/events/events_base.c
--- linux-libre-4.9.27-gnu/drivers/xen/events/events_base.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/xen/events/events_base.c	2017-05-14 08:00:37.000000000 -0400
@@ -1314,6 +1314,9 @@ static int rebind_irq_to_cpu(unsigned ir
 	if (!VALID_EVTCHN(evtchn))
 		return -1;
 
+	if (!xen_support_evtchn_rebind())
+		return -1;
+
 	/* Send future instances of this interrupt to other vcpu. */
 	bind_vcpu.port = evtchn;
 	bind_vcpu.vcpu = xen_vcpu_nr(tcpu);
@@ -1647,15 +1650,20 @@ void xen_callback_vector(void)
 {
 	int rc;
 	uint64_t callback_via;
-
-	callback_via = HVM_CALLBACK_VECTOR(HYPERVISOR_CALLBACK_VECTOR);
-	rc = xen_set_callback_via(callback_via);
-	BUG_ON(rc);
-	pr_info("Xen HVM callback vector for event delivery is enabled\n");
-	/* in the restore case the vector has already been allocated */
-	if (!test_bit(HYPERVISOR_CALLBACK_VECTOR, used_vectors))
-		alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR,
-				xen_hvm_callback_vector);
+	if (xen_have_vector_callback) {
+		callback_via = HVM_CALLBACK_VECTOR(HYPERVISOR_CALLBACK_VECTOR);
+		rc = xen_set_callback_via(callback_via);
+		if (rc) {
+			pr_err("Request for Xen HVM callback vector failed\n");
+			xen_have_vector_callback = 0;
+			return;
+		}
+		pr_info("Xen HVM callback vector for event delivery is enabled\n");
+		/* in the restore case the vector has already been allocated */
+		if (!test_bit(HYPERVISOR_CALLBACK_VECTOR, used_vectors))
+			alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR,
+					xen_hvm_callback_vector);
+	}
 }
 #else
 void xen_callback_vector(void) {}
diff -druNp --no-dereference linux-libre-4.9.27-gnu/drivers/xen/platform-pci.c linux-libre-4.9.28-gnu/drivers/xen/platform-pci.c
--- linux-libre-4.9.27-gnu/drivers/xen/platform-pci.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/drivers/xen/platform-pci.c	2017-05-14 08:00:37.000000000 -0400
@@ -42,6 +42,7 @@
 static unsigned long platform_mmio;
 static unsigned long platform_mmio_alloc;
 static unsigned long platform_mmiolen;
+static uint64_t callback_via;
 
 static unsigned long alloc_xen_mmio(unsigned long len)
 {
@@ -54,6 +55,51 @@ static unsigned long alloc_xen_mmio(unsi
 	return addr;
 }
 
+static uint64_t get_callback_via(struct pci_dev *pdev)
+{
+	u8 pin;
+	int irq;
+
+	irq = pdev->irq;
+	if (irq < 16)
+		return irq; /* ISA IRQ */
+
+	pin = pdev->pin;
+
+	/* We don't know the GSI. Specify the PCI INTx line instead. */
+	return ((uint64_t)0x01 << 56) | /* PCI INTx identifier */
+		((uint64_t)pci_domain_nr(pdev->bus) << 32) |
+		((uint64_t)pdev->bus->number << 16) |
+		((uint64_t)(pdev->devfn & 0xff) << 8) |
+		((uint64_t)(pin - 1) & 3);
+}
+
+static irqreturn_t do_hvm_evtchn_intr(int irq, void *dev_id)
+{
+	xen_hvm_evtchn_do_upcall();
+	return IRQ_HANDLED;
+}
+
+static int xen_allocate_irq(struct pci_dev *pdev)
+{
+	return request_irq(pdev->irq, do_hvm_evtchn_intr,
+			IRQF_NOBALANCING | IRQF_TRIGGER_RISING,
+			"xen-platform-pci", pdev);
+}
+
+static int platform_pci_resume(struct pci_dev *pdev)
+{
+	int err;
+	if (xen_have_vector_callback)
+		return 0;
+	err = xen_set_callback_via(callback_via);
+	if (err) {
+		dev_err(&pdev->dev, "platform_pci_resume failure!\n");
+		return err;
+	}
+	return 0;
+}
+
 static int platform_pci_probe(struct pci_dev *pdev,
 			      const struct pci_device_id *ent)
 {
@@ -92,6 +138,21 @@ static int platform_pci_probe(struct pci
 	platform_mmio = mmio_addr;
 	platform_mmiolen = mmio_len;
 
+	if (!xen_have_vector_callback) {
+		ret = xen_allocate_irq(pdev);
+		if (ret) {
+			dev_warn(&pdev->dev, "request_irq failed err=%d\n", ret);
+			goto out;
+		}
+		callback_via = get_callback_via(pdev);
+		ret = xen_set_callback_via(callback_via);
+		if (ret) {
+			dev_warn(&pdev->dev, "Unable to set the evtchn callback "
+					 "err=%d\n", ret);
+			goto out;
+		}
+	}
+
 	max_nr_gframes = gnttab_max_grant_frames();
 	grant_frames = alloc_xen_mmio(PAGE_SIZE * max_nr_gframes);
 	ret = gnttab_setup_auto_xlat_frames(grant_frames);
@@ -123,6 +184,9 @@ static struct pci_driver platform_driver
 	.name =           DRV_NAME,
 	.probe =          platform_pci_probe,
 	.id_table =       platform_pci_tbl,
+#ifdef CONFIG_PM
+	.resume_early =   platform_pci_resume,
+#endif
 };
 
 static int __init platform_pci_init(void)
diff -druNp --no-dereference linux-libre-4.9.27-gnu/fs/9p/acl.c linux-libre-4.9.28-gnu/fs/9p/acl.c
--- linux-libre-4.9.27-gnu/fs/9p/acl.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/fs/9p/acl.c	2017-05-14 08:00:37.000000000 -0400
@@ -277,6 +277,7 @@ static int v9fs_xattr_set_acl(const stru
 	case ACL_TYPE_ACCESS:
 		if (acl) {
 			struct iattr iattr;
+			struct posix_acl *old_acl = acl;
 
 			retval = posix_acl_update_mode(inode, &iattr.ia_mode, &acl);
 			if (retval)
@@ -287,6 +288,7 @@ static int v9fs_xattr_set_acl(const stru
 				 * by the mode bits. So don't
 				 * update ACL.
 				 */
+				posix_acl_release(old_acl);
 				value = NULL;
 				size = 0;
 			}
diff -druNp --no-dereference linux-libre-4.9.27-gnu/fs/block_dev.c linux-libre-4.9.28-gnu/fs/block_dev.c
--- linux-libre-4.9.27-gnu/fs/block_dev.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/fs/block_dev.c	2017-05-14 08:00:37.000000000 -0400
@@ -1165,7 +1165,6 @@ int revalidate_disk(struct gendisk *disk
 
 	if (disk->fops->revalidate_disk)
 		ret = disk->fops->revalidate_disk(disk);
-	blk_integrity_revalidate(disk);
 	bdev = bdget_disk(disk, 0);
 	if (!bdev)
 		return ret;
diff -druNp --no-dereference linux-libre-4.9.27-gnu/fs/f2fs/super.c linux-libre-4.9.28-gnu/fs/f2fs/super.c
--- linux-libre-4.9.27-gnu/fs/f2fs/super.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/fs/f2fs/super.c	2017-05-14 08:00:37.000000000 -0400
@@ -1405,6 +1405,13 @@ static int sanity_check_raw_super(struct
 		return 1;
 	}
 
+	if (le32_to_cpu(raw_super->segment_count) > F2FS_MAX_SEGMENT) {
+		f2fs_msg(sb, KERN_INFO,
+			"Invalid segment count (%u)",
+			le32_to_cpu(raw_super->segment_count));
+		return 1;
+	}
+
 	/* check CP/SIT/NAT/SSA/MAIN_AREA area boundary */
 	if (sanity_check_area_boundary(sbi, bh))
 		return 1;
diff -druNp --no-dereference linux-libre-4.9.27-gnu/include/linux/f2fs_fs.h linux-libre-4.9.28-gnu/include/linux/f2fs_fs.h
--- linux-libre-4.9.27-gnu/include/linux/f2fs_fs.h	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/include/linux/f2fs_fs.h	2017-05-14 08:00:37.000000000 -0400
@@ -286,6 +286,12 @@ struct f2fs_nat_block {
 #define SIT_ENTRY_PER_BLOCK (PAGE_SIZE / sizeof(struct f2fs_sit_entry))
 
 /*
+ * F2FS uses 4 bytes to represent block address. As a result, supported size of
+ * disk is 16 TB and it equals to 16 * 1024 * 1024 / 2 segments.
+ */
+#define F2FS_MAX_SEGMENT       ((16 * 1024 * 1024) / 2)
+
+/*
  * Note that f2fs_sit_entry->vblocks has the following bit-field information.
  * [15:10] : allocation type such as CURSEG_XXXX_TYPE
  * [9:0] : valid block count
diff -druNp --no-dereference linux-libre-4.9.27-gnu/include/linux/genhd.h linux-libre-4.9.28-gnu/include/linux/genhd.h
--- linux-libre-4.9.27-gnu/include/linux/genhd.h	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/include/linux/genhd.h	2017-05-14 08:00:37.000000000 -0400
@@ -731,11 +731,9 @@ static inline void part_nr_sects_write(s
 #if defined(CONFIG_BLK_DEV_INTEGRITY)
 extern void blk_integrity_add(struct gendisk *);
 extern void blk_integrity_del(struct gendisk *);
-extern void blk_integrity_revalidate(struct gendisk *);
 #else	/* CONFIG_BLK_DEV_INTEGRITY */
 static inline void blk_integrity_add(struct gendisk *disk) { }
 static inline void blk_integrity_del(struct gendisk *disk) { }
-static inline void blk_integrity_revalidate(struct gendisk *disk) { }
 #endif	/* CONFIG_BLK_DEV_INTEGRITY */
 
 #else /* CONFIG_BLOCK */
diff -druNp --no-dereference linux-libre-4.9.27-gnu/include/linux/usb/chipidea.h linux-libre-4.9.28-gnu/include/linux/usb/chipidea.h
--- linux-libre-4.9.27-gnu/include/linux/usb/chipidea.h	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/include/linux/usb/chipidea.h	2017-05-14 08:00:37.000000000 -0400
@@ -14,6 +14,7 @@ struct ci_hdrc;
  * struct ci_hdrc_cable - structure for external connector cable state tracking
  * @state: current state of the line
  * @changed: set to true when extcon event happen
+ * @enabled: set to true if we've enabled the vbus or id interrupt
  * @edev: device which generate events
  * @ci: driver state of the chipidea device
  * @nb: hold event notification callback
@@ -22,6 +23,7 @@ struct ci_hdrc;
 struct ci_hdrc_cable {
 	bool				state;
 	bool				changed;
+	bool				enabled;
 	struct extcon_dev		*edev;
 	struct ci_hdrc			*ci;
 	struct notifier_block		nb;
diff -druNp --no-dereference linux-libre-4.9.27-gnu/include/net/addrconf.h linux-libre-4.9.28-gnu/include/net/addrconf.h
--- linux-libre-4.9.27-gnu/include/net/addrconf.h	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/include/net/addrconf.h	2017-05-14 08:00:37.000000000 -0400
@@ -20,6 +20,8 @@
 #define ADDRCONF_TIMER_FUZZ		(HZ / 4)
 #define ADDRCONF_TIMER_FUZZ_MAX		(HZ)
 
+#define ADDRCONF_NOTIFY_PRIORITY	0
+
 #include <linux/in.h>
 #include <linux/in6.h>
 
diff -druNp --no-dereference linux-libre-4.9.27-gnu/include/net/ip6_route.h linux-libre-4.9.28-gnu/include/net/ip6_route.h
--- linux-libre-4.9.27-gnu/include/net/ip6_route.h	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/include/net/ip6_route.h	2017-05-14 08:00:37.000000000 -0400
@@ -84,6 +84,7 @@ struct dst_entry *ip6_route_lookup(struc
 struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
 			       int ifindex, struct flowi6 *fl6, int flags);
 
+void ip6_route_init_special_entries(void);
 int ip6_route_init(void);
 void ip6_route_cleanup(void);
 
diff -druNp --no-dereference linux-libre-4.9.27-gnu/include/xen/xen.h linux-libre-4.9.28-gnu/include/xen/xen.h
--- linux-libre-4.9.27-gnu/include/xen/xen.h	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/include/xen/xen.h	2017-05-14 08:00:37.000000000 -0400
@@ -38,7 +38,8 @@ extern enum xen_domain_type xen_domain_t
  */
 #include <xen/features.h>
 #define xen_pvh_domain() (xen_pv_domain() && \
-			  xen_feature(XENFEAT_auto_translated_physmap))
+			  xen_feature(XENFEAT_auto_translated_physmap) && \
+			  xen_have_vector_callback)
 #else
 #define xen_pvh_domain()	(0)
 #endif
diff -druNp --no-dereference linux-libre-4.9.27-gnu/kernel/bpf/verifier.c linux-libre-4.9.28-gnu/kernel/bpf/verifier.c
--- linux-libre-4.9.27-gnu/kernel/bpf/verifier.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/kernel/bpf/verifier.c	2017-05-14 08:00:37.000000000 -0400
@@ -279,7 +279,8 @@ static const char *const bpf_jmp_string[
 	[BPF_EXIT >> 4] = "exit",
 };
 
-static void print_bpf_insn(struct bpf_insn *insn)
+static void print_bpf_insn(const struct bpf_verifier_env *env,
+			   const struct bpf_insn *insn)
 {
 	u8 class = BPF_CLASS(insn->code);
 
@@ -343,9 +344,19 @@ static void print_bpf_insn(struct bpf_in
 				insn->code,
 				bpf_ldst_string[BPF_SIZE(insn->code) >> 3],
 				insn->src_reg, insn->imm);
-		} else if (BPF_MODE(insn->code) == BPF_IMM) {
-			verbose("(%02x) r%d = 0x%x\n",
-				insn->code, insn->dst_reg, insn->imm);
+		} else if (BPF_MODE(insn->code) == BPF_IMM &&
+			   BPF_SIZE(insn->code) == BPF_DW) {
+			/* At this point, we already made sure that the second
+			 * part of the ldimm64 insn is accessible.
+			 */
+			u64 imm = ((u64)(insn + 1)->imm << 32) | (u32)insn->imm;
+			bool map_ptr = insn->src_reg == BPF_PSEUDO_MAP_FD;
+
+			if (map_ptr && !env->allow_ptr_leaks)
+				imm = 0;
+
+			verbose("(%02x) r%d = 0x%llx\n", insn->code,
+				insn->dst_reg, (unsigned long long)imm);
 		} else {
 			verbose("BUG_ld_%02x\n", insn->code);
 			return;
@@ -1749,6 +1760,17 @@ static int check_alu_op(struct bpf_verif
 			return 0;
 		} else if (opcode == BPF_ADD &&
 			   BPF_CLASS(insn->code) == BPF_ALU64 &&
+			   dst_reg->type == PTR_TO_STACK &&
+			   ((BPF_SRC(insn->code) == BPF_X &&
+			     regs[insn->src_reg].type == CONST_IMM) ||
+			    BPF_SRC(insn->code) == BPF_K)) {
+			if (BPF_SRC(insn->code) == BPF_X)
+				dst_reg->imm += regs[insn->src_reg].imm;
+			else
+				dst_reg->imm += insn->imm;
+			return 0;
+		} else if (opcode == BPF_ADD &&
+			   BPF_CLASS(insn->code) == BPF_ALU64 &&
 			   (dst_reg->type == PTR_TO_PACKET ||
 			    (BPF_SRC(insn->code) == BPF_X &&
 			     regs[insn->src_reg].type == PTR_TO_PACKET))) {
@@ -2663,7 +2685,7 @@ static int do_check(struct bpf_verifier_
 
 		if (log_level) {
 			verbose("%d: ", insn_idx);
-			print_bpf_insn(insn);
+			print_bpf_insn(env, insn);
 		}
 
 		err = ext_analyzer_insn_hook(env, insn_idx, prev_insn_idx);
diff -druNp --no-dereference linux-libre-4.9.27-gnu/lib/test_bpf.c linux-libre-4.9.28-gnu/lib/test_bpf.c
--- linux-libre-4.9.27-gnu/lib/test_bpf.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/lib/test_bpf.c	2017-05-14 08:00:37.000000000 -0400
@@ -4656,6 +4656,51 @@ static struct bpf_test tests[] = {
 		{ },
 		{ { 0, 1 } },
 	},
+	{
+		/* Mainly testing JIT + imm64 here. */
+		"JMP_JGE_X: ldimm64 test 1",
+		.u.insns_int = {
+			BPF_ALU32_IMM(BPF_MOV, R0, 0),
+			BPF_LD_IMM64(R1, 3),
+			BPF_LD_IMM64(R2, 2),
+			BPF_JMP_REG(BPF_JGE, R1, R2, 2),
+			BPF_LD_IMM64(R0, 0xffffffffffffffffUL),
+			BPF_LD_IMM64(R0, 0xeeeeeeeeeeeeeeeeUL),
+			BPF_EXIT_INSN(),
+		},
+		INTERNAL,
+		{ },
+		{ { 0, 0xeeeeeeeeU } },
+	},
+	{
+		"JMP_JGE_X: ldimm64 test 2",
+		.u.insns_int = {
+			BPF_ALU32_IMM(BPF_MOV, R0, 0),
+			BPF_LD_IMM64(R1, 3),
+			BPF_LD_IMM64(R2, 2),
+			BPF_JMP_REG(BPF_JGE, R1, R2, 0),
+			BPF_LD_IMM64(R0, 0xffffffffffffffffUL),
+			BPF_EXIT_INSN(),
+		},
+		INTERNAL,
+		{ },
+		{ { 0, 0xffffffffU } },
+	},
+	{
+		"JMP_JGE_X: ldimm64 test 3",
+		.u.insns_int = {
+			BPF_ALU32_IMM(BPF_MOV, R0, 1),
+			BPF_LD_IMM64(R1, 3),
+			BPF_LD_IMM64(R2, 2),
+			BPF_JMP_REG(BPF_JGE, R1, R2, 4),
+			BPF_LD_IMM64(R0, 0xffffffffffffffffUL),
+			BPF_LD_IMM64(R0, 0xeeeeeeeeeeeeeeeeUL),
+			BPF_EXIT_INSN(),
+		},
+		INTERNAL,
+		{ },
+		{ { 0, 1 } },
+	},
 	/* BPF_JMP | BPF_JNE | BPF_X */
 	{
 		"JMP_JNE_X: if (3 != 2) return 1",
diff -druNp --no-dereference linux-libre-4.9.27-gnu/Makefile linux-libre-4.9.28-gnu/Makefile
--- linux-libre-4.9.27-gnu/Makefile	2017-05-08 03:47:27.000000000 -0400
+++ linux-libre-4.9.28-gnu/Makefile	2017-05-14 16:19:54.000000000 -0400
@@ -1,6 +1,6 @@
 VERSION = 4
 PATCHLEVEL = 9
-SUBLEVEL = 27
+SUBLEVEL = 28
 EXTRAVERSION = -gnu
 NAME = Roaring Lionus
 
diff -druNp --no-dereference linux-libre-4.9.27-gnu/net/core/rtnetlink.c linux-libre-4.9.28-gnu/net/core/rtnetlink.c
--- linux-libre-4.9.27-gnu/net/core/rtnetlink.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/net/core/rtnetlink.c	2017-05-14 08:00:37.000000000 -0400
@@ -1059,7 +1059,7 @@ static int rtnl_phys_port_name_fill(stru
 		return err;
 	}
 
-	if (nla_put(skb, IFLA_PHYS_PORT_NAME, strlen(name), name))
+	if (nla_put_string(skb, IFLA_PHYS_PORT_NAME, name))
 		return -EMSGSIZE;
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.9.27-gnu/net/ipv4/raw.c linux-libre-4.9.28-gnu/net/ipv4/raw.c
--- linux-libre-4.9.27-gnu/net/ipv4/raw.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/net/ipv4/raw.c	2017-05-14 08:00:37.000000000 -0400
@@ -356,6 +356,9 @@ static int raw_send_hdrinc(struct sock *
 			       rt->dst.dev->mtu);
 		return -EMSGSIZE;
 	}
+	if (length < sizeof(struct iphdr))
+		return -EINVAL;
+
 	if (flags&MSG_PROBE)
 		goto out;
 
diff -druNp --no-dereference linux-libre-4.9.27-gnu/net/ipv4/tcp_lp.c linux-libre-4.9.28-gnu/net/ipv4/tcp_lp.c
--- linux-libre-4.9.27-gnu/net/ipv4/tcp_lp.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/net/ipv4/tcp_lp.c	2017-05-14 08:00:37.000000000 -0400
@@ -264,13 +264,15 @@ static void tcp_lp_pkts_acked(struct soc
 {
 	struct tcp_sock *tp = tcp_sk(sk);
 	struct lp *lp = inet_csk_ca(sk);
+	u32 delta;
 
 	if (sample->rtt_us > 0)
 		tcp_lp_rtt_sample(sk, sample->rtt_us);
 
 	/* calc inference */
-	if (tcp_time_stamp > tp->rx_opt.rcv_tsecr)
-		lp->inference = 3 * (tcp_time_stamp - tp->rx_opt.rcv_tsecr);
+	delta = tcp_time_stamp - tp->rx_opt.rcv_tsecr;
+	if ((s32)delta > 0)
+		lp->inference = 3 * delta;
 
 	/* test if within inference */
 	if (lp->last_drop && (tcp_time_stamp - lp->last_drop < lp->inference))
diff -druNp --no-dereference linux-libre-4.9.27-gnu/net/ipv4/tcp_minisocks.c linux-libre-4.9.28-gnu/net/ipv4/tcp_minisocks.c
--- linux-libre-4.9.27-gnu/net/ipv4/tcp_minisocks.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/net/ipv4/tcp_minisocks.c	2017-05-14 08:00:37.000000000 -0400
@@ -543,6 +543,7 @@ struct sock *tcp_create_openreq_child(co
 			newicsk->icsk_ack.last_seg_size = skb->len - newtp->tcp_header_len;
 		newtp->rx_opt.mss_clamp = req->mss;
 		tcp_ecn_openreq_child(newtp, req);
+		newtp->fastopen_req = NULL;
 		newtp->fastopen_rsk = NULL;
 		newtp->syn_data_acked = 0;
 		newtp->rack.mstamp.v64 = 0;
diff -druNp --no-dereference linux-libre-4.9.27-gnu/net/ipv4/tcp_output.c linux-libre-4.9.28-gnu/net/ipv4/tcp_output.c
--- linux-libre-4.9.27-gnu/net/ipv4/tcp_output.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/net/ipv4/tcp_output.c	2017-05-14 08:00:37.000000000 -0400
@@ -1246,7 +1246,7 @@ int tcp_fragment(struct sock *sk, struct
  * eventually). The difference is that pulled data not copied, but
  * immediately discarded.
  */
-static void __pskb_trim_head(struct sk_buff *skb, int len)
+static int __pskb_trim_head(struct sk_buff *skb, int len)
 {
 	struct skb_shared_info *shinfo;
 	int i, k, eat;
@@ -1256,7 +1256,7 @@ static void __pskb_trim_head(struct sk_b
 		__skb_pull(skb, eat);
 		len -= eat;
 		if (!len)
-			return;
+			return 0;
 	}
 	eat = len;
 	k = 0;
@@ -1282,23 +1282,28 @@ static void __pskb_trim_head(struct sk_b
 	skb_reset_tail_pointer(skb);
 	skb->data_len -= len;
 	skb->len = skb->data_len;
+	return len;
 }
 
 /* Remove acked data from a packet in the transmit queue. */
 int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len)
 {
+	u32 delta_truesize;
+
 	if (skb_unclone(skb, GFP_ATOMIC))
 		return -ENOMEM;
 
-	__pskb_trim_head(skb, len);
+	delta_truesize = __pskb_trim_head(skb, len);
 
 	TCP_SKB_CB(skb)->seq += len;
 	skb->ip_summed = CHECKSUM_PARTIAL;
 
-	skb->truesize	     -= len;
-	sk->sk_wmem_queued   -= len;
-	sk_mem_uncharge(sk, len);
-	sock_set_flag(sk, SOCK_QUEUE_SHRUNK);
+	if (delta_truesize) {
+		skb->truesize	   -= delta_truesize;
+		sk->sk_wmem_queued -= delta_truesize;
+		sk_mem_uncharge(sk, delta_truesize);
+		sock_set_flag(sk, SOCK_QUEUE_SHRUNK);
+	}
 
 	/* Any change of skb->len requires recalculation of tso factor. */
 	if (tcp_skb_pcount(skb) > 1)
diff -druNp --no-dereference linux-libre-4.9.27-gnu/net/ipv6/addrconf.c linux-libre-4.9.28-gnu/net/ipv6/addrconf.c
--- linux-libre-4.9.27-gnu/net/ipv6/addrconf.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/net/ipv6/addrconf.c	2017-05-14 08:00:37.000000000 -0400
@@ -3278,7 +3278,8 @@ static int fixup_permanent_addr(struct i
 				      idev->dev, 0, 0);
 	}
 
-	addrconf_dad_start(ifp);
+	if (ifp->state == INET6_IFADDR_STATE_PREDAD)
+		addrconf_dad_start(ifp);
 
 	return 0;
 }
@@ -3491,6 +3492,7 @@ static int addrconf_notify(struct notifi
  */
 static struct notifier_block ipv6_dev_notf = {
 	.notifier_call = addrconf_notify,
+	.priority = ADDRCONF_NOTIFY_PRIORITY,
 };
 
 static void addrconf_type_change(struct net_device *dev, unsigned long event)
@@ -3627,7 +3629,7 @@ restart:
 		if (keep) {
 			/* set state to skip the notifier below */
 			state = INET6_IFADDR_STATE_DEAD;
-			ifa->state = 0;
+			ifa->state = INET6_IFADDR_STATE_PREDAD;
 			if (!(ifa->flags & IFA_F_NODAD))
 				ifa->flags |= IFA_F_TENTATIVE;
 
@@ -6263,6 +6265,8 @@ int __init addrconf_init(void)
 		goto errlo;
 	}
 
+	ip6_route_init_special_entries();
+
 	for (i = 0; i < IN6_ADDR_HSIZE; i++)
 		INIT_HLIST_HEAD(&inet6_addr_lst[i]);
 
diff -druNp --no-dereference linux-libre-4.9.27-gnu/net/ipv6/raw.c linux-libre-4.9.28-gnu/net/ipv6/raw.c
--- linux-libre-4.9.27-gnu/net/ipv6/raw.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/net/ipv6/raw.c	2017-05-14 08:00:37.000000000 -0400
@@ -630,6 +630,8 @@ static int rawv6_send_hdrinc(struct sock
 		ipv6_local_error(sk, EMSGSIZE, fl6, rt->dst.dev->mtu);
 		return -EMSGSIZE;
 	}
+	if (length < sizeof(struct ipv6hdr))
+		return -EINVAL;
 	if (flags&MSG_PROBE)
 		goto out;
 
diff -druNp --no-dereference linux-libre-4.9.27-gnu/net/ipv6/route.c linux-libre-4.9.28-gnu/net/ipv6/route.c
--- linux-libre-4.9.27-gnu/net/ipv6/route.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/net/ipv6/route.c	2017-05-14 08:00:37.000000000 -0400
@@ -3480,7 +3480,10 @@ static int ip6_route_dev_notify(struct n
 	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 	struct net *net = dev_net(dev);
 
-	if (event == NETDEV_REGISTER && (dev->flags & IFF_LOOPBACK)) {
+	if (!(dev->flags & IFF_LOOPBACK))
+		return NOTIFY_OK;
+
+	if (event == NETDEV_REGISTER) {
 		net->ipv6.ip6_null_entry->dst.dev = dev;
 		net->ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(dev);
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
@@ -3489,6 +3492,12 @@ static int ip6_route_dev_notify(struct n
 		net->ipv6.ip6_blk_hole_entry->dst.dev = dev;
 		net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev);
 #endif
+	 } else if (event == NETDEV_UNREGISTER) {
+		in6_dev_put(net->ipv6.ip6_null_entry->rt6i_idev);
+#ifdef CONFIG_IPV6_MULTIPLE_TABLES
+		in6_dev_put(net->ipv6.ip6_prohibit_entry->rt6i_idev);
+		in6_dev_put(net->ipv6.ip6_blk_hole_entry->rt6i_idev);
+#endif
 	}
 
 	return NOTIFY_OK;
@@ -3795,9 +3804,24 @@ static struct pernet_operations ip6_rout
 
 static struct notifier_block ip6_route_dev_notifier = {
 	.notifier_call = ip6_route_dev_notify,
-	.priority = 0,
+	.priority = ADDRCONF_NOTIFY_PRIORITY - 10,
 };
 
+void __init ip6_route_init_special_entries(void)
+{
+	/* Registering of the loopback is done before this portion of code,
+	 * the loopback reference in rt6_info will not be taken, do it
+	 * manually for init_net */
+	init_net.ipv6.ip6_null_entry->dst.dev = init_net.loopback_dev;
+	init_net.ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
+  #ifdef CONFIG_IPV6_MULTIPLE_TABLES
+	init_net.ipv6.ip6_prohibit_entry->dst.dev = init_net.loopback_dev;
+	init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
+	init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev;
+	init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
+  #endif
+}
+
 int __init ip6_route_init(void)
 {
 	int ret;
@@ -3824,17 +3848,6 @@ int __init ip6_route_init(void)
 
 	ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops_template.kmem_cachep;
 
-	/* Registering of the loopback is done before this portion of code,
-	 * the loopback reference in rt6_info will not be taken, do it
-	 * manually for init_net */
-	init_net.ipv6.ip6_null_entry->dst.dev = init_net.loopback_dev;
-	init_net.ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
-  #ifdef CONFIG_IPV6_MULTIPLE_TABLES
-	init_net.ipv6.ip6_prohibit_entry->dst.dev = init_net.loopback_dev;
-	init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
-	init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev;
-	init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
-  #endif
 	ret = fib6_init();
 	if (ret)
 		goto out_register_subsys;
diff -druNp --no-dereference linux-libre-4.9.27-gnu/samples/bpf/test_verifier.c linux-libre-4.9.28-gnu/samples/bpf/test_verifier.c
--- linux-libre-4.9.27-gnu/samples/bpf/test_verifier.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/samples/bpf/test_verifier.c	2017-05-14 08:00:37.000000000 -0400
@@ -1218,16 +1218,22 @@ static struct bpf_test tests[] = {
 		.result = ACCEPT,
 	},
 	{
-		"unpriv: obfuscate stack pointer",
+		"stack pointer arithmetic",
 		.insns = {
-			BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
-			BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
-			BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+			BPF_MOV64_IMM(BPF_REG_1, 4),
+			BPF_JMP_IMM(BPF_JA, 0, 0, 0),
+			BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
+			BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -10),
+			BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -10),
+			BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
+			BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_1),
+			BPF_ST_MEM(0, BPF_REG_2, 4, 0),
+			BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
+			BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 8),
+			BPF_ST_MEM(0, BPF_REG_2, 4, 0),
 			BPF_MOV64_IMM(BPF_REG_0, 0),
 			BPF_EXIT_INSN(),
 		},
-		.errstr_unpriv = "R2 pointer arithmetic",
-		.result_unpriv = REJECT,
 		.result = ACCEPT,
 	},
 	{
diff -druNp --no-dereference linux-libre-4.9.27-gnu/sound/pci/hda/hda_intel.c linux-libre-4.9.28-gnu/sound/pci/hda/hda_intel.c
--- linux-libre-4.9.27-gnu/sound/pci/hda/hda_intel.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/sound/pci/hda/hda_intel.c	2017-05-14 08:00:37.000000000 -0400
@@ -2155,7 +2155,20 @@ static void azx_remove(struct pci_dev *p
 		/* cancel the pending probing work */
 		chip = card->private_data;
 		hda = container_of(chip, struct hda_intel, chip);
+		/* FIXME: below is an ugly workaround.
+		 * Both device_release_driver() and driver_probe_device()
+		 * take *both* the device's and its parent's lock before
+		 * calling the remove() and probe() callbacks.  The codec
+		 * probe takes the locks of both the codec itself and its
+		 * parent, i.e. the PCI controller dev.  Meanwhile, when
+		 * the PCI controller is unbound, it takes its lock, too
+		 * ==> ouch, a deadlock!
+		 * As a workaround, we unlock temporarily here the controller
+		 * device during cancel_work_sync() call.
+		 */
+		device_unlock(&pci->dev);
 		cancel_work_sync(&hda->probe_work);
+		device_lock(&pci->dev);
 
 		snd_card_free(card);
 	}
diff -druNp --no-dereference linux-libre-4.9.27-gnu/tools/power/cpupower/utils/helpers/cpuid.c linux-libre-4.9.28-gnu/tools/power/cpupower/utils/helpers/cpuid.c
--- linux-libre-4.9.27-gnu/tools/power/cpupower/utils/helpers/cpuid.c	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/tools/power/cpupower/utils/helpers/cpuid.c	2017-05-14 08:00:37.000000000 -0400
@@ -156,6 +156,7 @@ out:
 					 */
 			case 0x2C:	/* Westmere EP - Gulftown */
 				cpu_info->caps |= CPUPOWER_CAP_HAS_TURBO_RATIO;
+				break;
 			case 0x2A:	/* SNB */
 			case 0x2D:	/* SNB Xeon */
 			case 0x3A:	/* IVB */
diff -druNp --no-dereference linux-libre-4.9.27-gnu/tools/testing/selftests/x86/Makefile linux-libre-4.9.28-gnu/tools/testing/selftests/x86/Makefile
--- linux-libre-4.9.27-gnu/tools/testing/selftests/x86/Makefile	2017-05-08 01:48:32.000000000 -0400
+++ linux-libre-4.9.28-gnu/tools/testing/selftests/x86/Makefile	2017-05-14 08:00:37.000000000 -0400
@@ -5,7 +5,7 @@ include ../lib.mk
 .PHONY: all all_32 all_64 warn_32bit_failure clean
 
 TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt ptrace_syscall test_mremap_vdso \
-			check_initial_reg_state sigreturn ldt_gdt iopl \
+			check_initial_reg_state sigreturn ldt_gdt iopl mpx-mini-test \
 			protection_keys
 TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault test_syscall_vdso unwind_vdso \
 			test_FCMOV test_FCOMI test_FISTTP \
