commit: 955ea98ae8f0a8ab351b6f0fcc453cc22925f4e2 Author: Mike Pagano <mpagano <AT> gentoo <DOT> org> AuthorDate: Sun Jan 15 22:58:57 2017 +0000 Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org> CommitDate: Sun Jan 15 22:58:57 2017 +0000 URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=955ea98a
Linux patch 4.9.4 0000_README | 4 + 1003_linux-4.9.4.patch | 1748 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1752 insertions(+) diff --git a/0000_README b/0000_README index 2657c73..ffd4b57 100644 --- a/0000_README +++ b/0000_README @@ -55,6 +55,10 @@ Patch: 1002_linux-4.9.3.patch From: http://www.kernel.org Desc: Linux 4.9.3 +Patch: 1003_linux-4.9.4.patch +From: http://www.kernel.org +Desc: Linux 4.9.4 + Patch: 1500_XATTR_USER_PREFIX.patch From: https://bugs.gentoo.org/show_bug.cgi?id=470644 Desc: Support for namespace user.pax.* on tmpfs. diff --git a/1003_linux-4.9.4.patch b/1003_linux-4.9.4.patch new file mode 100644 index 0000000..039dc5a --- /dev/null +++ b/1003_linux-4.9.4.patch @@ -0,0 +1,1748 @@ +diff --git a/Makefile b/Makefile +index ae42a0aaab06..9175706bfe7f 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 4 + PATCHLEVEL = 9 +-SUBLEVEL = 3 ++SUBLEVEL = 4 + EXTRAVERSION = + NAME = Roaring Lionus + +diff --git a/arch/arm/configs/qcom_defconfig b/arch/arm/configs/qcom_defconfig +index c2dff4fd5fc4..9f6d2a69a6f7 100644 +--- a/arch/arm/configs/qcom_defconfig ++++ b/arch/arm/configs/qcom_defconfig +@@ -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 --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile +index 5b37ec29996e..e37ceb81a379 100644 +--- a/arch/arm/mach-omap2/Makefile ++++ b/arch/arm/mach-omap2/Makefile +@@ -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 --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c +index bab814d2f37d..60f5e838a3bc 100644 +--- a/arch/arm/mach-omap2/board-generic.c ++++ b/arch/arm/mach-omap2/board-generic.c +@@ -306,7 +306,7 @@ DT_MACHINE_START(AM43_DT, "Generic AM43 (Flattened Device Tree)") + .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 --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h +index deed42e1dd9c..6dcca2957e23 100644 +--- a/arch/arm/mach-omap2/common.h ++++ b/arch/arm/mach-omap2/common.h +@@ -262,8 +262,6 @@ extern void __iomem *omap4_get_sar_ram_base(void); + 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 cpu); + 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 --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c +index 0e9acdd95d70..f0da5259762a 100644 +--- a/arch/arm/mach-omap2/io.c ++++ b/arch/arm/mach-omap2/io.c +@@ -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 --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c +index ad982465efd0..7d62ad48c7c9 100644 +--- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c ++++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c +@@ -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 cpu, unsigned int power_state) + 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 --git a/arch/arm/mach-omap2/omap4-sar-layout.h b/arch/arm/mach-omap2/omap4-sar-layout.h +index 792b1069f724..5b2966a0f733 100644 +--- a/arch/arm/mach-omap2/omap4-sar-layout.h ++++ b/arch/arm/mach-omap2/omap4-sar-layout.h +@@ -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 --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c +index 5e2e2218a402..b2f2448bfa6d 100644 +--- a/arch/arm/mach-omap2/timer.c ++++ b/arch/arm/mach-omap2/timer.c +@@ -510,18 +510,19 @@ void __init omap3_secure_sync32k_timer_init(void) + } + #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 --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c +index 12b94357fbc1..c725baf119e1 100644 +--- a/arch/arm/mach-pxa/pxa25x.c ++++ b/arch/arm/mach-pxa/pxa25x.c +@@ -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 --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c +index d12002cd63bc..ed118648313f 100644 +--- a/arch/arm/mach-zynq/common.c ++++ b/arch/arm/mach-zynq/common.c +@@ -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 --git a/arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-b.dts b/arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-b.dts +index 7841b724e340..4617759670da 100644 +--- a/arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-b.dts ++++ b/arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-b.dts +@@ -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 --git a/arch/arm64/boot/dts/broadcom/bcm2837.dtsi b/arch/arm64/boot/dts/broadcom/bcm2837.dtsi +index 8216bbb29fe0..c1f719b7097a 100644 +--- a/arch/arm64/boot/dts/broadcom/bcm2837.dtsi ++++ b/arch/arm64/boot/dts/broadcom/bcm2837.dtsi +@@ -1,7 +1,7 @@ + #include "bcm283x.dtsi" + + / { +- compatible = "brcm,bcm2836"; ++ compatible = "brcm,bcm2837"; + + soc { + ranges = <0x7e000000 0x3f000000 0x1000000>, +diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi +index 1c71e256601d..6c03c1702bb3 100644 +--- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi +@@ -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 --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S +index 93cf7a5846a6..030d72df5dd5 100644 +--- a/arch/powerpc/kernel/misc_32.S ++++ b/arch/powerpc/kernel/misc_32.S +@@ -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 --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c +index fe04a04dab8e..15f743615923 100644 +--- a/arch/x86/net/bpf_jit_comp.c ++++ b/arch/x86/net/bpf_jit_comp.c +@@ -1172,6 +1172,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) + set_memory_ro((unsigned long)header, header->pages); + prog->bpf_func = (void *)image; + prog->jited = 1; ++ } else { ++ prog = orig_prog; + } + + out_addrs: +diff --git a/drivers/bus/arm-ccn.c b/drivers/bus/arm-ccn.c +index d1074d9b38ba..aee83462b796 100644 +--- a/drivers/bus/arm-ccn.c ++++ b/drivers/bus/arm-ccn.c +@@ -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 --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c +index 97ae60fa1584..bb8a77a5985f 100644 +--- a/drivers/clk/clkdev.c ++++ b/drivers/clk/clkdev.c +@@ -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 --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h +index 685e9e065287..da832d3cdca7 100644 +--- a/drivers/gpu/drm/i915/i915_drv.h ++++ b/drivers/gpu/drm/i915/i915_drv.h +@@ -3684,6 +3684,8 @@ extern void intel_display_print_error_state(struct drm_i915_error_state_buf *e, + + 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 --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c +index 71441c329603..c9e83f39ec0a 100644 +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -6262,36 +6262,25 @@ skl_dpll0_disable(struct drm_i915_private *dev_priv) + 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 --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c +index 103cefdb9ddd..985cb31f4b44 100644 +--- a/drivers/gpu/drm/i915/intel_pm.c ++++ b/drivers/gpu/drm/i915/intel_pm.c +@@ -7955,6 +7955,81 @@ int sandybridge_pcode_write(struct drm_i915_private *dev_priv, + 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 --git a/drivers/hid/hid-cypress.c b/drivers/hid/hid-cypress.c +index 1b764d1745f3..1689568b597d 100644 +--- a/drivers/hid/hid-cypress.c ++++ b/drivers/hid/hid-cypress.c +@@ -39,6 +39,9 @@ static __u8 *cp_report_fixup(struct hid_device *hdev, __u8 *rdesc, + 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 --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c +index 9ec33b51a0ed..2ce7ae97ac91 100644 +--- a/drivers/net/dsa/bcm_sf2.c ++++ b/drivers/net/dsa/bcm_sf2.c +@@ -393,7 +393,7 @@ static int bcm_sf2_sw_mdio_read(struct mii_bus *bus, int addr, int regnum) + 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 mii_bus *bus, int addr, int regnum, + 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 platform_device *pdev) + 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 platform_device *pdev) + 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 platform_device *pdev) + 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 --git a/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c +index d17c24227900..90e81ae9f3bc 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c +@@ -247,6 +247,7 @@ static int set_flow_attrs(u32 *match_c, u32 *match_v, + } + 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 --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +index 246d98ebb588..5dc3e2453ff5 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -3773,14 +3773,7 @@ static void mlx5e_nic_enable(struct mlx5e_priv *priv) + + 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 mlx5e_priv *priv) + 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_core_dev *mdev, struct net_device *netdev) + 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_core_dev *mdev, struct net_device *netdev) + 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 --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c +index 1fffe48a93cc..cbfac06b7ffd 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c +@@ -109,7 +109,6 @@ static bool mlx5e_am_on_top(struct mlx5e_rx_am *am) + 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_rx_am *am) + 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_am *am) + 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 mlx5e_rx_am_sample *start, + 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 --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +index be1f7333ab7f..c7011ef4e351 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +@@ -1703,7 +1703,7 @@ int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw, + + 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 --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c +index ada24e103b02..92bd13ddc39d 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c +@@ -468,6 +468,13 @@ static int handle_hca_cap(struct mlx5_core_dev *dev) + 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(struct mlx5_core_dev *mdev, int i) + 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(struct mlx5_core_dev *mdev, int i) + 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_core_dev *dev, struct mlx5_priv *priv, + { + 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_detected(struct pci_dev *pdev, + + 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 --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +index caf069a465f2..b2893fbe25e5 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -3349,12 +3349,6 @@ int stmmac_dvr_probe(struct device *device, + 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 *device, + 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 --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c +index efb84f092492..4b5cb162442b 100644 +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -3576,39 +3576,87 @@ static bool delay_autosuspend(struct r8152 *tp) + 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 --git a/drivers/net/vrf.c b/drivers/net/vrf.c +index 820de6a9ddde..95cf1d844781 100644 +--- a/drivers/net/vrf.c ++++ b/drivers/net/vrf.c +@@ -263,7 +263,9 @@ static netdev_tx_t vrf_process_v4_outbound(struct sk_buff *skb, + .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 *net, struct sock *sk, + 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 *net, struct sock *sk, struct sk_buff *s + 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 pf, unsigned int hook, + { + 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(struct net_device *vrf_dev, + */ + 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 net_device *vrf_dev, + 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_net, struct net_device *dev, + 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 --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c +index 264466f59c57..4ac928bf1f8e 100644 +--- a/drivers/net/wireless/realtek/rtlwifi/base.c ++++ b/drivers/net/wireless/realtek/rtlwifi/base.c +@@ -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_hw *hw, struct sk_buff *skb, u8 is_tx, + + 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 --git a/drivers/net/wireless/realtek/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c +index 8e7f23c11680..4da4e458142c 100644 +--- a/drivers/net/wireless/realtek/rtlwifi/core.c ++++ b/drivers/net/wireless/realtek/rtlwifi/core.c +@@ -1150,10 +1150,8 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, + } 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 ieee80211_hw *hw, + } + + 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 --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c +index 0dfa9eac3926..5be4fc96002d 100644 +--- a/drivers/net/wireless/realtek/rtlwifi/pci.c ++++ b/drivers/net/wireless/realtek/rtlwifi/pci.c +@@ -663,11 +663,9 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio) + } + + 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 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) + } + 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 --git a/drivers/net/wireless/realtek/rtlwifi/ps.c b/drivers/net/wireless/realtek/rtlwifi/ps.c +index 18d979affc18..d0ffc4d508cf 100644 +--- a/drivers/net/wireless/realtek/rtlwifi/ps.c ++++ b/drivers/net/wireless/realtek/rtlwifi/ps.c +@@ -407,8 +407,8 @@ void rtl_lps_set_psmode(struct ieee80211_hw *hw, u8 rt_psmode) + } + } + +-/*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 *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 *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 work_struct *work) + 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 --git a/drivers/net/wireless/realtek/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c +index 32aa5c1d070a..3837bbdecf05 100644 +--- a/drivers/net/wireless/realtek/rtlwifi/usb.c ++++ b/drivers/net/wireless/realtek/rtlwifi/usb.c +@@ -1067,6 +1067,7 @@ int rtl_usb_probe(struct usb_interface *intf, + 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 --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c +index ded37025b445..6b001c4a5640 100644 +--- a/drivers/spi/spi-orion.c ++++ b/drivers/spi/spi-orion.c +@@ -138,37 +138,62 @@ static int orion_spi_baudrate_set(struct spi_device *spi, unsigned int speed) + 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; +- +- best_err = speed; +- best_spr = 0; +- best_sppr = 0; +- +- /* Iterate over the valid range looking for best fit */ +- for (sppr = 0; sppr < 8; sppr++) { +- sppr2 = 0x1 << sppr; +- +- spr = tclk_hz / sppr2; +- spr = DIV_ROUND_UP(spr, speed); +- if ((spr == 0) || (spr > 15)) +- continue; +- +- clk = tclk_hz / (spr * sppr2); +- err = speed - clk; +- +- if (err < best_err) { +- best_spr = spr; +- best_sppr = sppr; +- best_err = 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. ++ */ + +- if ((best_sppr == 0) && (best_spr == 0)) +- return -EINVAL; ++ /* best integer divider: */ ++ unsigned divider = DIV_ROUND_UP(tclk_hz, speed); ++ unsigned spr, sppr; ++ ++ if (divider < 16) { ++ /* This is the easy case, divider is less than 16 */ ++ spr = divider; ++ sppr = 0; ++ ++ } 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; ++ ++ /* ++ * 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; ++ ++ /* ++ * 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; ++ ++ /* ++ * 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 --git a/include/linux/netdevice.h b/include/linux/netdevice.h +index e16a2a980ea8..d83590ef74a1 100644 +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -2502,14 +2502,19 @@ static inline int skb_gro_header_hard(struct sk_buff *skb, unsigned int hlen) + 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 --git a/net/core/dev.c b/net/core/dev.c +index 6666b28b6815..e1d731fdc72c 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -4453,7 +4453,9 @@ static void skb_gro_reset_offset(struct sk_buff *skb) + 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 --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c +index 72cfb0c61125..ca2c9c8b9a3e 100644 +--- a/net/core/drop_monitor.c ++++ b/net/core/drop_monitor.c +@@ -80,6 +80,7 @@ static struct sk_buff *reset_per_cpu_data(struct per_cpu_dm_data *data) + 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_data(struct per_cpu_dm_data *data) + + 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 --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c +index c6d8207ffa7e..32e4e0158846 100644 +--- a/net/core/flow_dissector.c ++++ b/net/core/flow_dissector.c +@@ -445,8 +445,9 @@ bool __skb_flow_dissect(const struct sk_buff *skb, + 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 --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c +index a6196cf844f6..b7f9ae7b1c5f 100644 +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -3886,6 +3886,9 @@ static int rtnl_stats_get(struct sk_buff *skb, struct nlmsghdr *nlh) + 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_buff *skb, struct netlink_callback *cb) + + 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 --git a/net/core/sock.c b/net/core/sock.c +index 00a074dbfe9b..bc6543f7de36 100644 +--- a/net/core/sock.c ++++ b/net/core/sock.c +@@ -222,7 +222,7 @@ static const char *const af_family_key_strings[AF_MAX+1] = { + "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_key_strings[AF_MAX+1] = { + "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_key_strings[AF_MAX+1] = { + "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 --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c +index 5fff951a0a49..da3862124545 100644 +--- a/net/dsa/dsa2.c ++++ b/net/dsa/dsa2.c +@@ -394,9 +394,11 @@ static int dsa_dst_apply(struct dsa_switch_tree *dst) + 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_switch_tree *dst) + 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 --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c +index 161fc0f0d752..3e4f183fc241 100644 +--- a/net/ipv4/fib_frontend.c ++++ b/net/ipv4/fib_frontend.c +@@ -85,7 +85,7 @@ struct fib_table *fib_new_table(struct net *net, u32 id) + 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 --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c +index 388d3e21629b..a8508b79b406 100644 +--- a/net/ipv4/fib_semantics.c ++++ b/net/ipv4/fib_semantics.c +@@ -1617,8 +1617,13 @@ void fib_select_multipath(struct fib_result *res, int hash) + 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, struct fib_result *res, + #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 --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c +index 15db786d50ed..32a08bc010bf 100644 +--- a/net/ipv4/igmp.c ++++ b/net/ipv4/igmp.c +@@ -219,9 +219,14 @@ static void igmp_start_timer(struct ip_mc_list *im, int max_delay) + 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 --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c +index b8a2d63d1fb8..f226f4086e05 100644 +--- a/net/ipv4/ip_sockglue.c ++++ b/net/ipv4/ip_sockglue.c +@@ -137,7 +137,7 @@ static void ip_cmsg_recv_dstaddr(struct msghdr *msg, struct sk_buff *skb) + 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 sock *sk, struct sk_buff *skb) + * 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 --git a/net/ipv4/route.c b/net/ipv4/route.c +index 2a57566e6e91..8197b06d9aaa 100644 +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -1902,7 +1902,8 @@ out: return err; + } + } + +- 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 --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c +index ccf40550c475..8616d17cf08f 100644 +--- a/net/ipv6/datagram.c ++++ b/net/ipv6/datagram.c +@@ -700,7 +700,7 @@ void ip6_datagram_recv_specific_ctl(struct sock *sk, struct msghdr *msg, + 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 --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c +index 89c59e656f44..fc7b4017ba24 100644 +--- a/net/ipv6/ip6_offload.c ++++ b/net/ipv6/ip6_offload.c +@@ -191,6 +191,7 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, + 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 --git a/net/ipv6/raw.c b/net/ipv6/raw.c +index 054a1d84fc5e..869ffc76befa 100644 +--- a/net/ipv6/raw.c ++++ b/net/ipv6/raw.c +@@ -589,7 +589,11 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, + } + + 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 --git a/net/sched/cls_api.c b/net/sched/cls_api.c +index b05d4a2155b0..c1a4b5d30814 100644 +--- a/net/sched/cls_api.c ++++ b/net/sched/cls_api.c +@@ -148,13 +148,15 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n) + 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 --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c +index 904442421db3..eee299bb6bcf 100644 +--- a/net/sched/cls_flower.c ++++ b/net/sched/cls_flower.c +@@ -149,10 +149,14 @@ static int fl_classify(struct sk_buff *skb, const struct tcf_proto *tp, + + 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 --git a/net/sctp/socket.c b/net/sctp/socket.c +index f23ad913dc7a..ca12aa346c0d 100644 +--- a/net/sctp/socket.c ++++ b/net/sctp/socket.c +@@ -4479,9 +4479,10 @@ int sctp_transport_lookup_process(int (*cb)(struct sctp_transport *, void *), + + 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 --git a/net/sunrpc/xprtrdma/svc_rdma_backchannel.c b/net/sunrpc/xprtrdma/svc_rdma_backchannel.c +index 20027f8de129..6035c5a380a6 100644 +--- a/net/sunrpc/xprtrdma/svc_rdma_backchannel.c ++++ b/net/sunrpc/xprtrdma/svc_rdma_backchannel.c +@@ -359,6 +359,7 @@ xprt_setup_rdma_bc(struct xprt_create *args) + 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 --git a/sound/firewire/tascam/tascam-stream.c b/sound/firewire/tascam/tascam-stream.c +index 4ad3bd7fd445..f1657a4e0621 100644 +--- a/sound/firewire/tascam/tascam-stream.c ++++ b/sound/firewire/tascam/tascam-stream.c +@@ -343,7 +343,7 @@ int snd_tscm_stream_init_duplex(struct snd_tscm *tscm) + 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 --git a/sound/usb/quirks.c b/sound/usb/quirks.c +index 2782155ae3ce..93bb14e7e0f7 100644 +--- a/sound/usb/quirks.c ++++ b/sound/usb/quirks.c +@@ -1135,6 +1135,7 @@ bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip) + 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 --git a/tools/virtio/linux/compiler.h b/tools/virtio/linux/compiler.h +index 845960e1cbf2..c9ccfd42ec13 100644 +--- a/tools/virtio/linux/compiler.h ++++ b/tools/virtio/linux/compiler.h +@@ -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
