diff -druNp --no-dereference linux-libre-4.9.3-gnu/arch/arm/configs/qcom_defconfig linux-libre-4.9.4-gnu/arch/arm/configs/qcom_defconfig
--- linux-libre-4.9.3-gnu/arch/arm/configs/qcom_defconfig	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/arch/arm/configs/qcom_defconfig	2017-01-15 07:43:07.000000000 -0500
@@ -162,8 +162,8 @@ CONFIG_APQ_MMCC_8084=y
 CONFIG_IPQ_LCC_806X=y
 CONFIG_MSM_GCC_8660=y
 CONFIG_MSM_LCC_8960=y
-CONFIG_MSM_GCC_9615=y
-CONFIG_MSM_LCC_9615=y
+CONFIG_MDM_GCC_9615=y
+CONFIG_MDM_LCC_9615=y
 CONFIG_MSM_MMCC_8960=y
 CONFIG_MSM_MMCC_8974=y
 CONFIG_HWSPINLOCK_QCOM=y
diff -druNp --no-dereference linux-libre-4.9.3-gnu/arch/arm/mach-omap2/board-generic.c linux-libre-4.9.4-gnu/arch/arm/mach-omap2/board-generic.c
--- linux-libre-4.9.3-gnu/arch/arm/mach-omap2/board-generic.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/arch/arm/mach-omap2/board-generic.c	2017-01-15 07:43:07.000000000 -0500
@@ -306,7 +306,7 @@ DT_MACHINE_START(AM43_DT, "Generic AM43
 	.init_late	= am43xx_init_late,
 	.init_irq	= omap_gic_of_init,
 	.init_machine	= omap_generic_init,
-	.init_time	= omap4_local_timer_init,
+	.init_time	= omap3_gptimer_timer_init,
 	.dt_compat	= am43_boards_compat,
 	.restart	= omap44xx_restart,
 MACHINE_END
diff -druNp --no-dereference linux-libre-4.9.3-gnu/arch/arm/mach-omap2/common.h linux-libre-4.9.4-gnu/arch/arm/mach-omap2/common.h
--- linux-libre-4.9.3-gnu/arch/arm/mach-omap2/common.h	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/arch/arm/mach-omap2/common.h	2017-01-15 07:43:07.000000000 -0500
@@ -262,8 +262,6 @@ extern void __iomem *omap4_get_sar_ram_b
 extern void omap4_mpuss_early_init(void);
 extern void omap_do_wfi(void);
 
-extern void omap4_secondary_startup(void);
-extern void omap4460_secondary_startup(void);
 
 #ifdef CONFIG_SMP
 /* Needed for secondary core boot */
@@ -275,16 +273,11 @@ extern void omap4_cpu_die(unsigned int c
 extern int omap4_cpu_kill(unsigned int cpu);
 
 extern const struct smp_operations omap4_smp_ops;
-
-extern void omap5_secondary_startup(void);
-extern void omap5_secondary_hyp_startup(void);
 #endif
 
 #if defined(CONFIG_SMP) && defined(CONFIG_PM)
 extern int omap4_mpuss_init(void);
 extern int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state);
-extern int omap4_finish_suspend(unsigned long cpu_state);
-extern void omap4_cpu_resume(void);
 extern int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state);
 #else
 static inline int omap4_enter_lowpower(unsigned int cpu,
@@ -305,14 +298,41 @@ static inline int omap4_mpuss_init(void)
 	return 0;
 }
 
+#endif
+
+#ifdef CONFIG_ARCH_OMAP4
+void omap4_secondary_startup(void);
+void omap4460_secondary_startup(void);
+int omap4_finish_suspend(unsigned long cpu_state);
+void omap4_cpu_resume(void);
+#else
+static inline void omap4_secondary_startup(void)
+{
+}
+
+static inline void omap4460_secondary_startup(void)
+{
+}
 static inline int omap4_finish_suspend(unsigned long cpu_state)
 {
 	return 0;
 }
-
 static inline void omap4_cpu_resume(void)
-{}
+{
+}
+#endif
 
+#if defined(CONFIG_SOC_OMAP5) || defined(CONFIG_SOC_DRA7XX)
+void omap5_secondary_startup(void);
+void omap5_secondary_hyp_startup(void);
+#else
+static inline void omap5_secondary_startup(void)
+{
+}
+
+static inline void omap5_secondary_hyp_startup(void)
+{
+}
 #endif
 
 void pdata_quirks_init(const struct of_device_id *);
diff -druNp --no-dereference linux-libre-4.9.3-gnu/arch/arm/mach-omap2/io.c linux-libre-4.9.4-gnu/arch/arm/mach-omap2/io.c
--- linux-libre-4.9.3-gnu/arch/arm/mach-omap2/io.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/arch/arm/mach-omap2/io.c	2017-01-15 07:43:07.000000000 -0500
@@ -717,10 +717,11 @@ void __init omap5_init_early(void)
 			      OMAP2_L4_IO_ADDRESS(OMAP54XX_SCM_BASE));
 	omap2_set_globals_prcm_mpu(OMAP2_L4_IO_ADDRESS(OMAP54XX_PRCM_MPU_BASE));
 	omap2_control_base_init();
-	omap4_pm_init_early();
 	omap2_prcm_base_init();
 	omap5xxx_check_revision();
 	omap4_sar_ram_init();
+	omap4_mpuss_early_init();
+	omap4_pm_init_early();
 	omap54xx_voltagedomains_init();
 	omap54xx_powerdomains_init();
 	omap54xx_clockdomains_init();
diff -druNp --no-dereference linux-libre-4.9.3-gnu/arch/arm/mach-omap2/Makefile linux-libre-4.9.4-gnu/arch/arm/mach-omap2/Makefile
--- linux-libre-4.9.3-gnu/arch/arm/mach-omap2/Makefile	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/arch/arm/mach-omap2/Makefile	2017-01-15 07:43:07.000000000 -0500
@@ -80,7 +80,7 @@ endif
 # Power Management
 omap-4-5-pm-common			= omap-mpuss-lowpower.o
 obj-$(CONFIG_ARCH_OMAP4)		+= $(omap-4-5-pm-common)
-obj-$(CONFIG_ARCH_OMAP5)		+= $(omap-4-5-pm-common)
+obj-$(CONFIG_SOC_OMAP5)			+= $(omap-4-5-pm-common)
 obj-$(CONFIG_OMAP_PM_NOOP)		+= omap-pm-noop.o
 
 ifeq ($(CONFIG_PM),y)
diff -druNp --no-dereference linux-libre-4.9.3-gnu/arch/arm/mach-omap2/omap4-sar-layout.h linux-libre-4.9.4-gnu/arch/arm/mach-omap2/omap4-sar-layout.h
--- linux-libre-4.9.3-gnu/arch/arm/mach-omap2/omap4-sar-layout.h	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/arch/arm/mach-omap2/omap4-sar-layout.h	2017-01-15 07:43:07.000000000 -0500
@@ -31,6 +31,8 @@
 /* CPUx Wakeup Non-Secure Physical Address offsets in SAR_BANK3 */
 #define CPU0_WAKEUP_NS_PA_ADDR_OFFSET		0xa04
 #define CPU1_WAKEUP_NS_PA_ADDR_OFFSET		0xa08
+#define OMAP5_CPU0_WAKEUP_NS_PA_ADDR_OFFSET	0xe00
+#define OMAP5_CPU1_WAKEUP_NS_PA_ADDR_OFFSET	0xe04
 
 #define SAR_BACKUP_STATUS_OFFSET		(SAR_BANK3_OFFSET + 0x500)
 #define SAR_SECURE_RAM_SIZE_OFFSET		(SAR_BANK3_OFFSET + 0x504)
diff -druNp --no-dereference linux-libre-4.9.3-gnu/arch/arm/mach-omap2/omap-mpuss-lowpower.c linux-libre-4.9.4-gnu/arch/arm/mach-omap2/omap-mpuss-lowpower.c
--- linux-libre-4.9.3-gnu/arch/arm/mach-omap2/omap-mpuss-lowpower.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/arch/arm/mach-omap2/omap-mpuss-lowpower.c	2017-01-15 07:43:07.000000000 -0500
@@ -48,6 +48,7 @@
 #include <asm/smp_scu.h>
 #include <asm/pgalloc.h>
 #include <asm/suspend.h>
+#include <asm/virt.h>
 #include <asm/hardware/cache-l2x0.h>
 
 #include "soc.h"
@@ -244,10 +245,9 @@ int omap4_enter_lowpower(unsigned int cp
 		save_state = 1;
 		break;
 	case PWRDM_POWER_RET:
-		if (IS_PM44XX_ERRATUM(PM_OMAP4_CPU_OSWR_DISABLE)) {
+		if (IS_PM44XX_ERRATUM(PM_OMAP4_CPU_OSWR_DISABLE))
 			save_state = 0;
-			break;
-		}
+		break;
 	default:
 		/*
 		 * CPUx CSWR is invalid hardware state. Also CPUx OSWR
@@ -371,8 +371,12 @@ int __init omap4_mpuss_init(void)
 	pm_info = &per_cpu(omap4_pm_info, 0x0);
 	if (sar_base) {
 		pm_info->scu_sar_addr = sar_base + SCU_OFFSET0;
-		pm_info->wkup_sar_addr = sar_base +
-					CPU0_WAKEUP_NS_PA_ADDR_OFFSET;
+		if (cpu_is_omap44xx())
+			pm_info->wkup_sar_addr = sar_base +
+				CPU0_WAKEUP_NS_PA_ADDR_OFFSET;
+		else
+			pm_info->wkup_sar_addr = sar_base +
+				OMAP5_CPU0_WAKEUP_NS_PA_ADDR_OFFSET;
 		pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET0;
 	}
 	pm_info->pwrdm = pwrdm_lookup("cpu0_pwrdm");
@@ -391,8 +395,12 @@ int __init omap4_mpuss_init(void)
 	pm_info = &per_cpu(omap4_pm_info, 0x1);
 	if (sar_base) {
 		pm_info->scu_sar_addr = sar_base + SCU_OFFSET1;
-		pm_info->wkup_sar_addr = sar_base +
-					CPU1_WAKEUP_NS_PA_ADDR_OFFSET;
+		if (cpu_is_omap44xx())
+			pm_info->wkup_sar_addr = sar_base +
+				CPU1_WAKEUP_NS_PA_ADDR_OFFSET;
+		else
+			pm_info->wkup_sar_addr = sar_base +
+				OMAP5_CPU1_WAKEUP_NS_PA_ADDR_OFFSET;
 		pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET1;
 	}
 
@@ -453,15 +461,24 @@ void __init omap4_mpuss_early_init(void)
 {
 	unsigned long startup_pa;
 
-	if (!cpu_is_omap44xx())
+	if (!(cpu_is_omap44xx() || soc_is_omap54xx()))
 		return;
 
 	sar_base = omap4_get_sar_ram_base();
 
 	if (cpu_is_omap443x())
 		startup_pa = virt_to_phys(omap4_secondary_startup);
-	else
+	else if (cpu_is_omap446x())
 		startup_pa = virt_to_phys(omap4460_secondary_startup);
+	else if ((__boot_cpu_mode & MODE_MASK) == HYP_MODE)
+		startup_pa = virt_to_phys(omap5_secondary_hyp_startup);
+	else
+		startup_pa = virt_to_phys(omap5_secondary_startup);
 
-	writel_relaxed(startup_pa, sar_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET);
+	if (cpu_is_omap44xx())
+		writel_relaxed(startup_pa, sar_base +
+			       CPU1_WAKEUP_NS_PA_ADDR_OFFSET);
+	else
+		writel_relaxed(startup_pa, sar_base +
+			       OMAP5_CPU1_WAKEUP_NS_PA_ADDR_OFFSET);
 }
diff -druNp --no-dereference linux-libre-4.9.3-gnu/arch/arm/mach-omap2/timer.c linux-libre-4.9.4-gnu/arch/arm/mach-omap2/timer.c
--- linux-libre-4.9.3-gnu/arch/arm/mach-omap2/timer.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/arch/arm/mach-omap2/timer.c	2017-01-15 07:43:07.000000000 -0500
@@ -510,18 +510,19 @@ void __init omap3_secure_sync32k_timer_i
 }
 #endif /* CONFIG_ARCH_OMAP3 */
 
-#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_AM33XX)
+#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_AM33XX) || \
+	defined(CONFIG_SOC_AM43XX)
 void __init omap3_gptimer_timer_init(void)
 {
 	__omap_sync32k_timer_init(2, "timer_sys_ck", NULL,
 			1, "timer_sys_ck", "ti,timer-alwon", true);
-
-	clocksource_probe();
+	if (of_have_populated_dt())
+		clocksource_probe();
 }
 #endif
 
 #if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) ||		\
-	defined(CONFIG_SOC_DRA7XX) || defined(CONFIG_SOC_AM43XX)
+	defined(CONFIG_SOC_DRA7XX)
 static void __init omap4_sync32k_timer_init(void)
 {
 	__omap_sync32k_timer_init(1, "timer_32k_ck", "ti,timer-alwon",
diff -druNp --no-dereference linux-libre-4.9.3-gnu/arch/arm/mach-pxa/pxa25x.c linux-libre-4.9.4-gnu/arch/arm/mach-pxa/pxa25x.c
--- linux-libre-4.9.3-gnu/arch/arm/mach-pxa/pxa25x.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/arch/arm/mach-pxa/pxa25x.c	2017-01-15 07:43:07.000000000 -0500
@@ -156,7 +156,7 @@ static int __init __init
 pxa25x_dt_init_irq(struct device_node *node, struct device_node *parent)
 {
 	pxa_dt_irq_init(pxa25x_set_wake);
-	set_handle_irq(ichp_handle_irq);
+	set_handle_irq(icip_handle_irq);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9.3-gnu/arch/arm/mach-zynq/common.c linux-libre-4.9.4-gnu/arch/arm/mach-zynq/common.c
--- linux-libre-4.9.3-gnu/arch/arm/mach-zynq/common.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/arch/arm/mach-zynq/common.c	2017-01-15 07:43:07.000000000 -0500
@@ -59,7 +59,7 @@ void __iomem *zynq_scu_base;
 static void __init zynq_memory_init(void)
 {
 	if (!__pa(PAGE_OFFSET))
-		memblock_reserve(__pa(PAGE_OFFSET), __pa(swapper_pg_dir));
+		memblock_reserve(__pa(PAGE_OFFSET), 0x80000);
 }
 
 static struct platform_device zynq_cpuidle_device = {
diff -druNp --no-dereference linux-libre-4.9.3-gnu/arch/arm64/boot/dts/broadcom/bcm2837.dtsi linux-libre-4.9.4-gnu/arch/arm64/boot/dts/broadcom/bcm2837.dtsi
--- linux-libre-4.9.3-gnu/arch/arm64/boot/dts/broadcom/bcm2837.dtsi	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/arch/arm64/boot/dts/broadcom/bcm2837.dtsi	2017-01-15 07:43:07.000000000 -0500
@@ -1,7 +1,7 @@
 #include "bcm283x.dtsi"
 
 / {
-	compatible = "brcm,bcm2836";
+	compatible = "brcm,bcm2837";
 
 	soc {
 		ranges = <0x7e000000 0x3f000000 0x1000000>,
diff -druNp --no-dereference linux-libre-4.9.3-gnu/arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-b.dts linux-libre-4.9.4-gnu/arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-b.dts
--- linux-libre-4.9.3-gnu/arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-b.dts	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-b.dts	2017-01-15 07:43:07.000000000 -0500
@@ -15,13 +15,6 @@
 		act {
 			gpios = <&gpio 47 0>;
 		};
-
-		pwr {
-			label = "PWR";
-			gpios = <&gpio 35 0>;
-			default-state = "keep";
-			linux,default-trigger = "default-on";
-		};
 	};
 };
 
diff -druNp --no-dereference linux-libre-4.9.3-gnu/arch/arm64/boot/dts/mediatek/mt8173.dtsi linux-libre-4.9.4-gnu/arch/arm64/boot/dts/mediatek/mt8173.dtsi
--- linux-libre-4.9.3-gnu/arch/arm64/boot/dts/mediatek/mt8173.dtsi	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/arch/arm64/boot/dts/mediatek/mt8173.dtsi	2017-01-15 07:43:07.000000000 -0500
@@ -450,6 +450,9 @@
 		auxadc: auxadc@11001000 {
 			compatible = "mediatek,mt8173-auxadc";
 			reg = <0 0x11001000 0 0x1000>;
+			clocks = <&pericfg CLK_PERI_AUXADC>;
+			clock-names = "main";
+			#io-channel-cells = <1>;
 		};
 
 		uart0: serial@11002000 {
diff -druNp --no-dereference linux-libre-4.9.3-gnu/arch/powerpc/kernel/misc_32.S linux-libre-4.9.4-gnu/arch/powerpc/kernel/misc_32.S
--- linux-libre-4.9.3-gnu/arch/powerpc/kernel/misc_32.S	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/arch/powerpc/kernel/misc_32.S	2017-01-15 07:43:07.000000000 -0500
@@ -296,7 +296,7 @@ _GLOBAL(flush_instruction_cache)
 	lis	r3, KERNELBASE@h
 	iccci	0,r3
 #endif
-#elif CONFIG_FSL_BOOKE
+#elif defined(CONFIG_FSL_BOOKE)
 BEGIN_FTR_SECTION
 	mfspr   r3,SPRN_L1CSR0
 	ori     r3,r3,L1CSR0_CFI|L1CSR0_CLFC
diff -druNp --no-dereference linux-libre-4.9.3-gnu/arch/x86/net/bpf_jit_comp.c linux-libre-4.9.4-gnu/arch/x86/net/bpf_jit_comp.c
--- linux-libre-4.9.3-gnu/arch/x86/net/bpf_jit_comp.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/arch/x86/net/bpf_jit_comp.c	2017-01-15 07:43:07.000000000 -0500
@@ -1172,6 +1172,8 @@ struct bpf_prog *bpf_int_jit_compile(str
 		set_memory_ro((unsigned long)header, header->pages);
 		prog->bpf_func = (void *)image;
 		prog->jited = 1;
+	} else {
+		prog = orig_prog;
 	}
 
 out_addrs:
diff -druNp --no-dereference linux-libre-4.9.3-gnu/drivers/bus/arm-ccn.c linux-libre-4.9.4-gnu/drivers/bus/arm-ccn.c
--- linux-libre-4.9.3-gnu/drivers/bus/arm-ccn.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/drivers/bus/arm-ccn.c	2017-01-15 07:43:07.000000000 -0500
@@ -1570,7 +1570,10 @@ static int __init arm_ccn_init(void)
 	for (i = 0; i < ARRAY_SIZE(arm_ccn_pmu_events); i++)
 		arm_ccn_pmu_events_attrs[i] = &arm_ccn_pmu_events[i].attr.attr;
 
-	return platform_driver_register(&arm_ccn_driver);
+	ret = platform_driver_register(&arm_ccn_driver);
+	if (ret)
+		cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_CCN_ONLINE);
+	return ret;
 }
 
 static void __exit arm_ccn_exit(void)
diff -druNp --no-dereference linux-libre-4.9.3-gnu/drivers/clk/clkdev.c linux-libre-4.9.4-gnu/drivers/clk/clkdev.c
--- linux-libre-4.9.3-gnu/drivers/clk/clkdev.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/drivers/clk/clkdev.c	2017-01-15 07:43:07.000000000 -0500
@@ -448,12 +448,20 @@ EXPORT_SYMBOL(clk_register_clkdev);
  *
  * con_id or dev_id may be NULL as a wildcard, just as in the rest of
  * clkdev.
+ *
+ * To make things easier for mass registration, we detect error clk_hws
+ * from a previous clk_hw_register_*() call, and return the error code for
+ * those.  This is to permit this function to be called immediately
+ * after clk_hw_register_*().
  */
 int clk_hw_register_clkdev(struct clk_hw *hw, const char *con_id,
 	const char *dev_id)
 {
 	struct clk_lookup *cl;
 
+	if (IS_ERR(hw))
+		return PTR_ERR(hw);
+
 	/*
 	 * Since dev_id can be NULL, and NULL is handled specially, we must
 	 * pass it as either a NULL format string, or with "%s".
diff -druNp --no-dereference linux-libre-4.9.3-gnu/drivers/gpu/drm/i915/i915_drv.h linux-libre-4.9.4-gnu/drivers/gpu/drm/i915/i915_drv.h
--- linux-libre-4.9.3-gnu/drivers/gpu/drm/i915/i915_drv.h	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/drivers/gpu/drm/i915/i915_drv.h	2017-01-15 07:43:07.000000000 -0500
@@ -3684,6 +3684,8 @@ extern void intel_display_print_error_st
 
 int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u32 mbox, u32 *val);
 int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u32 mbox, u32 val);
+int skl_pcode_request(struct drm_i915_private *dev_priv, u32 mbox, u32 request,
+		      u32 reply_mask, u32 reply, int timeout_base_ms);
 
 /* intel_sideband.c */
 u32 vlv_punit_read(struct drm_i915_private *dev_priv, u32 addr);
diff -druNp --no-dereference linux-libre-4.9.3-gnu/drivers/gpu/drm/i915/intel_display.c linux-libre-4.9.4-gnu/drivers/gpu/drm/i915/intel_display.c
--- linux-libre-4.9.3-gnu/drivers/gpu/drm/i915/intel_display.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/drivers/gpu/drm/i915/intel_display.c	2017-01-15 07:43:07.000000000 -0500
@@ -6262,36 +6262,25 @@ skl_dpll0_disable(struct drm_i915_privat
 	dev_priv->cdclk_pll.vco = 0;
 }
 
-static bool skl_cdclk_pcu_ready(struct drm_i915_private *dev_priv)
-{
-	int ret;
-	u32 val;
-
-	/* inform PCU we want to change CDCLK */
-	val = SKL_CDCLK_PREPARE_FOR_CHANGE;
-	mutex_lock(&dev_priv->rps.hw_lock);
-	ret = sandybridge_pcode_read(dev_priv, SKL_PCODE_CDCLK_CONTROL, &val);
-	mutex_unlock(&dev_priv->rps.hw_lock);
-
-	return ret == 0 && (val & SKL_CDCLK_READY_FOR_CHANGE);
-}
-
-static bool skl_cdclk_wait_for_pcu_ready(struct drm_i915_private *dev_priv)
-{
-	return _wait_for(skl_cdclk_pcu_ready(dev_priv), 3000, 10) == 0;
-}
-
 static void skl_set_cdclk(struct drm_i915_private *dev_priv, int cdclk, int vco)
 {
 	struct drm_device *dev = &dev_priv->drm;
 	u32 freq_select, pcu_ack;
+	int ret;
 
 	WARN_ON((cdclk == 24000) != (vco == 0));
 
 	DRM_DEBUG_DRIVER("Changing CDCLK to %d kHz (VCO %d kHz)\n", cdclk, vco);
 
-	if (!skl_cdclk_wait_for_pcu_ready(dev_priv)) {
-		DRM_ERROR("failed to inform PCU about cdclk change\n");
+	mutex_lock(&dev_priv->rps.hw_lock);
+	ret = skl_pcode_request(dev_priv, SKL_PCODE_CDCLK_CONTROL,
+				SKL_CDCLK_PREPARE_FOR_CHANGE,
+				SKL_CDCLK_READY_FOR_CHANGE,
+				SKL_CDCLK_READY_FOR_CHANGE, 3);
+	mutex_unlock(&dev_priv->rps.hw_lock);
+	if (ret) {
+		DRM_ERROR("Failed to inform PCU about cdclk change (%d)\n",
+			  ret);
 		return;
 	}
 
diff -druNp --no-dereference linux-libre-4.9.3-gnu/drivers/gpu/drm/i915/intel_pm.c linux-libre-4.9.4-gnu/drivers/gpu/drm/i915/intel_pm.c
--- linux-libre-4.9.3-gnu/drivers/gpu/drm/i915/intel_pm.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/drivers/gpu/drm/i915/intel_pm.c	2017-01-15 07:43:07.000000000 -0500
@@ -7955,6 +7955,81 @@ int sandybridge_pcode_write(struct drm_i
 	return 0;
 }
 
+static bool skl_pcode_try_request(struct drm_i915_private *dev_priv, u32 mbox,
+				  u32 request, u32 reply_mask, u32 reply,
+				  u32 *status)
+{
+	u32 val = request;
+
+	*status = sandybridge_pcode_read(dev_priv, mbox, &val);
+
+	return *status || ((val & reply_mask) == reply);
+}
+
+/**
+ * skl_pcode_request - send PCODE request until acknowledgment
+ * @dev_priv: device private
+ * @mbox: PCODE mailbox ID the request is targeted for
+ * @request: request ID
+ * @reply_mask: mask used to check for request acknowledgment
+ * @reply: value used to check for request acknowledgment
+ * @timeout_base_ms: timeout for polling with preemption enabled
+ *
+ * Keep resending the @request to @mbox until PCODE acknowledges it, PCODE
+ * reports an error or an overall timeout of @timeout_base_ms+10 ms expires.
+ * The request is acknowledged once the PCODE reply dword equals @reply after
+ * applying @reply_mask. Polling is first attempted with preemption enabled
+ * for @timeout_base_ms and if this times out for another 10 ms with
+ * preemption disabled.
+ *
+ * Returns 0 on success, %-ETIMEDOUT in case of a timeout, <0 in case of some
+ * other error as reported by PCODE.
+ */
+int skl_pcode_request(struct drm_i915_private *dev_priv, u32 mbox, u32 request,
+		      u32 reply_mask, u32 reply, int timeout_base_ms)
+{
+	u32 status;
+	int ret;
+
+	WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
+
+#define COND skl_pcode_try_request(dev_priv, mbox, request, reply_mask, reply, \
+				   &status)
+
+	/*
+	 * Prime the PCODE by doing a request first. Normally it guarantees
+	 * that a subsequent request, at most @timeout_base_ms later, succeeds.
+	 * _wait_for() doesn't guarantee when its passed condition is evaluated
+	 * first, so send the first request explicitly.
+	 */
+	if (COND) {
+		ret = 0;
+		goto out;
+	}
+	ret = _wait_for(COND, timeout_base_ms * 1000, 10);
+	if (!ret)
+		goto out;
+
+	/*
+	 * The above can time out if the number of requests was low (2 in the
+	 * worst case) _and_ PCODE was busy for some reason even after a
+	 * (queued) request and @timeout_base_ms delay. As a workaround retry
+	 * the poll with preemption disabled to maximize the number of
+	 * requests. Increase the timeout from @timeout_base_ms to 50ms to
+	 * account for interrupts that could reduce the number of these
+	 * requests.
+	 */
+	DRM_DEBUG_KMS("PCODE timeout, retrying with preemption disabled\n");
+	WARN_ON_ONCE(timeout_base_ms > 3);
+	preempt_disable();
+	ret = wait_for_atomic(COND, 50);
+	preempt_enable();
+
+out:
+	return ret ? ret : status;
+#undef COND
+}
+
 static int byt_gpu_freq(struct drm_i915_private *dev_priv, int val)
 {
 	/*
diff -druNp --no-dereference linux-libre-4.9.3-gnu/drivers/hid/hid-cypress.c linux-libre-4.9.4-gnu/drivers/hid/hid-cypress.c
--- linux-libre-4.9.3-gnu/drivers/hid/hid-cypress.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/drivers/hid/hid-cypress.c	2017-01-15 07:43:07.000000000 -0500
@@ -39,6 +39,9 @@ static __u8 *cp_report_fixup(struct hid_
 	if (!(quirks & CP_RDESC_SWAPPED_MIN_MAX))
 		return rdesc;
 
+	if (*rsize < 4)
+		return rdesc;
+
 	for (i = 0; i < *rsize - 4; i++)
 		if (rdesc[i] == 0x29 && rdesc[i + 2] == 0x19) {
 			rdesc[i] = 0x19;
diff -druNp --no-dereference linux-libre-4.9.3-gnu/drivers/net/dsa/bcm_sf2.c linux-libre-4.9.4-gnu/drivers/net/dsa/bcm_sf2.c
--- linux-libre-4.9.3-gnu/drivers/net/dsa/bcm_sf2.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/drivers/net/dsa/bcm_sf2.c	2017-01-15 07:43:07.000000000 -0500
@@ -393,7 +393,7 @@ static int bcm_sf2_sw_mdio_read(struct m
 	if (addr == BRCM_PSEUDO_PHY_ADDR && priv->indir_phy_mask & BIT(addr))
 		return bcm_sf2_sw_indir_rw(priv, 1, addr, regnum, 0);
 	else
-		return mdiobus_read(priv->master_mii_bus, addr, regnum);
+		return mdiobus_read_nested(priv->master_mii_bus, addr, regnum);
 }
 
 static int bcm_sf2_sw_mdio_write(struct mii_bus *bus, int addr, int regnum,
@@ -407,7 +407,7 @@ static int bcm_sf2_sw_mdio_write(struct
 	if (addr == BRCM_PSEUDO_PHY_ADDR && priv->indir_phy_mask & BIT(addr))
 		bcm_sf2_sw_indir_rw(priv, 0, addr, regnum, val);
 	else
-		mdiobus_write(priv->master_mii_bus, addr, regnum, val);
+		mdiobus_write_nested(priv->master_mii_bus, addr, regnum, val);
 
 	return 0;
 }
@@ -982,6 +982,7 @@ static int bcm_sf2_sw_probe(struct platf
 	const char *reg_names[BCM_SF2_REGS_NUM] = BCM_SF2_REGS_NAME;
 	struct device_node *dn = pdev->dev.of_node;
 	struct b53_platform_data *pdata;
+	struct dsa_switch_ops *ops;
 	struct bcm_sf2_priv *priv;
 	struct b53_device *dev;
 	struct dsa_switch *ds;
@@ -995,6 +996,10 @@ static int bcm_sf2_sw_probe(struct platf
 	if (!priv)
 		return -ENOMEM;
 
+	ops = devm_kzalloc(&pdev->dev, sizeof(*ops), GFP_KERNEL);
+	if (!ops)
+		return -ENOMEM;
+
 	dev = b53_switch_alloc(&pdev->dev, &bcm_sf2_io_ops, priv);
 	if (!dev)
 		return -ENOMEM;
@@ -1014,6 +1019,8 @@ static int bcm_sf2_sw_probe(struct platf
 	ds = dev->ds;
 
 	/* Override the parts that are non-standard wrt. normal b53 devices */
+	memcpy(ops, ds->ops, sizeof(*ops));
+	ds->ops = ops;
 	ds->ops->get_tag_protocol = bcm_sf2_sw_get_tag_protocol;
 	ds->ops->setup = bcm_sf2_sw_setup;
 	ds->ops->get_phy_flags = bcm_sf2_sw_get_phy_flags;
diff -druNp --no-dereference linux-libre-4.9.3-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c linux-libre-4.9.4-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c
--- linux-libre-4.9.3-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c	2017-01-15 07:43:07.000000000 -0500
@@ -247,6 +247,7 @@ static int set_flow_attrs(u32 *match_c,
 	}
 	if (fs->flow_type & FLOW_MAC_EXT &&
 	    !is_zero_ether_addr(fs->m_ext.h_dest)) {
+		mask_spec(fs->m_ext.h_dest, fs->h_ext.h_dest, ETH_ALEN);
 		ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4,
 					     outer_headers_c, dmac_47_16),
 				fs->m_ext.h_dest);
diff -druNp --no-dereference linux-libre-4.9.3-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_main.c linux-libre-4.9.4-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
--- linux-libre-4.9.3-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_main.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_main.c	2017-01-15 07:43:07.000000000 -0500
@@ -3773,14 +3773,7 @@ static void mlx5e_nic_enable(struct mlx5
 
 	mlx5_lag_add(mdev, netdev);
 
-	if (mlx5e_vxlan_allowed(mdev)) {
-		rtnl_lock();
-		udp_tunnel_get_rx_info(netdev);
-		rtnl_unlock();
-	}
-
 	mlx5e_enable_async_events(priv);
-	queue_work(priv->wq, &priv->set_rx_mode_work);
 
 	if (MLX5_CAP_GEN(mdev, vport_group_manager)) {
 		mlx5_query_nic_vport_mac_address(mdev, 0, rep.hw_id);
@@ -3790,6 +3783,18 @@ static void mlx5e_nic_enable(struct mlx5
 		rep.priv_data = priv;
 		mlx5_eswitch_register_vport_rep(esw, 0, &rep);
 	}
+
+	if (netdev->reg_state != NETREG_REGISTERED)
+		return;
+
+	/* Device already registered: sync netdev system state */
+	if (mlx5e_vxlan_allowed(mdev)) {
+		rtnl_lock();
+		udp_tunnel_get_rx_info(netdev);
+		rtnl_unlock();
+	}
+
+	queue_work(priv->wq, &priv->set_rx_mode_work);
 }
 
 static void mlx5e_nic_disable(struct mlx5e_priv *priv)
@@ -3937,10 +3942,6 @@ void mlx5e_detach_netdev(struct mlx5_cor
 	const struct mlx5e_profile *profile = priv->profile;
 
 	set_bit(MLX5E_STATE_DESTROYING, &priv->state);
-	if (profile->disable)
-		profile->disable(priv);
-
-	flush_workqueue(priv->wq);
 
 	rtnl_lock();
 	if (netif_running(netdev))
@@ -3948,6 +3949,10 @@ void mlx5e_detach_netdev(struct mlx5_cor
 	netif_device_detach(netdev);
 	rtnl_unlock();
 
+	if (profile->disable)
+		profile->disable(priv);
+	flush_workqueue(priv->wq);
+
 	mlx5e_destroy_q_counter(priv);
 	profile->cleanup_rx(priv);
 	mlx5e_close_drop_rq(priv);
diff -druNp --no-dereference linux-libre-4.9.3-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c linux-libre-4.9.4-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c
--- linux-libre-4.9.3-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c	2017-01-15 07:43:07.000000000 -0500
@@ -109,7 +109,6 @@ static bool mlx5e_am_on_top(struct mlx5e
 	switch (am->tune_state) {
 	case MLX5E_AM_PARKING_ON_TOP:
 	case MLX5E_AM_PARKING_TIRED:
-		WARN_ONCE(true, "mlx5e_am_on_top: PARKING\n");
 		return true;
 	case MLX5E_AM_GOING_RIGHT:
 		return (am->steps_left > 1) && (am->steps_right == 1);
@@ -123,7 +122,6 @@ static void mlx5e_am_turn(struct mlx5e_r
 	switch (am->tune_state) {
 	case MLX5E_AM_PARKING_ON_TOP:
 	case MLX5E_AM_PARKING_TIRED:
-		WARN_ONCE(true, "mlx5e_am_turn: PARKING\n");
 		break;
 	case MLX5E_AM_GOING_RIGHT:
 		am->tune_state = MLX5E_AM_GOING_LEFT;
@@ -144,7 +142,6 @@ static int mlx5e_am_step(struct mlx5e_rx
 	switch (am->tune_state) {
 	case MLX5E_AM_PARKING_ON_TOP:
 	case MLX5E_AM_PARKING_TIRED:
-		WARN_ONCE(true, "mlx5e_am_step: PARKING\n");
 		break;
 	case MLX5E_AM_GOING_RIGHT:
 		if (am->profile_ix == (MLX5E_PARAMS_AM_NUM_PROFILES - 1))
@@ -282,10 +279,8 @@ static void mlx5e_am_calc_stats(struct m
 	u32 delta_us = ktime_us_delta(end->time, start->time);
 	unsigned int npkts = end->pkt_ctr - start->pkt_ctr;
 
-	if (!delta_us) {
-		WARN_ONCE(true, "mlx5e_am_calc_stats: delta_us=0\n");
+	if (!delta_us)
 		return;
-	}
 
 	curr_stats->ppms =            (npkts * USEC_PER_MSEC) / delta_us;
 	curr_stats->epms = (MLX5E_AM_NEVENTS * USEC_PER_MSEC) / delta_us;
diff -druNp --no-dereference linux-libre-4.9.3-gnu/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c linux-libre-4.9.4-gnu/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
--- linux-libre-4.9.3-gnu/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c	2017-01-15 07:43:07.000000000 -0500
@@ -1703,7 +1703,7 @@ int mlx5_eswitch_set_vport_mac(struct ml
 
 	if (!ESW_ALLOWED(esw))
 		return -EPERM;
-	if (!LEGAL_VPORT(esw, vport))
+	if (!LEGAL_VPORT(esw, vport) || is_multicast_ether_addr(mac))
 		return -EINVAL;
 
 	mutex_lock(&esw->state_lock);
diff -druNp --no-dereference linux-libre-4.9.3-gnu/drivers/net/ethernet/mellanox/mlx5/core/main.c linux-libre-4.9.4-gnu/drivers/net/ethernet/mellanox/mlx5/core/main.c
--- linux-libre-4.9.3-gnu/drivers/net/ethernet/mellanox/mlx5/core/main.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/drivers/net/ethernet/mellanox/mlx5/core/main.c	2017-01-15 07:43:07.000000000 -0500
@@ -468,6 +468,13 @@ static int handle_hca_cap(struct mlx5_co
 	MLX5_SET(cmd_hca_cap, set_hca_cap, pkey_table_size,
 		 to_fw_pkey_sz(dev, 128));
 
+	/* Check log_max_qp from HCA caps to set in current profile */
+	if (MLX5_CAP_GEN_MAX(dev, log_max_qp) < profile[prof_sel].log_max_qp) {
+		mlx5_core_warn(dev, "log_max_qp value in current profile is %d, changing it to HCA capability limit (%d)\n",
+			       profile[prof_sel].log_max_qp,
+			       MLX5_CAP_GEN_MAX(dev, log_max_qp));
+		profile[prof_sel].log_max_qp = MLX5_CAP_GEN_MAX(dev, log_max_qp);
+	}
 	if (prof->mask & MLX5_PROF_MASK_QP_SIZE)
 		MLX5_SET(cmd_hca_cap, set_hca_cap, log_max_qp,
 			 prof->log_max_qp);
@@ -540,7 +547,6 @@ static int mlx5_irq_set_affinity_hint(st
 	struct mlx5_priv *priv  = &mdev->priv;
 	struct msix_entry *msix = priv->msix_arr;
 	int irq                 = msix[i + MLX5_EQ_VEC_COMP_BASE].vector;
-	int numa_node           = priv->numa_node;
 	int err;
 
 	if (!zalloc_cpumask_var(&priv->irq_info[i].mask, GFP_KERNEL)) {
@@ -548,7 +554,7 @@ static int mlx5_irq_set_affinity_hint(st
 		return -ENOMEM;
 	}
 
-	cpumask_set_cpu(cpumask_local_spread(i, numa_node),
+	cpumask_set_cpu(cpumask_local_spread(i, priv->numa_node),
 			priv->irq_info[i].mask);
 
 	err = irq_set_affinity_hint(irq, priv->irq_info[i].mask);
@@ -1152,6 +1158,8 @@ static int mlx5_unload_one(struct mlx5_c
 {
 	int err = 0;
 
+	mlx5_drain_health_wq(dev);
+
 	mutex_lock(&dev->intf_state_mutex);
 	if (test_bit(MLX5_INTERFACE_STATE_DOWN, &dev->intf_state)) {
 		dev_warn(&dev->pdev->dev, "%s: interface is down, NOP\n",
@@ -1312,10 +1320,9 @@ static pci_ers_result_t mlx5_pci_err_det
 
 	mlx5_enter_error_state(dev);
 	mlx5_unload_one(dev, priv, false);
-	/* In case of kernel call save the pci state and drain health wq */
+	/* In case of kernel call save the pci state */
 	if (state) {
 		pci_save_state(pdev);
-		mlx5_drain_health_wq(dev);
 		mlx5_pci_disable_device(dev);
 	}
 
diff -druNp --no-dereference linux-libre-4.9.3-gnu/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c linux-libre-4.9.4-gnu/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
--- linux-libre-4.9.3-gnu/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c	2017-01-15 07:43:07.000000000 -0500
@@ -3349,12 +3349,6 @@ int stmmac_dvr_probe(struct device *devi
 	spin_lock_init(&priv->lock);
 	spin_lock_init(&priv->tx_lock);
 
-	ret = register_netdev(ndev);
-	if (ret) {
-		pr_err("%s: ERROR %i registering the device\n", __func__, ret);
-		goto error_netdev_register;
-	}
-
 	/* If a specific clk_csr value is passed from the platform
 	 * this means that the CSR Clock Range selection cannot be
 	 * changed at run-time and it is fixed. Viceversa the driver'll try to
@@ -3376,15 +3370,24 @@ int stmmac_dvr_probe(struct device *devi
 		if (ret < 0) {
 			pr_debug("%s: MDIO bus (id: %d) registration failed",
 				 __func__, priv->plat->bus_id);
-			goto error_mdio_register;
+			goto error_napi_register;
 		}
 	}
 
-	return 0;
+	ret = register_netdev(ndev);
+	if (ret) {
+		pr_err("%s: ERROR %i registering the device\n", __func__, ret);
+		goto error_netdev_register;
+	}
+
+	return ret;
 
-error_mdio_register:
-	unregister_netdev(ndev);
 error_netdev_register:
+	if (priv->hw->pcs != STMMAC_PCS_RGMII &&
+	    priv->hw->pcs != STMMAC_PCS_TBI &&
+	    priv->hw->pcs != STMMAC_PCS_RTBI)
+		stmmac_mdio_unregister(ndev);
+error_napi_register:
 	netif_napi_del(&priv->napi);
 error_hw_init:
 	clk_disable_unprepare(priv->pclk);
diff -druNp --no-dereference linux-libre-4.9.3-gnu/drivers/net/usb/r8152.c linux-libre-4.9.4-gnu/drivers/net/usb/r8152.c
--- linux-libre-4.9.3-gnu/drivers/net/usb/r8152.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/drivers/net/usb/r8152.c	2017-01-15 07:43:07.000000000 -0500
@@ -3576,39 +3576,87 @@ static bool delay_autosuspend(struct r81
 		return false;
 }
 
-static int rtl8152_suspend(struct usb_interface *intf, pm_message_t message)
+static int rtl8152_rumtime_suspend(struct r8152 *tp)
 {
-	struct r8152 *tp = usb_get_intfdata(intf);
 	struct net_device *netdev = tp->netdev;
 	int ret = 0;
 
-	mutex_lock(&tp->control);
+	if (netif_running(netdev) && test_bit(WORK_ENABLE, &tp->flags)) {
+		u32 rcr = 0;
 
-	if (PMSG_IS_AUTO(message)) {
-		if (netif_running(netdev) && delay_autosuspend(tp)) {
+		if (delay_autosuspend(tp)) {
 			ret = -EBUSY;
 			goto out1;
 		}
 
-		set_bit(SELECTIVE_SUSPEND, &tp->flags);
-	} else {
-		netif_device_detach(netdev);
+		if (netif_carrier_ok(netdev)) {
+			u32 ocp_data;
+
+			rcr = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
+			ocp_data = rcr & ~RCR_ACPT_ALL;
+			ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data);
+			rxdy_gated_en(tp, true);
+			ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA,
+						 PLA_OOB_CTRL);
+			if (!(ocp_data & RXFIFO_EMPTY)) {
+				rxdy_gated_en(tp, false);
+				ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, rcr);
+				ret = -EBUSY;
+				goto out1;
+			}
+		}
+
+		clear_bit(WORK_ENABLE, &tp->flags);
+		usb_kill_urb(tp->intr_urb);
+
+		tp->rtl_ops.autosuspend_en(tp, true);
+
+		if (netif_carrier_ok(netdev)) {
+			napi_disable(&tp->napi);
+			rtl_stop_rx(tp);
+			rxdy_gated_en(tp, false);
+			ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, rcr);
+			napi_enable(&tp->napi);
+		}
 	}
 
+	set_bit(SELECTIVE_SUSPEND, &tp->flags);
+
+out1:
+	return ret;
+}
+
+static int rtl8152_system_suspend(struct r8152 *tp)
+{
+	struct net_device *netdev = tp->netdev;
+	int ret = 0;
+
+	netif_device_detach(netdev);
+
 	if (netif_running(netdev) && test_bit(WORK_ENABLE, &tp->flags)) {
 		clear_bit(WORK_ENABLE, &tp->flags);
 		usb_kill_urb(tp->intr_urb);
 		napi_disable(&tp->napi);
-		if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) {
-			rtl_stop_rx(tp);
-			tp->rtl_ops.autosuspend_en(tp, true);
-		} else {
-			cancel_delayed_work_sync(&tp->schedule);
-			tp->rtl_ops.down(tp);
-		}
+		cancel_delayed_work_sync(&tp->schedule);
+		tp->rtl_ops.down(tp);
 		napi_enable(&tp->napi);
 	}
-out1:
+
+	return ret;
+}
+
+static int rtl8152_suspend(struct usb_interface *intf, pm_message_t message)
+{
+	struct r8152 *tp = usb_get_intfdata(intf);
+	int ret;
+
+	mutex_lock(&tp->control);
+
+	if (PMSG_IS_AUTO(message))
+		ret = rtl8152_rumtime_suspend(tp);
+	else
+		ret = rtl8152_system_suspend(tp);
+
 	mutex_unlock(&tp->control);
 
 	return ret;
diff -druNp --no-dereference linux-libre-4.9.3-gnu/drivers/net/vrf.c linux-libre-4.9.4-gnu/drivers/net/vrf.c
--- linux-libre-4.9.3-gnu/drivers/net/vrf.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/drivers/net/vrf.c	2017-01-15 07:43:07.000000000 -0500
@@ -263,7 +263,9 @@ static netdev_tx_t vrf_process_v4_outbou
 		.flowi4_iif = LOOPBACK_IFINDEX,
 		.flowi4_tos = RT_TOS(ip4h->tos),
 		.flowi4_flags = FLOWI_FLAG_ANYSRC | FLOWI_FLAG_SKIP_NH_OIF,
+		.flowi4_proto = ip4h->protocol,
 		.daddr = ip4h->daddr,
+		.saddr = ip4h->saddr,
 	};
 	struct net *net = dev_net(vrf_dev);
 	struct rtable *rt;
@@ -371,6 +373,8 @@ static int vrf_finish_output6(struct net
 	struct in6_addr *nexthop;
 	int ret;
 
+	nf_reset(skb);
+
 	skb->protocol = htons(ETH_P_IPV6);
 	skb->dev = dev;
 
@@ -552,6 +556,8 @@ static int vrf_finish_output(struct net
 	u32 nexthop;
 	int ret = -EINVAL;
 
+	nf_reset(skb);
+
 	/* Be paranoid, rather than too clever. */
 	if (unlikely(skb_headroom(skb) < hh_len && dev->header_ops)) {
 		struct sk_buff *skb2;
@@ -850,8 +856,6 @@ static struct sk_buff *vrf_rcv_nfhook(u8
 {
 	struct net *net = dev_net(dev);
 
-	nf_reset(skb);
-
 	if (NF_HOOK(pf, hook, net, NULL, skb, dev, NULL, vrf_rcv_finish) < 0)
 		skb = NULL;    /* kfree_skb(skb) handled by nf code */
 
@@ -966,6 +970,7 @@ static struct sk_buff *vrf_ip6_rcv(struc
 	 */
 	need_strict = rt6_need_strict(&ipv6_hdr(skb)->daddr);
 	if (!ipv6_ndisc_frame(skb) && !need_strict) {
+		vrf_rx_stats(vrf_dev, skb->len);
 		skb->dev = vrf_dev;
 		skb->skb_iif = vrf_dev->ifindex;
 
@@ -1007,6 +1012,8 @@ static struct sk_buff *vrf_ip_rcv(struct
 		goto out;
 	}
 
+	vrf_rx_stats(vrf_dev, skb->len);
+
 	skb_push(skb, skb->mac_len);
 	dev_queue_xmit_nit(skb, vrf_dev);
 	skb_pull(skb, skb->mac_len);
@@ -1232,6 +1239,8 @@ static int vrf_newlink(struct net *src_n
 		return -EINVAL;
 
 	vrf->tb_id = nla_get_u32(data[IFLA_VRF_TABLE]);
+	if (vrf->tb_id == RT_TABLE_UNSPEC)
+		return -EINVAL;
 
 	dev->priv_flags |= IFF_L3MDEV_MASTER;
 
diff -druNp --no-dereference linux-libre-4.9.3-gnu/drivers/net/wireless/realtek/rtlwifi/base.c linux-libre-4.9.4-gnu/drivers/net/wireless/realtek/rtlwifi/base.c
--- linux-libre-4.9.3-gnu/drivers/net/wireless/realtek/rtlwifi/base.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/drivers/net/wireless/realtek/rtlwifi/base.c	2017-01-15 07:43:07.000000000 -0500
@@ -1303,12 +1303,13 @@ EXPORT_SYMBOL_GPL(rtl_action_proc);
 
 static void setup_arp_tx(struct rtl_priv *rtlpriv, struct rtl_ps_ctl *ppsc)
 {
+	struct ieee80211_hw *hw = rtlpriv->hw;
+
 	rtlpriv->ra.is_special_data = true;
 	if (rtlpriv->cfg->ops->get_btc_status())
 		rtlpriv->btcoexist.btc_ops->btc_special_packet_notify(
 					rtlpriv, 1);
-	rtlpriv->enter_ps = false;
-	schedule_work(&rtlpriv->works.lps_change_work);
+	rtl_lps_leave(hw);
 	ppsc->last_delaylps_stamp_jiffies = jiffies;
 }
 
@@ -1381,8 +1382,7 @@ u8 rtl_is_special_data(struct ieee80211_
 
 		if (is_tx) {
 			rtlpriv->ra.is_special_data = true;
-			rtlpriv->enter_ps = false;
-			schedule_work(&rtlpriv->works.lps_change_work);
+			rtl_lps_leave(hw);
 			ppsc->last_delaylps_stamp_jiffies = jiffies;
 		}
 
diff -druNp --no-dereference linux-libre-4.9.3-gnu/drivers/net/wireless/realtek/rtlwifi/core.c linux-libre-4.9.4-gnu/drivers/net/wireless/realtek/rtlwifi/core.c
--- linux-libre-4.9.3-gnu/drivers/net/wireless/realtek/rtlwifi/core.c	2017-01-12 21:24:12.000000000 -0500
+++ linux-libre-4.9.4-gnu/drivers/net/wireless/realtek/rtlwifi/core.c	2017-01-15 17:43:13.000000000 -0500
@@ -1150,10 +1150,8 @@ static void rtl_op_bss_info_changed(stru
 		} else {
 			mstatus = RT_MEDIA_DISCONNECT;
 
-			if (mac->link_state == MAC80211_LINKED) {
-				rtlpriv->enter_ps = false;
-				schedule_work(&rtlpriv->works.lps_change_work);
-			}
+			if (mac->link_state == MAC80211_LINKED)
+				rtl_lps_leave(hw);
 			if (ppsc->p2p_ps_info.p2p_ps_mode > P2P_PS_NONE)
 				rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE);
 			mac->link_state = MAC80211_NOLINK;
@@ -1431,8 +1429,7 @@ static void rtl_op_sw_scan_start(struct
 	}
 
 	if (mac->link_state == MAC80211_LINKED) {
-		rtlpriv->enter_ps = false;
-		schedule_work(&rtlpriv->works.lps_change_work);
+		rtl_lps_leave(hw);
 		mac->link_state = MAC80211_LINKED_SCANNING;
 	} else {
 		rtl_ips_nic_on(hw);
diff -druNp --no-dereference linux-libre-4.9.3-gnu/drivers/net/wireless/realtek/rtlwifi/pci.c linux-libre-4.9.4-gnu/drivers/net/wireless/realtek/rtlwifi/pci.c
--- linux-libre-4.9.3-gnu/drivers/net/wireless/realtek/rtlwifi/pci.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/drivers/net/wireless/realtek/rtlwifi/pci.c	2017-01-15 07:43:07.000000000 -0500
@@ -663,11 +663,9 @@ tx_status_ok:
 	}
 
 	if (((rtlpriv->link_info.num_rx_inperiod +
-		rtlpriv->link_info.num_tx_inperiod) > 8) ||
-		(rtlpriv->link_info.num_rx_inperiod > 2)) {
-		rtlpriv->enter_ps = false;
-		schedule_work(&rtlpriv->works.lps_change_work);
-	}
+	      rtlpriv->link_info.num_tx_inperiod) > 8) ||
+	      (rtlpriv->link_info.num_rx_inperiod > 2))
+		rtl_lps_leave(hw);
 }
 
 static int _rtl_pci_init_one_rxdesc(struct ieee80211_hw *hw,
@@ -918,10 +916,8 @@ new_trx_end:
 		}
 		if (((rtlpriv->link_info.num_rx_inperiod +
 		      rtlpriv->link_info.num_tx_inperiod) > 8) ||
-		      (rtlpriv->link_info.num_rx_inperiod > 2)) {
-			rtlpriv->enter_ps = false;
-			schedule_work(&rtlpriv->works.lps_change_work);
-		}
+		      (rtlpriv->link_info.num_rx_inperiod > 2))
+			rtl_lps_leave(hw);
 		skb = new_skb;
 no_new:
 		if (rtlpriv->use_new_trx_flow) {
diff -druNp --no-dereference linux-libre-4.9.3-gnu/drivers/net/wireless/realtek/rtlwifi/ps.c linux-libre-4.9.4-gnu/drivers/net/wireless/realtek/rtlwifi/ps.c
--- linux-libre-4.9.3-gnu/drivers/net/wireless/realtek/rtlwifi/ps.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/drivers/net/wireless/realtek/rtlwifi/ps.c	2017-01-15 07:43:07.000000000 -0500
@@ -407,8 +407,8 @@ void rtl_lps_set_psmode(struct ieee80211
 	}
 }
 
-/*Enter the leisure power save mode.*/
-void rtl_lps_enter(struct ieee80211_hw *hw)
+/* Interrupt safe routine to enter the leisure power save mode.*/
+static void rtl_lps_enter_core(struct ieee80211_hw *hw)
 {
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
@@ -444,10 +444,9 @@ void rtl_lps_enter(struct ieee80211_hw *
 
 	spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
 }
-EXPORT_SYMBOL(rtl_lps_enter);
 
-/*Leave the leisure power save mode.*/
-void rtl_lps_leave(struct ieee80211_hw *hw)
+/* Interrupt safe routine to leave the leisure power save mode.*/
+static void rtl_lps_leave_core(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
@@ -477,7 +476,6 @@ void rtl_lps_leave(struct ieee80211_hw *
 	}
 	spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
 }
-EXPORT_SYMBOL(rtl_lps_leave);
 
 /* For sw LPS*/
 void rtl_swlps_beacon(struct ieee80211_hw *hw, void *data, unsigned int len)
@@ -670,12 +668,34 @@ void rtl_lps_change_work_callback(struct
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 
 	if (rtlpriv->enter_ps)
-		rtl_lps_enter(hw);
+		rtl_lps_enter_core(hw);
 	else
-		rtl_lps_leave(hw);
+		rtl_lps_leave_core(hw);
 }
 EXPORT_SYMBOL_GPL(rtl_lps_change_work_callback);
 
+void rtl_lps_enter(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	if (!in_interrupt())
+		return rtl_lps_enter_core(hw);
+	rtlpriv->enter_ps = true;
+	schedule_work(&rtlpriv->works.lps_change_work);
+}
+EXPORT_SYMBOL_GPL(rtl_lps_enter);
+
+void rtl_lps_leave(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	if (!in_interrupt())
+		return rtl_lps_leave_core(hw);
+	rtlpriv->enter_ps = false;
+	schedule_work(&rtlpriv->works.lps_change_work);
+}
+EXPORT_SYMBOL_GPL(rtl_lps_leave);
+
 void rtl_swlps_wq_callback(void *data)
 {
 	struct rtl_works *rtlworks = container_of_dwork_rtl(data,
diff -druNp --no-dereference linux-libre-4.9.3-gnu/drivers/net/wireless/realtek/rtlwifi/usb.c linux-libre-4.9.4-gnu/drivers/net/wireless/realtek/rtlwifi/usb.c
--- linux-libre-4.9.3-gnu/drivers/net/wireless/realtek/rtlwifi/usb.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/drivers/net/wireless/realtek/rtlwifi/usb.c	2017-01-15 07:43:07.000000000 -0500
@@ -1067,6 +1067,7 @@ int rtl_usb_probe(struct usb_interface *
 		return -ENOMEM;
 	}
 	rtlpriv = hw->priv;
+	rtlpriv->hw = hw;
 	rtlpriv->usb_data = kzalloc(RTL_USB_MAX_RX_COUNT * sizeof(u32),
 				    GFP_KERNEL);
 	if (!rtlpriv->usb_data)
diff -druNp --no-dereference linux-libre-4.9.3-gnu/drivers/spi/spi-orion.c linux-libre-4.9.4-gnu/drivers/spi/spi-orion.c
--- linux-libre-4.9.3-gnu/drivers/spi/spi-orion.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/drivers/spi/spi-orion.c	2017-01-15 07:43:07.000000000 -0500
@@ -138,37 +138,62 @@ static int orion_spi_baudrate_set(struct
 	tclk_hz = clk_get_rate(orion_spi->clk);
 
 	if (devdata->typ == ARMADA_SPI) {
-		unsigned int clk, spr, sppr, sppr2, err;
-		unsigned int best_spr, best_sppr, best_err;
+		/*
+		 * Given the core_clk (tclk_hz) and the target rate (speed) we
+		 * determine the best values for SPR (in [0 .. 15]) and SPPR (in
+		 * [0..7]) such that
+		 *
+		 * 	core_clk / (SPR * 2 ** SPPR)
+		 *
+		 * is as big as possible but not bigger than speed.
+		 */
 
-		best_err = speed;
-		best_spr = 0;
-		best_sppr = 0;
+		/* best integer divider: */
+		unsigned divider = DIV_ROUND_UP(tclk_hz, speed);
+		unsigned spr, sppr;
 
-		/* Iterate over the valid range looking for best fit */
-		for (sppr = 0; sppr < 8; sppr++) {
-			sppr2 = 0x1 << sppr;
+		if (divider < 16) {
+			/* This is the easy case, divider is less than 16 */
+			spr = divider;
+			sppr = 0;
 
-			spr = tclk_hz / sppr2;
-			spr = DIV_ROUND_UP(spr, speed);
-			if ((spr == 0) || (spr > 15))
-				continue;
+		} else {
+			unsigned two_pow_sppr;
+			/*
+			 * Find the highest bit set in divider. This and the
+			 * three next bits define SPR (apart from rounding).
+			 * SPPR is then the number of zero bits that must be
+			 * appended:
+			 */
+			sppr = fls(divider) - 4;
 
-			clk = tclk_hz / (spr * sppr2);
-			err = speed - clk;
+			/*
+			 * As SPR only has 4 bits, we have to round divider up
+			 * to the next multiple of 2 ** sppr.
+			 */
+			two_pow_sppr = 1 << sppr;
+			divider = (divider + two_pow_sppr - 1) & -two_pow_sppr;
 
-			if (err < best_err) {
-				best_spr = spr;
-				best_sppr = sppr;
-				best_err = err;
-			}
-		}
+			/*
+			 * recalculate sppr as rounding up divider might have
+			 * increased it enough to change the position of the
+			 * highest set bit. In this case the bit that now
+			 * doesn't make it into SPR is 0, so there is no need to
+			 * round again.
+			 */
+			sppr = fls(divider) - 4;
+			spr = divider >> sppr;
 
-		if ((best_sppr == 0) && (best_spr == 0))
-			return -EINVAL;
+			/*
+			 * Now do range checking. SPR is constructed to have a
+			 * width of 4 bits, so this is fine for sure. So we
+			 * still need to check for sppr to fit into 3 bits:
+			 */
+			if (sppr > 7)
+				return -EINVAL;
+		}
 
-		prescale = ((best_sppr & 0x6) << 5) |
-			((best_sppr & 0x1) << 4) | best_spr;
+		prescale = ((sppr & 0x6) << 5) | ((sppr & 0x1) << 4) | spr;
 	} else {
 		/*
 		 * the supported rates are: 4,6,8...30
diff -druNp --no-dereference linux-libre-4.9.3-gnu/include/linux/netdevice.h linux-libre-4.9.4-gnu/include/linux/netdevice.h
--- linux-libre-4.9.3-gnu/include/linux/netdevice.h	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/include/linux/netdevice.h	2017-01-15 07:43:07.000000000 -0500
@@ -2502,14 +2502,19 @@ static inline int skb_gro_header_hard(st
 	return NAPI_GRO_CB(skb)->frag0_len < hlen;
 }
 
+static inline void skb_gro_frag0_invalidate(struct sk_buff *skb)
+{
+	NAPI_GRO_CB(skb)->frag0 = NULL;
+	NAPI_GRO_CB(skb)->frag0_len = 0;
+}
+
 static inline void *skb_gro_header_slow(struct sk_buff *skb, unsigned int hlen,
 					unsigned int offset)
 {
 	if (!pskb_may_pull(skb, hlen))
 		return NULL;
 
-	NAPI_GRO_CB(skb)->frag0 = NULL;
-	NAPI_GRO_CB(skb)->frag0_len = 0;
+	skb_gro_frag0_invalidate(skb);
 	return skb->data + offset;
 }
 
diff -druNp --no-dereference linux-libre-4.9.3-gnu/Makefile linux-libre-4.9.4-gnu/Makefile
--- linux-libre-4.9.3-gnu/Makefile	2017-01-12 21:07:46.000000000 -0500
+++ linux-libre-4.9.4-gnu/Makefile	2017-01-15 17:25:39.000000000 -0500
@@ -1,6 +1,6 @@
 VERSION = 4
 PATCHLEVEL = 9
-SUBLEVEL = 3
+SUBLEVEL = 4
 EXTRAVERSION = -gnu
 NAME = Roaring Lionus
 
diff -druNp --no-dereference linux-libre-4.9.3-gnu/net/core/dev.c linux-libre-4.9.4-gnu/net/core/dev.c
--- linux-libre-4.9.3-gnu/net/core/dev.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/net/core/dev.c	2017-01-15 07:43:07.000000000 -0500
@@ -4453,7 +4453,9 @@ static void skb_gro_reset_offset(struct
 	    pinfo->nr_frags &&
 	    !PageHighMem(skb_frag_page(frag0))) {
 		NAPI_GRO_CB(skb)->frag0 = skb_frag_address(frag0);
-		NAPI_GRO_CB(skb)->frag0_len = skb_frag_size(frag0);
+		NAPI_GRO_CB(skb)->frag0_len = min_t(unsigned int,
+						    skb_frag_size(frag0),
+						    skb->end - skb->tail);
 	}
 }
 
diff -druNp --no-dereference linux-libre-4.9.3-gnu/net/core/drop_monitor.c linux-libre-4.9.4-gnu/net/core/drop_monitor.c
--- linux-libre-4.9.3-gnu/net/core/drop_monitor.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/net/core/drop_monitor.c	2017-01-15 07:43:07.000000000 -0500
@@ -80,6 +80,7 @@ static struct sk_buff *reset_per_cpu_dat
 	struct nlattr *nla;
 	struct sk_buff *skb;
 	unsigned long flags;
+	void *msg_header;
 
 	al = sizeof(struct net_dm_alert_msg);
 	al += dm_hit_limit * sizeof(struct net_dm_drop_point);
@@ -87,21 +88,41 @@ static struct sk_buff *reset_per_cpu_dat
 
 	skb = genlmsg_new(al, GFP_KERNEL);
 
-	if (skb) {
-		genlmsg_put(skb, 0, 0, &net_drop_monitor_family,
-				0, NET_DM_CMD_ALERT);
-		nla = nla_reserve(skb, NLA_UNSPEC,
-				  sizeof(struct net_dm_alert_msg));
-		msg = nla_data(nla);
-		memset(msg, 0, al);
-	} else {
-		mod_timer(&data->send_timer, jiffies + HZ / 10);
+	if (!skb)
+		goto err;
+
+	msg_header = genlmsg_put(skb, 0, 0, &net_drop_monitor_family,
+				 0, NET_DM_CMD_ALERT);
+	if (!msg_header) {
+		nlmsg_free(skb);
+		skb = NULL;
+		goto err;
 	}
+	nla = nla_reserve(skb, NLA_UNSPEC,
+			  sizeof(struct net_dm_alert_msg));
+	if (!nla) {
+		nlmsg_free(skb);
+		skb = NULL;
+		goto err;
+	}
+	msg = nla_data(nla);
+	memset(msg, 0, al);
+	goto out;
 
+err:
+	mod_timer(&data->send_timer, jiffies + HZ / 10);
+out:
 	spin_lock_irqsave(&data->lock, flags);
 	swap(data->skb, skb);
 	spin_unlock_irqrestore(&data->lock, flags);
 
+	if (skb) {
+		struct nlmsghdr *nlh = (struct nlmsghdr *)skb->data;
+		struct genlmsghdr *gnlh = (struct genlmsghdr *)nlmsg_data(nlh);
+
+		genlmsg_end(skb, genlmsg_data(gnlh));
+	}
+
 	return skb;
 }
 
diff -druNp --no-dereference linux-libre-4.9.3-gnu/net/core/flow_dissector.c linux-libre-4.9.4-gnu/net/core/flow_dissector.c
--- linux-libre-4.9.3-gnu/net/core/flow_dissector.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/net/core/flow_dissector.c	2017-01-15 07:43:07.000000000 -0500
@@ -445,8 +445,9 @@ ip_proto_again:
 			if (hdr->flags & GRE_ACK)
 				offset += sizeof(((struct pptp_gre_header *)0)->ack);
 
-			ppp_hdr = skb_header_pointer(skb, nhoff + offset,
-						     sizeof(_ppp_hdr), _ppp_hdr);
+			ppp_hdr = __skb_header_pointer(skb, nhoff + offset,
+						     sizeof(_ppp_hdr),
+						     data, hlen, _ppp_hdr);
 			if (!ppp_hdr)
 				goto out_bad;
 
diff -druNp --no-dereference linux-libre-4.9.3-gnu/net/core/rtnetlink.c linux-libre-4.9.4-gnu/net/core/rtnetlink.c
--- linux-libre-4.9.3-gnu/net/core/rtnetlink.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/net/core/rtnetlink.c	2017-01-15 07:43:07.000000000 -0500
@@ -3886,6 +3886,9 @@ static int rtnl_stats_get(struct sk_buff
 	u32 filter_mask;
 	int err;
 
+	if (nlmsg_len(nlh) < sizeof(*ifsm))
+		return -EINVAL;
+
 	ifsm = nlmsg_data(nlh);
 	if (ifsm->ifindex > 0)
 		dev = __dev_get_by_index(net, ifsm->ifindex);
@@ -3935,6 +3938,9 @@ static int rtnl_stats_dump(struct sk_buf
 
 	cb->seq = net->dev_base_seq;
 
+	if (nlmsg_len(cb->nlh) < sizeof(*ifsm))
+		return -EINVAL;
+
 	ifsm = nlmsg_data(cb->nlh);
 	filter_mask = ifsm->filter_mask;
 	if (!filter_mask)
diff -druNp --no-dereference linux-libre-4.9.3-gnu/net/core/sock.c linux-libre-4.9.4-gnu/net/core/sock.c
--- linux-libre-4.9.3-gnu/net/core/sock.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/net/core/sock.c	2017-01-15 07:43:07.000000000 -0500
@@ -222,7 +222,7 @@ static const char *const af_family_key_s
   "sk_lock-AF_RXRPC" , "sk_lock-AF_ISDN"     , "sk_lock-AF_PHONET"   ,
   "sk_lock-AF_IEEE802154", "sk_lock-AF_CAIF" , "sk_lock-AF_ALG"      ,
   "sk_lock-AF_NFC"   , "sk_lock-AF_VSOCK"    , "sk_lock-AF_KCM"      ,
-  "sk_lock-AF_MAX"
+  "sk_lock-AF_QIPCRTR", "sk_lock-AF_MAX"
 };
 static const char *const af_family_slock_key_strings[AF_MAX+1] = {
   "slock-AF_UNSPEC", "slock-AF_UNIX"     , "slock-AF_INET"     ,
@@ -239,7 +239,7 @@ static const char *const af_family_slock
   "slock-AF_RXRPC" , "slock-AF_ISDN"     , "slock-AF_PHONET"   ,
   "slock-AF_IEEE802154", "slock-AF_CAIF" , "slock-AF_ALG"      ,
   "slock-AF_NFC"   , "slock-AF_VSOCK"    ,"slock-AF_KCM"       ,
-  "slock-AF_MAX"
+  "slock-AF_QIPCRTR", "slock-AF_MAX"
 };
 static const char *const af_family_clock_key_strings[AF_MAX+1] = {
   "clock-AF_UNSPEC", "clock-AF_UNIX"     , "clock-AF_INET"     ,
@@ -256,7 +256,7 @@ static const char *const af_family_clock
   "clock-AF_RXRPC" , "clock-AF_ISDN"     , "clock-AF_PHONET"   ,
   "clock-AF_IEEE802154", "clock-AF_CAIF" , "clock-AF_ALG"      ,
   "clock-AF_NFC"   , "clock-AF_VSOCK"    , "clock-AF_KCM"      ,
-  "clock-AF_MAX"
+  "clock-AF_QIPCRTR", "clock-AF_MAX"
 };
 
 /*
diff -druNp --no-dereference linux-libre-4.9.3-gnu/net/dsa/dsa2.c linux-libre-4.9.4-gnu/net/dsa/dsa2.c
--- linux-libre-4.9.3-gnu/net/dsa/dsa2.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/net/dsa/dsa2.c	2017-01-15 07:43:07.000000000 -0500
@@ -394,9 +394,11 @@ static int dsa_dst_apply(struct dsa_swit
 			return err;
 	}
 
-	err = dsa_cpu_port_ethtool_setup(dst->ds[0]);
-	if (err)
-		return err;
+	if (dst->ds[0]) {
+		err = dsa_cpu_port_ethtool_setup(dst->ds[0]);
+		if (err)
+			return err;
+	}
 
 	/* If we use a tagging format that doesn't have an ethertype
 	 * field, make sure that all packets from this point on get
@@ -433,7 +435,8 @@ static void dsa_dst_unapply(struct dsa_s
 		dsa_ds_unapply(dst, ds);
 	}
 
-	dsa_cpu_port_ethtool_restore(dst->ds[0]);
+	if (dst->ds[0])
+		dsa_cpu_port_ethtool_restore(dst->ds[0]);
 
 	pr_info("DSA: tree %d unapplied\n", dst->tree);
 	dst->applied = false;
diff -druNp --no-dereference linux-libre-4.9.3-gnu/net/ipv4/fib_frontend.c linux-libre-4.9.4-gnu/net/ipv4/fib_frontend.c
--- linux-libre-4.9.3-gnu/net/ipv4/fib_frontend.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/net/ipv4/fib_frontend.c	2017-01-15 07:43:07.000000000 -0500
@@ -85,7 +85,7 @@ struct fib_table *fib_new_table(struct n
 	if (tb)
 		return tb;
 
-	if (id == RT_TABLE_LOCAL)
+	if (id == RT_TABLE_LOCAL && !net->ipv4.fib_has_custom_rules)
 		alias = fib_new_table(net, RT_TABLE_MAIN);
 
 	tb = fib_trie_table(id, alias);
diff -druNp --no-dereference linux-libre-4.9.3-gnu/net/ipv4/fib_semantics.c linux-libre-4.9.4-gnu/net/ipv4/fib_semantics.c
--- linux-libre-4.9.3-gnu/net/ipv4/fib_semantics.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/net/ipv4/fib_semantics.c	2017-01-15 07:43:07.000000000 -0500
@@ -1617,8 +1617,13 @@ void fib_select_multipath(struct fib_res
 void fib_select_path(struct net *net, struct fib_result *res,
 		     struct flowi4 *fl4, int mp_hash)
 {
+	bool oif_check;
+
+	oif_check = (fl4->flowi4_oif == 0 ||
+		     fl4->flowi4_flags & FLOWI_FLAG_SKIP_NH_OIF);
+
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
-	if (res->fi->fib_nhs > 1 && fl4->flowi4_oif == 0) {
+	if (res->fi->fib_nhs > 1 && oif_check) {
 		if (mp_hash < 0)
 			mp_hash = get_hash_from_flowi4(fl4) >> 1;
 
@@ -1628,7 +1633,7 @@ void fib_select_path(struct net *net, st
 #endif
 	if (!res->prefixlen &&
 	    res->table->tb_num_default > 1 &&
-	    res->type == RTN_UNICAST && !fl4->flowi4_oif)
+	    res->type == RTN_UNICAST && oif_check)
 		fib_select_default(fl4, res);
 
 	if (!fl4->saddr)
diff -druNp --no-dereference linux-libre-4.9.3-gnu/net/ipv4/igmp.c linux-libre-4.9.4-gnu/net/ipv4/igmp.c
--- linux-libre-4.9.3-gnu/net/ipv4/igmp.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/net/ipv4/igmp.c	2017-01-15 07:43:07.000000000 -0500
@@ -219,9 +219,14 @@ static void igmp_start_timer(struct ip_m
 static void igmp_gq_start_timer(struct in_device *in_dev)
 {
 	int tv = prandom_u32() % in_dev->mr_maxdelay;
+	unsigned long exp = jiffies + tv + 2;
+
+	if (in_dev->mr_gq_running &&
+	    time_after_eq(exp, (in_dev->mr_gq_timer).expires))
+		return;
 
 	in_dev->mr_gq_running = 1;
-	if (!mod_timer(&in_dev->mr_gq_timer, jiffies+tv+2))
+	if (!mod_timer(&in_dev->mr_gq_timer, exp))
 		in_dev_hold(in_dev);
 }
 
diff -druNp --no-dereference linux-libre-4.9.3-gnu/net/ipv4/ip_sockglue.c linux-libre-4.9.4-gnu/net/ipv4/ip_sockglue.c
--- linux-libre-4.9.3-gnu/net/ipv4/ip_sockglue.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/net/ipv4/ip_sockglue.c	2017-01-15 07:43:07.000000000 -0500
@@ -137,7 +137,7 @@ static void ip_cmsg_recv_dstaddr(struct
 	const struct iphdr *iph = ip_hdr(skb);
 	__be16 *ports = (__be16 *)skb_transport_header(skb);
 
-	if (skb_transport_offset(skb) + 4 > skb->len)
+	if (skb_transport_offset(skb) + 4 > (int)skb->len)
 		return;
 
 	/* All current transport protocols have the port numbers in the
@@ -1202,8 +1202,14 @@ void ipv4_pktinfo_prepare(const struct s
 		 * which has interface index (iif) as the first member of the
 		 * underlying inet{6}_skb_parm struct. This code then overlays
 		 * PKTINFO_SKB_CB and in_pktinfo also has iif as the first
-		 * element so the iif is picked up from the prior IPCB
+		 * element so the iif is picked up from the prior IPCB. If iif
+		 * is the loopback interface, then return the sending interface
+		 * (e.g., process binds socket to eth0 for Tx which is
+		 * redirected to loopback in the rtable/dst).
 		 */
+		if (pktinfo->ipi_ifindex == LOOPBACK_IFINDEX)
+			pktinfo->ipi_ifindex = inet_iif(skb);
+
 		pktinfo->ipi_spec_dst.s_addr = fib_compute_spec_dst(skb);
 	} else {
 		pktinfo->ipi_ifindex = 0;
diff -druNp --no-dereference linux-libre-4.9.3-gnu/net/ipv4/route.c linux-libre-4.9.4-gnu/net/ipv4/route.c
--- linux-libre-4.9.3-gnu/net/ipv4/route.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/net/ipv4/route.c	2017-01-15 07:43:07.000000000 -0500
@@ -1902,7 +1902,8 @@ local_input:
 		}
 	}
 
-	rth = rt_dst_alloc(net->loopback_dev, flags | RTCF_LOCAL, res.type,
+	rth = rt_dst_alloc(l3mdev_master_dev_rcu(dev) ? : net->loopback_dev,
+			   flags | RTCF_LOCAL, res.type,
 			   IN_DEV_CONF_GET(in_dev, NOPOLICY), false, do_cache);
 	if (!rth)
 		goto e_nobufs;
diff -druNp --no-dereference linux-libre-4.9.3-gnu/net/ipv6/datagram.c linux-libre-4.9.4-gnu/net/ipv6/datagram.c
--- linux-libre-4.9.3-gnu/net/ipv6/datagram.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/net/ipv6/datagram.c	2017-01-15 07:43:07.000000000 -0500
@@ -700,7 +700,7 @@ void ip6_datagram_recv_specific_ctl(stru
 		struct sockaddr_in6 sin6;
 		__be16 *ports = (__be16 *) skb_transport_header(skb);
 
-		if (skb_transport_offset(skb) + 4 <= skb->len) {
+		if (skb_transport_offset(skb) + 4 <= (int)skb->len) {
 			/* All current transport protocols have the port numbers in the
 			 * first four bytes of the transport header and this function is
 			 * written with this assumption in mind.
diff -druNp --no-dereference linux-libre-4.9.3-gnu/net/ipv6/ip6_offload.c linux-libre-4.9.4-gnu/net/ipv6/ip6_offload.c
--- linux-libre-4.9.3-gnu/net/ipv6/ip6_offload.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/net/ipv6/ip6_offload.c	2017-01-15 07:43:07.000000000 -0500
@@ -191,6 +191,7 @@ static struct sk_buff **ipv6_gro_receive
 	ops = rcu_dereference(inet6_offloads[proto]);
 	if (!ops || !ops->callbacks.gro_receive) {
 		__pskb_pull(skb, skb_gro_offset(skb));
+		skb_gro_frag0_invalidate(skb);
 		proto = ipv6_gso_pull_exthdrs(skb, proto);
 		skb_gro_pull(skb, -skb_transport_offset(skb));
 		skb_reset_transport_header(skb);
diff -druNp --no-dereference linux-libre-4.9.3-gnu/net/ipv6/raw.c linux-libre-4.9.4-gnu/net/ipv6/raw.c
--- linux-libre-4.9.3-gnu/net/ipv6/raw.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/net/ipv6/raw.c	2017-01-15 07:43:07.000000000 -0500
@@ -589,7 +589,11 @@ static int rawv6_push_pending_frames(str
 	}
 
 	offset += skb_transport_offset(skb);
-	BUG_ON(skb_copy_bits(skb, offset, &csum, 2));
+	err = skb_copy_bits(skb, offset, &csum, 2);
+	if (err < 0) {
+		ip6_flush_pending_frames(sk);
+		goto out;
+	}
 
 	/* in case cksum was not initialized */
 	if (unlikely(csum))
diff -druNp --no-dereference linux-libre-4.9.3-gnu/net/sched/cls_api.c linux-libre-4.9.4-gnu/net/sched/cls_api.c
--- linux-libre-4.9.3-gnu/net/sched/cls_api.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/net/sched/cls_api.c	2017-01-15 07:43:07.000000000 -0500
@@ -148,13 +148,15 @@ static int tc_ctl_tfilter(struct sk_buff
 	unsigned long cl;
 	unsigned long fh;
 	int err;
-	int tp_created = 0;
+	int tp_created;
 
 	if ((n->nlmsg_type != RTM_GETTFILTER) &&
 	    !netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN))
 		return -EPERM;
 
 replay:
+	tp_created = 0;
+
 	err = nlmsg_parse(n, sizeof(*t), tca, TCA_MAX, NULL);
 	if (err < 0)
 		return err;
diff -druNp --no-dereference linux-libre-4.9.3-gnu/net/sched/cls_flower.c linux-libre-4.9.4-gnu/net/sched/cls_flower.c
--- linux-libre-4.9.3-gnu/net/sched/cls_flower.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/net/sched/cls_flower.c	2017-01-15 07:43:07.000000000 -0500
@@ -149,10 +149,14 @@ static int fl_classify(struct sk_buff *s
 
 		switch (ip_tunnel_info_af(info)) {
 		case AF_INET:
+			skb_key.enc_control.addr_type =
+				FLOW_DISSECTOR_KEY_IPV4_ADDRS;
 			skb_key.enc_ipv4.src = key->u.ipv4.src;
 			skb_key.enc_ipv4.dst = key->u.ipv4.dst;
 			break;
 		case AF_INET6:
+			skb_key.enc_control.addr_type =
+				FLOW_DISSECTOR_KEY_IPV6_ADDRS;
 			skb_key.enc_ipv6.src = key->u.ipv6.src;
 			skb_key.enc_ipv6.dst = key->u.ipv6.dst;
 			break;
diff -druNp --no-dereference linux-libre-4.9.3-gnu/net/sctp/socket.c linux-libre-4.9.4-gnu/net/sctp/socket.c
--- linux-libre-4.9.3-gnu/net/sctp/socket.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/net/sctp/socket.c	2017-01-15 07:43:07.000000000 -0500
@@ -4479,9 +4479,10 @@ int sctp_transport_lookup_process(int (*
 
 	rcu_read_lock();
 	transport = sctp_addrs_lookup_transport(net, laddr, paddr);
-	if (!transport || !sctp_transport_hold(transport))
+	if (!transport || !sctp_transport_hold(transport)) {
+		rcu_read_unlock();
 		goto out;
-
+	}
 	rcu_read_unlock();
 	err = cb(transport, p);
 	sctp_transport_put(transport);
diff -druNp --no-dereference linux-libre-4.9.3-gnu/net/sunrpc/xprtrdma/svc_rdma_backchannel.c linux-libre-4.9.4-gnu/net/sunrpc/xprtrdma/svc_rdma_backchannel.c
--- linux-libre-4.9.3-gnu/net/sunrpc/xprtrdma/svc_rdma_backchannel.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/net/sunrpc/xprtrdma/svc_rdma_backchannel.c	2017-01-15 07:43:07.000000000 -0500
@@ -359,6 +359,7 @@ xprt_setup_rdma_bc(struct xprt_create *a
 out_fail:
 	xprt_rdma_free_addresses(xprt);
 	args->bc_xprt->xpt_bc_xprt = NULL;
+	args->bc_xprt->xpt_bc_xps = NULL;
 	xprt_put(xprt);
 	xprt_free(xprt);
 	return ERR_PTR(-EINVAL);
diff -druNp --no-dereference linux-libre-4.9.3-gnu/sound/firewire/tascam/tascam-stream.c linux-libre-4.9.4-gnu/sound/firewire/tascam/tascam-stream.c
--- linux-libre-4.9.3-gnu/sound/firewire/tascam/tascam-stream.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/sound/firewire/tascam/tascam-stream.c	2017-01-15 07:43:07.000000000 -0500
@@ -343,7 +343,7 @@ int snd_tscm_stream_init_duplex(struct s
 	if (err < 0)
 		amdtp_stream_destroy(&tscm->rx_stream);
 
-	return 0;
+	return err;
 }
 
 /* At bus reset, streaming is stopped and some registers are clear. */
diff -druNp --no-dereference linux-libre-4.9.3-gnu/sound/usb/quirks.c linux-libre-4.9.4-gnu/sound/usb/quirks.c
--- linux-libre-4.9.3-gnu/sound/usb/quirks.c	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/sound/usb/quirks.c	2017-01-15 07:43:07.000000000 -0500
@@ -1135,6 +1135,7 @@ bool snd_usb_get_sample_rate_quirk(struc
 	case USB_ID(0x045E, 0x076F): /* MS Lifecam HD-6000 */
 	case USB_ID(0x045E, 0x0772): /* MS Lifecam Studio */
 	case USB_ID(0x045E, 0x0779): /* MS Lifecam HD-3000 */
+	case USB_ID(0x047F, 0x02F7): /* Plantronics BT-600 */
 	case USB_ID(0x047F, 0x0415): /* Plantronics BT-300 */
 	case USB_ID(0x047F, 0xAA05): /* Plantronics DA45 */
 	case USB_ID(0x04D8, 0xFEEA): /* Benchmark DAC1 Pre */
diff -druNp --no-dereference linux-libre-4.9.3-gnu/tools/virtio/linux/compiler.h linux-libre-4.9.4-gnu/tools/virtio/linux/compiler.h
--- linux-libre-4.9.3-gnu/tools/virtio/linux/compiler.h	2017-01-12 05:41:42.000000000 -0500
+++ linux-libre-4.9.4-gnu/tools/virtio/linux/compiler.h	2017-01-15 07:43:07.000000000 -0500
@@ -4,6 +4,6 @@
 #define WRITE_ONCE(var, val) \
 	(*((volatile typeof(val) *)(&(var))) = (val))
 
-#define READ_ONCE(var) (*((volatile typeof(val) *)(&(var))))
+#define READ_ONCE(var) (*((volatile typeof(var) *)(&(var))))
 
 #endif
