From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id E7401138334 for ; Sun, 22 Jul 2018 15:13:43 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id B4617E0828; Sun, 22 Jul 2018 15:13:41 +0000 (UTC) Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id 5BE31E0828 for ; Sun, 22 Jul 2018 15:13:41 +0000 (UTC) Received: from oystercatcher.gentoo.org (oystercatcher.gentoo.org [148.251.78.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id B75D4335D5F for ; Sun, 22 Jul 2018 15:13:39 +0000 (UTC) Received: from localhost.localdomain (localhost [IPv6:::1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id 0DC0236B for ; Sun, 22 Jul 2018 15:13:38 +0000 (UTC) From: "Mike Pagano" To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Mike Pagano" Message-ID: <1532272407.65f99f63c5af7d1bcb8ae58f3a40c1da65ac0a33.mpagano@gentoo> Subject: [gentoo-commits] proj/linux-patches:4.14 commit in: / X-VCS-Repository: proj/linux-patches X-VCS-Files: 0000_README 1056_linux-4.14.57.patch X-VCS-Directories: / X-VCS-Committer: mpagano X-VCS-Committer-Name: Mike Pagano X-VCS-Revision: 65f99f63c5af7d1bcb8ae58f3a40c1da65ac0a33 X-VCS-Branch: 4.14 Date: Sun, 22 Jul 2018 15:13:38 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org X-Archives-Salt: b9b04f13-7eea-4591-9170-8ef3fc85bea4 X-Archives-Hash: 3102f10a8e02d83dc6bb40d2b07249f9 commit: 65f99f63c5af7d1bcb8ae58f3a40c1da65ac0a33 Author: Mike Pagano gentoo org> AuthorDate: Sun Jul 22 15:13:27 2018 +0000 Commit: Mike Pagano gentoo org> CommitDate: Sun Jul 22 15:13:27 2018 +0000 URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=65f99f63 Linux patch 4.14.57 0000_README | 4 + 1056_linux-4.14.57.patch | 4952 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 4956 insertions(+) diff --git a/0000_README b/0000_README index 08bc278..d3e06d1 100644 --- a/0000_README +++ b/0000_README @@ -267,6 +267,10 @@ Patch: 1055_linux-4.14.56.patch From: http://www.kernel.org Desc: Linux 4.14.56 +Patch: 1056_linux-4.14.57.patch +From: http://www.kernel.org +Desc: Linux 4.14.57 + 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/1056_linux-4.14.57.patch b/1056_linux-4.14.57.patch new file mode 100644 index 0000000..9d401de --- /dev/null +++ b/1056_linux-4.14.57.patch @@ -0,0 +1,4952 @@ +diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt +index 0380a45ecf4b..d6d7669e667f 100644 +--- a/Documentation/admin-guide/kernel-parameters.txt ++++ b/Documentation/admin-guide/kernel-parameters.txt +@@ -3997,6 +3997,23 @@ + expediting. Set to zero to disable automatic + expediting. + ++ ssbd= [ARM64,HW] ++ Speculative Store Bypass Disable control ++ ++ On CPUs that are vulnerable to the Speculative ++ Store Bypass vulnerability and offer a ++ firmware based mitigation, this parameter ++ indicates how the mitigation should be used: ++ ++ force-on: Unconditionally enable mitigation for ++ for both kernel and userspace ++ force-off: Unconditionally disable mitigation for ++ for both kernel and userspace ++ kernel: Always enable mitigation in the ++ kernel, and offer a prctl interface ++ to allow userspace to register its ++ interest in being mitigated too. ++ + stack_guard_gap= [MM] + override the default stack gap protection. The value + is in page units and it defines how many pages prior +diff --git a/Makefile b/Makefile +index acbb0e3d29c9..a44d6b2adb76 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 4 + PATCHLEVEL = 14 +-SUBLEVEL = 56 ++SUBLEVEL = 57 + EXTRAVERSION = + NAME = Petit Gorille + +diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h +index 8f973e3b7348..65572e14306c 100644 +--- a/arch/arm/include/asm/kvm_host.h ++++ b/arch/arm/include/asm/kvm_host.h +@@ -302,4 +302,16 @@ static inline bool kvm_arm_harden_branch_predictor(void) + return false; + } + ++#define KVM_SSBD_UNKNOWN -1 ++#define KVM_SSBD_FORCE_DISABLE 0 ++#define KVM_SSBD_KERNEL 1 ++#define KVM_SSBD_FORCE_ENABLE 2 ++#define KVM_SSBD_MITIGATED 3 ++ ++static inline int kvm_arm_have_ssbd(void) ++{ ++ /* No way to detect it yet, pretend it is not there. */ ++ return KVM_SSBD_UNKNOWN; ++} ++ + #endif /* __ARM_KVM_HOST_H__ */ +diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h +index 08cd720eae01..8a098e65f5f8 100644 +--- a/arch/arm/include/asm/kvm_mmu.h ++++ b/arch/arm/include/asm/kvm_mmu.h +@@ -28,6 +28,13 @@ + */ + #define kern_hyp_va(kva) (kva) + ++/* Contrary to arm64, there is no need to generate a PC-relative address */ ++#define hyp_symbol_addr(s) \ ++ ({ \ ++ typeof(s) *addr = &(s); \ ++ addr; \ ++ }) ++ + /* + * KVM_MMU_CACHE_MIN_PAGES is the number of stage2 page table translation levels. + */ +@@ -247,6 +254,11 @@ static inline int kvm_map_vectors(void) + return 0; + } + ++static inline int hyp_map_aux_data(void) ++{ ++ return 0; ++} ++ + #endif /* !__ASSEMBLY__ */ + + #endif /* __ARM_KVM_MMU_H__ */ +diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig +index 2d5f7aca156d..1bbb89d37f57 100644 +--- a/arch/arm64/Kconfig ++++ b/arch/arm64/Kconfig +@@ -849,6 +849,15 @@ config HARDEN_BRANCH_PREDICTOR + + If unsure, say Y. + ++config ARM64_SSBD ++ bool "Speculative Store Bypass Disable" if EXPERT ++ default y ++ help ++ This enables mitigation of the bypassing of previous stores ++ by speculative loads. ++ ++ If unsure, say Y. ++ + menuconfig ARMV8_DEPRECATED + bool "Emulate deprecated/obsolete ARMv8 instructions" + depends on COMPAT +diff --git a/arch/arm64/include/asm/alternative.h b/arch/arm64/include/asm/alternative.h +index 4a85c6952a22..a91933b1e2e6 100644 +--- a/arch/arm64/include/asm/alternative.h ++++ b/arch/arm64/include/asm/alternative.h +@@ -5,6 +5,8 @@ + #include + #include + ++#define ARM64_CB_PATCH ARM64_NCAPS ++ + #ifndef __ASSEMBLY__ + + #include +@@ -12,6 +14,8 @@ + #include + #include + ++extern int alternatives_applied; ++ + struct alt_instr { + s32 orig_offset; /* offset to original instruction */ + s32 alt_offset; /* offset to replacement instruction */ +@@ -20,12 +24,19 @@ struct alt_instr { + u8 alt_len; /* size of new instruction(s), <= orig_len */ + }; + ++typedef void (*alternative_cb_t)(struct alt_instr *alt, ++ __le32 *origptr, __le32 *updptr, int nr_inst); ++ + void __init apply_alternatives_all(void); + void apply_alternatives(void *start, size_t length); + +-#define ALTINSTR_ENTRY(feature) \ ++#define ALTINSTR_ENTRY(feature,cb) \ + " .word 661b - .\n" /* label */ \ ++ " .if " __stringify(cb) " == 0\n" \ + " .word 663f - .\n" /* new instruction */ \ ++ " .else\n" \ ++ " .word " __stringify(cb) "- .\n" /* callback */ \ ++ " .endif\n" \ + " .hword " __stringify(feature) "\n" /* feature bit */ \ + " .byte 662b-661b\n" /* source len */ \ + " .byte 664f-663f\n" /* replacement len */ +@@ -43,15 +54,18 @@ void apply_alternatives(void *start, size_t length); + * but most assemblers die if insn1 or insn2 have a .inst. This should + * be fixed in a binutils release posterior to 2.25.51.0.2 (anything + * containing commit 4e4d08cf7399b606 or c1baaddf8861). ++ * ++ * Alternatives with callbacks do not generate replacement instructions. + */ +-#define __ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg_enabled) \ ++#define __ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg_enabled, cb) \ + ".if "__stringify(cfg_enabled)" == 1\n" \ + "661:\n\t" \ + oldinstr "\n" \ + "662:\n" \ + ".pushsection .altinstructions,\"a\"\n" \ +- ALTINSTR_ENTRY(feature) \ ++ ALTINSTR_ENTRY(feature,cb) \ + ".popsection\n" \ ++ " .if " __stringify(cb) " == 0\n" \ + ".pushsection .altinstr_replacement, \"a\"\n" \ + "663:\n\t" \ + newinstr "\n" \ +@@ -59,11 +73,17 @@ void apply_alternatives(void *start, size_t length); + ".popsection\n\t" \ + ".org . - (664b-663b) + (662b-661b)\n\t" \ + ".org . - (662b-661b) + (664b-663b)\n" \ ++ ".else\n\t" \ ++ "663:\n\t" \ ++ "664:\n\t" \ ++ ".endif\n" \ + ".endif\n" + + #define _ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg, ...) \ +- __ALTERNATIVE_CFG(oldinstr, newinstr, feature, IS_ENABLED(cfg)) ++ __ALTERNATIVE_CFG(oldinstr, newinstr, feature, IS_ENABLED(cfg), 0) + ++#define ALTERNATIVE_CB(oldinstr, cb) \ ++ __ALTERNATIVE_CFG(oldinstr, "NOT_AN_INSTRUCTION", ARM64_CB_PATCH, 1, cb) + #else + + #include +@@ -130,6 +150,14 @@ void apply_alternatives(void *start, size_t length); + 661: + .endm + ++.macro alternative_cb cb ++ .set .Lasm_alt_mode, 0 ++ .pushsection .altinstructions, "a" ++ altinstruction_entry 661f, \cb, ARM64_CB_PATCH, 662f-661f, 0 ++ .popsection ++661: ++.endm ++ + /* + * Provide the other half of the alternative code sequence. + */ +@@ -155,6 +183,13 @@ void apply_alternatives(void *start, size_t length); + .org . - (662b-661b) + (664b-663b) + .endm + ++/* ++ * Callback-based alternative epilogue ++ */ ++.macro alternative_cb_end ++662: ++.endm ++ + /* + * Provides a trivial alternative or default sequence consisting solely + * of NOPs. The number of NOPs is chosen automatically to match the +diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h +index 25b2a4161c7a..66aea4aa455d 100644 +--- a/arch/arm64/include/asm/assembler.h ++++ b/arch/arm64/include/asm/assembler.h +@@ -260,7 +260,11 @@ lr .req x30 // link register + #else + adr_l \dst, \sym + #endif ++alternative_if_not ARM64_HAS_VIRT_HOST_EXTN + mrs \tmp, tpidr_el1 ++alternative_else ++ mrs \tmp, tpidr_el2 ++alternative_endif + add \dst, \dst, \tmp + .endm + +@@ -271,7 +275,11 @@ lr .req x30 // link register + */ + .macro ldr_this_cpu dst, sym, tmp + adr_l \dst, \sym ++alternative_if_not ARM64_HAS_VIRT_HOST_EXTN + mrs \tmp, tpidr_el1 ++alternative_else ++ mrs \tmp, tpidr_el2 ++alternative_endif + ldr \dst, [\dst, \tmp] + .endm + +diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h +index 2e7b236bc596..76c0d23ca161 100644 +--- a/arch/arm64/include/asm/cpucaps.h ++++ b/arch/arm64/include/asm/cpucaps.h +@@ -43,7 +43,8 @@ + #define ARM64_UNMAP_KERNEL_AT_EL0 23 + #define ARM64_HARDEN_BRANCH_PREDICTOR 24 + #define ARM64_HARDEN_BP_POST_GUEST_EXIT 25 ++#define ARM64_SSBD 26 + +-#define ARM64_NCAPS 26 ++#define ARM64_NCAPS 27 + + #endif /* __ASM_CPUCAPS_H */ +diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h +index 428ee1f2468c..c5bc80a03515 100644 +--- a/arch/arm64/include/asm/cpufeature.h ++++ b/arch/arm64/include/asm/cpufeature.h +@@ -262,6 +262,28 @@ static inline bool system_uses_ttbr0_pan(void) + !cpus_have_const_cap(ARM64_HAS_PAN); + } + ++#define ARM64_SSBD_UNKNOWN -1 ++#define ARM64_SSBD_FORCE_DISABLE 0 ++#define ARM64_SSBD_KERNEL 1 ++#define ARM64_SSBD_FORCE_ENABLE 2 ++#define ARM64_SSBD_MITIGATED 3 ++ ++static inline int arm64_get_ssbd_state(void) ++{ ++#ifdef CONFIG_ARM64_SSBD ++ extern int ssbd_state; ++ return ssbd_state; ++#else ++ return ARM64_SSBD_UNKNOWN; ++#endif ++} ++ ++#ifdef CONFIG_ARM64_SSBD ++void arm64_set_ssbd_mitigation(bool state); ++#else ++static inline void arm64_set_ssbd_mitigation(bool state) {} ++#endif ++ + #endif /* __ASSEMBLY__ */ + + #endif +diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h +index a7ef5a051911..1a6d02350fc6 100644 +--- a/arch/arm64/include/asm/kvm_asm.h ++++ b/arch/arm64/include/asm/kvm_asm.h +@@ -33,6 +33,10 @@ + #define KVM_ARM64_DEBUG_DIRTY_SHIFT 0 + #define KVM_ARM64_DEBUG_DIRTY (1 << KVM_ARM64_DEBUG_DIRTY_SHIFT) + ++#define VCPU_WORKAROUND_2_FLAG_SHIFT 0 ++#define VCPU_WORKAROUND_2_FLAG (_AC(1, UL) << VCPU_WORKAROUND_2_FLAG_SHIFT) ++ ++/* Translate a kernel address of @sym into its equivalent linear mapping */ + #define kvm_ksym_ref(sym) \ + ({ \ + void *val = &sym; \ +@@ -68,6 +72,43 @@ extern u32 __init_stage2_translation(void); + + extern void __qcom_hyp_sanitize_btac_predictors(void); + ++/* Home-grown __this_cpu_{ptr,read} variants that always work at HYP */ ++#define __hyp_this_cpu_ptr(sym) \ ++ ({ \ ++ void *__ptr = hyp_symbol_addr(sym); \ ++ __ptr += read_sysreg(tpidr_el2); \ ++ (typeof(&sym))__ptr; \ ++ }) ++ ++#define __hyp_this_cpu_read(sym) \ ++ ({ \ ++ *__hyp_this_cpu_ptr(sym); \ ++ }) ++ ++#else /* __ASSEMBLY__ */ ++ ++.macro hyp_adr_this_cpu reg, sym, tmp ++ adr_l \reg, \sym ++ mrs \tmp, tpidr_el2 ++ add \reg, \reg, \tmp ++.endm ++ ++.macro hyp_ldr_this_cpu reg, sym, tmp ++ adr_l \reg, \sym ++ mrs \tmp, tpidr_el2 ++ ldr \reg, [\reg, \tmp] ++.endm ++ ++.macro get_host_ctxt reg, tmp ++ hyp_adr_this_cpu \reg, kvm_host_cpu_state, \tmp ++.endm ++ ++.macro get_vcpu_ptr vcpu, ctxt ++ get_host_ctxt \ctxt, \vcpu ++ ldr \vcpu, [\ctxt, #HOST_CONTEXT_VCPU] ++ kern_hyp_va \vcpu ++.endm ++ + #endif + + #endif /* __ARM_KVM_ASM_H__ */ +diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h +index 8abec9f7f430..b01ad3489bd8 100644 +--- a/arch/arm64/include/asm/kvm_host.h ++++ b/arch/arm64/include/asm/kvm_host.h +@@ -194,6 +194,8 @@ struct kvm_cpu_context { + u64 sys_regs[NR_SYS_REGS]; + u32 copro[NR_COPRO_REGS]; + }; ++ ++ struct kvm_vcpu *__hyp_running_vcpu; + }; + + typedef struct kvm_cpu_context kvm_cpu_context_t; +@@ -208,6 +210,9 @@ struct kvm_vcpu_arch { + /* Exception Information */ + struct kvm_vcpu_fault_info fault; + ++ /* State of various workarounds, see kvm_asm.h for bit assignment */ ++ u64 workaround_flags; ++ + /* Guest debug state */ + u64 debug_flags; + +@@ -348,10 +353,15 @@ int kvm_perf_teardown(void); + + struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr); + ++void __kvm_set_tpidr_el2(u64 tpidr_el2); ++DECLARE_PER_CPU(kvm_cpu_context_t, kvm_host_cpu_state); ++ + static inline void __cpu_init_hyp_mode(phys_addr_t pgd_ptr, + unsigned long hyp_stack_ptr, + unsigned long vector_ptr) + { ++ u64 tpidr_el2; ++ + /* + * Call initialization code, and switch to the full blown HYP code. + * If the cpucaps haven't been finalized yet, something has gone very +@@ -360,6 +370,16 @@ static inline void __cpu_init_hyp_mode(phys_addr_t pgd_ptr, + */ + BUG_ON(!static_branch_likely(&arm64_const_caps_ready)); + __kvm_call_hyp((void *)pgd_ptr, hyp_stack_ptr, vector_ptr); ++ ++ /* ++ * Calculate the raw per-cpu offset without a translation from the ++ * kernel's mapping to the linear mapping, and store it in tpidr_el2 ++ * so that we can use adr_l to access per-cpu variables in EL2. ++ */ ++ tpidr_el2 = (u64)this_cpu_ptr(&kvm_host_cpu_state) ++ - (u64)kvm_ksym_ref(kvm_host_cpu_state); ++ ++ kvm_call_hyp(__kvm_set_tpidr_el2, tpidr_el2); + } + + static inline void kvm_arch_hardware_unsetup(void) {} +@@ -392,4 +412,27 @@ static inline bool kvm_arm_harden_branch_predictor(void) + return cpus_have_const_cap(ARM64_HARDEN_BRANCH_PREDICTOR); + } + ++#define KVM_SSBD_UNKNOWN -1 ++#define KVM_SSBD_FORCE_DISABLE 0 ++#define KVM_SSBD_KERNEL 1 ++#define KVM_SSBD_FORCE_ENABLE 2 ++#define KVM_SSBD_MITIGATED 3 ++ ++static inline int kvm_arm_have_ssbd(void) ++{ ++ switch (arm64_get_ssbd_state()) { ++ case ARM64_SSBD_FORCE_DISABLE: ++ return KVM_SSBD_FORCE_DISABLE; ++ case ARM64_SSBD_KERNEL: ++ return KVM_SSBD_KERNEL; ++ case ARM64_SSBD_FORCE_ENABLE: ++ return KVM_SSBD_FORCE_ENABLE; ++ case ARM64_SSBD_MITIGATED: ++ return KVM_SSBD_MITIGATED; ++ case ARM64_SSBD_UNKNOWN: ++ default: ++ return KVM_SSBD_UNKNOWN; ++ } ++} ++ + #endif /* __ARM64_KVM_HOST_H__ */ +diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h +index fe55b516f018..e42c1f0ae6cf 100644 +--- a/arch/arm64/include/asm/kvm_mmu.h ++++ b/arch/arm64/include/asm/kvm_mmu.h +@@ -130,6 +130,26 @@ static inline unsigned long __kern_hyp_va(unsigned long v) + + #define kern_hyp_va(v) ((typeof(v))(__kern_hyp_va((unsigned long)(v)))) + ++/* ++ * Obtain the PC-relative address of a kernel symbol ++ * s: symbol ++ * ++ * The goal of this macro is to return a symbol's address based on a ++ * PC-relative computation, as opposed to a loading the VA from a ++ * constant pool or something similar. This works well for HYP, as an ++ * absolute VA is guaranteed to be wrong. Only use this if trying to ++ * obtain the address of a symbol (i.e. not something you obtained by ++ * following a pointer). ++ */ ++#define hyp_symbol_addr(s) \ ++ ({ \ ++ typeof(s) *addr; \ ++ asm("adrp %0, %1\n" \ ++ "add %0, %0, :lo12:%1\n" \ ++ : "=r" (addr) : "S" (&s)); \ ++ addr; \ ++ }) ++ + /* + * We currently only support a 40bit IPA. + */ +@@ -363,5 +383,29 @@ static inline int kvm_map_vectors(void) + } + #endif + ++#ifdef CONFIG_ARM64_SSBD ++DECLARE_PER_CPU_READ_MOSTLY(u64, arm64_ssbd_callback_required); ++ ++static inline int hyp_map_aux_data(void) ++{ ++ int cpu, err; ++ ++ for_each_possible_cpu(cpu) { ++ u64 *ptr; ++ ++ ptr = per_cpu_ptr(&arm64_ssbd_callback_required, cpu); ++ err = create_hyp_mappings(ptr, ptr + 1, PAGE_HYP); ++ if (err) ++ return err; ++ } ++ return 0; ++} ++#else ++static inline int hyp_map_aux_data(void) ++{ ++ return 0; ++} ++#endif ++ + #endif /* __ASSEMBLY__ */ + #endif /* __ARM64_KVM_MMU_H__ */ +diff --git a/arch/arm64/include/asm/percpu.h b/arch/arm64/include/asm/percpu.h +index 3bd498e4de4c..43393208229e 100644 +--- a/arch/arm64/include/asm/percpu.h ++++ b/arch/arm64/include/asm/percpu.h +@@ -16,11 +16,15 @@ + #ifndef __ASM_PERCPU_H + #define __ASM_PERCPU_H + ++#include + #include + + static inline void set_my_cpu_offset(unsigned long off) + { +- asm volatile("msr tpidr_el1, %0" :: "r" (off) : "memory"); ++ asm volatile(ALTERNATIVE("msr tpidr_el1, %0", ++ "msr tpidr_el2, %0", ++ ARM64_HAS_VIRT_HOST_EXTN) ++ :: "r" (off) : "memory"); + } + + static inline unsigned long __my_cpu_offset(void) +@@ -31,7 +35,10 @@ static inline unsigned long __my_cpu_offset(void) + * We want to allow caching the value, so avoid using volatile and + * instead use a fake stack read to hazard against barrier(). + */ +- asm("mrs %0, tpidr_el1" : "=r" (off) : ++ asm(ALTERNATIVE("mrs %0, tpidr_el1", ++ "mrs %0, tpidr_el2", ++ ARM64_HAS_VIRT_HOST_EXTN) ++ : "=r" (off) : + "Q" (*(const unsigned long *)current_stack_pointer)); + + return off; +diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h +index ddded6497a8a..fc786d344e46 100644 +--- a/arch/arm64/include/asm/thread_info.h ++++ b/arch/arm64/include/asm/thread_info.h +@@ -92,6 +92,7 @@ void arch_setup_new_exec(void); + #define TIF_RESTORE_SIGMASK 20 + #define TIF_SINGLESTEP 21 + #define TIF_32BIT 22 /* 32bit process */ ++#define TIF_SSBD 23 /* Wants SSB mitigation */ + + #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) + #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) +diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile +index def8d5623fd1..714fe90dbf66 100644 +--- a/arch/arm64/kernel/Makefile ++++ b/arch/arm64/kernel/Makefile +@@ -54,6 +54,7 @@ arm64-obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o \ + arm64-obj-$(CONFIG_ARM64_RELOC_TEST) += arm64-reloc-test.o + arm64-reloc-test-y := reloc_test_core.o reloc_test_syms.o + arm64-obj-$(CONFIG_CRASH_DUMP) += crash_dump.o ++arm64-obj-$(CONFIG_ARM64_SSBD) += ssbd.o + + ifeq ($(CONFIG_KVM),y) + arm64-obj-$(CONFIG_HARDEN_BRANCH_PREDICTOR) += bpi.o +diff --git a/arch/arm64/kernel/alternative.c b/arch/arm64/kernel/alternative.c +index 6dd0a3a3e5c9..5c4bce4ac381 100644 +--- a/arch/arm64/kernel/alternative.c ++++ b/arch/arm64/kernel/alternative.c +@@ -32,6 +32,8 @@ + #define ALT_ORIG_PTR(a) __ALT_PTR(a, orig_offset) + #define ALT_REPL_PTR(a) __ALT_PTR(a, alt_offset) + ++int alternatives_applied; ++ + struct alt_region { + struct alt_instr *begin; + struct alt_instr *end; +@@ -105,32 +107,53 @@ static u32 get_alt_insn(struct alt_instr *alt, __le32 *insnptr, __le32 *altinsnp + return insn; + } + ++static void patch_alternative(struct alt_instr *alt, ++ __le32 *origptr, __le32 *updptr, int nr_inst) ++{ ++ __le32 *replptr; ++ int i; ++ ++ replptr = ALT_REPL_PTR(alt); ++ for (i = 0; i < nr_inst; i++) { ++ u32 insn; ++ ++ insn = get_alt_insn(alt, origptr + i, replptr + i); ++ updptr[i] = cpu_to_le32(insn); ++ } ++} ++ + static void __apply_alternatives(void *alt_region, bool use_linear_alias) + { + struct alt_instr *alt; + struct alt_region *region = alt_region; +- __le32 *origptr, *replptr, *updptr; ++ __le32 *origptr, *updptr; ++ alternative_cb_t alt_cb; + + for (alt = region->begin; alt < region->end; alt++) { +- u32 insn; +- int i, nr_inst; ++ int nr_inst; + +- if (!cpus_have_cap(alt->cpufeature)) ++ /* Use ARM64_CB_PATCH as an unconditional patch */ ++ if (alt->cpufeature < ARM64_CB_PATCH && ++ !cpus_have_cap(alt->cpufeature)) + continue; + +- BUG_ON(alt->alt_len != alt->orig_len); ++ if (alt->cpufeature == ARM64_CB_PATCH) ++ BUG_ON(alt->alt_len != 0); ++ else ++ BUG_ON(alt->alt_len != alt->orig_len); + + pr_info_once("patching kernel code\n"); + + origptr = ALT_ORIG_PTR(alt); +- replptr = ALT_REPL_PTR(alt); + updptr = use_linear_alias ? lm_alias(origptr) : origptr; +- nr_inst = alt->alt_len / sizeof(insn); ++ nr_inst = alt->orig_len / AARCH64_INSN_SIZE; + +- for (i = 0; i < nr_inst; i++) { +- insn = get_alt_insn(alt, origptr + i, replptr + i); +- updptr[i] = cpu_to_le32(insn); +- } ++ if (alt->cpufeature < ARM64_CB_PATCH) ++ alt_cb = patch_alternative; ++ else ++ alt_cb = ALT_REPL_PTR(alt); ++ ++ alt_cb(alt, origptr, updptr, nr_inst); + + flush_icache_range((uintptr_t)origptr, + (uintptr_t)(origptr + nr_inst)); +@@ -143,7 +166,6 @@ static void __apply_alternatives(void *alt_region, bool use_linear_alias) + */ + static int __apply_alternatives_multi_stop(void *unused) + { +- static int patched = 0; + struct alt_region region = { + .begin = (struct alt_instr *)__alt_instructions, + .end = (struct alt_instr *)__alt_instructions_end, +@@ -151,14 +173,14 @@ static int __apply_alternatives_multi_stop(void *unused) + + /* We always have a CPU 0 at this point (__init) */ + if (smp_processor_id()) { +- while (!READ_ONCE(patched)) ++ while (!READ_ONCE(alternatives_applied)) + cpu_relax(); + isb(); + } else { +- BUG_ON(patched); ++ BUG_ON(alternatives_applied); + __apply_alternatives(®ion, true); + /* Barriers provided by the cache flushing */ +- WRITE_ONCE(patched, 1); ++ WRITE_ONCE(alternatives_applied, 1); + } + + return 0; +diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c +index af247d10252f..b5e43b01b396 100644 +--- a/arch/arm64/kernel/asm-offsets.c ++++ b/arch/arm64/kernel/asm-offsets.c +@@ -131,11 +131,13 @@ int main(void) + BLANK(); + #ifdef CONFIG_KVM_ARM_HOST + DEFINE(VCPU_CONTEXT, offsetof(struct kvm_vcpu, arch.ctxt)); ++ DEFINE(VCPU_WORKAROUND_FLAGS, offsetof(struct kvm_vcpu, arch.workaround_flags)); + DEFINE(CPU_GP_REGS, offsetof(struct kvm_cpu_context, gp_regs)); + DEFINE(CPU_USER_PT_REGS, offsetof(struct kvm_regs, regs)); + DEFINE(CPU_FP_REGS, offsetof(struct kvm_regs, fp_regs)); + DEFINE(VCPU_FPEXC32_EL2, offsetof(struct kvm_vcpu, arch.ctxt.sys_regs[FPEXC32_EL2])); + DEFINE(VCPU_HOST_CONTEXT, offsetof(struct kvm_vcpu, arch.host_cpu_context)); ++ DEFINE(HOST_CONTEXT_VCPU, offsetof(struct kvm_cpu_context, __hyp_running_vcpu)); + #endif + #ifdef CONFIG_CPU_PM + DEFINE(CPU_SUSPEND_SZ, sizeof(struct cpu_suspend_ctx)); +diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c +index b5a28336c077..eccdb28b4a39 100644 +--- a/arch/arm64/kernel/cpu_errata.c ++++ b/arch/arm64/kernel/cpu_errata.c +@@ -228,6 +228,178 @@ static int qcom_enable_link_stack_sanitization(void *data) + } + #endif /* CONFIG_HARDEN_BRANCH_PREDICTOR */ + ++#ifdef CONFIG_ARM64_SSBD ++DEFINE_PER_CPU_READ_MOSTLY(u64, arm64_ssbd_callback_required); ++ ++int ssbd_state __read_mostly = ARM64_SSBD_KERNEL; ++ ++static const struct ssbd_options { ++ const char *str; ++ int state; ++} ssbd_options[] = { ++ { "force-on", ARM64_SSBD_FORCE_ENABLE, }, ++ { "force-off", ARM64_SSBD_FORCE_DISABLE, }, ++ { "kernel", ARM64_SSBD_KERNEL, }, ++}; ++ ++static int __init ssbd_cfg(char *buf) ++{ ++ int i; ++ ++ if (!buf || !buf[0]) ++ return -EINVAL; ++ ++ for (i = 0; i < ARRAY_SIZE(ssbd_options); i++) { ++ int len = strlen(ssbd_options[i].str); ++ ++ if (strncmp(buf, ssbd_options[i].str, len)) ++ continue; ++ ++ ssbd_state = ssbd_options[i].state; ++ return 0; ++ } ++ ++ return -EINVAL; ++} ++early_param("ssbd", ssbd_cfg); ++ ++void __init arm64_update_smccc_conduit(struct alt_instr *alt, ++ __le32 *origptr, __le32 *updptr, ++ int nr_inst) ++{ ++ u32 insn; ++ ++ BUG_ON(nr_inst != 1); ++ ++ switch (psci_ops.conduit) { ++ case PSCI_CONDUIT_HVC: ++ insn = aarch64_insn_get_hvc_value(); ++ break; ++ case PSCI_CONDUIT_SMC: ++ insn = aarch64_insn_get_smc_value(); ++ break; ++ default: ++ return; ++ } ++ ++ *updptr = cpu_to_le32(insn); ++} ++ ++void __init arm64_enable_wa2_handling(struct alt_instr *alt, ++ __le32 *origptr, __le32 *updptr, ++ int nr_inst) ++{ ++ BUG_ON(nr_inst != 1); ++ /* ++ * Only allow mitigation on EL1 entry/exit and guest ++ * ARCH_WORKAROUND_2 handling if the SSBD state allows it to ++ * be flipped. ++ */ ++ if (arm64_get_ssbd_state() == ARM64_SSBD_KERNEL) ++ *updptr = cpu_to_le32(aarch64_insn_gen_nop()); ++} ++ ++void arm64_set_ssbd_mitigation(bool state) ++{ ++ switch (psci_ops.conduit) { ++ case PSCI_CONDUIT_HVC: ++ arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_WORKAROUND_2, state, NULL); ++ break; ++ ++ case PSCI_CONDUIT_SMC: ++ arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_2, state, NULL); ++ break; ++ ++ default: ++ WARN_ON_ONCE(1); ++ break; ++ } ++} ++ ++static bool has_ssbd_mitigation(const struct arm64_cpu_capabilities *entry, ++ int scope) ++{ ++ struct arm_smccc_res res; ++ bool required = true; ++ s32 val; ++ ++ WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible()); ++ ++ if (psci_ops.smccc_version == SMCCC_VERSION_1_0) { ++ ssbd_state = ARM64_SSBD_UNKNOWN; ++ return false; ++ } ++ ++ switch (psci_ops.conduit) { ++ case PSCI_CONDUIT_HVC: ++ arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, ++ ARM_SMCCC_ARCH_WORKAROUND_2, &res); ++ break; ++ ++ case PSCI_CONDUIT_SMC: ++ arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, ++ ARM_SMCCC_ARCH_WORKAROUND_2, &res); ++ break; ++ ++ default: ++ ssbd_state = ARM64_SSBD_UNKNOWN; ++ return false; ++ } ++ ++ val = (s32)res.a0; ++ ++ switch (val) { ++ case SMCCC_RET_NOT_SUPPORTED: ++ ssbd_state = ARM64_SSBD_UNKNOWN; ++ return false; ++ ++ case SMCCC_RET_NOT_REQUIRED: ++ pr_info_once("%s mitigation not required\n", entry->desc); ++ ssbd_state = ARM64_SSBD_MITIGATED; ++ return false; ++ ++ case SMCCC_RET_SUCCESS: ++ required = true; ++ break; ++ ++ case 1: /* Mitigation not required on this CPU */ ++ required = false; ++ break; ++ ++ default: ++ WARN_ON(1); ++ return false; ++ } ++ ++ switch (ssbd_state) { ++ case ARM64_SSBD_FORCE_DISABLE: ++ pr_info_once("%s disabled from command-line\n", entry->desc); ++ arm64_set_ssbd_mitigation(false); ++ required = false; ++ break; ++ ++ case ARM64_SSBD_KERNEL: ++ if (required) { ++ __this_cpu_write(arm64_ssbd_callback_required, 1); ++ arm64_set_ssbd_mitigation(true); ++ } ++ break; ++ ++ case ARM64_SSBD_FORCE_ENABLE: ++ pr_info_once("%s forced from command-line\n", entry->desc); ++ arm64_set_ssbd_mitigation(true); ++ required = true; ++ break; ++ ++ default: ++ WARN_ON(1); ++ break; ++ } ++ ++ return required; ++} ++#endif /* CONFIG_ARM64_SSBD */ ++ + #define MIDR_RANGE(model, min, max) \ + .def_scope = SCOPE_LOCAL_CPU, \ + .matches = is_affected_midr_range, \ +@@ -425,6 +597,14 @@ const struct arm64_cpu_capabilities arm64_errata[] = { + MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2), + .enable = enable_smccc_arch_workaround_1, + }, ++#endif ++#ifdef CONFIG_ARM64_SSBD ++ { ++ .desc = "Speculative Store Bypass Disable", ++ .def_scope = SCOPE_LOCAL_CPU, ++ .capability = ARM64_SSBD, ++ .matches = has_ssbd_mitigation, ++ }, + #endif + { + } +diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c +index 718822ab6e4b..376cf12edf0c 100644 +--- a/arch/arm64/kernel/cpufeature.c ++++ b/arch/arm64/kernel/cpufeature.c +@@ -880,6 +880,22 @@ static int __init parse_kpti(char *str) + early_param("kpti", parse_kpti); + #endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */ + ++static int cpu_copy_el2regs(void *__unused) ++{ ++ /* ++ * Copy register values that aren't redirected by hardware. ++ * ++ * Before code patching, we only set tpidr_el1, all CPUs need to copy ++ * this value to tpidr_el2 before we patch the code. Once we've done ++ * that, freshly-onlined CPUs will set tpidr_el2, so we don't need to ++ * do anything here. ++ */ ++ if (!alternatives_applied) ++ write_sysreg(read_sysreg(tpidr_el1), tpidr_el2); ++ ++ return 0; ++} ++ + static const struct arm64_cpu_capabilities arm64_features[] = { + { + .desc = "GIC system register CPU interface", +@@ -949,6 +965,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = { + .capability = ARM64_HAS_VIRT_HOST_EXTN, + .def_scope = SCOPE_SYSTEM, + .matches = runs_at_el2, ++ .enable = cpu_copy_el2regs, + }, + { + .desc = "32-bit EL0 Support", +diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S +index 93958d1341bb..c1ffa95c0ad2 100644 +--- a/arch/arm64/kernel/entry.S ++++ b/arch/arm64/kernel/entry.S +@@ -18,6 +18,7 @@ + * along with this program. If not, see . + */ + ++#include + #include + #include + +@@ -137,6 +138,25 @@ alternative_else_nop_endif + add \dst, \dst, #(\sym - .entry.tramp.text) + .endm + ++ // This macro corrupts x0-x3. It is the caller's duty ++ // to save/restore them if required. ++ .macro apply_ssbd, state, targ, tmp1, tmp2 ++#ifdef CONFIG_ARM64_SSBD ++alternative_cb arm64_enable_wa2_handling ++ b \targ ++alternative_cb_end ++ ldr_this_cpu \tmp2, arm64_ssbd_callback_required, \tmp1 ++ cbz \tmp2, \targ ++ ldr \tmp2, [tsk, #TSK_TI_FLAGS] ++ tbnz \tmp2, #TIF_SSBD, \targ ++ mov w0, #ARM_SMCCC_ARCH_WORKAROUND_2 ++ mov w1, #\state ++alternative_cb arm64_update_smccc_conduit ++ nop // Patched to SMC/HVC #0 ++alternative_cb_end ++#endif ++ .endm ++ + .macro kernel_entry, el, regsize = 64 + .if \regsize == 32 + mov w0, w0 // zero upper 32 bits of x0 +@@ -163,6 +183,14 @@ alternative_else_nop_endif + ldr x19, [tsk, #TSK_TI_FLAGS] // since we can unmask debug + disable_step_tsk x19, x20 // exceptions when scheduling. + ++ apply_ssbd 1, 1f, x22, x23 ++ ++#ifdef CONFIG_ARM64_SSBD ++ ldp x0, x1, [sp, #16 * 0] ++ ldp x2, x3, [sp, #16 * 1] ++#endif ++1: ++ + mov x29, xzr // fp pointed to user-space + .else + add x21, sp, #S_FRAME_SIZE +@@ -301,6 +329,8 @@ alternative_if ARM64_WORKAROUND_845719 + alternative_else_nop_endif + #endif + 3: ++ apply_ssbd 0, 5f, x0, x1 ++5: + .endif + + msr elr_el1, x21 // set up the return data +diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c +index 095d3c170f5d..a028cc95afe1 100644 +--- a/arch/arm64/kernel/hibernate.c ++++ b/arch/arm64/kernel/hibernate.c +@@ -313,6 +313,17 @@ int swsusp_arch_suspend(void) + + sleep_cpu = -EINVAL; + __cpu_suspend_exit(); ++ ++ /* ++ * Just in case the boot kernel did turn the SSBD ++ * mitigation off behind our back, let's set the state ++ * to what we expect it to be. ++ */ ++ switch (arm64_get_ssbd_state()) { ++ case ARM64_SSBD_FORCE_ENABLE: ++ case ARM64_SSBD_KERNEL: ++ arm64_set_ssbd_mitigation(true); ++ } + } + + local_dbg_restore(flags); +diff --git a/arch/arm64/kernel/ssbd.c b/arch/arm64/kernel/ssbd.c +new file mode 100644 +index 000000000000..0560738c1d5c +--- /dev/null ++++ b/arch/arm64/kernel/ssbd.c +@@ -0,0 +1,108 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2018 ARM Ltd, All Rights Reserved. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++/* ++ * prctl interface for SSBD ++ */ ++static int ssbd_prctl_set(struct task_struct *task, unsigned long ctrl) ++{ ++ int state = arm64_get_ssbd_state(); ++ ++ /* Unsupported */ ++ if (state == ARM64_SSBD_UNKNOWN) ++ return -EINVAL; ++ ++ /* Treat the unaffected/mitigated state separately */ ++ if (state == ARM64_SSBD_MITIGATED) { ++ switch (ctrl) { ++ case PR_SPEC_ENABLE: ++ return -EPERM; ++ case PR_SPEC_DISABLE: ++ case PR_SPEC_FORCE_DISABLE: ++ return 0; ++ } ++ } ++ ++ /* ++ * Things are a bit backward here: the arm64 internal API ++ * *enables the mitigation* when the userspace API *disables ++ * speculation*. So much fun. ++ */ ++ switch (ctrl) { ++ case PR_SPEC_ENABLE: ++ /* If speculation is force disabled, enable is not allowed */ ++ if (state == ARM64_SSBD_FORCE_ENABLE || ++ task_spec_ssb_force_disable(task)) ++ return -EPERM; ++ task_clear_spec_ssb_disable(task); ++ clear_tsk_thread_flag(task, TIF_SSBD); ++ break; ++ case PR_SPEC_DISABLE: ++ if (state == ARM64_SSBD_FORCE_DISABLE) ++ return -EPERM; ++ task_set_spec_ssb_disable(task); ++ set_tsk_thread_flag(task, TIF_SSBD); ++ break; ++ case PR_SPEC_FORCE_DISABLE: ++ if (state == ARM64_SSBD_FORCE_DISABLE) ++ return -EPERM; ++ task_set_spec_ssb_disable(task); ++ task_set_spec_ssb_force_disable(task); ++ set_tsk_thread_flag(task, TIF_SSBD); ++ break; ++ default: ++ return -ERANGE; ++ } ++ ++ return 0; ++} ++ ++int arch_prctl_spec_ctrl_set(struct task_struct *task, unsigned long which, ++ unsigned long ctrl) ++{ ++ switch (which) { ++ case PR_SPEC_STORE_BYPASS: ++ return ssbd_prctl_set(task, ctrl); ++ default: ++ return -ENODEV; ++ } ++} ++ ++static int ssbd_prctl_get(struct task_struct *task) ++{ ++ switch (arm64_get_ssbd_state()) { ++ case ARM64_SSBD_UNKNOWN: ++ return -EINVAL; ++ case ARM64_SSBD_FORCE_ENABLE: ++ return PR_SPEC_DISABLE; ++ case ARM64_SSBD_KERNEL: ++ if (task_spec_ssb_force_disable(task)) ++ return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE; ++ if (task_spec_ssb_disable(task)) ++ return PR_SPEC_PRCTL | PR_SPEC_DISABLE; ++ return PR_SPEC_PRCTL | PR_SPEC_ENABLE; ++ case ARM64_SSBD_FORCE_DISABLE: ++ return PR_SPEC_ENABLE; ++ default: ++ return PR_SPEC_NOT_AFFECTED; ++ } ++} ++ ++int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which) ++{ ++ switch (which) { ++ case PR_SPEC_STORE_BYPASS: ++ return ssbd_prctl_get(task); ++ default: ++ return -ENODEV; ++ } ++} +diff --git a/arch/arm64/kernel/suspend.c b/arch/arm64/kernel/suspend.c +index 77cd655e6eb7..7a655e60cf4b 100644 +--- a/arch/arm64/kernel/suspend.c ++++ b/arch/arm64/kernel/suspend.c +@@ -62,6 +62,14 @@ void notrace __cpu_suspend_exit(void) + */ + if (hw_breakpoint_restore) + hw_breakpoint_restore(cpu); ++ ++ /* ++ * On resume, firmware implementing dynamic mitigation will ++ * have turned the mitigation on. If the user has forcefully ++ * disabled it, make sure their wishes are obeyed. ++ */ ++ if (arm64_get_ssbd_state() == ARM64_SSBD_FORCE_DISABLE) ++ arm64_set_ssbd_mitigation(false); + } + + /* +diff --git a/arch/arm64/kvm/hyp-init.S b/arch/arm64/kvm/hyp-init.S +index 870828c364c5..dea20651a5f1 100644 +--- a/arch/arm64/kvm/hyp-init.S ++++ b/arch/arm64/kvm/hyp-init.S +@@ -122,6 +122,10 @@ CPU_BE( orr x4, x4, #SCTLR_ELx_EE) + kern_hyp_va x2 + msr vbar_el2, x2 + ++ /* copy tpidr_el1 into tpidr_el2 for use by HYP */ ++ mrs x1, tpidr_el1 ++ msr tpidr_el2, x1 ++ + /* Hello, World! */ + eret + ENDPROC(__kvm_hyp_init) +diff --git a/arch/arm64/kvm/hyp/entry.S b/arch/arm64/kvm/hyp/entry.S +index 9c45c6af1f58..a7b3c198d4de 100644 +--- a/arch/arm64/kvm/hyp/entry.S ++++ b/arch/arm64/kvm/hyp/entry.S +@@ -62,9 +62,6 @@ ENTRY(__guest_enter) + // Store the host regs + save_callee_saved_regs x1 + +- // Store the host_ctxt for use at exit time +- str x1, [sp, #-16]! +- + add x18, x0, #VCPU_CONTEXT + + // Restore guest regs x0-x17 +@@ -118,8 +115,7 @@ ENTRY(__guest_exit) + // Store the guest regs x19-x29, lr + save_callee_saved_regs x1 + +- // Restore the host_ctxt from the stack +- ldr x2, [sp], #16 ++ get_host_ctxt x2, x3 + + // Now restore the host regs + restore_callee_saved_regs x2 +@@ -159,6 +155,10 @@ abort_guest_exit_end: + ENDPROC(__guest_exit) + + ENTRY(__fpsimd_guest_restore) ++ // x0: esr ++ // x1: vcpu ++ // x2-x29,lr: vcpu regs ++ // vcpu x0-x1 on the stack + stp x2, x3, [sp, #-16]! + stp x4, lr, [sp, #-16]! + +@@ -173,7 +173,7 @@ alternative_else + alternative_endif + isb + +- mrs x3, tpidr_el2 ++ mov x3, x1 + + ldr x0, [x3, #VCPU_HOST_CONTEXT] + kern_hyp_va x0 +diff --git a/arch/arm64/kvm/hyp/hyp-entry.S b/arch/arm64/kvm/hyp/hyp-entry.S +index f49b53331d28..3c283fd8c8f5 100644 +--- a/arch/arm64/kvm/hyp/hyp-entry.S ++++ b/arch/arm64/kvm/hyp/hyp-entry.S +@@ -57,13 +57,8 @@ ENDPROC(__vhe_hyp_call) + el1_sync: // Guest trapped into EL2 + stp x0, x1, [sp, #-16]! + +-alternative_if_not ARM64_HAS_VIRT_HOST_EXTN +- mrs x1, esr_el2 +-alternative_else +- mrs x1, esr_el1 +-alternative_endif +- lsr x0, x1, #ESR_ELx_EC_SHIFT +- ++ mrs x0, esr_el2 ++ lsr x0, x0, #ESR_ELx_EC_SHIFT + cmp x0, #ESR_ELx_EC_HVC64 + ccmp x0, #ESR_ELx_EC_HVC32, #4, ne + b.ne el1_trap +@@ -111,14 +106,55 @@ el1_hvc_guest: + */ + ldr x1, [sp] // Guest's x0 + eor w1, w1, #ARM_SMCCC_ARCH_WORKAROUND_1 ++ cbz w1, wa_epilogue ++ ++ /* ARM_SMCCC_ARCH_WORKAROUND_2 handling */ ++ eor w1, w1, #(ARM_SMCCC_ARCH_WORKAROUND_1 ^ \ ++ ARM_SMCCC_ARCH_WORKAROUND_2) + cbnz w1, el1_trap +- mov x0, x1 ++ ++#ifdef CONFIG_ARM64_SSBD ++alternative_cb arm64_enable_wa2_handling ++ b wa2_end ++alternative_cb_end ++ get_vcpu_ptr x2, x0 ++ ldr x0, [x2, #VCPU_WORKAROUND_FLAGS] ++ ++ // Sanitize the argument and update the guest flags ++ ldr x1, [sp, #8] // Guest's x1 ++ clz w1, w1 // Murphy's device: ++ lsr w1, w1, #5 // w1 = !!w1 without using ++ eor w1, w1, #1 // the flags... ++ bfi x0, x1, #VCPU_WORKAROUND_2_FLAG_SHIFT, #1 ++ str x0, [x2, #VCPU_WORKAROUND_FLAGS] ++ ++ /* Check that we actually need to perform the call */ ++ hyp_ldr_this_cpu x0, arm64_ssbd_callback_required, x2 ++ cbz x0, wa2_end ++ ++ mov w0, #ARM_SMCCC_ARCH_WORKAROUND_2 ++ smc #0 ++ ++ /* Don't leak data from the SMC call */ ++ mov x3, xzr ++wa2_end: ++ mov x2, xzr ++ mov x1, xzr ++#endif ++ ++wa_epilogue: ++ mov x0, xzr + add sp, sp, #16 + eret + + el1_trap: ++ get_vcpu_ptr x1, x0 ++ ++ mrs x0, esr_el2 ++ lsr x0, x0, #ESR_ELx_EC_SHIFT + /* + * x0: ESR_EC ++ * x1: vcpu pointer + */ + + /* +@@ -132,19 +168,18 @@ alternative_if_not ARM64_HAS_NO_FPSIMD + b.eq __fpsimd_guest_restore + alternative_else_nop_endif + +- mrs x1, tpidr_el2 + mov x0, #ARM_EXCEPTION_TRAP + b __guest_exit + + el1_irq: + stp x0, x1, [sp, #-16]! +- mrs x1, tpidr_el2 ++ get_vcpu_ptr x1, x0 + mov x0, #ARM_EXCEPTION_IRQ + b __guest_exit + + el1_error: + stp x0, x1, [sp, #-16]! +- mrs x1, tpidr_el2 ++ get_vcpu_ptr x1, x0 + mov x0, #ARM_EXCEPTION_EL1_SERROR + b __guest_exit + +@@ -179,6 +214,11 @@ ENTRY(__hyp_do_panic) + eret + ENDPROC(__hyp_do_panic) + ++ENTRY(__hyp_panic) ++ get_host_ctxt x0, x1 ++ b hyp_panic ++ENDPROC(__hyp_panic) ++ + .macro invalid_vector label, target = __hyp_panic + .align 2 + \label: +diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c +index e08ae6b6b63e..b2f1992c6234 100644 +--- a/arch/arm64/kvm/hyp/switch.c ++++ b/arch/arm64/kvm/hyp/switch.c +@@ -15,6 +15,7 @@ + * along with this program. If not, see . + */ + ++#include + #include + #include + #include +@@ -281,6 +282,39 @@ static void __hyp_text __skip_instr(struct kvm_vcpu *vcpu) + write_sysreg_el2(*vcpu_pc(vcpu), elr); + } + ++static inline bool __hyp_text __needs_ssbd_off(struct kvm_vcpu *vcpu) ++{ ++ if (!cpus_have_const_cap(ARM64_SSBD)) ++ return false; ++ ++ return !(vcpu->arch.workaround_flags & VCPU_WORKAROUND_2_FLAG); ++} ++ ++static void __hyp_text __set_guest_arch_workaround_state(struct kvm_vcpu *vcpu) ++{ ++#ifdef CONFIG_ARM64_SSBD ++ /* ++ * The host runs with the workaround always present. If the ++ * guest wants it disabled, so be it... ++ */ ++ if (__needs_ssbd_off(vcpu) && ++ __hyp_this_cpu_read(arm64_ssbd_callback_required)) ++ arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_2, 0, NULL); ++#endif ++} ++ ++static void __hyp_text __set_host_arch_workaround_state(struct kvm_vcpu *vcpu) ++{ ++#ifdef CONFIG_ARM64_SSBD ++ /* ++ * If the guest has disabled the workaround, bring it back on. ++ */ ++ if (__needs_ssbd_off(vcpu) && ++ __hyp_this_cpu_read(arm64_ssbd_callback_required)) ++ arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_2, 1, NULL); ++#endif ++} ++ + int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu) + { + struct kvm_cpu_context *host_ctxt; +@@ -289,9 +323,9 @@ int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu) + u64 exit_code; + + vcpu = kern_hyp_va(vcpu); +- write_sysreg(vcpu, tpidr_el2); + + host_ctxt = kern_hyp_va(vcpu->arch.host_cpu_context); ++ host_ctxt->__hyp_running_vcpu = vcpu; + guest_ctxt = &vcpu->arch.ctxt; + + __sysreg_save_host_state(host_ctxt); +@@ -311,6 +345,8 @@ int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu) + __sysreg_restore_guest_state(guest_ctxt); + __debug_restore_state(vcpu, kern_hyp_va(vcpu->arch.debug_ptr), guest_ctxt); + ++ __set_guest_arch_workaround_state(vcpu); ++ + /* Jump in the fire! */ + again: + exit_code = __guest_enter(vcpu, host_ctxt); +@@ -367,6 +403,8 @@ int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu) + /* 0 falls through to be handled out of EL2 */ + } + ++ __set_host_arch_workaround_state(vcpu); ++ + if (cpus_have_const_cap(ARM64_HARDEN_BP_POST_GUEST_EXIT)) { + u32 midr = read_cpuid_id(); + +@@ -406,7 +444,8 @@ int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu) + + static const char __hyp_panic_string[] = "HYP panic:\nPS:%08llx PC:%016llx ESR:%08llx\nFAR:%016llx HPFAR:%016llx PAR:%016llx\nVCPU:%p\n"; + +-static void __hyp_text __hyp_call_panic_nvhe(u64 spsr, u64 elr, u64 par) ++static void __hyp_text __hyp_call_panic_nvhe(u64 spsr, u64 elr, u64 par, ++ struct kvm_vcpu *vcpu) + { + unsigned long str_va; + +@@ -420,35 +459,32 @@ static void __hyp_text __hyp_call_panic_nvhe(u64 spsr, u64 elr, u64 par) + __hyp_do_panic(str_va, + spsr, elr, + read_sysreg(esr_el2), read_sysreg_el2(far), +- read_sysreg(hpfar_el2), par, +- (void *)read_sysreg(tpidr_el2)); ++ read_sysreg(hpfar_el2), par, vcpu); + } + +-static void __hyp_text __hyp_call_panic_vhe(u64 spsr, u64 elr, u64 par) ++static void __hyp_text __hyp_call_panic_vhe(u64 spsr, u64 elr, u64 par, ++ struct kvm_vcpu *vcpu) + { + panic(__hyp_panic_string, + spsr, elr, + read_sysreg_el2(esr), read_sysreg_el2(far), +- read_sysreg(hpfar_el2), par, +- (void *)read_sysreg(tpidr_el2)); ++ read_sysreg(hpfar_el2), par, vcpu); + } + + static hyp_alternate_select(__hyp_call_panic, + __hyp_call_panic_nvhe, __hyp_call_panic_vhe, + ARM64_HAS_VIRT_HOST_EXTN); + +-void __hyp_text __noreturn __hyp_panic(void) ++void __hyp_text __noreturn hyp_panic(struct kvm_cpu_context *host_ctxt) + { ++ struct kvm_vcpu *vcpu = NULL; ++ + u64 spsr = read_sysreg_el2(spsr); + u64 elr = read_sysreg_el2(elr); + u64 par = read_sysreg(par_el1); + + if (read_sysreg(vttbr_el2)) { +- struct kvm_vcpu *vcpu; +- struct kvm_cpu_context *host_ctxt; +- +- vcpu = (struct kvm_vcpu *)read_sysreg(tpidr_el2); +- host_ctxt = kern_hyp_va(vcpu->arch.host_cpu_context); ++ vcpu = host_ctxt->__hyp_running_vcpu; + __timer_save_state(vcpu); + __deactivate_traps(vcpu); + __deactivate_vm(vcpu); +@@ -456,7 +492,7 @@ void __hyp_text __noreturn __hyp_panic(void) + } + + /* Call panic for real */ +- __hyp_call_panic()(spsr, elr, par); ++ __hyp_call_panic()(spsr, elr, par, vcpu); + + unreachable(); + } +diff --git a/arch/arm64/kvm/hyp/sysreg-sr.c b/arch/arm64/kvm/hyp/sysreg-sr.c +index 934137647837..e19d89cabf2a 100644 +--- a/arch/arm64/kvm/hyp/sysreg-sr.c ++++ b/arch/arm64/kvm/hyp/sysreg-sr.c +@@ -27,8 +27,8 @@ static void __hyp_text __sysreg_do_nothing(struct kvm_cpu_context *ctxt) { } + /* + * Non-VHE: Both host and guest must save everything. + * +- * VHE: Host must save tpidr*_el[01], actlr_el1, mdscr_el1, sp0, pc, +- * pstate, and guest must save everything. ++ * VHE: Host must save tpidr*_el0, actlr_el1, mdscr_el1, sp_el0, ++ * and guest must save everything. + */ + + static void __hyp_text __sysreg_save_common_state(struct kvm_cpu_context *ctxt) +@@ -36,11 +36,8 @@ static void __hyp_text __sysreg_save_common_state(struct kvm_cpu_context *ctxt) + ctxt->sys_regs[ACTLR_EL1] = read_sysreg(actlr_el1); + ctxt->sys_regs[TPIDR_EL0] = read_sysreg(tpidr_el0); + ctxt->sys_regs[TPIDRRO_EL0] = read_sysreg(tpidrro_el0); +- ctxt->sys_regs[TPIDR_EL1] = read_sysreg(tpidr_el1); + ctxt->sys_regs[MDSCR_EL1] = read_sysreg(mdscr_el1); + ctxt->gp_regs.regs.sp = read_sysreg(sp_el0); +- ctxt->gp_regs.regs.pc = read_sysreg_el2(elr); +- ctxt->gp_regs.regs.pstate = read_sysreg_el2(spsr); + } + + static void __hyp_text __sysreg_save_state(struct kvm_cpu_context *ctxt) +@@ -62,10 +59,13 @@ static void __hyp_text __sysreg_save_state(struct kvm_cpu_context *ctxt) + ctxt->sys_regs[AMAIR_EL1] = read_sysreg_el1(amair); + ctxt->sys_regs[CNTKCTL_EL1] = read_sysreg_el1(cntkctl); + ctxt->sys_regs[PAR_EL1] = read_sysreg(par_el1); ++ ctxt->sys_regs[TPIDR_EL1] = read_sysreg(tpidr_el1); + + ctxt->gp_regs.sp_el1 = read_sysreg(sp_el1); + ctxt->gp_regs.elr_el1 = read_sysreg_el1(elr); + ctxt->gp_regs.spsr[KVM_SPSR_EL1]= read_sysreg_el1(spsr); ++ ctxt->gp_regs.regs.pc = read_sysreg_el2(elr); ++ ctxt->gp_regs.regs.pstate = read_sysreg_el2(spsr); + } + + static hyp_alternate_select(__sysreg_call_save_host_state, +@@ -89,11 +89,8 @@ static void __hyp_text __sysreg_restore_common_state(struct kvm_cpu_context *ctx + write_sysreg(ctxt->sys_regs[ACTLR_EL1], actlr_el1); + write_sysreg(ctxt->sys_regs[TPIDR_EL0], tpidr_el0); + write_sysreg(ctxt->sys_regs[TPIDRRO_EL0], tpidrro_el0); +- write_sysreg(ctxt->sys_regs[TPIDR_EL1], tpidr_el1); + write_sysreg(ctxt->sys_regs[MDSCR_EL1], mdscr_el1); + write_sysreg(ctxt->gp_regs.regs.sp, sp_el0); +- write_sysreg_el2(ctxt->gp_regs.regs.pc, elr); +- write_sysreg_el2(ctxt->gp_regs.regs.pstate, spsr); + } + + static void __hyp_text __sysreg_restore_state(struct kvm_cpu_context *ctxt) +@@ -115,10 +112,13 @@ static void __hyp_text __sysreg_restore_state(struct kvm_cpu_context *ctxt) + write_sysreg_el1(ctxt->sys_regs[AMAIR_EL1], amair); + write_sysreg_el1(ctxt->sys_regs[CNTKCTL_EL1], cntkctl); + write_sysreg(ctxt->sys_regs[PAR_EL1], par_el1); ++ write_sysreg(ctxt->sys_regs[TPIDR_EL1], tpidr_el1); + + write_sysreg(ctxt->gp_regs.sp_el1, sp_el1); + write_sysreg_el1(ctxt->gp_regs.elr_el1, elr); + write_sysreg_el1(ctxt->gp_regs.spsr[KVM_SPSR_EL1],spsr); ++ write_sysreg_el2(ctxt->gp_regs.regs.pc, elr); ++ write_sysreg_el2(ctxt->gp_regs.regs.pstate, spsr); + } + + static hyp_alternate_select(__sysreg_call_restore_host_state, +@@ -183,3 +183,8 @@ void __hyp_text __sysreg32_restore_state(struct kvm_vcpu *vcpu) + if (vcpu->arch.debug_flags & KVM_ARM64_DEBUG_DIRTY) + write_sysreg(sysreg[DBGVCR32_EL2], dbgvcr32_el2); + } ++ ++void __hyp_text __kvm_set_tpidr_el2(u64 tpidr_el2) ++{ ++ asm("msr tpidr_el2, %0": : "r" (tpidr_el2)); ++} +diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c +index 3256b9228e75..a74311beda35 100644 +--- a/arch/arm64/kvm/reset.c ++++ b/arch/arm64/kvm/reset.c +@@ -122,6 +122,10 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu) + /* Reset PMU */ + kvm_pmu_vcpu_reset(vcpu); + ++ /* Default workaround setup is enabled (if supported) */ ++ if (kvm_arm_have_ssbd() == KVM_SSBD_KERNEL) ++ vcpu->arch.workaround_flags |= VCPU_WORKAROUND_2_FLAG; ++ + /* Reset timer */ + return kvm_timer_vcpu_reset(vcpu); + } +diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S +index bf0821b7b1ab..10c835f13f62 100644 +--- a/arch/arm64/mm/proc.S ++++ b/arch/arm64/mm/proc.S +@@ -70,7 +70,11 @@ ENTRY(cpu_do_suspend) + mrs x8, mdscr_el1 + mrs x9, oslsr_el1 + mrs x10, sctlr_el1 ++alternative_if_not ARM64_HAS_VIRT_HOST_EXTN + mrs x11, tpidr_el1 ++alternative_else ++ mrs x11, tpidr_el2 ++alternative_endif + mrs x12, sp_el0 + stp x2, x3, [x0] + stp x4, xzr, [x0, #16] +@@ -116,7 +120,11 @@ ENTRY(cpu_do_resume) + msr mdscr_el1, x10 + + msr sctlr_el1, x12 ++alternative_if_not ARM64_HAS_VIRT_HOST_EXTN + msr tpidr_el1, x13 ++alternative_else ++ msr tpidr_el2, x13 ++alternative_endif + msr sp_el0, x14 + /* + * Restore oslsr_el1 by writing oslar_el1 +diff --git a/arch/x86/include/asm/asm.h b/arch/x86/include/asm/asm.h +index 386a6900e206..3bf87f92b932 100644 +--- a/arch/x86/include/asm/asm.h ++++ b/arch/x86/include/asm/asm.h +@@ -46,6 +46,65 @@ + #define _ASM_SI __ASM_REG(si) + #define _ASM_DI __ASM_REG(di) + ++#ifndef __x86_64__ ++/* 32 bit */ ++ ++#define _ASM_ARG1 _ASM_AX ++#define _ASM_ARG2 _ASM_DX ++#define _ASM_ARG3 _ASM_CX ++ ++#define _ASM_ARG1L eax ++#define _ASM_ARG2L edx ++#define _ASM_ARG3L ecx ++ ++#define _ASM_ARG1W ax ++#define _ASM_ARG2W dx ++#define _ASM_ARG3W cx ++ ++#define _ASM_ARG1B al ++#define _ASM_ARG2B dl ++#define _ASM_ARG3B cl ++ ++#else ++/* 64 bit */ ++ ++#define _ASM_ARG1 _ASM_DI ++#define _ASM_ARG2 _ASM_SI ++#define _ASM_ARG3 _ASM_DX ++#define _ASM_ARG4 _ASM_CX ++#define _ASM_ARG5 r8 ++#define _ASM_ARG6 r9 ++ ++#define _ASM_ARG1Q rdi ++#define _ASM_ARG2Q rsi ++#define _ASM_ARG3Q rdx ++#define _ASM_ARG4Q rcx ++#define _ASM_ARG5Q r8 ++#define _ASM_ARG6Q r9 ++ ++#define _ASM_ARG1L edi ++#define _ASM_ARG2L esi ++#define _ASM_ARG3L edx ++#define _ASM_ARG4L ecx ++#define _ASM_ARG5L r8d ++#define _ASM_ARG6L r9d ++ ++#define _ASM_ARG1W di ++#define _ASM_ARG2W si ++#define _ASM_ARG3W dx ++#define _ASM_ARG4W cx ++#define _ASM_ARG5W r8w ++#define _ASM_ARG6W r9w ++ ++#define _ASM_ARG1B dil ++#define _ASM_ARG2B sil ++#define _ASM_ARG3B dl ++#define _ASM_ARG4B cl ++#define _ASM_ARG5B r8b ++#define _ASM_ARG6B r9b ++ ++#endif ++ + /* + * Macros to generate condition code outputs from inline assembly, + * The output operand must be type "bool". +diff --git a/arch/x86/include/asm/irqflags.h b/arch/x86/include/asm/irqflags.h +index 89f08955fff7..c4fc17220df9 100644 +--- a/arch/x86/include/asm/irqflags.h ++++ b/arch/x86/include/asm/irqflags.h +@@ -13,7 +13,7 @@ + * Interrupt control: + */ + +-static inline unsigned long native_save_fl(void) ++extern inline unsigned long native_save_fl(void) + { + unsigned long flags; + +diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile +index 295abaa58add..4137f7ba0f88 100644 +--- a/arch/x86/kernel/Makefile ++++ b/arch/x86/kernel/Makefile +@@ -58,6 +58,7 @@ obj-y += alternative.o i8253.o pci-nommu.o hw_breakpoint.o + obj-y += tsc.o tsc_msr.o io_delay.o rtc.o + obj-y += pci-iommu_table.o + obj-y += resource.o ++obj-y += irqflags.o + + obj-y += process.o + obj-y += fpu/ +diff --git a/arch/x86/kernel/irqflags.S b/arch/x86/kernel/irqflags.S +new file mode 100644 +index 000000000000..ddeeaac8adda +--- /dev/null ++++ b/arch/x86/kernel/irqflags.S +@@ -0,0 +1,26 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++ ++#include ++#include ++#include ++ ++/* ++ * unsigned long native_save_fl(void) ++ */ ++ENTRY(native_save_fl) ++ pushf ++ pop %_ASM_AX ++ ret ++ENDPROC(native_save_fl) ++EXPORT_SYMBOL(native_save_fl) ++ ++/* ++ * void native_restore_fl(unsigned long flags) ++ * %eax/%rdi: flags ++ */ ++ENTRY(native_restore_fl) ++ push %_ASM_ARG1 ++ popf ++ ret ++ENDPROC(native_restore_fl) ++EXPORT_SYMBOL(native_restore_fl) +diff --git a/block/blk-core.c b/block/blk-core.c +index 6f6e21821d2d..68bae6338ad4 100644 +--- a/block/blk-core.c ++++ b/block/blk-core.c +@@ -779,7 +779,6 @@ EXPORT_SYMBOL(blk_alloc_queue); + int blk_queue_enter(struct request_queue *q, bool nowait) + { + while (true) { +- int ret; + + if (percpu_ref_tryget_live(&q->q_usage_counter)) + return 0; +@@ -796,13 +795,11 @@ int blk_queue_enter(struct request_queue *q, bool nowait) + */ + smp_rmb(); + +- ret = wait_event_interruptible(q->mq_freeze_wq, +- !atomic_read(&q->mq_freeze_depth) || +- blk_queue_dying(q)); ++ wait_event(q->mq_freeze_wq, ++ !atomic_read(&q->mq_freeze_depth) || ++ blk_queue_dying(q)); + if (blk_queue_dying(q)) + return -ENODEV; +- if (ret) +- return ret; + } + } + +diff --git a/crypto/af_alg.c b/crypto/af_alg.c +index 815ee1075574..42dfdd1fd6d8 100644 +--- a/crypto/af_alg.c ++++ b/crypto/af_alg.c +@@ -1183,8 +1183,10 @@ int af_alg_get_rsgl(struct sock *sk, struct msghdr *msg, int flags, + + /* make one iovec available as scatterlist */ + err = af_alg_make_sg(&rsgl->sgl, &msg->msg_iter, seglen); +- if (err < 0) ++ if (err < 0) { ++ rsgl->sg_num_bytes = 0; + return err; ++ } + + /* chain the new scatterlist with previous one */ + if (areq->last_rsgl) +diff --git a/drivers/atm/zatm.c b/drivers/atm/zatm.c +index a8d2eb0ceb8d..2c288d1f42bb 100644 +--- a/drivers/atm/zatm.c ++++ b/drivers/atm/zatm.c +@@ -1483,6 +1483,8 @@ static int zatm_ioctl(struct atm_dev *dev,unsigned int cmd,void __user *arg) + return -EFAULT; + if (pool < 0 || pool > ZATM_LAST_POOL) + return -EINVAL; ++ pool = array_index_nospec(pool, ++ ZATM_LAST_POOL + 1); + if (copy_from_user(&info, + &((struct zatm_pool_req __user *) arg)->info, + sizeof(info))) return -EFAULT; +diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c +index 8b432d6e846d..c9ce716247c1 100644 +--- a/drivers/cpufreq/cppc_cpufreq.c ++++ b/drivers/cpufreq/cppc_cpufreq.c +@@ -126,6 +126,49 @@ static void cppc_cpufreq_stop_cpu(struct cpufreq_policy *policy) + cpu->perf_caps.lowest_perf, cpu_num, ret); + } + ++/* ++ * The PCC subspace describes the rate at which platform can accept commands ++ * on the shared PCC channel (including READs which do not count towards freq ++ * trasition requests), so ideally we need to use the PCC values as a fallback ++ * if we don't have a platform specific transition_delay_us ++ */ ++#ifdef CONFIG_ARM64 ++#include ++ ++static unsigned int cppc_cpufreq_get_transition_delay_us(int cpu) ++{ ++ unsigned long implementor = read_cpuid_implementor(); ++ unsigned long part_num = read_cpuid_part_number(); ++ unsigned int delay_us = 0; ++ ++ switch (implementor) { ++ case ARM_CPU_IMP_QCOM: ++ switch (part_num) { ++ case QCOM_CPU_PART_FALKOR_V1: ++ case QCOM_CPU_PART_FALKOR: ++ delay_us = 10000; ++ break; ++ default: ++ delay_us = cppc_get_transition_latency(cpu) / NSEC_PER_USEC; ++ break; ++ } ++ break; ++ default: ++ delay_us = cppc_get_transition_latency(cpu) / NSEC_PER_USEC; ++ break; ++ } ++ ++ return delay_us; ++} ++ ++#else ++ ++static unsigned int cppc_cpufreq_get_transition_delay_us(int cpu) ++{ ++ return cppc_get_transition_latency(cpu) / NSEC_PER_USEC; ++} ++#endif ++ + static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy) + { + struct cppc_cpudata *cpu; +@@ -163,8 +206,7 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy) + policy->cpuinfo.max_freq = cppc_dmi_max_khz; + + policy->cpuinfo.transition_latency = cppc_get_transition_latency(cpu_num); +- policy->transition_delay_us = cppc_get_transition_latency(cpu_num) / +- NSEC_PER_USEC; ++ policy->transition_delay_us = cppc_cpufreq_get_transition_delay_us(cpu_num); + policy->shared_type = cpu->shared_type; + + if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) { +diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c +index 65dc78b91dea..3f9eee7e555f 100644 +--- a/drivers/crypto/amcc/crypto4xx_core.c ++++ b/drivers/crypto/amcc/crypto4xx_core.c +@@ -207,7 +207,7 @@ static u32 crypto4xx_build_pdr(struct crypto4xx_device *dev) + dev->pdr_pa); + return -ENOMEM; + } +- memset(dev->pdr, 0, sizeof(struct ce_pd) * PPC4XX_NUM_PD); ++ memset(dev->pdr, 0, sizeof(struct ce_pd) * PPC4XX_NUM_PD); + dev->shadow_sa_pool = dma_alloc_coherent(dev->core_dev->device, + 256 * PPC4XX_NUM_PD, + &dev->shadow_sa_pool_pa, +@@ -240,13 +240,15 @@ static u32 crypto4xx_build_pdr(struct crypto4xx_device *dev) + + static void crypto4xx_destroy_pdr(struct crypto4xx_device *dev) + { +- if (dev->pdr != NULL) ++ if (dev->pdr) + dma_free_coherent(dev->core_dev->device, + sizeof(struct ce_pd) * PPC4XX_NUM_PD, + dev->pdr, dev->pdr_pa); ++ + if (dev->shadow_sa_pool) + dma_free_coherent(dev->core_dev->device, 256 * PPC4XX_NUM_PD, + dev->shadow_sa_pool, dev->shadow_sa_pool_pa); ++ + if (dev->shadow_sr_pool) + dma_free_coherent(dev->core_dev->device, + sizeof(struct sa_state_record) * PPC4XX_NUM_PD, +@@ -416,12 +418,12 @@ static u32 crypto4xx_build_sdr(struct crypto4xx_device *dev) + + static void crypto4xx_destroy_sdr(struct crypto4xx_device *dev) + { +- if (dev->sdr != NULL) ++ if (dev->sdr) + dma_free_coherent(dev->core_dev->device, + sizeof(struct ce_sd) * PPC4XX_NUM_SD, + dev->sdr, dev->sdr_pa); + +- if (dev->scatter_buffer_va != NULL) ++ if (dev->scatter_buffer_va) + dma_free_coherent(dev->core_dev->device, + dev->scatter_buffer_size * PPC4XX_NUM_SD, + dev->scatter_buffer_va, +@@ -1033,12 +1035,10 @@ int crypto4xx_register_alg(struct crypto4xx_device *sec_dev, + break; + } + +- if (rc) { +- list_del(&alg->entry); ++ if (rc) + kfree(alg); +- } else { ++ else + list_add_tail(&alg->entry, &sec_dev->alg_list); +- } + } + + return 0; +@@ -1193,7 +1193,7 @@ static int crypto4xx_probe(struct platform_device *ofdev) + + rc = crypto4xx_build_gdr(core_dev->dev); + if (rc) +- goto err_build_gdr; ++ goto err_build_pdr; + + rc = crypto4xx_build_sdr(core_dev->dev); + if (rc) +@@ -1236,12 +1236,11 @@ static int crypto4xx_probe(struct platform_device *ofdev) + err_request_irq: + irq_dispose_mapping(core_dev->irq); + tasklet_kill(&core_dev->tasklet); +- crypto4xx_destroy_sdr(core_dev->dev); + err_build_sdr: ++ crypto4xx_destroy_sdr(core_dev->dev); + crypto4xx_destroy_gdr(core_dev->dev); +-err_build_gdr: +- crypto4xx_destroy_pdr(core_dev->dev); + err_build_pdr: ++ crypto4xx_destroy_pdr(core_dev->dev); + kfree(core_dev->dev); + err_alloc_dev: + kfree(core_dev); +diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c +index 72f381522cb2..a22828713c1c 100644 +--- a/drivers/media/rc/rc-main.c ++++ b/drivers/media/rc/rc-main.c +@@ -1824,11 +1824,11 @@ void rc_unregister_device(struct rc_dev *dev) + if (!dev) + return; + +- del_timer_sync(&dev->timer_keyup); +- + if (dev->driver_type == RC_DRIVER_IR_RAW) + ir_raw_event_unregister(dev); + ++ del_timer_sync(&dev->timer_keyup); ++ + rc_free_rx_device(dev); + + device_del(&dev->dev); +diff --git a/drivers/mtd/nand/denali_dt.c b/drivers/mtd/nand/denali_dt.c +index 56e2e177644d..3f4f4aea0e8b 100644 +--- a/drivers/mtd/nand/denali_dt.c ++++ b/drivers/mtd/nand/denali_dt.c +@@ -122,7 +122,11 @@ static int denali_dt_probe(struct platform_device *pdev) + if (ret) + return ret; + +- denali->clk_x_rate = clk_get_rate(dt->clk); ++ /* ++ * Hardcode the clock rate for the backward compatibility. ++ * This works for both SOCFPGA and UniPhier. ++ */ ++ denali->clk_x_rate = 200000000; + + ret = denali_init(denali); + if (ret) +diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c +index 567ee54504bc..5e5022fa1d04 100644 +--- a/drivers/net/ethernet/atheros/alx/main.c ++++ b/drivers/net/ethernet/atheros/alx/main.c +@@ -1897,13 +1897,19 @@ static int alx_resume(struct device *dev) + struct pci_dev *pdev = to_pci_dev(dev); + struct alx_priv *alx = pci_get_drvdata(pdev); + struct alx_hw *hw = &alx->hw; ++ int err; + + alx_reset_phy(hw); + + if (!netif_running(alx->dev)) + return 0; + netif_device_attach(alx->dev); +- return __alx_open(alx, true); ++ ++ rtnl_lock(); ++ err = __alx_open(alx, true); ++ rtnl_unlock(); ++ ++ return err; + } + + static SIMPLE_DEV_PM_OPS(alx_pm_ops, alx_suspend, alx_resume); +diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c +index 4f3845a58126..68470c7c630a 100644 +--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c ++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c +@@ -1062,7 +1062,8 @@ static int bcm_enet_open(struct net_device *dev) + val = enet_readl(priv, ENET_CTL_REG); + val |= ENET_CTL_ENABLE_MASK; + enet_writel(priv, val, ENET_CTL_REG); +- enet_dma_writel(priv, ENETDMA_CFG_EN_MASK, ENETDMA_CFG_REG); ++ if (priv->dma_has_sram) ++ enet_dma_writel(priv, ENETDMA_CFG_EN_MASK, ENETDMA_CFG_REG); + enet_dmac_writel(priv, priv->dma_chan_en_mask, + ENETDMAC_CHANCFG, priv->rx_chan); + +@@ -1773,7 +1774,9 @@ static int bcm_enet_probe(struct platform_device *pdev) + ret = PTR_ERR(priv->mac_clk); + goto out; + } +- clk_prepare_enable(priv->mac_clk); ++ ret = clk_prepare_enable(priv->mac_clk); ++ if (ret) ++ goto out_put_clk_mac; + + /* initialize default and fetch platform data */ + priv->rx_ring_size = BCMENET_DEF_RX_DESC; +@@ -1805,9 +1808,11 @@ static int bcm_enet_probe(struct platform_device *pdev) + if (IS_ERR(priv->phy_clk)) { + ret = PTR_ERR(priv->phy_clk); + priv->phy_clk = NULL; +- goto out_put_clk_mac; ++ goto out_disable_clk_mac; + } +- clk_prepare_enable(priv->phy_clk); ++ ret = clk_prepare_enable(priv->phy_clk); ++ if (ret) ++ goto out_put_clk_phy; + } + + /* do minimal hardware init to be able to probe mii bus */ +@@ -1901,13 +1906,16 @@ static int bcm_enet_probe(struct platform_device *pdev) + out_uninit_hw: + /* turn off mdc clock */ + enet_writel(priv, 0, ENET_MIISC_REG); +- if (priv->phy_clk) { ++ if (priv->phy_clk) + clk_disable_unprepare(priv->phy_clk); ++ ++out_put_clk_phy: ++ if (priv->phy_clk) + clk_put(priv->phy_clk); +- } + +-out_put_clk_mac: ++out_disable_clk_mac: + clk_disable_unprepare(priv->mac_clk); ++out_put_clk_mac: + clk_put(priv->mac_clk); + out: + free_netdev(dev); +@@ -2752,7 +2760,9 @@ static int bcm_enetsw_probe(struct platform_device *pdev) + ret = PTR_ERR(priv->mac_clk); + goto out_unmap; + } +- clk_enable(priv->mac_clk); ++ ret = clk_prepare_enable(priv->mac_clk); ++ if (ret) ++ goto out_put_clk; + + priv->rx_chan = 0; + priv->tx_chan = 1; +@@ -2773,7 +2783,7 @@ static int bcm_enetsw_probe(struct platform_device *pdev) + + ret = register_netdev(dev); + if (ret) +- goto out_put_clk; ++ goto out_disable_clk; + + netif_carrier_off(dev); + platform_set_drvdata(pdev, dev); +@@ -2782,6 +2792,9 @@ static int bcm_enetsw_probe(struct platform_device *pdev) + + return 0; + ++out_disable_clk: ++ clk_disable_unprepare(priv->mac_clk); ++ + out_put_clk: + clk_put(priv->mac_clk); + +@@ -2813,6 +2826,9 @@ static int bcm_enetsw_remove(struct platform_device *pdev) + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(res->start, resource_size(res)); + ++ clk_disable_unprepare(priv->mac_clk); ++ clk_put(priv->mac_clk); ++ + free_netdev(dev); + return 0; + } +diff --git a/drivers/net/ethernet/cadence/macb_ptp.c b/drivers/net/ethernet/cadence/macb_ptp.c +index 2220c771092b..678835136bf8 100755 +--- a/drivers/net/ethernet/cadence/macb_ptp.c ++++ b/drivers/net/ethernet/cadence/macb_ptp.c +@@ -170,10 +170,7 @@ static int gem_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) + + if (delta > TSU_NSEC_MAX_VAL) { + gem_tsu_get_time(&bp->ptp_clock_info, &now); +- if (sign) +- now = timespec64_sub(now, then); +- else +- now = timespec64_add(now, then); ++ now = timespec64_add(now, then); + + gem_tsu_set_time(&bp->ptp_clock_info, + (const struct timespec64 *)&now); +diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c +index 6a015362c340..bf291e90cdb0 100644 +--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c ++++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c +@@ -51,6 +51,7 @@ + #include + #include + #include ++#include + + #include "common.h" + #include "cxgb3_ioctl.h" +@@ -2268,6 +2269,7 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr) + + if (t.qset_idx >= nqsets) + return -EINVAL; ++ t.qset_idx = array_index_nospec(t.qset_idx, nqsets); + + q = &adapter->params.sge.qset[q1 + t.qset_idx]; + t.rspq_size = q->rspq_size; +diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +index 20a8018d41ef..b68d94b49a8a 100644 +--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c ++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +@@ -2211,9 +2211,10 @@ static struct sk_buff *ixgbe_build_skb(struct ixgbe_ring *rx_ring, + return skb; + } + +-#define IXGBE_XDP_PASS 0 +-#define IXGBE_XDP_CONSUMED 1 +-#define IXGBE_XDP_TX 2 ++#define IXGBE_XDP_PASS 0 ++#define IXGBE_XDP_CONSUMED BIT(0) ++#define IXGBE_XDP_TX BIT(1) ++#define IXGBE_XDP_REDIR BIT(2) + + static int ixgbe_xmit_xdp_ring(struct ixgbe_adapter *adapter, + struct xdp_buff *xdp); +@@ -2242,7 +2243,7 @@ static struct sk_buff *ixgbe_run_xdp(struct ixgbe_adapter *adapter, + case XDP_REDIRECT: + err = xdp_do_redirect(adapter->netdev, xdp, xdp_prog); + if (!err) +- result = IXGBE_XDP_TX; ++ result = IXGBE_XDP_REDIR; + else + result = IXGBE_XDP_CONSUMED; + break; +@@ -2302,7 +2303,7 @@ static int ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, + unsigned int mss = 0; + #endif /* IXGBE_FCOE */ + u16 cleaned_count = ixgbe_desc_unused(rx_ring); +- bool xdp_xmit = false; ++ unsigned int xdp_xmit = 0; + + while (likely(total_rx_packets < budget)) { + union ixgbe_adv_rx_desc *rx_desc; +@@ -2342,8 +2343,10 @@ static int ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, + } + + if (IS_ERR(skb)) { +- if (PTR_ERR(skb) == -IXGBE_XDP_TX) { +- xdp_xmit = true; ++ unsigned int xdp_res = -PTR_ERR(skb); ++ ++ if (xdp_res & (IXGBE_XDP_TX | IXGBE_XDP_REDIR)) { ++ xdp_xmit |= xdp_res; + ixgbe_rx_buffer_flip(rx_ring, rx_buffer, size); + } else { + rx_buffer->pagecnt_bias++; +@@ -2415,7 +2418,10 @@ static int ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, + total_rx_packets++; + } + +- if (xdp_xmit) { ++ if (xdp_xmit & IXGBE_XDP_REDIR) ++ xdp_do_flush_map(); ++ ++ if (xdp_xmit & IXGBE_XDP_TX) { + struct ixgbe_ring *ring = adapter->xdp_ring[smp_processor_id()]; + + /* Force memory writes to complete before letting h/w +@@ -2423,8 +2429,6 @@ static int ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, + */ + wmb(); + writel(ring->next_to_use, ring->tail); +- +- xdp_do_flush_map(); + } + + u64_stats_update_begin(&rx_ring->syncp); +diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c +index d28f873169a9..3deaa3413313 100644 +--- a/drivers/net/ethernet/marvell/mvneta.c ++++ b/drivers/net/ethernet/marvell/mvneta.c +@@ -1959,7 +1959,7 @@ static int mvneta_rx_swbm(struct mvneta_port *pp, int rx_todo, + rx_bytes = rx_desc->data_size - (ETH_FCS_LEN + MVNETA_MH_SIZE); + index = rx_desc - rxq->descs; + data = rxq->buf_virt_addr[index]; +- phys_addr = rx_desc->buf_phys_addr; ++ phys_addr = rx_desc->buf_phys_addr - pp->rx_offset_correction; + + if (!mvneta_rxq_desc_is_first_last(rx_status) || + (rx_status & MVNETA_RXD_ERR_SUMMARY)) { +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +index 3efe45bc2471..cf94fdf25155 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +@@ -801,6 +801,7 @@ static void cmd_work_handler(struct work_struct *work) + unsigned long flags; + bool poll_cmd = ent->polling; + int alloc_ret; ++ int cmd_mode; + + sem = ent->page_queue ? &cmd->pages_sem : &cmd->sem; + down(sem); +@@ -847,6 +848,7 @@ static void cmd_work_handler(struct work_struct *work) + set_signature(ent, !cmd->checksum_disabled); + dump_command(dev, ent, 1); + ent->ts1 = ktime_get_ns(); ++ cmd_mode = cmd->mode; + + if (ent->callback) + schedule_delayed_work(&ent->cb_timeout_work, cb_timeout); +@@ -871,7 +873,7 @@ static void cmd_work_handler(struct work_struct *work) + iowrite32be(1 << ent->idx, &dev->iseg->cmd_dbell); + mmiowb(); + /* if not in polling don't use ent after this point */ +- if (cmd->mode == CMD_MODE_POLLING || poll_cmd) { ++ if (cmd_mode == CMD_MODE_POLLING || poll_cmd) { + poll_timeout(ent); + /* make sure we read the descriptor after ownership is SW */ + rmb(); +@@ -1272,7 +1274,7 @@ static ssize_t outlen_write(struct file *filp, const char __user *buf, + { + struct mlx5_core_dev *dev = filp->private_data; + struct mlx5_cmd_debug *dbg = &dev->cmd.dbg; +- char outlen_str[8]; ++ char outlen_str[8] = {0}; + int outlen; + void *ptr; + int err; +@@ -1287,8 +1289,6 @@ static ssize_t outlen_write(struct file *filp, const char __user *buf, + if (copy_from_user(outlen_str, buf, count)) + return -EFAULT; + +- outlen_str[7] = 0; +- + err = sscanf(outlen_str, "%d", &outlen); + if (err < 0) + return err; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +index 337ce9423794..bf34264c734b 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -2626,7 +2626,7 @@ void mlx5e_activate_priv_channels(struct mlx5e_priv *priv) + mlx5e_activate_channels(&priv->channels); + netif_tx_start_all_queues(priv->netdev); + +- if (MLX5_VPORT_MANAGER(priv->mdev)) ++ if (MLX5_ESWITCH_MANAGER(priv->mdev)) + mlx5e_add_sqs_fwd_rules(priv); + + mlx5e_wait_channels_min_rx_wqes(&priv->channels); +@@ -2637,7 +2637,7 @@ void mlx5e_deactivate_priv_channels(struct mlx5e_priv *priv) + { + mlx5e_redirect_rqts_to_drop(priv); + +- if (MLX5_VPORT_MANAGER(priv->mdev)) ++ if (MLX5_ESWITCH_MANAGER(priv->mdev)) + mlx5e_remove_sqs_fwd_rules(priv); + + /* FIXME: This is a W/A only for tx timeout watch dog false alarm when +@@ -4127,7 +4127,7 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev) + mlx5e_set_netdev_dev_addr(netdev); + + #if IS_ENABLED(CONFIG_MLX5_ESWITCH) +- if (MLX5_VPORT_MANAGER(mdev)) ++ if (MLX5_ESWITCH_MANAGER(mdev)) + netdev->switchdev_ops = &mlx5e_switchdev_ops; + #endif + +@@ -4273,7 +4273,7 @@ static void mlx5e_nic_enable(struct mlx5e_priv *priv) + + mlx5e_enable_async_events(priv); + +- if (MLX5_VPORT_MANAGER(priv->mdev)) ++ if (MLX5_ESWITCH_MANAGER(priv->mdev)) + mlx5e_register_vport_reps(priv); + + if (netdev->reg_state != NETREG_REGISTERED) +@@ -4300,7 +4300,7 @@ static void mlx5e_nic_disable(struct mlx5e_priv *priv) + + queue_work(priv->wq, &priv->set_rx_mode_work); + +- if (MLX5_VPORT_MANAGER(priv->mdev)) ++ if (MLX5_ESWITCH_MANAGER(priv->mdev)) + mlx5e_unregister_vport_reps(priv); + + mlx5e_disable_async_events(priv); +@@ -4483,7 +4483,7 @@ static void *mlx5e_add(struct mlx5_core_dev *mdev) + return NULL; + + #ifdef CONFIG_MLX5_ESWITCH +- if (MLX5_VPORT_MANAGER(mdev)) { ++ if (MLX5_ESWITCH_MANAGER(mdev)) { + rpriv = mlx5e_alloc_nic_rep_priv(mdev); + if (!rpriv) { + mlx5_core_warn(mdev, "Failed to alloc NIC rep priv data\n"); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +index 4727e7390834..281911698f72 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +@@ -710,7 +710,7 @@ bool mlx5e_is_uplink_rep(struct mlx5e_priv *priv) + struct mlx5e_rep_priv *rpriv = priv->ppriv; + struct mlx5_eswitch_rep *rep; + +- if (!MLX5_CAP_GEN(priv->mdev, vport_group_manager)) ++ if (!MLX5_ESWITCH_MANAGER(priv->mdev)) + return false; + + rep = rpriv->rep; +@@ -724,8 +724,12 @@ bool mlx5e_is_uplink_rep(struct mlx5e_priv *priv) + static bool mlx5e_is_vf_vport_rep(struct mlx5e_priv *priv) + { + struct mlx5e_rep_priv *rpriv = priv->ppriv; +- struct mlx5_eswitch_rep *rep = rpriv->rep; ++ struct mlx5_eswitch_rep *rep; + ++ if (!MLX5_ESWITCH_MANAGER(priv->mdev)) ++ return false; ++ ++ rep = rpriv->rep; + if (rep && rep->vport != FDB_UPLINK_VPORT) + return true; + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +index 82e37250ed01..667415301066 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +@@ -1535,7 +1535,7 @@ int mlx5_eswitch_enable_sriov(struct mlx5_eswitch *esw, int nvfs, int mode) + if (!ESW_ALLOWED(esw)) + return 0; + +- if (!MLX5_CAP_GEN(esw->dev, eswitch_flow_table) || ++ if (!MLX5_ESWITCH_MANAGER(esw->dev) || + !MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, ft_support)) { + esw_warn(esw->dev, "E-Switch FDB is not supported, aborting ...\n"); + return -EOPNOTSUPP; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +index 565c8b7a399a..10bf770675f3 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +@@ -39,6 +39,8 @@ + #include + #include "lib/mpfs.h" + ++#define MLX5_ESWITCH_MANAGER(mdev) MLX5_CAP_GEN(mdev, eswitch_manager) ++ + enum { + SRIOV_NONE, + SRIOV_LEGACY, +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +index d9fd8570b07c..c699055c0ffd 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +@@ -912,8 +912,8 @@ static int mlx5_devlink_eswitch_check(struct devlink *devlink) + if (MLX5_CAP_GEN(dev, port_type) != MLX5_CAP_PORT_TYPE_ETH) + return -EOPNOTSUPP; + +- if (!MLX5_CAP_GEN(dev, vport_group_manager)) +- return -EOPNOTSUPP; ++ if(!MLX5_ESWITCH_MANAGER(dev)) ++ return -EPERM; + + if (dev->priv.eswitch->mode == SRIOV_NONE) + return -EOPNOTSUPP; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +index 33e5ff081e36..dd05cf148845 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +@@ -36,6 +36,7 @@ + #include "mlx5_core.h" + #include "fs_core.h" + #include "fs_cmd.h" ++#include "eswitch.h" + #include "diag/fs_tracepoint.h" + + #define INIT_TREE_NODE_ARRAY_SIZE(...) (sizeof((struct init_tree_node[]){__VA_ARGS__}) /\ +@@ -2211,7 +2212,7 @@ int mlx5_init_fs(struct mlx5_core_dev *dev) + goto err; + } + +- if (MLX5_CAP_GEN(dev, eswitch_flow_table)) { ++ if (MLX5_ESWITCH_MANAGER(dev)) { + if (MLX5_CAP_ESW_FLOWTABLE_FDB(dev, ft_support)) { + err = init_fdb_root_ns(steering); + if (err) +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw.c b/drivers/net/ethernet/mellanox/mlx5/core/fw.c +index 2c71557d1cee..d69897a1e2ce 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fw.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fw.c +@@ -34,6 +34,7 @@ + #include + #include + #include "mlx5_core.h" ++#include "eswitch.h" + #include "../../mlxfw/mlxfw.h" + + static int mlx5_cmd_query_adapter(struct mlx5_core_dev *dev, u32 *out, +@@ -152,13 +153,13 @@ int mlx5_query_hca_caps(struct mlx5_core_dev *dev) + } + + if (MLX5_CAP_GEN(dev, vport_group_manager) && +- MLX5_CAP_GEN(dev, eswitch_flow_table)) { ++ MLX5_ESWITCH_MANAGER(dev)) { + err = mlx5_core_get_caps(dev, MLX5_CAP_ESWITCH_FLOW_TABLE); + if (err) + return err; + } + +- if (MLX5_CAP_GEN(dev, eswitch_flow_table)) { ++ if (MLX5_ESWITCH_MANAGER(dev)) { + err = mlx5_core_get_caps(dev, MLX5_CAP_ESWITCH); + if (err) + return err; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c +index 7cb67122e8b5..22811ecd8fcd 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c +@@ -34,6 +34,7 @@ + #include + #include + #include "mlx5_core.h" ++#include "eswitch.h" + #include "lib/mpfs.h" + + /* HW L2 Table (MPFS) management */ +@@ -98,7 +99,7 @@ int mlx5_mpfs_init(struct mlx5_core_dev *dev) + int l2table_size = 1 << MLX5_CAP_GEN(dev, log_max_l2_table); + struct mlx5_mpfs *mpfs; + +- if (!MLX5_VPORT_MANAGER(dev)) ++ if (!MLX5_ESWITCH_MANAGER(dev)) + return 0; + + mpfs = kzalloc(sizeof(*mpfs), GFP_KERNEL); +@@ -122,7 +123,7 @@ void mlx5_mpfs_cleanup(struct mlx5_core_dev *dev) + { + struct mlx5_mpfs *mpfs = dev->priv.mpfs; + +- if (!MLX5_VPORT_MANAGER(dev)) ++ if (!MLX5_ESWITCH_MANAGER(dev)) + return; + + WARN_ON(!hlist_empty(mpfs->hash)); +@@ -137,7 +138,7 @@ int mlx5_mpfs_add_mac(struct mlx5_core_dev *dev, u8 *mac) + u32 index; + int err; + +- if (!MLX5_VPORT_MANAGER(dev)) ++ if (!MLX5_ESWITCH_MANAGER(dev)) + return 0; + + mutex_lock(&mpfs->lock); +@@ -179,7 +180,7 @@ int mlx5_mpfs_del_mac(struct mlx5_core_dev *dev, u8 *mac) + int err = 0; + u32 index; + +- if (!MLX5_VPORT_MANAGER(dev)) ++ if (!MLX5_ESWITCH_MANAGER(dev)) + return 0; + + mutex_lock(&mpfs->lock); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c b/drivers/net/ethernet/mellanox/mlx5/core/port.c +index e07061f565d6..ccb6287aeeb7 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/port.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c +@@ -641,7 +641,7 @@ EXPORT_SYMBOL_GPL(mlx5_query_port_prio_tc); + static int mlx5_set_port_qetcr_reg(struct mlx5_core_dev *mdev, u32 *in, + int inlen) + { +- u32 out[MLX5_ST_SZ_DW(qtct_reg)]; ++ u32 out[MLX5_ST_SZ_DW(qetc_reg)]; + + if (!MLX5_CAP_GEN(mdev, ets)) + return -EOPNOTSUPP; +@@ -653,7 +653,7 @@ static int mlx5_set_port_qetcr_reg(struct mlx5_core_dev *mdev, u32 *in, + static int mlx5_query_port_qetcr_reg(struct mlx5_core_dev *mdev, u32 *out, + int outlen) + { +- u32 in[MLX5_ST_SZ_DW(qtct_reg)]; ++ u32 in[MLX5_ST_SZ_DW(qetc_reg)]; + + if (!MLX5_CAP_GEN(mdev, ets)) + return -EOPNOTSUPP; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sriov.c b/drivers/net/ethernet/mellanox/mlx5/core/sriov.c +index 2a8b529ce6dd..a0674962f02c 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/sriov.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/sriov.c +@@ -88,6 +88,9 @@ static int mlx5_device_enable_sriov(struct mlx5_core_dev *dev, int num_vfs) + return -EBUSY; + } + ++ if (!MLX5_ESWITCH_MANAGER(dev)) ++ goto enable_vfs_hca; ++ + err = mlx5_eswitch_enable_sriov(dev->priv.eswitch, num_vfs, SRIOV_LEGACY); + if (err) { + mlx5_core_warn(dev, +@@ -95,6 +98,7 @@ static int mlx5_device_enable_sriov(struct mlx5_core_dev *dev, int num_vfs) + return err; + } + ++enable_vfs_hca: + for (vf = 0; vf < num_vfs; vf++) { + err = mlx5_core_enable_hca(dev, vf + 1); + if (err) { +@@ -140,7 +144,8 @@ static void mlx5_device_disable_sriov(struct mlx5_core_dev *dev) + } + + out: +- mlx5_eswitch_disable_sriov(dev->priv.eswitch); ++ if (MLX5_ESWITCH_MANAGER(dev)) ++ mlx5_eswitch_disable_sriov(dev->priv.eswitch); + + if (mlx5_wait_for_vf_pages(dev)) + mlx5_core_warn(dev, "timeout reclaiming VFs pages\n"); +diff --git a/drivers/net/ethernet/qlogic/qed/qed_dcbx.c b/drivers/net/ethernet/qlogic/qed/qed_dcbx.c +index 8f6ccc0c39e5..b306961b02fd 100644 +--- a/drivers/net/ethernet/qlogic/qed/qed_dcbx.c ++++ b/drivers/net/ethernet/qlogic/qed/qed_dcbx.c +@@ -700,9 +700,9 @@ qed_dcbx_get_local_lldp_params(struct qed_hwfn *p_hwfn, + p_local = &p_hwfn->p_dcbx_info->lldp_local[LLDP_NEAREST_BRIDGE]; + + memcpy(params->lldp_local.local_chassis_id, p_local->local_chassis_id, +- ARRAY_SIZE(p_local->local_chassis_id)); ++ sizeof(p_local->local_chassis_id)); + memcpy(params->lldp_local.local_port_id, p_local->local_port_id, +- ARRAY_SIZE(p_local->local_port_id)); ++ sizeof(p_local->local_port_id)); + } + + static void +@@ -714,9 +714,9 @@ qed_dcbx_get_remote_lldp_params(struct qed_hwfn *p_hwfn, + p_remote = &p_hwfn->p_dcbx_info->lldp_remote[LLDP_NEAREST_BRIDGE]; + + memcpy(params->lldp_remote.peer_chassis_id, p_remote->peer_chassis_id, +- ARRAY_SIZE(p_remote->peer_chassis_id)); ++ sizeof(p_remote->peer_chassis_id)); + memcpy(params->lldp_remote.peer_port_id, p_remote->peer_port_id, +- ARRAY_SIZE(p_remote->peer_port_id)); ++ sizeof(p_remote->peer_port_id)); + } + + static int +diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c +index 58a689fb04db..ef2374699726 100644 +--- a/drivers/net/ethernet/qlogic/qed/qed_dev.c ++++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c +@@ -1782,7 +1782,7 @@ int qed_hw_init(struct qed_dev *cdev, struct qed_hw_init_params *p_params) + DP_INFO(p_hwfn, "Failed to update driver state\n"); + + rc = qed_mcp_ov_update_eswitch(p_hwfn, p_hwfn->p_main_ptt, +- QED_OV_ESWITCH_VEB); ++ QED_OV_ESWITCH_NONE); + if (rc) + DP_INFO(p_hwfn, "Failed to update eswitch mode\n"); + } +diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c +index 27832885a87f..2c958921dfb3 100644 +--- a/drivers/net/ethernet/qlogic/qed/qed_main.c ++++ b/drivers/net/ethernet/qlogic/qed/qed_main.c +@@ -779,6 +779,14 @@ static int qed_slowpath_setup_int(struct qed_dev *cdev, + /* We want a minimum of one slowpath and one fastpath vector per hwfn */ + cdev->int_params.in.min_msix_cnt = cdev->num_hwfns * 2; + ++ if (is_kdump_kernel()) { ++ DP_INFO(cdev, ++ "Kdump kernel: Limit the max number of requested MSI-X vectors to %hd\n", ++ cdev->int_params.in.min_msix_cnt); ++ cdev->int_params.in.num_vectors = ++ cdev->int_params.in.min_msix_cnt; ++ } ++ + rc = qed_set_int_mode(cdev, false); + if (rc) { + DP_ERR(cdev, "qed_slowpath_setup_int ERR\n"); +diff --git a/drivers/net/ethernet/qlogic/qed/qed_sriov.c b/drivers/net/ethernet/qlogic/qed/qed_sriov.c +index 3f40b1de7957..d08fe350ab6c 100644 +--- a/drivers/net/ethernet/qlogic/qed/qed_sriov.c ++++ b/drivers/net/ethernet/qlogic/qed/qed_sriov.c +@@ -4396,6 +4396,8 @@ static void qed_sriov_enable_qid_config(struct qed_hwfn *hwfn, + static int qed_sriov_enable(struct qed_dev *cdev, int num) + { + struct qed_iov_vf_init_params params; ++ struct qed_hwfn *hwfn; ++ struct qed_ptt *ptt; + int i, j, rc; + + if (num >= RESC_NUM(&cdev->hwfns[0], QED_VPORT)) { +@@ -4408,8 +4410,8 @@ static int qed_sriov_enable(struct qed_dev *cdev, int num) + + /* Initialize HW for VF access */ + for_each_hwfn(cdev, j) { +- struct qed_hwfn *hwfn = &cdev->hwfns[j]; +- struct qed_ptt *ptt = qed_ptt_acquire(hwfn); ++ hwfn = &cdev->hwfns[j]; ++ ptt = qed_ptt_acquire(hwfn); + + /* Make sure not to use more than 16 queues per VF */ + params.num_queues = min_t(int, +@@ -4445,6 +4447,19 @@ static int qed_sriov_enable(struct qed_dev *cdev, int num) + goto err; + } + ++ hwfn = QED_LEADING_HWFN(cdev); ++ ptt = qed_ptt_acquire(hwfn); ++ if (!ptt) { ++ DP_ERR(hwfn, "Failed to acquire ptt\n"); ++ rc = -EBUSY; ++ goto err; ++ } ++ ++ rc = qed_mcp_ov_update_eswitch(hwfn, ptt, QED_OV_ESWITCH_VEB); ++ if (rc) ++ DP_INFO(cdev, "Failed to update eswitch mode\n"); ++ qed_ptt_release(hwfn, ptt); ++ + return num; + + err: +diff --git a/drivers/net/ethernet/qlogic/qede/qede_ptp.c b/drivers/net/ethernet/qlogic/qede/qede_ptp.c +index 9b2280badaf7..475f6ae5d4b3 100644 +--- a/drivers/net/ethernet/qlogic/qede/qede_ptp.c ++++ b/drivers/net/ethernet/qlogic/qede/qede_ptp.c +@@ -337,8 +337,14 @@ int qede_ptp_get_ts_info(struct qede_dev *edev, struct ethtool_ts_info *info) + { + struct qede_ptp *ptp = edev->ptp; + +- if (!ptp) +- return -EIO; ++ if (!ptp) { ++ info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE | ++ SOF_TIMESTAMPING_RX_SOFTWARE | ++ SOF_TIMESTAMPING_SOFTWARE; ++ info->phc_index = -1; ++ ++ return 0; ++ } + + info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE | + SOF_TIMESTAMPING_RX_SOFTWARE | +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +index 9866d2e34cdd..27f2e650e27b 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -914,6 +914,7 @@ static void stmmac_check_pcs_mode(struct stmmac_priv *priv) + static int stmmac_init_phy(struct net_device *dev) + { + struct stmmac_priv *priv = netdev_priv(dev); ++ u32 tx_cnt = priv->plat->tx_queues_to_use; + struct phy_device *phydev; + char phy_id_fmt[MII_BUS_ID_SIZE + 3]; + char bus_id[MII_BUS_ID_SIZE]; +@@ -954,6 +955,15 @@ static int stmmac_init_phy(struct net_device *dev) + phydev->advertising &= ~(SUPPORTED_1000baseT_Half | + SUPPORTED_1000baseT_Full); + ++ /* ++ * Half-duplex mode not supported with multiqueue ++ * half-duplex can only works with single queue ++ */ ++ if (tx_cnt > 1) ++ phydev->supported &= ~(SUPPORTED_1000baseT_Half | ++ SUPPORTED_100baseT_Half | ++ SUPPORTED_10baseT_Half); ++ + /* + * Broken HW is sometimes missing the pull-up resistor on the + * MDIO line, which results in reads to non-existent devices returning +diff --git a/drivers/net/ethernet/sun/sungem.c b/drivers/net/ethernet/sun/sungem.c +index fa607d062cb3..15cd086e3f47 100644 +--- a/drivers/net/ethernet/sun/sungem.c ++++ b/drivers/net/ethernet/sun/sungem.c +@@ -59,8 +59,7 @@ + #include + #include "sungem.h" + +-/* Stripping FCS is causing problems, disabled for now */ +-#undef STRIP_FCS ++#define STRIP_FCS + + #define DEFAULT_MSG (NETIF_MSG_DRV | \ + NETIF_MSG_PROBE | \ +@@ -434,7 +433,7 @@ static int gem_rxmac_reset(struct gem *gp) + writel(desc_dma & 0xffffffff, gp->regs + RXDMA_DBLOW); + writel(RX_RING_SIZE - 4, gp->regs + RXDMA_KICK); + val = (RXDMA_CFG_BASE | (RX_OFFSET << 10) | +- ((14 / 2) << 13) | RXDMA_CFG_FTHRESH_128); ++ (ETH_HLEN << 13) | RXDMA_CFG_FTHRESH_128); + writel(val, gp->regs + RXDMA_CFG); + if (readl(gp->regs + GREG_BIFCFG) & GREG_BIFCFG_M66EN) + writel(((5 & RXDMA_BLANK_IPKTS) | +@@ -759,7 +758,6 @@ static int gem_rx(struct gem *gp, int work_to_do) + struct net_device *dev = gp->dev; + int entry, drops, work_done = 0; + u32 done; +- __sum16 csum; + + if (netif_msg_rx_status(gp)) + printk(KERN_DEBUG "%s: rx interrupt, done: %d, rx_new: %d\n", +@@ -854,9 +852,13 @@ static int gem_rx(struct gem *gp, int work_to_do) + skb = copy_skb; + } + +- csum = (__force __sum16)htons((status & RXDCTRL_TCPCSUM) ^ 0xffff); +- skb->csum = csum_unfold(csum); +- skb->ip_summed = CHECKSUM_COMPLETE; ++ if (likely(dev->features & NETIF_F_RXCSUM)) { ++ __sum16 csum; ++ ++ csum = (__force __sum16)htons((status & RXDCTRL_TCPCSUM) ^ 0xffff); ++ skb->csum = csum_unfold(csum); ++ skb->ip_summed = CHECKSUM_COMPLETE; ++ } + skb->protocol = eth_type_trans(skb, gp->dev); + + napi_gro_receive(&gp->napi, skb); +@@ -1760,7 +1762,7 @@ static void gem_init_dma(struct gem *gp) + writel(0, gp->regs + TXDMA_KICK); + + val = (RXDMA_CFG_BASE | (RX_OFFSET << 10) | +- ((14 / 2) << 13) | RXDMA_CFG_FTHRESH_128); ++ (ETH_HLEN << 13) | RXDMA_CFG_FTHRESH_128); + writel(val, gp->regs + RXDMA_CFG); + + writel(desc_dma >> 32, gp->regs + RXDMA_DBHI); +@@ -2986,8 +2988,8 @@ static int gem_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) + pci_set_drvdata(pdev, dev); + + /* We can do scatter/gather and HW checksum */ +- dev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM; +- dev->features |= dev->hw_features | NETIF_F_RXCSUM; ++ dev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_RXCSUM; ++ dev->features = dev->hw_features; + if (pci_using_dac) + dev->features |= NETIF_F_HIGHDMA; + +diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c +index fbc825ac97ab..cb51448389a1 100644 +--- a/drivers/net/geneve.c ++++ b/drivers/net/geneve.c +@@ -474,7 +474,7 @@ static struct sk_buff **geneve_gro_receive(struct sock *sk, + out_unlock: + rcu_read_unlock(); + out: +- NAPI_GRO_CB(skb)->flush |= flush; ++ skb_gro_flush_final(skb, pp, flush); + + return pp; + } +diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h +index 01017dd88802..cb250cacf721 100644 +--- a/drivers/net/hyperv/hyperv_net.h ++++ b/drivers/net/hyperv/hyperv_net.h +@@ -207,7 +207,7 @@ int netvsc_recv_callback(struct net_device *net, + void netvsc_channel_cb(void *context); + int netvsc_poll(struct napi_struct *napi, int budget); + +-void rndis_set_subchannel(struct work_struct *w); ++int rndis_set_subchannel(struct net_device *ndev, struct netvsc_device *nvdev); + int rndis_filter_open(struct netvsc_device *nvdev); + int rndis_filter_close(struct netvsc_device *nvdev); + struct netvsc_device *rndis_filter_device_add(struct hv_device *dev, +diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c +index 4647ecbe6f36..701be5d81062 100644 +--- a/drivers/net/hyperv/netvsc.c ++++ b/drivers/net/hyperv/netvsc.c +@@ -62,6 +62,41 @@ void netvsc_switch_datapath(struct net_device *ndev, bool vf) + VM_PKT_DATA_INBAND, 0); + } + ++/* Worker to setup sub channels on initial setup ++ * Initial hotplug event occurs in softirq context ++ * and can't wait for channels. ++ */ ++static void netvsc_subchan_work(struct work_struct *w) ++{ ++ struct netvsc_device *nvdev = ++ container_of(w, struct netvsc_device, subchan_work); ++ struct rndis_device *rdev; ++ int i, ret; ++ ++ /* Avoid deadlock with device removal already under RTNL */ ++ if (!rtnl_trylock()) { ++ schedule_work(w); ++ return; ++ } ++ ++ rdev = nvdev->extension; ++ if (rdev) { ++ ret = rndis_set_subchannel(rdev->ndev, nvdev); ++ if (ret == 0) { ++ netif_device_attach(rdev->ndev); ++ } else { ++ /* fallback to only primary channel */ ++ for (i = 1; i < nvdev->num_chn; i++) ++ netif_napi_del(&nvdev->chan_table[i].napi); ++ ++ nvdev->max_chn = 1; ++ nvdev->num_chn = 1; ++ } ++ } ++ ++ rtnl_unlock(); ++} ++ + static struct netvsc_device *alloc_net_device(void) + { + struct netvsc_device *net_device; +@@ -78,7 +113,7 @@ static struct netvsc_device *alloc_net_device(void) + + init_completion(&net_device->channel_init_wait); + init_waitqueue_head(&net_device->subchan_open); +- INIT_WORK(&net_device->subchan_work, rndis_set_subchannel); ++ INIT_WORK(&net_device->subchan_work, netvsc_subchan_work); + + return net_device; + } +diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c +index 6890478a0851..aeabeb107fed 100644 +--- a/drivers/net/hyperv/netvsc_drv.c ++++ b/drivers/net/hyperv/netvsc_drv.c +@@ -911,8 +911,20 @@ static int netvsc_attach(struct net_device *ndev, + if (IS_ERR(nvdev)) + return PTR_ERR(nvdev); + +- /* Note: enable and attach happen when sub-channels setup */ ++ if (nvdev->num_chn > 1) { ++ ret = rndis_set_subchannel(ndev, nvdev); ++ ++ /* if unavailable, just proceed with one queue */ ++ if (ret) { ++ nvdev->max_chn = 1; ++ nvdev->num_chn = 1; ++ } ++ } ++ ++ /* In any case device is now ready */ ++ netif_device_attach(ndev); + ++ /* Note: enable and attach happen when sub-channels setup */ + netif_carrier_off(ndev); + + if (netif_running(ndev)) { +@@ -2035,6 +2047,9 @@ static int netvsc_probe(struct hv_device *dev, + + memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN); + ++ if (nvdev->num_chn > 1) ++ schedule_work(&nvdev->subchan_work); ++ + /* hw_features computed in rndis_netdev_set_hwcaps() */ + net->features = net->hw_features | + NETIF_F_HIGHDMA | NETIF_F_SG | +diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c +index d1ae184008b4..cb03a6ea076a 100644 +--- a/drivers/net/hyperv/rndis_filter.c ++++ b/drivers/net/hyperv/rndis_filter.c +@@ -1055,29 +1055,15 @@ static void netvsc_sc_open(struct vmbus_channel *new_sc) + * This breaks overlap of processing the host message for the + * new primary channel with the initialization of sub-channels. + */ +-void rndis_set_subchannel(struct work_struct *w) ++int rndis_set_subchannel(struct net_device *ndev, struct netvsc_device *nvdev) + { +- struct netvsc_device *nvdev +- = container_of(w, struct netvsc_device, subchan_work); + struct nvsp_message *init_packet = &nvdev->channel_init_pkt; +- struct net_device_context *ndev_ctx; +- struct rndis_device *rdev; +- struct net_device *ndev; +- struct hv_device *hv_dev; ++ struct net_device_context *ndev_ctx = netdev_priv(ndev); ++ struct hv_device *hv_dev = ndev_ctx->device_ctx; ++ struct rndis_device *rdev = nvdev->extension; + int i, ret; + +- if (!rtnl_trylock()) { +- schedule_work(w); +- return; +- } +- +- rdev = nvdev->extension; +- if (!rdev) +- goto unlock; /* device was removed */ +- +- ndev = rdev->ndev; +- ndev_ctx = netdev_priv(ndev); +- hv_dev = ndev_ctx->device_ctx; ++ ASSERT_RTNL(); + + memset(init_packet, 0, sizeof(struct nvsp_message)); + init_packet->hdr.msg_type = NVSP_MSG5_TYPE_SUBCHANNEL; +@@ -1091,13 +1077,13 @@ void rndis_set_subchannel(struct work_struct *w) + VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); + if (ret) { + netdev_err(ndev, "sub channel allocate send failed: %d\n", ret); +- goto failed; ++ return ret; + } + + wait_for_completion(&nvdev->channel_init_wait); + if (init_packet->msg.v5_msg.subchn_comp.status != NVSP_STAT_SUCCESS) { + netdev_err(ndev, "sub channel request failed\n"); +- goto failed; ++ return -EIO; + } + + nvdev->num_chn = 1 + +@@ -1116,21 +1102,7 @@ void rndis_set_subchannel(struct work_struct *w) + for (i = 0; i < VRSS_SEND_TAB_SIZE; i++) + ndev_ctx->tx_table[i] = i % nvdev->num_chn; + +- netif_device_attach(ndev); +- rtnl_unlock(); +- return; +- +-failed: +- /* fallback to only primary channel */ +- for (i = 1; i < nvdev->num_chn; i++) +- netif_napi_del(&nvdev->chan_table[i].napi); +- +- nvdev->max_chn = 1; +- nvdev->num_chn = 1; +- +- netif_device_attach(ndev); +-unlock: +- rtnl_unlock(); ++ return 0; + } + + static int rndis_netdev_set_hwcaps(struct rndis_device *rndis_device, +@@ -1321,21 +1293,12 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev, + netif_napi_add(net, &net_device->chan_table[i].napi, + netvsc_poll, NAPI_POLL_WEIGHT); + +- if (net_device->num_chn > 1) +- schedule_work(&net_device->subchan_work); ++ return net_device; + + out: +- /* if unavailable, just proceed with one queue */ +- if (ret) { +- net_device->max_chn = 1; +- net_device->num_chn = 1; +- } +- +- /* No sub channels, device is ready */ +- if (net_device->num_chn == 1) +- netif_device_attach(net); +- +- return net_device; ++ /* setting up multiple channels failed */ ++ net_device->max_chn = 1; ++ net_device->num_chn = 1; + + err_dev_remv: + rndis_filter_device_remove(dev, net_device); +diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c +index c74893c1e620..e7f7a1a002ee 100644 +--- a/drivers/net/ipvlan/ipvlan_main.c ++++ b/drivers/net/ipvlan/ipvlan_main.c +@@ -546,7 +546,8 @@ int ipvlan_link_new(struct net *src_net, struct net_device *dev, + ipvlan->dev = dev; + ipvlan->port = port; + ipvlan->sfeatures = IPVLAN_FEATURES; +- ipvlan_adjust_mtu(ipvlan, phy_dev); ++ if (!tb[IFLA_MTU]) ++ ipvlan_adjust_mtu(ipvlan, phy_dev); + INIT_LIST_HEAD(&ipvlan->addrs); + + /* If the port-id base is at the MAX value, then wrap it around and +diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c +index 9881edc568ba..0aa91ab9a0fb 100644 +--- a/drivers/net/usb/lan78xx.c ++++ b/drivers/net/usb/lan78xx.c +@@ -3197,6 +3197,7 @@ static void lan78xx_tx_bh(struct lan78xx_net *dev) + pkt_cnt = 0; + count = 0; + length = 0; ++ spin_lock_irqsave(&tqp->lock, flags); + for (skb = tqp->next; pkt_cnt < tqp->qlen; skb = skb->next) { + if (skb_is_gso(skb)) { + if (pkt_cnt) { +@@ -3205,7 +3206,8 @@ static void lan78xx_tx_bh(struct lan78xx_net *dev) + } + count = 1; + length = skb->len - TX_OVERHEAD; +- skb2 = skb_dequeue(tqp); ++ __skb_unlink(skb, tqp); ++ spin_unlock_irqrestore(&tqp->lock, flags); + goto gso_skb; + } + +@@ -3214,6 +3216,7 @@ static void lan78xx_tx_bh(struct lan78xx_net *dev) + skb_totallen = skb->len + roundup(skb_totallen, sizeof(u32)); + pkt_cnt++; + } ++ spin_unlock_irqrestore(&tqp->lock, flags); + + /* copy to a single skb */ + skb = alloc_skb(skb_totallen, GFP_ATOMIC); +diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c +index b23ee948e7c9..0db500bf86d9 100644 +--- a/drivers/net/usb/qmi_wwan.c ++++ b/drivers/net/usb/qmi_wwan.c +@@ -1245,6 +1245,7 @@ static const struct usb_device_id products[] = { + {QMI_FIXED_INTF(0x413c, 0x81b3, 8)}, /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card (rev3) */ + {QMI_FIXED_INTF(0x413c, 0x81b6, 8)}, /* Dell Wireless 5811e */ + {QMI_FIXED_INTF(0x413c, 0x81b6, 10)}, /* Dell Wireless 5811e */ ++ {QMI_FIXED_INTF(0x413c, 0x81d7, 1)}, /* Dell Wireless 5821e */ + {QMI_FIXED_INTF(0x03f0, 0x4e1d, 8)}, /* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */ + {QMI_FIXED_INTF(0x03f0, 0x9d1d, 1)}, /* HP lt4120 Snapdragon X5 LTE */ + {QMI_FIXED_INTF(0x22de, 0x9061, 3)}, /* WeTelecom WPD-600N */ +diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c +index aa88b640cb6c..0fa64cc1a011 100644 +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -3959,7 +3959,8 @@ static int rtl8152_close(struct net_device *netdev) + #ifdef CONFIG_PM_SLEEP + unregister_pm_notifier(&tp->pm_notifier); + #endif +- napi_disable(&tp->napi); ++ if (!test_bit(RTL8152_UNPLUG, &tp->flags)) ++ napi_disable(&tp->napi); + clear_bit(WORK_ENABLE, &tp->flags); + usb_kill_urb(tp->intr_urb); + cancel_delayed_work_sync(&tp->schedule); +diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c +index 3d9c5b35a4a7..bbdb46916dc3 100644 +--- a/drivers/net/vxlan.c ++++ b/drivers/net/vxlan.c +@@ -623,9 +623,7 @@ static struct sk_buff **vxlan_gro_receive(struct sock *sk, + flush = 0; + + out: +- skb_gro_remcsum_cleanup(skb, &grc); +- skb->remcsum_offload = 0; +- NAPI_GRO_CB(skb)->flush |= flush; ++ skb_gro_flush_final_remcsum(skb, pp, flush, &grc); + + return pp; + } +diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c +index 93256f8bc0b5..ec82c1c3f12e 100644 +--- a/drivers/net/wireless/realtek/rtlwifi/base.c ++++ b/drivers/net/wireless/realtek/rtlwifi/base.c +@@ -483,18 +483,21 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw) + + } + +-void rtl_deinit_deferred_work(struct ieee80211_hw *hw) ++void rtl_deinit_deferred_work(struct ieee80211_hw *hw, bool ips_wq) + { + struct rtl_priv *rtlpriv = rtl_priv(hw); + + del_timer_sync(&rtlpriv->works.watchdog_timer); + +- cancel_delayed_work(&rtlpriv->works.watchdog_wq); +- cancel_delayed_work(&rtlpriv->works.ips_nic_off_wq); +- cancel_delayed_work(&rtlpriv->works.ps_work); +- cancel_delayed_work(&rtlpriv->works.ps_rfon_wq); +- cancel_delayed_work(&rtlpriv->works.fwevt_wq); +- cancel_delayed_work(&rtlpriv->works.c2hcmd_wq); ++ cancel_delayed_work_sync(&rtlpriv->works.watchdog_wq); ++ if (ips_wq) ++ cancel_delayed_work(&rtlpriv->works.ips_nic_off_wq); ++ else ++ cancel_delayed_work_sync(&rtlpriv->works.ips_nic_off_wq); ++ cancel_delayed_work_sync(&rtlpriv->works.ps_work); ++ cancel_delayed_work_sync(&rtlpriv->works.ps_rfon_wq); ++ cancel_delayed_work_sync(&rtlpriv->works.fwevt_wq); ++ cancel_delayed_work_sync(&rtlpriv->works.c2hcmd_wq); + } + EXPORT_SYMBOL_GPL(rtl_deinit_deferred_work); + +diff --git a/drivers/net/wireless/realtek/rtlwifi/base.h b/drivers/net/wireless/realtek/rtlwifi/base.h +index b56d1b7f5567..cbbb5be36a09 100644 +--- a/drivers/net/wireless/realtek/rtlwifi/base.h ++++ b/drivers/net/wireless/realtek/rtlwifi/base.h +@@ -121,7 +121,7 @@ void rtl_init_rfkill(struct ieee80211_hw *hw); + void rtl_deinit_rfkill(struct ieee80211_hw *hw); + + void rtl_watch_dog_timer_callback(unsigned long data); +-void rtl_deinit_deferred_work(struct ieee80211_hw *hw); ++void rtl_deinit_deferred_work(struct ieee80211_hw *hw, bool ips_wq); + + bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx); + int rtlwifi_rate_mapping(struct ieee80211_hw *hw, bool isht, +diff --git a/drivers/net/wireless/realtek/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c +index c53cbf3d52bd..b01123138797 100644 +--- a/drivers/net/wireless/realtek/rtlwifi/core.c ++++ b/drivers/net/wireless/realtek/rtlwifi/core.c +@@ -130,7 +130,6 @@ static void rtl_fw_do_work(const struct firmware *firmware, void *context, + firmware->size); + rtlpriv->rtlhal.wowlan_fwsize = firmware->size; + } +- rtlpriv->rtlhal.fwsize = firmware->size; + release_firmware(firmware); + } + +@@ -196,7 +195,7 @@ static void rtl_op_stop(struct ieee80211_hw *hw) + /* reset sec info */ + rtl_cam_reset_sec_info(hw); + +- rtl_deinit_deferred_work(hw); ++ rtl_deinit_deferred_work(hw, false); + } + rtlpriv->intf_ops->adapter_stop(hw); + +diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c +index d7331225c5f3..457a0f725c8a 100644 +--- a/drivers/net/wireless/realtek/rtlwifi/pci.c ++++ b/drivers/net/wireless/realtek/rtlwifi/pci.c +@@ -2359,7 +2359,7 @@ void rtl_pci_disconnect(struct pci_dev *pdev) + ieee80211_unregister_hw(hw); + rtlmac->mac80211_registered = 0; + } else { +- rtl_deinit_deferred_work(hw); ++ rtl_deinit_deferred_work(hw, false); + rtlpriv->intf_ops->adapter_stop(hw); + } + rtlpriv->cfg->ops->disable_interrupt(hw); +diff --git a/drivers/net/wireless/realtek/rtlwifi/ps.c b/drivers/net/wireless/realtek/rtlwifi/ps.c +index 07ee3096f50e..f6d00613c53d 100644 +--- a/drivers/net/wireless/realtek/rtlwifi/ps.c ++++ b/drivers/net/wireless/realtek/rtlwifi/ps.c +@@ -66,7 +66,7 @@ bool rtl_ps_disable_nic(struct ieee80211_hw *hw) + struct rtl_priv *rtlpriv = rtl_priv(hw); + + /*<1> Stop all timer */ +- rtl_deinit_deferred_work(hw); ++ rtl_deinit_deferred_work(hw, true); + + /*<2> Disable Interrupt */ + rtlpriv->cfg->ops->disable_interrupt(hw); +@@ -287,7 +287,7 @@ void rtl_ips_nic_on(struct ieee80211_hw *hw) + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + enum rf_pwrstate rtstate; + +- cancel_delayed_work(&rtlpriv->works.ips_nic_off_wq); ++ cancel_delayed_work_sync(&rtlpriv->works.ips_nic_off_wq); + + spin_lock(&rtlpriv->locks.ips_lock); + if (ppsc->inactiveps) { +diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c +index 5590d07d0918..820c42ff5384 100644 +--- a/drivers/net/wireless/realtek/rtlwifi/usb.c ++++ b/drivers/net/wireless/realtek/rtlwifi/usb.c +@@ -1150,7 +1150,7 @@ void rtl_usb_disconnect(struct usb_interface *intf) + ieee80211_unregister_hw(hw); + rtlmac->mac80211_registered = 0; + } else { +- rtl_deinit_deferred_work(hw); ++ rtl_deinit_deferred_work(hw, false); + rtlpriv->intf_ops->adapter_stop(hw); + } + /*deinit rfkill */ +diff --git a/drivers/pci/dwc/pci-exynos.c b/drivers/pci/dwc/pci-exynos.c +index 5596fdedbb94..ea03f1ec12a4 100644 +--- a/drivers/pci/dwc/pci-exynos.c ++++ b/drivers/pci/dwc/pci-exynos.c +@@ -695,7 +695,8 @@ static int __init exynos_pcie_probe(struct platform_device *pdev) + return ret; + } + +- if (ep->ops && ep->ops->get_clk_resources) { ++ if (ep->ops && ep->ops->get_clk_resources && ++ ep->ops->init_clk_resources) { + ret = ep->ops->get_clk_resources(ep); + if (ret) + return ret; +diff --git a/drivers/pci/host/pci-hyperv.c b/drivers/pci/host/pci-hyperv.c +index caea7c618207..4523d7e1bcb9 100644 +--- a/drivers/pci/host/pci-hyperv.c ++++ b/drivers/pci/host/pci-hyperv.c +@@ -1091,6 +1091,7 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) + struct pci_bus *pbus; + struct pci_dev *pdev; + struct cpumask *dest; ++ unsigned long flags; + struct compose_comp_ctxt comp; + struct tran_int_desc *int_desc; + struct { +@@ -1182,14 +1183,15 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) + * the channel callback directly when channel->target_cpu is + * the current CPU. When the higher level interrupt code + * calls us with interrupt enabled, let's add the +- * local_bh_disable()/enable() to avoid race. ++ * local_irq_save()/restore() to avoid race: ++ * hv_pci_onchannelcallback() can also run in tasklet. + */ +- local_bh_disable(); ++ local_irq_save(flags); + + if (hbus->hdev->channel->target_cpu == smp_processor_id()) + hv_pci_onchannelcallback(hbus); + +- local_bh_enable(); ++ local_irq_restore(flags); + + if (hpdev->state == hv_pcichild_ejecting) { + dev_err_once(&hbus->hdev->device, +diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c +index 00b8d4cdcac3..c01d1f3a1c7d 100644 +--- a/drivers/usb/host/xhci-hub.c ++++ b/drivers/usb/host/xhci-hub.c +@@ -366,7 +366,7 @@ int xhci_find_slot_id_by_port(struct usb_hcd *hcd, struct xhci_hcd *xhci, + + slot_id = 0; + for (i = 0; i < MAX_HC_SLOTS; i++) { +- if (!xhci->devs[i]) ++ if (!xhci->devs[i] || !xhci->devs[i]->udev) + continue; + speed = xhci->devs[i]->udev->speed; + if (((speed >= USB_SPEED_SUPER) == (hcd->speed >= HCD_USB3)) +diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c +index b0d606b2d06c..6123b4dd8638 100644 +--- a/drivers/vhost/net.c ++++ b/drivers/vhost/net.c +@@ -1186,7 +1186,8 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd) + if (ubufs) + vhost_net_ubuf_put_wait_and_free(ubufs); + err_ubufs: +- sockfd_put(sock); ++ if (sock) ++ sockfd_put(sock); + err_vq: + mutex_unlock(&vq->mutex); + err: +diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c +index b7c816f39404..6dd63981787a 100644 +--- a/fs/autofs4/dev-ioctl.c ++++ b/fs/autofs4/dev-ioctl.c +@@ -148,6 +148,15 @@ static int validate_dev_ioctl(int cmd, struct autofs_dev_ioctl *param) + cmd); + goto out; + } ++ } else { ++ unsigned int inr = _IOC_NR(cmd); ++ ++ if (inr == AUTOFS_DEV_IOCTL_OPENMOUNT_CMD || ++ inr == AUTOFS_DEV_IOCTL_REQUESTER_CMD || ++ inr == AUTOFS_DEV_IOCTL_ISMOUNTPOINT_CMD) { ++ err = -EINVAL; ++ goto out; ++ } + } + + err = 0; +@@ -284,7 +293,8 @@ static int autofs_dev_ioctl_openmount(struct file *fp, + dev_t devid; + int err, fd; + +- /* param->path has already been checked */ ++ /* param->path has been checked in validate_dev_ioctl() */ ++ + if (!param->openmount.devid) + return -EINVAL; + +@@ -446,10 +456,7 @@ static int autofs_dev_ioctl_requester(struct file *fp, + dev_t devid; + int err = -ENOENT; + +- if (param->size <= AUTOFS_DEV_IOCTL_SIZE) { +- err = -EINVAL; +- goto out; +- } ++ /* param->path has been checked in validate_dev_ioctl() */ + + devid = sbi->sb->s_dev; + +@@ -534,10 +541,7 @@ static int autofs_dev_ioctl_ismountpoint(struct file *fp, + unsigned int devid, magic; + int err = -ENOENT; + +- if (param->size <= AUTOFS_DEV_IOCTL_SIZE) { +- err = -EINVAL; +- goto out; +- } ++ /* param->path has been checked in validate_dev_ioctl() */ + + name = param->path; + type = param->ismountpoint.in.type; +diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c +index fc4c14a72366..bf4e22df7c97 100644 +--- a/fs/btrfs/tree-log.c ++++ b/fs/btrfs/tree-log.c +@@ -4214,6 +4214,110 @@ static int log_one_extent(struct btrfs_trans_handle *trans, + return ret; + } + ++/* ++ * Log all prealloc extents beyond the inode's i_size to make sure we do not ++ * lose them after doing a fast fsync and replaying the log. We scan the ++ * subvolume's root instead of iterating the inode's extent map tree because ++ * otherwise we can log incorrect extent items based on extent map conversion. ++ * That can happen due to the fact that extent maps are merged when they ++ * are not in the extent map tree's list of modified extents. ++ */ ++static int btrfs_log_prealloc_extents(struct btrfs_trans_handle *trans, ++ struct btrfs_inode *inode, ++ struct btrfs_path *path) ++{ ++ struct btrfs_root *root = inode->root; ++ struct btrfs_key key; ++ const u64 i_size = i_size_read(&inode->vfs_inode); ++ const u64 ino = btrfs_ino(inode); ++ struct btrfs_path *dst_path = NULL; ++ u64 last_extent = (u64)-1; ++ int ins_nr = 0; ++ int start_slot; ++ int ret; ++ ++ if (!(inode->flags & BTRFS_INODE_PREALLOC)) ++ return 0; ++ ++ key.objectid = ino; ++ key.type = BTRFS_EXTENT_DATA_KEY; ++ key.offset = i_size; ++ ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); ++ if (ret < 0) ++ goto out; ++ ++ while (true) { ++ struct extent_buffer *leaf = path->nodes[0]; ++ int slot = path->slots[0]; ++ ++ if (slot >= btrfs_header_nritems(leaf)) { ++ if (ins_nr > 0) { ++ ret = copy_items(trans, inode, dst_path, path, ++ &last_extent, start_slot, ++ ins_nr, 1, 0); ++ if (ret < 0) ++ goto out; ++ ins_nr = 0; ++ } ++ ret = btrfs_next_leaf(root, path); ++ if (ret < 0) ++ goto out; ++ if (ret > 0) { ++ ret = 0; ++ break; ++ } ++ continue; ++ } ++ ++ btrfs_item_key_to_cpu(leaf, &key, slot); ++ if (key.objectid > ino) ++ break; ++ if (WARN_ON_ONCE(key.objectid < ino) || ++ key.type < BTRFS_EXTENT_DATA_KEY || ++ key.offset < i_size) { ++ path->slots[0]++; ++ continue; ++ } ++ if (last_extent == (u64)-1) { ++ last_extent = key.offset; ++ /* ++ * Avoid logging extent items logged in past fsync calls ++ * and leading to duplicate keys in the log tree. ++ */ ++ do { ++ ret = btrfs_truncate_inode_items(trans, ++ root->log_root, ++ &inode->vfs_inode, ++ i_size, ++ BTRFS_EXTENT_DATA_KEY); ++ } while (ret == -EAGAIN); ++ if (ret) ++ goto out; ++ } ++ if (ins_nr == 0) ++ start_slot = slot; ++ ins_nr++; ++ path->slots[0]++; ++ if (!dst_path) { ++ dst_path = btrfs_alloc_path(); ++ if (!dst_path) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ } ++ } ++ if (ins_nr > 0) { ++ ret = copy_items(trans, inode, dst_path, path, &last_extent, ++ start_slot, ins_nr, 1, 0); ++ if (ret > 0) ++ ret = 0; ++ } ++out: ++ btrfs_release_path(path); ++ btrfs_free_path(dst_path); ++ return ret; ++} ++ + static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans, + struct btrfs_root *root, + struct btrfs_inode *inode, +@@ -4256,6 +4360,11 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans, + if (em->generation <= test_gen) + continue; + ++ /* We log prealloc extents beyond eof later. */ ++ if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags) && ++ em->start >= i_size_read(&inode->vfs_inode)) ++ continue; ++ + if (em->start < logged_start) + logged_start = em->start; + if ((em->start + em->len - 1) > logged_end) +@@ -4268,31 +4377,6 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans, + num++; + } + +- /* +- * Add all prealloc extents beyond the inode's i_size to make sure we +- * don't lose them after doing a fast fsync and replaying the log. +- */ +- if (inode->flags & BTRFS_INODE_PREALLOC) { +- struct rb_node *node; +- +- for (node = rb_last(&tree->map); node; node = rb_prev(node)) { +- em = rb_entry(node, struct extent_map, rb_node); +- if (em->start < i_size_read(&inode->vfs_inode)) +- break; +- if (!list_empty(&em->list)) +- continue; +- /* Same as above loop. */ +- if (++num > 32768) { +- list_del_init(&tree->modified_extents); +- ret = -EFBIG; +- goto process; +- } +- refcount_inc(&em->refs); +- set_bit(EXTENT_FLAG_LOGGING, &em->flags); +- list_add_tail(&em->list, &extents); +- } +- } +- + list_sort(NULL, &extents, extent_cmp); + btrfs_get_logged_extents(inode, logged_list, logged_start, logged_end); + /* +@@ -4337,6 +4421,9 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans, + up_write(&inode->dio_sem); + + btrfs_release_path(path); ++ if (!ret) ++ ret = btrfs_log_prealloc_extents(trans, inode, path); ++ + return ret; + } + +diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c +index 88a31e9340a0..d1516327b787 100644 +--- a/fs/ocfs2/aops.c ++++ b/fs/ocfs2/aops.c +@@ -134,6 +134,19 @@ static int ocfs2_symlink_get_block(struct inode *inode, sector_t iblock, + return err; + } + ++static int ocfs2_lock_get_block(struct inode *inode, sector_t iblock, ++ struct buffer_head *bh_result, int create) ++{ ++ int ret = 0; ++ struct ocfs2_inode_info *oi = OCFS2_I(inode); ++ ++ down_read(&oi->ip_alloc_sem); ++ ret = ocfs2_get_block(inode, iblock, bh_result, create); ++ up_read(&oi->ip_alloc_sem); ++ ++ return ret; ++} ++ + int ocfs2_get_block(struct inode *inode, sector_t iblock, + struct buffer_head *bh_result, int create) + { +@@ -2128,7 +2141,7 @@ static void ocfs2_dio_free_write_ctx(struct inode *inode, + * called like this: dio->get_blocks(dio->inode, fs_startblk, + * fs_count, map_bh, dio->rw == WRITE); + */ +-static int ocfs2_dio_get_block(struct inode *inode, sector_t iblock, ++static int ocfs2_dio_wr_get_block(struct inode *inode, sector_t iblock, + struct buffer_head *bh_result, int create) + { + struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); +@@ -2154,12 +2167,9 @@ static int ocfs2_dio_get_block(struct inode *inode, sector_t iblock, + * while file size will be changed. + */ + if (pos + total_len <= i_size_read(inode)) { +- down_read(&oi->ip_alloc_sem); +- /* This is the fast path for re-write. */ +- ret = ocfs2_get_block(inode, iblock, bh_result, create); +- +- up_read(&oi->ip_alloc_sem); + ++ /* This is the fast path for re-write. */ ++ ret = ocfs2_lock_get_block(inode, iblock, bh_result, create); + if (buffer_mapped(bh_result) && + !buffer_new(bh_result) && + ret == 0) +@@ -2424,9 +2434,9 @@ static ssize_t ocfs2_direct_IO(struct kiocb *iocb, struct iov_iter *iter) + return 0; + + if (iov_iter_rw(iter) == READ) +- get_block = ocfs2_get_block; ++ get_block = ocfs2_lock_get_block; + else +- get_block = ocfs2_dio_get_block; ++ get_block = ocfs2_dio_wr_get_block; + + return __blockdev_direct_IO(iocb, inode, inode->i_sb->s_bdev, + iter, get_block, +diff --git a/fs/ocfs2/cluster/nodemanager.c b/fs/ocfs2/cluster/nodemanager.c +index b17d180bdc16..c204ac9b49e5 100644 +--- a/fs/ocfs2/cluster/nodemanager.c ++++ b/fs/ocfs2/cluster/nodemanager.c +@@ -40,6 +40,9 @@ char *o2nm_fence_method_desc[O2NM_FENCE_METHODS] = { + "panic", /* O2NM_FENCE_PANIC */ + }; + ++static inline void o2nm_lock_subsystem(void); ++static inline void o2nm_unlock_subsystem(void); ++ + struct o2nm_node *o2nm_get_node_by_num(u8 node_num) + { + struct o2nm_node *node = NULL; +@@ -181,7 +184,10 @@ static struct o2nm_cluster *to_o2nm_cluster_from_node(struct o2nm_node *node) + { + /* through the first node_set .parent + * mycluster/nodes/mynode == o2nm_cluster->o2nm_node_group->o2nm_node */ +- return to_o2nm_cluster(node->nd_item.ci_parent->ci_parent); ++ if (node->nd_item.ci_parent) ++ return to_o2nm_cluster(node->nd_item.ci_parent->ci_parent); ++ else ++ return NULL; + } + + enum { +@@ -194,7 +200,7 @@ static ssize_t o2nm_node_num_store(struct config_item *item, const char *page, + size_t count) + { + struct o2nm_node *node = to_o2nm_node(item); +- struct o2nm_cluster *cluster = to_o2nm_cluster_from_node(node); ++ struct o2nm_cluster *cluster; + unsigned long tmp; + char *p = (char *)page; + int ret = 0; +@@ -214,6 +220,13 @@ static ssize_t o2nm_node_num_store(struct config_item *item, const char *page, + !test_bit(O2NM_NODE_ATTR_PORT, &node->nd_set_attributes)) + return -EINVAL; /* XXX */ + ++ o2nm_lock_subsystem(); ++ cluster = to_o2nm_cluster_from_node(node); ++ if (!cluster) { ++ o2nm_unlock_subsystem(); ++ return -EINVAL; ++ } ++ + write_lock(&cluster->cl_nodes_lock); + if (cluster->cl_nodes[tmp]) + ret = -EEXIST; +@@ -226,6 +239,8 @@ static ssize_t o2nm_node_num_store(struct config_item *item, const char *page, + set_bit(tmp, cluster->cl_nodes_bitmap); + } + write_unlock(&cluster->cl_nodes_lock); ++ o2nm_unlock_subsystem(); ++ + if (ret) + return ret; + +@@ -269,7 +284,7 @@ static ssize_t o2nm_node_ipv4_address_store(struct config_item *item, + size_t count) + { + struct o2nm_node *node = to_o2nm_node(item); +- struct o2nm_cluster *cluster = to_o2nm_cluster_from_node(node); ++ struct o2nm_cluster *cluster; + int ret, i; + struct rb_node **p, *parent; + unsigned int octets[4]; +@@ -286,6 +301,13 @@ static ssize_t o2nm_node_ipv4_address_store(struct config_item *item, + be32_add_cpu(&ipv4_addr, octets[i] << (i * 8)); + } + ++ o2nm_lock_subsystem(); ++ cluster = to_o2nm_cluster_from_node(node); ++ if (!cluster) { ++ o2nm_unlock_subsystem(); ++ return -EINVAL; ++ } ++ + ret = 0; + write_lock(&cluster->cl_nodes_lock); + if (o2nm_node_ip_tree_lookup(cluster, ipv4_addr, &p, &parent)) +@@ -298,6 +320,8 @@ static ssize_t o2nm_node_ipv4_address_store(struct config_item *item, + rb_insert_color(&node->nd_ip_node, &cluster->cl_node_ip_tree); + } + write_unlock(&cluster->cl_nodes_lock); ++ o2nm_unlock_subsystem(); ++ + if (ret) + return ret; + +@@ -315,7 +339,7 @@ static ssize_t o2nm_node_local_store(struct config_item *item, const char *page, + size_t count) + { + struct o2nm_node *node = to_o2nm_node(item); +- struct o2nm_cluster *cluster = to_o2nm_cluster_from_node(node); ++ struct o2nm_cluster *cluster; + unsigned long tmp; + char *p = (char *)page; + ssize_t ret; +@@ -333,17 +357,26 @@ static ssize_t o2nm_node_local_store(struct config_item *item, const char *page, + !test_bit(O2NM_NODE_ATTR_PORT, &node->nd_set_attributes)) + return -EINVAL; /* XXX */ + ++ o2nm_lock_subsystem(); ++ cluster = to_o2nm_cluster_from_node(node); ++ if (!cluster) { ++ ret = -EINVAL; ++ goto out; ++ } ++ + /* the only failure case is trying to set a new local node + * when a different one is already set */ + if (tmp && tmp == cluster->cl_has_local && +- cluster->cl_local_node != node->nd_num) +- return -EBUSY; ++ cluster->cl_local_node != node->nd_num) { ++ ret = -EBUSY; ++ goto out; ++ } + + /* bring up the rx thread if we're setting the new local node. */ + if (tmp && !cluster->cl_has_local) { + ret = o2net_start_listening(node); + if (ret) +- return ret; ++ goto out; + } + + if (!tmp && cluster->cl_has_local && +@@ -358,7 +391,11 @@ static ssize_t o2nm_node_local_store(struct config_item *item, const char *page, + cluster->cl_local_node = node->nd_num; + } + +- return count; ++ ret = count; ++ ++out: ++ o2nm_unlock_subsystem(); ++ return ret; + } + + CONFIGFS_ATTR(o2nm_node_, num); +@@ -738,6 +775,16 @@ static struct o2nm_cluster_group o2nm_cluster_group = { + }, + }; + ++static inline void o2nm_lock_subsystem(void) ++{ ++ mutex_lock(&o2nm_cluster_group.cs_subsys.su_mutex); ++} ++ ++static inline void o2nm_unlock_subsystem(void) ++{ ++ mutex_unlock(&o2nm_cluster_group.cs_subsys.su_mutex); ++} ++ + int o2nm_depend_item(struct config_item *item) + { + return configfs_depend_item(&o2nm_cluster_group.cs_subsys, item); +diff --git a/fs/reiserfs/prints.c b/fs/reiserfs/prints.c +index 64f49cafbc5b..cfb0c9ac2de4 100644 +--- a/fs/reiserfs/prints.c ++++ b/fs/reiserfs/prints.c +@@ -76,83 +76,99 @@ static char *le_type(struct reiserfs_key *key) + } + + /* %k */ +-static void sprintf_le_key(char *buf, struct reiserfs_key *key) ++static int scnprintf_le_key(char *buf, size_t size, struct reiserfs_key *key) + { + if (key) +- sprintf(buf, "[%d %d %s %s]", le32_to_cpu(key->k_dir_id), +- le32_to_cpu(key->k_objectid), le_offset(key), +- le_type(key)); ++ return scnprintf(buf, size, "[%d %d %s %s]", ++ le32_to_cpu(key->k_dir_id), ++ le32_to_cpu(key->k_objectid), le_offset(key), ++ le_type(key)); + else +- sprintf(buf, "[NULL]"); ++ return scnprintf(buf, size, "[NULL]"); + } + + /* %K */ +-static void sprintf_cpu_key(char *buf, struct cpu_key *key) ++static int scnprintf_cpu_key(char *buf, size_t size, struct cpu_key *key) + { + if (key) +- sprintf(buf, "[%d %d %s %s]", key->on_disk_key.k_dir_id, +- key->on_disk_key.k_objectid, reiserfs_cpu_offset(key), +- cpu_type(key)); ++ return scnprintf(buf, size, "[%d %d %s %s]", ++ key->on_disk_key.k_dir_id, ++ key->on_disk_key.k_objectid, ++ reiserfs_cpu_offset(key), cpu_type(key)); + else +- sprintf(buf, "[NULL]"); ++ return scnprintf(buf, size, "[NULL]"); + } + +-static void sprintf_de_head(char *buf, struct reiserfs_de_head *deh) ++static int scnprintf_de_head(char *buf, size_t size, ++ struct reiserfs_de_head *deh) + { + if (deh) +- sprintf(buf, +- "[offset=%d dir_id=%d objectid=%d location=%d state=%04x]", +- deh_offset(deh), deh_dir_id(deh), deh_objectid(deh), +- deh_location(deh), deh_state(deh)); ++ return scnprintf(buf, size, ++ "[offset=%d dir_id=%d objectid=%d location=%d state=%04x]", ++ deh_offset(deh), deh_dir_id(deh), ++ deh_objectid(deh), deh_location(deh), ++ deh_state(deh)); + else +- sprintf(buf, "[NULL]"); ++ return scnprintf(buf, size, "[NULL]"); + + } + +-static void sprintf_item_head(char *buf, struct item_head *ih) ++static int scnprintf_item_head(char *buf, size_t size, struct item_head *ih) + { + if (ih) { +- strcpy(buf, +- (ih_version(ih) == KEY_FORMAT_3_6) ? "*3.6* " : "*3.5*"); +- sprintf_le_key(buf + strlen(buf), &(ih->ih_key)); +- sprintf(buf + strlen(buf), ", item_len %d, item_location %d, " +- "free_space(entry_count) %d", +- ih_item_len(ih), ih_location(ih), ih_free_space(ih)); ++ char *p = buf; ++ char * const end = buf + size; ++ ++ p += scnprintf(p, end - p, "%s", ++ (ih_version(ih) == KEY_FORMAT_3_6) ? ++ "*3.6* " : "*3.5*"); ++ ++ p += scnprintf_le_key(p, end - p, &ih->ih_key); ++ ++ p += scnprintf(p, end - p, ++ ", item_len %d, item_location %d, free_space(entry_count) %d", ++ ih_item_len(ih), ih_location(ih), ++ ih_free_space(ih)); ++ return p - buf; + } else +- sprintf(buf, "[NULL]"); ++ return scnprintf(buf, size, "[NULL]"); + } + +-static void sprintf_direntry(char *buf, struct reiserfs_dir_entry *de) ++static int scnprintf_direntry(char *buf, size_t size, ++ struct reiserfs_dir_entry *de) + { + char name[20]; + + memcpy(name, de->de_name, de->de_namelen > 19 ? 19 : de->de_namelen); + name[de->de_namelen > 19 ? 19 : de->de_namelen] = 0; +- sprintf(buf, "\"%s\"==>[%d %d]", name, de->de_dir_id, de->de_objectid); ++ return scnprintf(buf, size, "\"%s\"==>[%d %d]", ++ name, de->de_dir_id, de->de_objectid); + } + +-static void sprintf_block_head(char *buf, struct buffer_head *bh) ++static int scnprintf_block_head(char *buf, size_t size, struct buffer_head *bh) + { +- sprintf(buf, "level=%d, nr_items=%d, free_space=%d rdkey ", +- B_LEVEL(bh), B_NR_ITEMS(bh), B_FREE_SPACE(bh)); ++ return scnprintf(buf, size, ++ "level=%d, nr_items=%d, free_space=%d rdkey ", ++ B_LEVEL(bh), B_NR_ITEMS(bh), B_FREE_SPACE(bh)); + } + +-static void sprintf_buffer_head(char *buf, struct buffer_head *bh) ++static int scnprintf_buffer_head(char *buf, size_t size, struct buffer_head *bh) + { +- sprintf(buf, +- "dev %pg, size %zd, blocknr %llu, count %d, state 0x%lx, page %p, (%s, %s, %s)", +- bh->b_bdev, bh->b_size, +- (unsigned long long)bh->b_blocknr, atomic_read(&(bh->b_count)), +- bh->b_state, bh->b_page, +- buffer_uptodate(bh) ? "UPTODATE" : "!UPTODATE", +- buffer_dirty(bh) ? "DIRTY" : "CLEAN", +- buffer_locked(bh) ? "LOCKED" : "UNLOCKED"); ++ return scnprintf(buf, size, ++ "dev %pg, size %zd, blocknr %llu, count %d, state 0x%lx, page %p, (%s, %s, %s)", ++ bh->b_bdev, bh->b_size, ++ (unsigned long long)bh->b_blocknr, ++ atomic_read(&(bh->b_count)), ++ bh->b_state, bh->b_page, ++ buffer_uptodate(bh) ? "UPTODATE" : "!UPTODATE", ++ buffer_dirty(bh) ? "DIRTY" : "CLEAN", ++ buffer_locked(bh) ? "LOCKED" : "UNLOCKED"); + } + +-static void sprintf_disk_child(char *buf, struct disk_child *dc) ++static int scnprintf_disk_child(char *buf, size_t size, struct disk_child *dc) + { +- sprintf(buf, "[dc_number=%d, dc_size=%u]", dc_block_number(dc), +- dc_size(dc)); ++ return scnprintf(buf, size, "[dc_number=%d, dc_size=%u]", ++ dc_block_number(dc), dc_size(dc)); + } + + static char *is_there_reiserfs_struct(char *fmt, int *what) +@@ -189,55 +205,60 @@ static void prepare_error_buf(const char *fmt, va_list args) + char *fmt1 = fmt_buf; + char *k; + char *p = error_buf; ++ char * const end = &error_buf[sizeof(error_buf)]; + int what; + + spin_lock(&error_lock); + +- strcpy(fmt1, fmt); ++ if (WARN_ON(strscpy(fmt_buf, fmt, sizeof(fmt_buf)) < 0)) { ++ strscpy(error_buf, "format string too long", end - error_buf); ++ goto out_unlock; ++ } + + while ((k = is_there_reiserfs_struct(fmt1, &what)) != NULL) { + *k = 0; + +- p += vsprintf(p, fmt1, args); ++ p += vscnprintf(p, end - p, fmt1, args); + + switch (what) { + case 'k': +- sprintf_le_key(p, va_arg(args, struct reiserfs_key *)); ++ p += scnprintf_le_key(p, end - p, ++ va_arg(args, struct reiserfs_key *)); + break; + case 'K': +- sprintf_cpu_key(p, va_arg(args, struct cpu_key *)); ++ p += scnprintf_cpu_key(p, end - p, ++ va_arg(args, struct cpu_key *)); + break; + case 'h': +- sprintf_item_head(p, va_arg(args, struct item_head *)); ++ p += scnprintf_item_head(p, end - p, ++ va_arg(args, struct item_head *)); + break; + case 't': +- sprintf_direntry(p, +- va_arg(args, +- struct reiserfs_dir_entry *)); ++ p += scnprintf_direntry(p, end - p, ++ va_arg(args, struct reiserfs_dir_entry *)); + break; + case 'y': +- sprintf_disk_child(p, +- va_arg(args, struct disk_child *)); ++ p += scnprintf_disk_child(p, end - p, ++ va_arg(args, struct disk_child *)); + break; + case 'z': +- sprintf_block_head(p, +- va_arg(args, struct buffer_head *)); ++ p += scnprintf_block_head(p, end - p, ++ va_arg(args, struct buffer_head *)); + break; + case 'b': +- sprintf_buffer_head(p, +- va_arg(args, struct buffer_head *)); ++ p += scnprintf_buffer_head(p, end - p, ++ va_arg(args, struct buffer_head *)); + break; + case 'a': +- sprintf_de_head(p, +- va_arg(args, +- struct reiserfs_de_head *)); ++ p += scnprintf_de_head(p, end - p, ++ va_arg(args, struct reiserfs_de_head *)); + break; + } + +- p += strlen(p); + fmt1 = k + 2; + } +- vsprintf(p, fmt1, args); ++ p += vscnprintf(p, end - p, fmt1, args); ++out_unlock: + spin_unlock(&error_lock); + + } +diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h +index a031897fca76..ca1d2cc2cdfa 100644 +--- a/include/linux/arm-smccc.h ++++ b/include/linux/arm-smccc.h +@@ -80,6 +80,11 @@ + ARM_SMCCC_SMC_32, \ + 0, 0x8000) + ++#define ARM_SMCCC_ARCH_WORKAROUND_2 \ ++ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ ++ ARM_SMCCC_SMC_32, \ ++ 0, 0x7fff) ++ + #ifndef __ASSEMBLY__ + + #include +@@ -291,5 +296,10 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1, + */ + #define arm_smccc_1_1_hvc(...) __arm_smccc_1_1(SMCCC_HVC_INST, __VA_ARGS__) + ++/* Return codes defined in ARM DEN 0070A */ ++#define SMCCC_RET_SUCCESS 0 ++#define SMCCC_RET_NOT_SUPPORTED -1 ++#define SMCCC_RET_NOT_REQUIRED -2 ++ + #endif /*__ASSEMBLY__*/ + #endif /*__LINUX_ARM_SMCCC_H*/ +diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h +index 0c27515d2cf6..8124815eb121 100644 +--- a/include/linux/atmdev.h ++++ b/include/linux/atmdev.h +@@ -214,6 +214,7 @@ struct atmphy_ops { + struct atm_skb_data { + struct atm_vcc *vcc; /* ATM VCC */ + unsigned long atm_options; /* ATM layer options */ ++ unsigned int acct_truesize; /* truesize accounted to vcc */ + }; + + #define VCC_HTABLE_SIZE 32 +@@ -241,6 +242,20 @@ void vcc_insert_socket(struct sock *sk); + + void atm_dev_release_vccs(struct atm_dev *dev); + ++static inline void atm_account_tx(struct atm_vcc *vcc, struct sk_buff *skb) ++{ ++ /* ++ * Because ATM skbs may not belong to a sock (and we don't ++ * necessarily want to), skb->truesize may be adjusted, ++ * escaping the hack in pskb_expand_head() which avoids ++ * doing so for some cases. So stash the value of truesize ++ * at the time we accounted it, and atm_pop_raw() can use ++ * that value later, in case it changes. ++ */ ++ refcount_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc); ++ ATM_SKB(skb)->acct_truesize = skb->truesize; ++ ATM_SKB(skb)->atm_options = vcc->atm_options; ++} + + static inline void atm_force_charge(struct atm_vcc *vcc,int truesize) + { +diff --git a/include/linux/backing-dev-defs.h b/include/linux/backing-dev-defs.h +index eac387a3bfef..3c1beffc861a 100644 +--- a/include/linux/backing-dev-defs.h ++++ b/include/linux/backing-dev-defs.h +@@ -22,7 +22,6 @@ struct dentry; + */ + enum wb_state { + WB_registered, /* bdi_register() was done */ +- WB_shutting_down, /* wb_shutdown() in progress */ + WB_writeback_running, /* Writeback is in progress */ + WB_has_dirty_io, /* Dirty inodes on ->b_{dirty|io|more_io} */ + }; +@@ -165,6 +164,7 @@ struct backing_dev_info { + #ifdef CONFIG_CGROUP_WRITEBACK + struct radix_tree_root cgwb_tree; /* radix tree of active cgroup wbs */ + struct rb_root cgwb_congested_tree; /* their congested states */ ++ struct mutex cgwb_release_mutex; /* protect shutdown of wb structs */ + #else + struct bdi_writeback_congested *wb_congested; + #endif +diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h +index f43113b8890b..c11032b06d68 100644 +--- a/include/linux/compiler-gcc.h ++++ b/include/linux/compiler-gcc.h +@@ -65,6 +65,18 @@ + #define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0])) + #endif + ++/* ++ * Feature detection for gnu_inline (gnu89 extern inline semantics). Either ++ * __GNUC_STDC_INLINE__ is defined (not using gnu89 extern inline semantics, ++ * and we opt in to the gnu89 semantics), or __GNUC_STDC_INLINE__ is not ++ * defined so the gnu89 semantics are the default. ++ */ ++#ifdef __GNUC_STDC_INLINE__ ++# define __gnu_inline __attribute__((gnu_inline)) ++#else ++# define __gnu_inline ++#endif ++ + /* + * Force always-inline if the user requests it so via the .config, + * or if gcc is too old. +@@ -72,19 +84,22 @@ + * -Wunused-function. This turns out to avoid the need for complex #ifdef + * directives. Suppress the warning in clang as well by using "unused" + * function attribute, which is redundant but not harmful for gcc. ++ * Prefer gnu_inline, so that extern inline functions do not emit an ++ * externally visible function. This makes extern inline behave as per gnu89 ++ * semantics rather than c99. This prevents multiple symbol definition errors ++ * of extern inline functions at link time. ++ * A lot of inline functions can cause havoc with function tracing. + */ + #if !defined(CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING) || \ + !defined(CONFIG_OPTIMIZE_INLINING) || (__GNUC__ < 4) +-#define inline inline __attribute__((always_inline,unused)) notrace +-#define __inline__ __inline__ __attribute__((always_inline,unused)) notrace +-#define __inline __inline __attribute__((always_inline,unused)) notrace ++#define inline \ ++ inline __attribute__((always_inline, unused)) notrace __gnu_inline + #else +-/* A lot of inline functions can cause havoc with function tracing */ +-#define inline inline __attribute__((unused)) notrace +-#define __inline__ __inline__ __attribute__((unused)) notrace +-#define __inline __inline __attribute__((unused)) notrace ++#define inline inline __attribute__((unused)) notrace __gnu_inline + #endif + ++#define __inline__ inline ++#define __inline inline + #define __always_inline inline __attribute__((always_inline)) + #define noinline __attribute__((noinline)) + +diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h +index f3765155fa4d..1d793d86d55f 100644 +--- a/include/linux/mlx5/mlx5_ifc.h ++++ b/include/linux/mlx5/mlx5_ifc.h +@@ -857,7 +857,7 @@ struct mlx5_ifc_cmd_hca_cap_bits { + u8 reserved_at_1a4[0x1]; + u8 ets[0x1]; + u8 nic_flow_table[0x1]; +- u8 eswitch_flow_table[0x1]; ++ u8 eswitch_manager[0x1]; + u8 early_vf_enable[0x1]; + u8 mcam_reg[0x1]; + u8 pcam_reg[0x1]; +diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h +index 46bf7cc7d5d5..2ea7ee1fb495 100644 +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -2668,11 +2668,31 @@ static inline void skb_gro_flush_final(struct sk_buff *skb, struct sk_buff **pp, + if (PTR_ERR(pp) != -EINPROGRESS) + NAPI_GRO_CB(skb)->flush |= flush; + } ++static inline void skb_gro_flush_final_remcsum(struct sk_buff *skb, ++ struct sk_buff **pp, ++ int flush, ++ struct gro_remcsum *grc) ++{ ++ if (PTR_ERR(pp) != -EINPROGRESS) { ++ NAPI_GRO_CB(skb)->flush |= flush; ++ skb_gro_remcsum_cleanup(skb, grc); ++ skb->remcsum_offload = 0; ++ } ++} + #else + static inline void skb_gro_flush_final(struct sk_buff *skb, struct sk_buff **pp, int flush) + { + NAPI_GRO_CB(skb)->flush |= flush; + } ++static inline void skb_gro_flush_final_remcsum(struct sk_buff *skb, ++ struct sk_buff **pp, ++ int flush, ++ struct gro_remcsum *grc) ++{ ++ NAPI_GRO_CB(skb)->flush |= flush; ++ skb_gro_remcsum_cleanup(skb, grc); ++ skb->remcsum_offload = 0; ++} + #endif + + static inline int dev_hard_header(struct sk_buff *skb, struct net_device *dev, +diff --git a/include/linux/string.h b/include/linux/string.h +index cfd83eb2f926..96115bf561b4 100644 +--- a/include/linux/string.h ++++ b/include/linux/string.h +@@ -28,7 +28,7 @@ extern char * strncpy(char *,const char *, __kernel_size_t); + size_t strlcpy(char *, const char *, size_t); + #endif + #ifndef __HAVE_ARCH_STRSCPY +-ssize_t __must_check strscpy(char *, const char *, size_t); ++ssize_t strscpy(char *, const char *, size_t); + #endif + #ifndef __HAVE_ARCH_STRCAT + extern char * strcat(char *, const char *); +diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c +index 03918a19cf2d..3b71d859ee38 100644 +--- a/kernel/time/clocksource.c ++++ b/kernel/time/clocksource.c +@@ -322,6 +322,8 @@ static void clocksource_enqueue_watchdog(struct clocksource *cs) + { + unsigned long flags; + ++ INIT_LIST_HEAD(&cs->wd_list); ++ + spin_lock_irqsave(&watchdog_lock, flags); + if (cs->flags & CLOCK_SOURCE_MUST_VERIFY) { + /* cs is a clocksource to be watched. */ +diff --git a/mm/backing-dev.c b/mm/backing-dev.c +index 6774e0369ebe..9386c98dac12 100644 +--- a/mm/backing-dev.c ++++ b/mm/backing-dev.c +@@ -356,15 +356,8 @@ static void wb_shutdown(struct bdi_writeback *wb) + spin_lock_bh(&wb->work_lock); + if (!test_and_clear_bit(WB_registered, &wb->state)) { + spin_unlock_bh(&wb->work_lock); +- /* +- * Wait for wb shutdown to finish if someone else is just +- * running wb_shutdown(). Otherwise we could proceed to wb / +- * bdi destruction before wb_shutdown() is finished. +- */ +- wait_on_bit(&wb->state, WB_shutting_down, TASK_UNINTERRUPTIBLE); + return; + } +- set_bit(WB_shutting_down, &wb->state); + spin_unlock_bh(&wb->work_lock); + + cgwb_remove_from_bdi_list(wb); +@@ -376,12 +369,6 @@ static void wb_shutdown(struct bdi_writeback *wb) + mod_delayed_work(bdi_wq, &wb->dwork, 0); + flush_delayed_work(&wb->dwork); + WARN_ON(!list_empty(&wb->work_list)); +- /* +- * Make sure bit gets cleared after shutdown is finished. Matches with +- * the barrier provided by test_and_clear_bit() above. +- */ +- smp_wmb(); +- clear_and_wake_up_bit(WB_shutting_down, &wb->state); + } + + static void wb_exit(struct bdi_writeback *wb) +@@ -505,10 +492,12 @@ static void cgwb_release_workfn(struct work_struct *work) + struct bdi_writeback *wb = container_of(work, struct bdi_writeback, + release_work); + ++ mutex_lock(&wb->bdi->cgwb_release_mutex); + wb_shutdown(wb); + + css_put(wb->memcg_css); + css_put(wb->blkcg_css); ++ mutex_unlock(&wb->bdi->cgwb_release_mutex); + + fprop_local_destroy_percpu(&wb->memcg_completions); + percpu_ref_exit(&wb->refcnt); +@@ -694,6 +683,7 @@ static int cgwb_bdi_init(struct backing_dev_info *bdi) + + INIT_RADIX_TREE(&bdi->cgwb_tree, GFP_ATOMIC); + bdi->cgwb_congested_tree = RB_ROOT; ++ mutex_init(&bdi->cgwb_release_mutex); + + ret = wb_init(&bdi->wb, bdi, 1, GFP_KERNEL); + if (!ret) { +@@ -714,7 +704,10 @@ static void cgwb_bdi_unregister(struct backing_dev_info *bdi) + spin_lock_irq(&cgwb_lock); + radix_tree_for_each_slot(slot, &bdi->cgwb_tree, &iter, 0) + cgwb_kill(*slot); ++ spin_unlock_irq(&cgwb_lock); + ++ mutex_lock(&bdi->cgwb_release_mutex); ++ spin_lock_irq(&cgwb_lock); + while (!list_empty(&bdi->wb_list)) { + wb = list_first_entry(&bdi->wb_list, struct bdi_writeback, + bdi_node); +@@ -723,6 +716,7 @@ static void cgwb_bdi_unregister(struct backing_dev_info *bdi) + spin_lock_irq(&cgwb_lock); + } + spin_unlock_irq(&cgwb_lock); ++ mutex_unlock(&bdi->cgwb_release_mutex); + } + + /** +diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c +index cf2e70003a53..cf82d970b0e4 100644 +--- a/net/8021q/vlan.c ++++ b/net/8021q/vlan.c +@@ -664,7 +664,7 @@ static struct sk_buff **vlan_gro_receive(struct sk_buff **head, + out_unlock: + rcu_read_unlock(); + out: +- NAPI_GRO_CB(skb)->flush |= flush; ++ skb_gro_flush_final(skb, pp, flush); + + return pp; + } +diff --git a/net/atm/br2684.c b/net/atm/br2684.c +index 4e111196f902..bc21f8e8daf2 100644 +--- a/net/atm/br2684.c ++++ b/net/atm/br2684.c +@@ -252,8 +252,7 @@ static int br2684_xmit_vcc(struct sk_buff *skb, struct net_device *dev, + + ATM_SKB(skb)->vcc = atmvcc = brvcc->atmvcc; + pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, atmvcc, atmvcc->dev); +- refcount_add(skb->truesize, &sk_atm(atmvcc)->sk_wmem_alloc); +- ATM_SKB(skb)->atm_options = atmvcc->atm_options; ++ atm_account_tx(atmvcc, skb); + dev->stats.tx_packets++; + dev->stats.tx_bytes += skb->len; + +diff --git a/net/atm/clip.c b/net/atm/clip.c +index 65f706e4344c..60920a42f640 100644 +--- a/net/atm/clip.c ++++ b/net/atm/clip.c +@@ -381,8 +381,7 @@ static netdev_tx_t clip_start_xmit(struct sk_buff *skb, + memcpy(here, llc_oui, sizeof(llc_oui)); + ((__be16 *) here)[3] = skb->protocol; + } +- refcount_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc); +- ATM_SKB(skb)->atm_options = vcc->atm_options; ++ atm_account_tx(vcc, skb); + entry->vccs->last_use = jiffies; + pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, vcc, vcc->dev); + old = xchg(&entry->vccs->xoff, 1); /* assume XOFF ... */ +diff --git a/net/atm/common.c b/net/atm/common.c +index 8a4f99114cd2..9e812c782a37 100644 +--- a/net/atm/common.c ++++ b/net/atm/common.c +@@ -630,10 +630,9 @@ int vcc_sendmsg(struct socket *sock, struct msghdr *m, size_t size) + goto out; + } + pr_debug("%d += %d\n", sk_wmem_alloc_get(sk), skb->truesize); +- refcount_add(skb->truesize, &sk->sk_wmem_alloc); ++ atm_account_tx(vcc, skb); + + skb->dev = NULL; /* for paths shared with net_device interfaces */ +- ATM_SKB(skb)->atm_options = vcc->atm_options; + if (!copy_from_iter_full(skb_put(skb, size), size, &m->msg_iter)) { + kfree_skb(skb); + error = -EFAULT; +diff --git a/net/atm/lec.c b/net/atm/lec.c +index 5741b6474dd9..9f2365694ad4 100644 +--- a/net/atm/lec.c ++++ b/net/atm/lec.c +@@ -182,9 +182,8 @@ lec_send(struct atm_vcc *vcc, struct sk_buff *skb) + struct net_device *dev = skb->dev; + + ATM_SKB(skb)->vcc = vcc; +- ATM_SKB(skb)->atm_options = vcc->atm_options; ++ atm_account_tx(vcc, skb); + +- refcount_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc); + if (vcc->send(vcc, skb) < 0) { + dev->stats.tx_dropped++; + return; +diff --git a/net/atm/mpc.c b/net/atm/mpc.c +index 5677147209e8..db9a1838687c 100644 +--- a/net/atm/mpc.c ++++ b/net/atm/mpc.c +@@ -555,8 +555,7 @@ static int send_via_shortcut(struct sk_buff *skb, struct mpoa_client *mpc) + sizeof(struct llc_snap_hdr)); + } + +- refcount_add(skb->truesize, &sk_atm(entry->shortcut)->sk_wmem_alloc); +- ATM_SKB(skb)->atm_options = entry->shortcut->atm_options; ++ atm_account_tx(entry->shortcut, skb); + entry->shortcut->send(entry->shortcut, skb); + entry->packets_fwded++; + mpc->in_ops->put(entry); +diff --git a/net/atm/pppoatm.c b/net/atm/pppoatm.c +index 21d9d341a619..af8c4b38b746 100644 +--- a/net/atm/pppoatm.c ++++ b/net/atm/pppoatm.c +@@ -350,8 +350,7 @@ static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb) + return 1; + } + +- refcount_add(skb->truesize, &sk_atm(ATM_SKB(skb)->vcc)->sk_wmem_alloc); +- ATM_SKB(skb)->atm_options = ATM_SKB(skb)->vcc->atm_options; ++ atm_account_tx(vcc, skb); + pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n", + skb, ATM_SKB(skb)->vcc, ATM_SKB(skb)->vcc->dev); + ret = ATM_SKB(skb)->vcc->send(ATM_SKB(skb)->vcc, skb) +diff --git a/net/atm/raw.c b/net/atm/raw.c +index ee10e8d46185..b3ba44aab0ee 100644 +--- a/net/atm/raw.c ++++ b/net/atm/raw.c +@@ -35,8 +35,8 @@ static void atm_pop_raw(struct atm_vcc *vcc, struct sk_buff *skb) + struct sock *sk = sk_atm(vcc); + + pr_debug("(%d) %d -= %d\n", +- vcc->vci, sk_wmem_alloc_get(sk), skb->truesize); +- WARN_ON(refcount_sub_and_test(skb->truesize, &sk->sk_wmem_alloc)); ++ vcc->vci, sk_wmem_alloc_get(sk), ATM_SKB(skb)->acct_truesize); ++ WARN_ON(refcount_sub_and_test(ATM_SKB(skb)->acct_truesize, &sk->sk_wmem_alloc)); + dev_kfree_skb_any(skb); + sk->sk_write_space(sk); + } +diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c +index 25738b20676d..54c7fe68040f 100644 +--- a/net/bridge/netfilter/ebtables.c ++++ b/net/bridge/netfilter/ebtables.c +@@ -398,6 +398,12 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct xt_tgchk_param *par, + watcher = xt_request_find_target(NFPROTO_BRIDGE, w->u.name, 0); + if (IS_ERR(watcher)) + return PTR_ERR(watcher); ++ ++ if (watcher->family != NFPROTO_BRIDGE) { ++ module_put(watcher->me); ++ return -ENOENT; ++ } ++ + w->u.watcher = watcher; + + par->target = watcher; +@@ -719,6 +725,13 @@ ebt_check_entry(struct ebt_entry *e, struct net *net, + goto cleanup_watchers; + } + ++ /* Reject UNSPEC, xtables verdicts/return values are incompatible */ ++ if (target->family != NFPROTO_BRIDGE) { ++ module_put(target->me); ++ ret = -ENOENT; ++ goto cleanup_watchers; ++ } ++ + t->u.target = target; + if (t->u.target == &ebt_standard_target) { + if (gap < sizeof(struct ebt_standard_target)) { +diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c +index 119c04317d48..03fcf3ee1534 100644 +--- a/net/dccp/ccids/ccid3.c ++++ b/net/dccp/ccids/ccid3.c +@@ -599,7 +599,7 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk, + { + struct ccid3_hc_rx_sock *hc = ccid3_hc_rx_sk(sk); + struct dccp_sock *dp = dccp_sk(sk); +- ktime_t now = ktime_get_real(); ++ ktime_t now = ktime_get(); + s64 delta = 0; + + switch (fbtype) { +@@ -624,15 +624,14 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk, + case CCID3_FBACK_PERIODIC: + delta = ktime_us_delta(now, hc->rx_tstamp_last_feedback); + if (delta <= 0) +- DCCP_BUG("delta (%ld) <= 0", (long)delta); +- else +- hc->rx_x_recv = scaled_div32(hc->rx_bytes_recv, delta); ++ delta = 1; ++ hc->rx_x_recv = scaled_div32(hc->rx_bytes_recv, delta); + break; + default: + return; + } + +- ccid3_pr_debug("Interval %ldusec, X_recv=%u, 1/p=%u\n", (long)delta, ++ ccid3_pr_debug("Interval %lldusec, X_recv=%u, 1/p=%u\n", delta, + hc->rx_x_recv, hc->rx_pinv); + + hc->rx_tstamp_last_feedback = now; +@@ -679,7 +678,8 @@ static int ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb) + static u32 ccid3_first_li(struct sock *sk) + { + struct ccid3_hc_rx_sock *hc = ccid3_hc_rx_sk(sk); +- u32 x_recv, p, delta; ++ u32 x_recv, p; ++ s64 delta; + u64 fval; + + if (hc->rx_rtt == 0) { +@@ -687,7 +687,9 @@ static u32 ccid3_first_li(struct sock *sk) + hc->rx_rtt = DCCP_FALLBACK_RTT; + } + +- delta = ktime_to_us(net_timedelta(hc->rx_tstamp_last_feedback)); ++ delta = ktime_us_delta(ktime_get(), hc->rx_tstamp_last_feedback); ++ if (delta <= 0) ++ delta = 1; + x_recv = scaled_div32(hc->rx_bytes_recv, delta); + if (x_recv == 0) { /* would also trigger divide-by-zero */ + DCCP_WARN("X_recv==0\n"); +diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c +index f0252768ecf4..5f5d9eafccf5 100644 +--- a/net/dns_resolver/dns_key.c ++++ b/net/dns_resolver/dns_key.c +@@ -87,35 +87,39 @@ dns_resolver_preparse(struct key_preparsed_payload *prep) + opt++; + kdebug("options: '%s'", opt); + do { ++ int opt_len, opt_nlen; + const char *eq; +- int opt_len, opt_nlen, opt_vlen, tmp; ++ char optval[128]; + + next_opt = memchr(opt, '#', end - opt) ?: end; + opt_len = next_opt - opt; +- if (opt_len <= 0 || opt_len > 128) { ++ if (opt_len <= 0 || opt_len > sizeof(optval)) { + pr_warn_ratelimited("Invalid option length (%d) for dns_resolver key\n", + opt_len); + return -EINVAL; + } + +- eq = memchr(opt, '=', opt_len) ?: end; +- opt_nlen = eq - opt; +- eq++; +- opt_vlen = next_opt - eq; /* will be -1 if no value */ ++ eq = memchr(opt, '=', opt_len); ++ if (eq) { ++ opt_nlen = eq - opt; ++ eq++; ++ memcpy(optval, eq, next_opt - eq); ++ optval[next_opt - eq] = '\0'; ++ } else { ++ opt_nlen = opt_len; ++ optval[0] = '\0'; ++ } + +- tmp = opt_vlen >= 0 ? opt_vlen : 0; +- kdebug("option '%*.*s' val '%*.*s'", +- opt_nlen, opt_nlen, opt, tmp, tmp, eq); ++ kdebug("option '%*.*s' val '%s'", ++ opt_nlen, opt_nlen, opt, optval); + + /* see if it's an error number representing a DNS error + * that's to be recorded as the result in this key */ + if (opt_nlen == sizeof(DNS_ERRORNO_OPTION) - 1 && + memcmp(opt, DNS_ERRORNO_OPTION, opt_nlen) == 0) { + kdebug("dns error number option"); +- if (opt_vlen <= 0) +- goto bad_option_value; + +- ret = kstrtoul(eq, 10, &derrno); ++ ret = kstrtoul(optval, 10, &derrno); + if (ret < 0) + goto bad_option_value; + +diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c +index 1540db65241a..c9ec1603666b 100644 +--- a/net/ipv4/fou.c ++++ b/net/ipv4/fou.c +@@ -448,9 +448,7 @@ static struct sk_buff **gue_gro_receive(struct sock *sk, + out_unlock: + rcu_read_unlock(); + out: +- NAPI_GRO_CB(skb)->flush |= flush; +- skb_gro_remcsum_cleanup(skb, &grc); +- skb->remcsum_offload = 0; ++ skb_gro_flush_final_remcsum(skb, pp, flush, &grc); + + return pp; + } +diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c +index 1859c473b21a..6a7d980105f6 100644 +--- a/net/ipv4/gre_offload.c ++++ b/net/ipv4/gre_offload.c +@@ -223,7 +223,7 @@ static struct sk_buff **gre_gro_receive(struct sk_buff **head, + out_unlock: + rcu_read_unlock(); + out: +- NAPI_GRO_CB(skb)->flush |= flush; ++ skb_gro_flush_final(skb, pp, flush); + + return pp; + } +diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c +index e7d15fb0d94d..24b066c32e06 100644 +--- a/net/ipv4/inet_hashtables.c ++++ b/net/ipv4/inet_hashtables.c +@@ -188,9 +188,9 @@ static inline int compute_score(struct sock *sk, struct net *net, + bool dev_match = (sk->sk_bound_dev_if == dif || + sk->sk_bound_dev_if == sdif); + +- if (exact_dif && !dev_match) ++ if (!dev_match) + return -1; +- if (sk->sk_bound_dev_if && dev_match) ++ if (sk->sk_bound_dev_if) + score += 4; + } + if (sk->sk_incoming_cpu == raw_smp_processor_id()) +diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c +index 0989e739d098..5a29dc5083a3 100644 +--- a/net/ipv4/sysctl_net_ipv4.c ++++ b/net/ipv4/sysctl_net_ipv4.c +@@ -258,8 +258,9 @@ static int proc_tcp_fastopen_key(struct ctl_table *ctl, int write, + { + struct ctl_table tbl = { .maxlen = (TCP_FASTOPEN_KEY_LENGTH * 2 + 10) }; + struct tcp_fastopen_context *ctxt; +- int ret; + u32 user_key[4]; /* 16 bytes, matching TCP_FASTOPEN_KEY_LENGTH */ ++ __le32 key[4]; ++ int ret, i; + + tbl.data = kmalloc(tbl.maxlen, GFP_KERNEL); + if (!tbl.data) +@@ -268,11 +269,14 @@ static int proc_tcp_fastopen_key(struct ctl_table *ctl, int write, + rcu_read_lock(); + ctxt = rcu_dereference(tcp_fastopen_ctx); + if (ctxt) +- memcpy(user_key, ctxt->key, TCP_FASTOPEN_KEY_LENGTH); ++ memcpy(key, ctxt->key, TCP_FASTOPEN_KEY_LENGTH); + else +- memset(user_key, 0, sizeof(user_key)); ++ memset(key, 0, sizeof(key)); + rcu_read_unlock(); + ++ for (i = 0; i < ARRAY_SIZE(key); i++) ++ user_key[i] = le32_to_cpu(key[i]); ++ + snprintf(tbl.data, tbl.maxlen, "%08x-%08x-%08x-%08x", + user_key[0], user_key[1], user_key[2], user_key[3]); + ret = proc_dostring(&tbl, write, buffer, lenp, ppos); +@@ -288,12 +292,16 @@ static int proc_tcp_fastopen_key(struct ctl_table *ctl, int write, + * first invocation of tcp_fastopen_cookie_gen + */ + tcp_fastopen_init_key_once(false); +- tcp_fastopen_reset_cipher(user_key, TCP_FASTOPEN_KEY_LENGTH); ++ ++ for (i = 0; i < ARRAY_SIZE(user_key); i++) ++ key[i] = cpu_to_le32(user_key[i]); ++ ++ tcp_fastopen_reset_cipher(key, TCP_FASTOPEN_KEY_LENGTH); + } + + bad_key: + pr_debug("proc FO key set 0x%x-%x-%x-%x <- 0x%s: %u\n", +- user_key[0], user_key[1], user_key[2], user_key[3], ++ user_key[0], user_key[1], user_key[2], user_key[3], + (char *)tbl.data, ret); + kfree(tbl.data); + return ret; +diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +index f0caff3139ed..5711b1b12d28 100644 +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -3194,6 +3194,15 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets, + + if (tcp_is_reno(tp)) { + tcp_remove_reno_sacks(sk, pkts_acked); ++ ++ /* If any of the cumulatively ACKed segments was ++ * retransmitted, non-SACK case cannot confirm that ++ * progress was due to original transmission due to ++ * lack of TCPCB_SACKED_ACKED bits even if some of ++ * the packets may have been never retransmitted. ++ */ ++ if (flag & FLAG_RETRANS_DATA_ACKED) ++ flag &= ~FLAG_ORIG_SACK_ACKED; + } else { + int delta; + +diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c +index ea6e6e7df0ee..cde2719fcb89 100644 +--- a/net/ipv4/udp_offload.c ++++ b/net/ipv4/udp_offload.c +@@ -295,7 +295,7 @@ struct sk_buff **udp_gro_receive(struct sk_buff **head, struct sk_buff *skb, + out_unlock: + rcu_read_unlock(); + out: +- NAPI_GRO_CB(skb)->flush |= flush; ++ skb_gro_flush_final(skb, pp, flush); + return pp; + } + EXPORT_SYMBOL(udp_gro_receive); +diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c +index b01858f5deb1..6dc93ac28261 100644 +--- a/net/ipv6/inet6_hashtables.c ++++ b/net/ipv6/inet6_hashtables.c +@@ -113,9 +113,9 @@ static inline int compute_score(struct sock *sk, struct net *net, + bool dev_match = (sk->sk_bound_dev_if == dif || + sk->sk_bound_dev_if == sdif); + +- if (exact_dif && !dev_match) ++ if (!dev_match) + return -1; +- if (sk->sk_bound_dev_if && dev_match) ++ if (sk->sk_bound_dev_if) + score++; + } + if (sk->sk_incoming_cpu == raw_smp_processor_id()) +diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c +index 64ec23388450..722a9db8c6a7 100644 +--- a/net/ipv6/netfilter/nf_conntrack_reasm.c ++++ b/net/ipv6/netfilter/nf_conntrack_reasm.c +@@ -618,6 +618,8 @@ int nf_ct_frag6_gather(struct net *net, struct sk_buff *skb, u32 user) + fq->q.meat == fq->q.len && + nf_ct_frag6_reasm(fq, skb, dev)) + ret = 0; ++ else ++ skb_dst_drop(skb); + + out_unlock: + spin_unlock_bh(&fq->q.lock); +diff --git a/net/ipv6/seg6_hmac.c b/net/ipv6/seg6_hmac.c +index 33fb35cbfac1..558fe8cc6d43 100644 +--- a/net/ipv6/seg6_hmac.c ++++ b/net/ipv6/seg6_hmac.c +@@ -373,7 +373,7 @@ static int seg6_hmac_init_algo(void) + return -ENOMEM; + + for_each_possible_cpu(cpu) { +- tfm = crypto_alloc_shash(algo->name, 0, GFP_KERNEL); ++ tfm = crypto_alloc_shash(algo->name, 0, 0); + if (IS_ERR(tfm)) + return PTR_ERR(tfm); + p_tfm = per_cpu_ptr(algo->tfms, cpu); +diff --git a/net/nfc/llcp_commands.c b/net/nfc/llcp_commands.c +index 2ceefa183cee..6a196e438b6c 100644 +--- a/net/nfc/llcp_commands.c ++++ b/net/nfc/llcp_commands.c +@@ -752,11 +752,14 @@ int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap, + pr_debug("Fragment %zd bytes remaining %zd", + frag_len, remaining_len); + +- pdu = nfc_alloc_send_skb(sock->dev, &sock->sk, MSG_DONTWAIT, ++ pdu = nfc_alloc_send_skb(sock->dev, &sock->sk, 0, + frag_len + LLCP_HEADER_SIZE, &err); + if (pdu == NULL) { +- pr_err("Could not allocate PDU\n"); +- continue; ++ pr_err("Could not allocate PDU (error=%d)\n", err); ++ len -= remaining_len; ++ if (len == 0) ++ len = err; ++ break; + } + + pdu = llcp_add_header(pdu, dsap, ssap, LLCP_PDU_UI); +diff --git a/net/nsh/nsh.c b/net/nsh/nsh.c +index 6df6f58a8103..5647905c88d6 100644 +--- a/net/nsh/nsh.c ++++ b/net/nsh/nsh.c +@@ -42,7 +42,7 @@ static struct sk_buff *nsh_gso_segment(struct sk_buff *skb, + __skb_pull(skb, nsh_len); + + skb_reset_mac_header(skb); +- skb_reset_mac_len(skb); ++ skb->mac_len = proto == htons(ETH_P_TEB) ? ETH_HLEN : 0; + skb->protocol = proto; + + features &= NETIF_F_SG; +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index 4fe2e34522d6..27dafe36f29c 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -2303,6 +2303,13 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, + if (po->stats.stats1.tp_drops) + status |= TP_STATUS_LOSING; + } ++ ++ if (do_vnet && ++ virtio_net_hdr_from_skb(skb, h.raw + macoff - ++ sizeof(struct virtio_net_hdr), ++ vio_le(), true, 0)) ++ goto drop_n_account; ++ + po->stats.stats1.tp_packets++; + if (copy_skb) { + status |= TP_STATUS_COPY; +@@ -2310,15 +2317,6 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, + } + spin_unlock(&sk->sk_receive_queue.lock); + +- if (do_vnet) { +- if (virtio_net_hdr_from_skb(skb, h.raw + macoff - +- sizeof(struct virtio_net_hdr), +- vio_le(), true, 0)) { +- spin_lock(&sk->sk_receive_queue.lock); +- goto drop_n_account; +- } +- } +- + skb_copy_bits(skb, 0, h.raw + macoff, snaplen); + + if (!(ts_status = tpacket_get_timestamp(skb, &ts, po->tp_tstamp))) +diff --git a/net/rds/loop.c b/net/rds/loop.c +index f2bf78de5688..dac6218a460e 100644 +--- a/net/rds/loop.c ++++ b/net/rds/loop.c +@@ -193,4 +193,5 @@ struct rds_transport rds_loop_transport = { + .inc_copy_to_user = rds_message_inc_copy_to_user, + .inc_free = rds_loop_inc_free, + .t_name = "loopback", ++ .t_type = RDS_TRANS_LOOP, + }; +diff --git a/net/rds/rds.h b/net/rds/rds.h +index d09f6c1facb4..f685d8b514e5 100644 +--- a/net/rds/rds.h ++++ b/net/rds/rds.h +@@ -454,6 +454,11 @@ struct rds_notifier { + int n_status; + }; + ++/* Available as part of RDS core, so doesn't need to participate ++ * in get_preferred transport etc ++ */ ++#define RDS_TRANS_LOOP 3 ++ + /** + * struct rds_transport - transport specific behavioural hooks + * +diff --git a/net/rds/recv.c b/net/rds/recv.c +index 555f07ccf0dc..c27cceae52e1 100644 +--- a/net/rds/recv.c ++++ b/net/rds/recv.c +@@ -103,6 +103,11 @@ static void rds_recv_rcvbuf_delta(struct rds_sock *rs, struct sock *sk, + rds_stats_add(s_recv_bytes_added_to_socket, delta); + else + rds_stats_add(s_recv_bytes_removed_from_socket, -delta); ++ ++ /* loop transport doesn't send/recv congestion updates */ ++ if (rs->rs_transport->t_type == RDS_TRANS_LOOP) ++ return; ++ + now_congested = rs->rs_rcv_bytes > rds_sk_rcvbuf(rs); + + rdsdebug("rs %p (%pI4:%u) recv bytes %d buf %d " +diff --git a/net/sched/sch_blackhole.c b/net/sched/sch_blackhole.c +index c98a61e980ba..9c4c2bb547d7 100644 +--- a/net/sched/sch_blackhole.c ++++ b/net/sched/sch_blackhole.c +@@ -21,7 +21,7 @@ static int blackhole_enqueue(struct sk_buff *skb, struct Qdisc *sch, + struct sk_buff **to_free) + { + qdisc_drop(skb, sch, to_free); +- return NET_XMIT_SUCCESS; ++ return NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; + } + + static struct sk_buff *blackhole_dequeue(struct Qdisc *sch) +diff --git a/net/strparser/strparser.c b/net/strparser/strparser.c +index c741365f77da..a68c754e84ea 100644 +--- a/net/strparser/strparser.c ++++ b/net/strparser/strparser.c +@@ -35,7 +35,6 @@ struct _strp_msg { + */ + struct strp_msg strp; + int accum_len; +- int early_eaten; + }; + + static inline struct _strp_msg *_strp_msg(struct sk_buff *skb) +@@ -115,20 +114,6 @@ static int __strp_recv(read_descriptor_t *desc, struct sk_buff *orig_skb, + head = strp->skb_head; + if (head) { + /* Message already in progress */ +- +- stm = _strp_msg(head); +- if (unlikely(stm->early_eaten)) { +- /* Already some number of bytes on the receive sock +- * data saved in skb_head, just indicate they +- * are consumed. +- */ +- eaten = orig_len <= stm->early_eaten ? +- orig_len : stm->early_eaten; +- stm->early_eaten -= eaten; +- +- return eaten; +- } +- + if (unlikely(orig_offset)) { + /* Getting data with a non-zero offset when a message is + * in progress is not expected. If it does happen, we +@@ -297,9 +282,9 @@ static int __strp_recv(read_descriptor_t *desc, struct sk_buff *orig_skb, + } + + stm->accum_len += cand_len; ++ eaten += cand_len; + strp->need_bytes = stm->strp.full_len - + stm->accum_len; +- stm->early_eaten = cand_len; + STRP_STATS_ADD(strp->stats.bytes, cand_len); + desc->count = 0; /* Stop reading socket */ + break; +diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c +index 97b9d4f671ac..2aaf46599126 100644 +--- a/net/sunrpc/xprtrdma/verbs.c ++++ b/net/sunrpc/xprtrdma/verbs.c +@@ -270,7 +270,6 @@ rpcrdma_conn_upcall(struct rdma_cm_id *id, struct rdma_cm_event *event) + wait_for_completion(&ia->ri_remove_done); + + ia->ri_id = NULL; +- ia->ri_pd = NULL; + ia->ri_device = NULL; + /* Return 1 to ensure the core destroys the id. */ + return 1; +@@ -464,7 +463,9 @@ rpcrdma_ia_remove(struct rpcrdma_ia *ia) + ia->ri_id->qp = NULL; + } + ib_free_cq(ep->rep_attr.recv_cq); ++ ep->rep_attr.recv_cq = NULL; + ib_free_cq(ep->rep_attr.send_cq); ++ ep->rep_attr.send_cq = NULL; + + /* The ULP is responsible for ensuring all DMA + * mappings and MRs are gone. +@@ -477,6 +478,8 @@ rpcrdma_ia_remove(struct rpcrdma_ia *ia) + rpcrdma_dma_unmap_regbuf(req->rl_recvbuf); + } + rpcrdma_destroy_mrs(buf); ++ ib_dealloc_pd(ia->ri_pd); ++ ia->ri_pd = NULL; + + /* Allow waiters to continue */ + complete(&ia->ri_remove_done); +@@ -650,14 +653,16 @@ rpcrdma_ep_destroy(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia) + + cancel_delayed_work_sync(&ep->rep_connect_worker); + +- if (ia->ri_id->qp) { ++ if (ia->ri_id && ia->ri_id->qp) { + rpcrdma_ep_disconnect(ep, ia); + rdma_destroy_qp(ia->ri_id); + ia->ri_id->qp = NULL; + } + +- ib_free_cq(ep->rep_attr.recv_cq); +- ib_free_cq(ep->rep_attr.send_cq); ++ if (ep->rep_attr.recv_cq) ++ ib_free_cq(ep->rep_attr.recv_cq); ++ if (ep->rep_attr.send_cq) ++ ib_free_cq(ep->rep_attr.send_cq); + } + + /* Re-establish a connection after a device removal event. +diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c +index 3c86614462f6..8ee4e667a414 100644 +--- a/net/tls/tls_sw.c ++++ b/net/tls/tls_sw.c +@@ -449,7 +449,7 @@ int tls_sw_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) + ret = tls_push_record(sk, msg->msg_flags, record_type); + if (!ret) + continue; +- if (ret == -EAGAIN) ++ if (ret < 0) + goto send_end; + + copied -= try_to_copy; +diff --git a/net/vmw_vsock/virtio_transport.c b/net/vmw_vsock/virtio_transport.c +index 403d86e80162..fdb294441682 100644 +--- a/net/vmw_vsock/virtio_transport.c ++++ b/net/vmw_vsock/virtio_transport.c +@@ -201,7 +201,7 @@ virtio_transport_send_pkt(struct virtio_vsock_pkt *pkt) + return -ENODEV; + } + +- if (le32_to_cpu(pkt->hdr.dst_cid) == vsock->guest_cid) ++ if (le64_to_cpu(pkt->hdr.dst_cid) == vsock->guest_cid) + return virtio_transport_send_pkt_loopback(vsock, pkt); + + if (pkt->reply) +diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c +index 9bee849db682..d5f1d8364571 100644 +--- a/virt/kvm/arm/arm.c ++++ b/virt/kvm/arm/arm.c +@@ -51,8 +51,8 @@ + __asm__(".arch_extension virt"); + #endif + ++DEFINE_PER_CPU(kvm_cpu_context_t, kvm_host_cpu_state); + static DEFINE_PER_CPU(unsigned long, kvm_arm_hyp_stack_page); +-static kvm_cpu_context_t __percpu *kvm_host_cpu_state; + + /* Per-CPU variable containing the currently running vcpu. */ + static DEFINE_PER_CPU(struct kvm_vcpu *, kvm_arm_running_vcpu); +@@ -351,7 +351,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) + } + + vcpu->cpu = cpu; +- vcpu->arch.host_cpu_context = this_cpu_ptr(kvm_host_cpu_state); ++ vcpu->arch.host_cpu_context = this_cpu_ptr(&kvm_host_cpu_state); + + kvm_arm_set_running_vcpu(vcpu); + +@@ -1259,19 +1259,8 @@ static inline void hyp_cpu_pm_exit(void) + } + #endif + +-static void teardown_common_resources(void) +-{ +- free_percpu(kvm_host_cpu_state); +-} +- + static int init_common_resources(void) + { +- kvm_host_cpu_state = alloc_percpu(kvm_cpu_context_t); +- if (!kvm_host_cpu_state) { +- kvm_err("Cannot allocate host CPU state\n"); +- return -ENOMEM; +- } +- + /* set size of VMID supported by CPU */ + kvm_vmid_bits = kvm_get_vmid_bits(); + kvm_info("%d-bit VMID\n", kvm_vmid_bits); +@@ -1413,7 +1402,7 @@ static int init_hyp_mode(void) + for_each_possible_cpu(cpu) { + kvm_cpu_context_t *cpu_ctxt; + +- cpu_ctxt = per_cpu_ptr(kvm_host_cpu_state, cpu); ++ cpu_ctxt = per_cpu_ptr(&kvm_host_cpu_state, cpu); + err = create_hyp_mappings(cpu_ctxt, cpu_ctxt + 1, PAGE_HYP); + + if (err) { +@@ -1422,6 +1411,10 @@ static int init_hyp_mode(void) + } + } + ++ err = hyp_map_aux_data(); ++ if (err) ++ kvm_err("Cannot map host auxilary data: %d\n", err); ++ + return 0; + + out_err: +@@ -1497,7 +1490,6 @@ int kvm_arch_init(void *opaque) + if (!in_hyp_mode) + teardown_hyp_mode(); + out_err: +- teardown_common_resources(); + return err; + } + +diff --git a/virt/kvm/arm/hyp/vgic-v2-sr.c b/virt/kvm/arm/hyp/vgic-v2-sr.c +index d7fd46fe9efb..4b4221b0d4ba 100644 +--- a/virt/kvm/arm/hyp/vgic-v2-sr.c ++++ b/virt/kvm/arm/hyp/vgic-v2-sr.c +@@ -139,7 +139,7 @@ int __hyp_text __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu) + return -1; + + rd = kvm_vcpu_dabt_get_rd(vcpu); +- addr = kern_hyp_va((kern_hyp_va(&kvm_vgic_global_state))->vcpu_base_va); ++ addr = kern_hyp_va(hyp_symbol_addr(kvm_vgic_global_state)->vcpu_base_va); + addr += fault_ipa - vgic->vgic_cpu_base; + + if (kvm_vcpu_dabt_iswrite(vcpu)) { +diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c +index c4762bef13c6..c95ab4c5a475 100644 +--- a/virt/kvm/arm/psci.c ++++ b/virt/kvm/arm/psci.c +@@ -405,7 +405,7 @@ static int kvm_psci_call(struct kvm_vcpu *vcpu) + int kvm_hvc_call_handler(struct kvm_vcpu *vcpu) + { + u32 func_id = smccc_get_function(vcpu); +- u32 val = PSCI_RET_NOT_SUPPORTED; ++ u32 val = SMCCC_RET_NOT_SUPPORTED; + u32 feature; + + switch (func_id) { +@@ -417,7 +417,21 @@ int kvm_hvc_call_handler(struct kvm_vcpu *vcpu) + switch(feature) { + case ARM_SMCCC_ARCH_WORKAROUND_1: + if (kvm_arm_harden_branch_predictor()) +- val = 0; ++ val = SMCCC_RET_SUCCESS; ++ break; ++ case ARM_SMCCC_ARCH_WORKAROUND_2: ++ switch (kvm_arm_have_ssbd()) { ++ case KVM_SSBD_FORCE_DISABLE: ++ case KVM_SSBD_UNKNOWN: ++ break; ++ case KVM_SSBD_KERNEL: ++ val = SMCCC_RET_SUCCESS; ++ break; ++ case KVM_SSBD_FORCE_ENABLE: ++ case KVM_SSBD_MITIGATED: ++ val = SMCCC_RET_NOT_REQUIRED; ++ break; ++ } + break; + } + break;