From 222c875761d4ab28fe184cf2d4edfdbe2b009aee Mon Sep 17 00:00:00 2001 From: Julian Sikorski Date: Thu, 6 Feb 2025 11:57:44 +0000 Subject: [PATCH] Update odroidxu4-current to 6.6.75 --- .../odroidxu4-6.6/patch-6.6.68-69.patch | 3750 +++++ .../odroidxu4-6.6/patch-6.6.69-70.patch | 12214 ++++++++++++++++ .../odroidxu4-6.6/patch-6.6.70-71.patch | 227 + .../odroidxu4-6.6/patch-6.6.71-72.patch | 4467 ++++++ .../odroidxu4-6.6/patch-6.6.72-73.patch | 586 + .../odroidxu4-6.6/patch-6.6.73-74.patch | 2591 ++++ .../odroidxu4-6.6/patch-6.6.74-75.patch | 1630 +++ 7 files changed, 25465 insertions(+) create mode 100644 patch/kernel/archive/odroidxu4-6.6/patch-6.6.68-69.patch create mode 100644 patch/kernel/archive/odroidxu4-6.6/patch-6.6.69-70.patch create mode 100644 patch/kernel/archive/odroidxu4-6.6/patch-6.6.70-71.patch create mode 100644 patch/kernel/archive/odroidxu4-6.6/patch-6.6.71-72.patch create mode 100644 patch/kernel/archive/odroidxu4-6.6/patch-6.6.72-73.patch create mode 100644 patch/kernel/archive/odroidxu4-6.6/patch-6.6.73-74.patch create mode 100644 patch/kernel/archive/odroidxu4-6.6/patch-6.6.74-75.patch diff --git a/patch/kernel/archive/odroidxu4-6.6/patch-6.6.68-69.patch b/patch/kernel/archive/odroidxu4-6.6/patch-6.6.68-69.patch new file mode 100644 index 0000000000..781cb1f236 --- /dev/null +++ b/patch/kernel/archive/odroidxu4-6.6/patch-6.6.68-69.patch @@ -0,0 +1,3750 @@ +diff --git a/Makefile b/Makefile +index d57bf1b75593d8..ec4d9d1d9b7ae7 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 6 + PATCHLEVEL = 6 +-SUBLEVEL = 68 ++SUBLEVEL = 69 + EXTRAVERSION = + NAME = Pinguïn Aangedreven + +diff --git a/arch/loongarch/include/asm/inst.h b/arch/loongarch/include/asm/inst.h +index 71e1ed4165c80d..4fa53ad82efb32 100644 +--- a/arch/loongarch/include/asm/inst.h ++++ b/arch/loongarch/include/asm/inst.h +@@ -655,7 +655,17 @@ DEF_EMIT_REG2I16_FORMAT(blt, blt_op) + DEF_EMIT_REG2I16_FORMAT(bge, bge_op) + DEF_EMIT_REG2I16_FORMAT(bltu, bltu_op) + DEF_EMIT_REG2I16_FORMAT(bgeu, bgeu_op) +-DEF_EMIT_REG2I16_FORMAT(jirl, jirl_op) ++ ++static inline void emit_jirl(union loongarch_instruction *insn, ++ enum loongarch_gpr rd, ++ enum loongarch_gpr rj, ++ int offset) ++{ ++ insn->reg2i16_format.opcode = jirl_op; ++ insn->reg2i16_format.immediate = offset; ++ insn->reg2i16_format.rd = rd; ++ insn->reg2i16_format.rj = rj; ++} + + #define DEF_EMIT_REG2BSTRD_FORMAT(NAME, OP) \ + static inline void emit_##NAME(union loongarch_instruction *insn, \ +diff --git a/arch/loongarch/kernel/efi.c b/arch/loongarch/kernel/efi.c +index de4f3def4af0b9..4ae77e9300d580 100644 +--- a/arch/loongarch/kernel/efi.c ++++ b/arch/loongarch/kernel/efi.c +@@ -90,7 +90,7 @@ static void __init init_screen_info(void) + memset(si, 0, sizeof(*si)); + early_memunmap(si, sizeof(*si)); + +- memblock_reserve(screen_info.lfb_base, screen_info.lfb_size); ++ memblock_reserve(__screen_info_lfb_base(&screen_info), screen_info.lfb_size); + } + + void __init efi_init(void) +diff --git a/arch/loongarch/kernel/inst.c b/arch/loongarch/kernel/inst.c +index 3050329556d118..14d7d700bcb98f 100644 +--- a/arch/loongarch/kernel/inst.c ++++ b/arch/loongarch/kernel/inst.c +@@ -332,7 +332,7 @@ u32 larch_insn_gen_jirl(enum loongarch_gpr rd, enum loongarch_gpr rj, int imm) + return INSN_BREAK; + } + +- emit_jirl(&insn, rj, rd, imm >> 2); ++ emit_jirl(&insn, rd, rj, imm >> 2); + + return insn.word; + } +diff --git a/arch/loongarch/net/bpf_jit.c b/arch/loongarch/net/bpf_jit.c +index 497f8b0a5f1efb..6595e992fda852 100644 +--- a/arch/loongarch/net/bpf_jit.c ++++ b/arch/loongarch/net/bpf_jit.c +@@ -181,13 +181,13 @@ static void __build_epilogue(struct jit_ctx *ctx, bool is_tail_call) + /* Set return value */ + emit_insn(ctx, addiw, LOONGARCH_GPR_A0, regmap[BPF_REG_0], 0); + /* Return to the caller */ +- emit_insn(ctx, jirl, LOONGARCH_GPR_RA, LOONGARCH_GPR_ZERO, 0); ++ emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_RA, 0); + } else { + /* + * Call the next bpf prog and skip the first instruction + * of TCC initialization. + */ +- emit_insn(ctx, jirl, LOONGARCH_GPR_T3, LOONGARCH_GPR_ZERO, 1); ++ emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_T3, 1); + } + } + +@@ -841,7 +841,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext + return ret; + + move_addr(ctx, t1, func_addr); +- emit_insn(ctx, jirl, t1, LOONGARCH_GPR_RA, 0); ++ emit_insn(ctx, jirl, LOONGARCH_GPR_RA, t1, 0); + move_reg(ctx, regmap[BPF_REG_0], LOONGARCH_GPR_A0); + break; + +diff --git a/arch/mips/Makefile b/arch/mips/Makefile +index f49807e1f19bc5..0888074f4dfef0 100644 +--- a/arch/mips/Makefile ++++ b/arch/mips/Makefile +@@ -299,7 +299,7 @@ drivers-$(CONFIG_PCI) += arch/mips/pci/ + ifdef CONFIG_64BIT + ifndef KBUILD_SYM32 + ifeq ($(shell expr $(load-y) \< 0xffffffff80000000), 0) +- KBUILD_SYM32 = y ++ KBUILD_SYM32 = $(call cc-option-yn, -msym32) + endif + endif + +diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h +index 2d53704d9f2461..e959a6b1a325ca 100644 +--- a/arch/mips/include/asm/mipsregs.h ++++ b/arch/mips/include/asm/mipsregs.h +@@ -2078,7 +2078,14 @@ do { \ + _ASM_INSN_IF_MIPS(0x4200000c) \ + _ASM_INSN32_IF_MM(0x0000517c) + #else /* !TOOLCHAIN_SUPPORTS_VIRT */ +-#define _ASM_SET_VIRT ".set\tvirt\n\t" ++#if MIPS_ISA_REV >= 5 ++#define _ASM_SET_VIRT_ISA ++#elif defined(CONFIG_64BIT) ++#define _ASM_SET_VIRT_ISA ".set\tmips64r5\n\t" ++#else ++#define _ASM_SET_VIRT_ISA ".set\tmips32r5\n\t" ++#endif ++#define _ASM_SET_VIRT _ASM_SET_VIRT_ISA ".set\tvirt\n\t" + #define _ASM_SET_MFGC0 _ASM_SET_VIRT + #define _ASM_SET_DMFGC0 _ASM_SET_VIRT + #define _ASM_SET_MTGC0 _ASM_SET_VIRT +@@ -2099,7 +2106,6 @@ do { \ + ({ int __res; \ + __asm__ __volatile__( \ + ".set\tpush\n\t" \ +- ".set\tmips32r5\n\t" \ + _ASM_SET_MFGC0 \ + "mfgc0\t%0, " #source ", %1\n\t" \ + _ASM_UNSET_MFGC0 \ +@@ -2113,7 +2119,6 @@ do { \ + ({ unsigned long long __res; \ + __asm__ __volatile__( \ + ".set\tpush\n\t" \ +- ".set\tmips64r5\n\t" \ + _ASM_SET_DMFGC0 \ + "dmfgc0\t%0, " #source ", %1\n\t" \ + _ASM_UNSET_DMFGC0 \ +@@ -2127,7 +2132,6 @@ do { \ + do { \ + __asm__ __volatile__( \ + ".set\tpush\n\t" \ +- ".set\tmips32r5\n\t" \ + _ASM_SET_MTGC0 \ + "mtgc0\t%z0, " #register ", %1\n\t" \ + _ASM_UNSET_MTGC0 \ +@@ -2140,7 +2144,6 @@ do { \ + do { \ + __asm__ __volatile__( \ + ".set\tpush\n\t" \ +- ".set\tmips64r5\n\t" \ + _ASM_SET_DMTGC0 \ + "dmtgc0\t%z0, " #register ", %1\n\t" \ + _ASM_UNSET_DMTGC0 \ +diff --git a/arch/powerpc/platforms/book3s/vas-api.c b/arch/powerpc/platforms/book3s/vas-api.c +index f381b177ea06ad..0b6365d85d1171 100644 +--- a/arch/powerpc/platforms/book3s/vas-api.c ++++ b/arch/powerpc/platforms/book3s/vas-api.c +@@ -464,7 +464,43 @@ static vm_fault_t vas_mmap_fault(struct vm_fault *vmf) + return VM_FAULT_SIGBUS; + } + ++/* ++ * During mmap() paste address, mapping VMA is saved in VAS window ++ * struct which is used to unmap during migration if the window is ++ * still open. But the user space can remove this mapping with ++ * munmap() before closing the window and the VMA address will ++ * be invalid. Set VAS window VMA to NULL in this function which ++ * is called before VMA free. ++ */ ++static void vas_mmap_close(struct vm_area_struct *vma) ++{ ++ struct file *fp = vma->vm_file; ++ struct coproc_instance *cp_inst = fp->private_data; ++ struct vas_window *txwin; ++ ++ /* Should not happen */ ++ if (!cp_inst || !cp_inst->txwin) { ++ pr_err("No attached VAS window for the paste address mmap\n"); ++ return; ++ } ++ ++ txwin = cp_inst->txwin; ++ /* ++ * task_ref.vma is set in coproc_mmap() during mmap paste ++ * address. So it has to be the same VMA that is getting freed. ++ */ ++ if (WARN_ON(txwin->task_ref.vma != vma)) { ++ pr_err("Invalid paste address mmaping\n"); ++ return; ++ } ++ ++ mutex_lock(&txwin->task_ref.mmap_mutex); ++ txwin->task_ref.vma = NULL; ++ mutex_unlock(&txwin->task_ref.mmap_mutex); ++} ++ + static const struct vm_operations_struct vas_vm_ops = { ++ .close = vas_mmap_close, + .fault = vas_mmap_fault, + }; + +diff --git a/arch/x86/include/asm/intel-family.h b/arch/x86/include/asm/intel-family.h +index 197316121f04e1..f81a851c46dca5 100644 +--- a/arch/x86/include/asm/intel-family.h ++++ b/arch/x86/include/asm/intel-family.h +@@ -40,134 +40,221 @@ + * their own names :-( + */ + ++#define IFM(_fam, _model) VFM_MAKE(X86_VENDOR_INTEL, _fam, _model) ++ + /* Wildcard match for FAM6 so X86_MATCH_INTEL_FAM6_MODEL(ANY) works */ + #define INTEL_FAM6_ANY X86_MODEL_ANY ++/* Wildcard match for FAM6 so X86_MATCH_VFM(ANY) works */ ++#define INTEL_ANY IFM(X86_FAMILY_ANY, X86_MODEL_ANY) + + #define INTEL_FAM6_CORE_YONAH 0x0E ++#define INTEL_CORE_YONAH IFM(6, 0x0E) + + #define INTEL_FAM6_CORE2_MEROM 0x0F ++#define INTEL_CORE2_MEROM IFM(6, 0x0F) + #define INTEL_FAM6_CORE2_MEROM_L 0x16 ++#define INTEL_CORE2_MEROM_L IFM(6, 0x16) + #define INTEL_FAM6_CORE2_PENRYN 0x17 ++#define INTEL_CORE2_PENRYN IFM(6, 0x17) + #define INTEL_FAM6_CORE2_DUNNINGTON 0x1D ++#define INTEL_CORE2_DUNNINGTON IFM(6, 0x1D) + + #define INTEL_FAM6_NEHALEM 0x1E ++#define INTEL_NEHALEM IFM(6, 0x1E) + #define INTEL_FAM6_NEHALEM_G 0x1F /* Auburndale / Havendale */ ++#define INTEL_NEHALEM_G IFM(6, 0x1F) /* Auburndale / Havendale */ + #define INTEL_FAM6_NEHALEM_EP 0x1A ++#define INTEL_NEHALEM_EP IFM(6, 0x1A) + #define INTEL_FAM6_NEHALEM_EX 0x2E ++#define INTEL_NEHALEM_EX IFM(6, 0x2E) + + #define INTEL_FAM6_WESTMERE 0x25 ++#define INTEL_WESTMERE IFM(6, 0x25) + #define INTEL_FAM6_WESTMERE_EP 0x2C ++#define INTEL_WESTMERE_EP IFM(6, 0x2C) + #define INTEL_FAM6_WESTMERE_EX 0x2F ++#define INTEL_WESTMERE_EX IFM(6, 0x2F) + + #define INTEL_FAM6_SANDYBRIDGE 0x2A ++#define INTEL_SANDYBRIDGE IFM(6, 0x2A) + #define INTEL_FAM6_SANDYBRIDGE_X 0x2D ++#define INTEL_SANDYBRIDGE_X IFM(6, 0x2D) + #define INTEL_FAM6_IVYBRIDGE 0x3A ++#define INTEL_IVYBRIDGE IFM(6, 0x3A) + #define INTEL_FAM6_IVYBRIDGE_X 0x3E ++#define INTEL_IVYBRIDGE_X IFM(6, 0x3E) + + #define INTEL_FAM6_HASWELL 0x3C ++#define INTEL_HASWELL IFM(6, 0x3C) + #define INTEL_FAM6_HASWELL_X 0x3F ++#define INTEL_HASWELL_X IFM(6, 0x3F) + #define INTEL_FAM6_HASWELL_L 0x45 ++#define INTEL_HASWELL_L IFM(6, 0x45) + #define INTEL_FAM6_HASWELL_G 0x46 ++#define INTEL_HASWELL_G IFM(6, 0x46) + + #define INTEL_FAM6_BROADWELL 0x3D ++#define INTEL_BROADWELL IFM(6, 0x3D) + #define INTEL_FAM6_BROADWELL_G 0x47 ++#define INTEL_BROADWELL_G IFM(6, 0x47) + #define INTEL_FAM6_BROADWELL_X 0x4F ++#define INTEL_BROADWELL_X IFM(6, 0x4F) + #define INTEL_FAM6_BROADWELL_D 0x56 ++#define INTEL_BROADWELL_D IFM(6, 0x56) + + #define INTEL_FAM6_SKYLAKE_L 0x4E /* Sky Lake */ ++#define INTEL_SKYLAKE_L IFM(6, 0x4E) /* Sky Lake */ + #define INTEL_FAM6_SKYLAKE 0x5E /* Sky Lake */ ++#define INTEL_SKYLAKE IFM(6, 0x5E) /* Sky Lake */ + #define INTEL_FAM6_SKYLAKE_X 0x55 /* Sky Lake */ ++#define INTEL_SKYLAKE_X IFM(6, 0x55) /* Sky Lake */ + /* CASCADELAKE_X 0x55 Sky Lake -- s: 7 */ + /* COOPERLAKE_X 0x55 Sky Lake -- s: 11 */ + + #define INTEL_FAM6_KABYLAKE_L 0x8E /* Sky Lake */ ++#define INTEL_KABYLAKE_L IFM(6, 0x8E) /* Sky Lake */ + /* AMBERLAKE_L 0x8E Sky Lake -- s: 9 */ + /* COFFEELAKE_L 0x8E Sky Lake -- s: 10 */ + /* WHISKEYLAKE_L 0x8E Sky Lake -- s: 11,12 */ + + #define INTEL_FAM6_KABYLAKE 0x9E /* Sky Lake */ ++#define INTEL_KABYLAKE IFM(6, 0x9E) /* Sky Lake */ + /* COFFEELAKE 0x9E Sky Lake -- s: 10-13 */ + + #define INTEL_FAM6_COMETLAKE 0xA5 /* Sky Lake */ ++#define INTEL_COMETLAKE IFM(6, 0xA5) /* Sky Lake */ + #define INTEL_FAM6_COMETLAKE_L 0xA6 /* Sky Lake */ ++#define INTEL_COMETLAKE_L IFM(6, 0xA6) /* Sky Lake */ + + #define INTEL_FAM6_CANNONLAKE_L 0x66 /* Palm Cove */ ++#define INTEL_CANNONLAKE_L IFM(6, 0x66) /* Palm Cove */ + + #define INTEL_FAM6_ICELAKE_X 0x6A /* Sunny Cove */ ++#define INTEL_ICELAKE_X IFM(6, 0x6A) /* Sunny Cove */ + #define INTEL_FAM6_ICELAKE_D 0x6C /* Sunny Cove */ ++#define INTEL_ICELAKE_D IFM(6, 0x6C) /* Sunny Cove */ + #define INTEL_FAM6_ICELAKE 0x7D /* Sunny Cove */ ++#define INTEL_ICELAKE IFM(6, 0x7D) /* Sunny Cove */ + #define INTEL_FAM6_ICELAKE_L 0x7E /* Sunny Cove */ ++#define INTEL_ICELAKE_L IFM(6, 0x7E) /* Sunny Cove */ + #define INTEL_FAM6_ICELAKE_NNPI 0x9D /* Sunny Cove */ ++#define INTEL_ICELAKE_NNPI IFM(6, 0x9D) /* Sunny Cove */ + + #define INTEL_FAM6_ROCKETLAKE 0xA7 /* Cypress Cove */ ++#define INTEL_ROCKETLAKE IFM(6, 0xA7) /* Cypress Cove */ + + #define INTEL_FAM6_TIGERLAKE_L 0x8C /* Willow Cove */ ++#define INTEL_TIGERLAKE_L IFM(6, 0x8C) /* Willow Cove */ + #define INTEL_FAM6_TIGERLAKE 0x8D /* Willow Cove */ ++#define INTEL_TIGERLAKE IFM(6, 0x8D) /* Willow Cove */ + + #define INTEL_FAM6_SAPPHIRERAPIDS_X 0x8F /* Golden Cove */ ++#define INTEL_SAPPHIRERAPIDS_X IFM(6, 0x8F) /* Golden Cove */ + + #define INTEL_FAM6_EMERALDRAPIDS_X 0xCF ++#define INTEL_EMERALDRAPIDS_X IFM(6, 0xCF) + + #define INTEL_FAM6_GRANITERAPIDS_X 0xAD ++#define INTEL_GRANITERAPIDS_X IFM(6, 0xAD) + #define INTEL_FAM6_GRANITERAPIDS_D 0xAE ++#define INTEL_GRANITERAPIDS_D IFM(6, 0xAE) + + /* "Hybrid" Processors (P-Core/E-Core) */ + + #define INTEL_FAM6_LAKEFIELD 0x8A /* Sunny Cove / Tremont */ ++#define INTEL_LAKEFIELD IFM(6, 0x8A) /* Sunny Cove / Tremont */ + + #define INTEL_FAM6_ALDERLAKE 0x97 /* Golden Cove / Gracemont */ ++#define INTEL_ALDERLAKE IFM(6, 0x97) /* Golden Cove / Gracemont */ + #define INTEL_FAM6_ALDERLAKE_L 0x9A /* Golden Cove / Gracemont */ ++#define INTEL_ALDERLAKE_L IFM(6, 0x9A) /* Golden Cove / Gracemont */ + + #define INTEL_FAM6_RAPTORLAKE 0xB7 /* Raptor Cove / Enhanced Gracemont */ ++#define INTEL_RAPTORLAKE IFM(6, 0xB7) /* Raptor Cove / Enhanced Gracemont */ + #define INTEL_FAM6_RAPTORLAKE_P 0xBA ++#define INTEL_RAPTORLAKE_P IFM(6, 0xBA) + #define INTEL_FAM6_RAPTORLAKE_S 0xBF ++#define INTEL_RAPTORLAKE_S IFM(6, 0xBF) + + #define INTEL_FAM6_METEORLAKE 0xAC ++#define INTEL_METEORLAKE IFM(6, 0xAC) + #define INTEL_FAM6_METEORLAKE_L 0xAA ++#define INTEL_METEORLAKE_L IFM(6, 0xAA) + + #define INTEL_FAM6_ARROWLAKE_H 0xC5 ++#define INTEL_ARROWLAKE_H IFM(6, 0xC5) + #define INTEL_FAM6_ARROWLAKE 0xC6 ++#define INTEL_ARROWLAKE IFM(6, 0xC6) ++#define INTEL_FAM6_ARROWLAKE_U 0xB5 ++#define INTEL_ARROWLAKE_U IFM(6, 0xB5) + + #define INTEL_FAM6_LUNARLAKE_M 0xBD ++#define INTEL_LUNARLAKE_M IFM(6, 0xBD) + + /* "Small Core" Processors (Atom/E-Core) */ + + #define INTEL_FAM6_ATOM_BONNELL 0x1C /* Diamondville, Pineview */ ++#define INTEL_ATOM_BONNELL IFM(6, 0x1C) /* Diamondville, Pineview */ + #define INTEL_FAM6_ATOM_BONNELL_MID 0x26 /* Silverthorne, Lincroft */ ++#define INTEL_ATOM_BONNELL_MID IFM(6, 0x26) /* Silverthorne, Lincroft */ + + #define INTEL_FAM6_ATOM_SALTWELL 0x36 /* Cedarview */ ++#define INTEL_ATOM_SALTWELL IFM(6, 0x36) /* Cedarview */ + #define INTEL_FAM6_ATOM_SALTWELL_MID 0x27 /* Penwell */ ++#define INTEL_ATOM_SALTWELL_MID IFM(6, 0x27) /* Penwell */ + #define INTEL_FAM6_ATOM_SALTWELL_TABLET 0x35 /* Cloverview */ ++#define INTEL_ATOM_SALTWELL_TABLET IFM(6, 0x35) /* Cloverview */ + + #define INTEL_FAM6_ATOM_SILVERMONT 0x37 /* Bay Trail, Valleyview */ ++#define INTEL_ATOM_SILVERMONT IFM(6, 0x37) /* Bay Trail, Valleyview */ + #define INTEL_FAM6_ATOM_SILVERMONT_D 0x4D /* Avaton, Rangely */ ++#define INTEL_ATOM_SILVERMONT_D IFM(6, 0x4D) /* Avaton, Rangely */ + #define INTEL_FAM6_ATOM_SILVERMONT_MID 0x4A /* Merriefield */ ++#define INTEL_ATOM_SILVERMONT_MID IFM(6, 0x4A) /* Merriefield */ + + #define INTEL_FAM6_ATOM_AIRMONT 0x4C /* Cherry Trail, Braswell */ ++#define INTEL_ATOM_AIRMONT IFM(6, 0x4C) /* Cherry Trail, Braswell */ + #define INTEL_FAM6_ATOM_AIRMONT_MID 0x5A /* Moorefield */ ++#define INTEL_ATOM_AIRMONT_MID IFM(6, 0x5A) /* Moorefield */ + #define INTEL_FAM6_ATOM_AIRMONT_NP 0x75 /* Lightning Mountain */ ++#define INTEL_ATOM_AIRMONT_NP IFM(6, 0x75) /* Lightning Mountain */ + + #define INTEL_FAM6_ATOM_GOLDMONT 0x5C /* Apollo Lake */ ++#define INTEL_ATOM_GOLDMONT IFM(6, 0x5C) /* Apollo Lake */ + #define INTEL_FAM6_ATOM_GOLDMONT_D 0x5F /* Denverton */ ++#define INTEL_ATOM_GOLDMONT_D IFM(6, 0x5F) /* Denverton */ + + /* Note: the micro-architecture is "Goldmont Plus" */ + #define INTEL_FAM6_ATOM_GOLDMONT_PLUS 0x7A /* Gemini Lake */ ++#define INTEL_ATOM_GOLDMONT_PLUS IFM(6, 0x7A) /* Gemini Lake */ + + #define INTEL_FAM6_ATOM_TREMONT_D 0x86 /* Jacobsville */ ++#define INTEL_ATOM_TREMONT_D IFM(6, 0x86) /* Jacobsville */ + #define INTEL_FAM6_ATOM_TREMONT 0x96 /* Elkhart Lake */ ++#define INTEL_ATOM_TREMONT IFM(6, 0x96) /* Elkhart Lake */ + #define INTEL_FAM6_ATOM_TREMONT_L 0x9C /* Jasper Lake */ ++#define INTEL_ATOM_TREMONT_L IFM(6, 0x9C) /* Jasper Lake */ + + #define INTEL_FAM6_ATOM_GRACEMONT 0xBE /* Alderlake N */ ++#define INTEL_ATOM_GRACEMONT IFM(6, 0xBE) /* Alderlake N */ + + #define INTEL_FAM6_ATOM_CRESTMONT_X 0xAF /* Sierra Forest */ ++#define INTEL_ATOM_CRESTMONT_X IFM(6, 0xAF) /* Sierra Forest */ + #define INTEL_FAM6_ATOM_CRESTMONT 0xB6 /* Grand Ridge */ ++#define INTEL_ATOM_CRESTMONT IFM(6, 0xB6) /* Grand Ridge */ ++ ++#define INTEL_FAM6_ATOM_DARKMONT_X 0xDD /* Clearwater Forest */ ++#define INTEL_ATOM_DARKMONT_X IFM(6, 0xDD) /* Clearwater Forest */ + + /* Xeon Phi */ + + #define INTEL_FAM6_XEON_PHI_KNL 0x57 /* Knights Landing */ ++#define INTEL_XEON_PHI_KNL IFM(6, 0x57) /* Knights Landing */ + #define INTEL_FAM6_XEON_PHI_KNM 0x85 /* Knights Mill */ ++#define INTEL_XEON_PHI_KNM IFM(6, 0x85) /* Knights Mill */ + + /* Family 5 */ + #define INTEL_FAM5_QUARK_X1000 0x09 /* Quark X1000 SoC */ ++#define INTEL_QUARK_X1000 IFM(5, 0x09) /* Quark X1000 SoC */ + + #endif /* _ASM_X86_INTEL_FAMILY_H */ +diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h +index 6e775303d687dd..428348e7f06c3a 100644 +--- a/arch/x86/include/asm/processor.h ++++ b/arch/x86/include/asm/processor.h +@@ -81,9 +81,23 @@ extern u16 __read_mostly tlb_lld_1g[NR_INFO]; + */ + + struct cpuinfo_x86 { +- __u8 x86; /* CPU family */ +- __u8 x86_vendor; /* CPU vendor */ +- __u8 x86_model; ++ union { ++ /* ++ * The particular ordering (low-to-high) of (vendor, ++ * family, model) is done in case range of models, like ++ * it is usually done on AMD, need to be compared. ++ */ ++ struct { ++ __u8 x86_model; ++ /* CPU family */ ++ __u8 x86; ++ /* CPU vendor */ ++ __u8 x86_vendor; ++ __u8 x86_reserved; ++ }; ++ /* combined vendor, family, model */ ++ __u32 x86_vfm; ++ }; + __u8 x86_stepping; + #ifdef CONFIG_X86_64 + /* Number of 4K pages in DTLB/ITLB combined(in pages): */ +diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c +index aa3e7ed0eb3d7f..4752a9f17ef615 100644 +--- a/arch/x86/kernel/cpu/intel.c ++++ b/arch/x86/kernel/cpu/intel.c +@@ -72,19 +72,19 @@ static bool cpu_model_supports_sld __ro_after_init; + */ + static void check_memory_type_self_snoop_errata(struct cpuinfo_x86 *c) + { +- switch (c->x86_model) { +- case INTEL_FAM6_CORE_YONAH: +- case INTEL_FAM6_CORE2_MEROM: +- case INTEL_FAM6_CORE2_MEROM_L: +- case INTEL_FAM6_CORE2_PENRYN: +- case INTEL_FAM6_CORE2_DUNNINGTON: +- case INTEL_FAM6_NEHALEM: +- case INTEL_FAM6_NEHALEM_G: +- case INTEL_FAM6_NEHALEM_EP: +- case INTEL_FAM6_NEHALEM_EX: +- case INTEL_FAM6_WESTMERE: +- case INTEL_FAM6_WESTMERE_EP: +- case INTEL_FAM6_SANDYBRIDGE: ++ switch (c->x86_vfm) { ++ case INTEL_CORE_YONAH: ++ case INTEL_CORE2_MEROM: ++ case INTEL_CORE2_MEROM_L: ++ case INTEL_CORE2_PENRYN: ++ case INTEL_CORE2_DUNNINGTON: ++ case INTEL_NEHALEM: ++ case INTEL_NEHALEM_G: ++ case INTEL_NEHALEM_EP: ++ case INTEL_NEHALEM_EX: ++ case INTEL_WESTMERE: ++ case INTEL_WESTMERE_EP: ++ case INTEL_SANDYBRIDGE: + setup_clear_cpu_cap(X86_FEATURE_SELFSNOOP); + } + } +@@ -106,9 +106,9 @@ static void probe_xeon_phi_r3mwait(struct cpuinfo_x86 *c) + */ + if (c->x86 != 6) + return; +- switch (c->x86_model) { +- case INTEL_FAM6_XEON_PHI_KNL: +- case INTEL_FAM6_XEON_PHI_KNM: ++ switch (c->x86_vfm) { ++ case INTEL_XEON_PHI_KNL: ++ case INTEL_XEON_PHI_KNM: + break; + default: + return; +@@ -134,32 +134,32 @@ static void probe_xeon_phi_r3mwait(struct cpuinfo_x86 *c) + * - Release note from 20180108 microcode release + */ + struct sku_microcode { +- u8 model; ++ u32 vfm; + u8 stepping; + u32 microcode; + }; + static const struct sku_microcode spectre_bad_microcodes[] = { +- { INTEL_FAM6_KABYLAKE, 0x0B, 0x80 }, +- { INTEL_FAM6_KABYLAKE, 0x0A, 0x80 }, +- { INTEL_FAM6_KABYLAKE, 0x09, 0x80 }, +- { INTEL_FAM6_KABYLAKE_L, 0x0A, 0x80 }, +- { INTEL_FAM6_KABYLAKE_L, 0x09, 0x80 }, +- { INTEL_FAM6_SKYLAKE_X, 0x03, 0x0100013e }, +- { INTEL_FAM6_SKYLAKE_X, 0x04, 0x0200003c }, +- { INTEL_FAM6_BROADWELL, 0x04, 0x28 }, +- { INTEL_FAM6_BROADWELL_G, 0x01, 0x1b }, +- { INTEL_FAM6_BROADWELL_D, 0x02, 0x14 }, +- { INTEL_FAM6_BROADWELL_D, 0x03, 0x07000011 }, +- { INTEL_FAM6_BROADWELL_X, 0x01, 0x0b000025 }, +- { INTEL_FAM6_HASWELL_L, 0x01, 0x21 }, +- { INTEL_FAM6_HASWELL_G, 0x01, 0x18 }, +- { INTEL_FAM6_HASWELL, 0x03, 0x23 }, +- { INTEL_FAM6_HASWELL_X, 0x02, 0x3b }, +- { INTEL_FAM6_HASWELL_X, 0x04, 0x10 }, +- { INTEL_FAM6_IVYBRIDGE_X, 0x04, 0x42a }, ++ { INTEL_KABYLAKE, 0x0B, 0x80 }, ++ { INTEL_KABYLAKE, 0x0A, 0x80 }, ++ { INTEL_KABYLAKE, 0x09, 0x80 }, ++ { INTEL_KABYLAKE_L, 0x0A, 0x80 }, ++ { INTEL_KABYLAKE_L, 0x09, 0x80 }, ++ { INTEL_SKYLAKE_X, 0x03, 0x0100013e }, ++ { INTEL_SKYLAKE_X, 0x04, 0x0200003c }, ++ { INTEL_BROADWELL, 0x04, 0x28 }, ++ { INTEL_BROADWELL_G, 0x01, 0x1b }, ++ { INTEL_BROADWELL_D, 0x02, 0x14 }, ++ { INTEL_BROADWELL_D, 0x03, 0x07000011 }, ++ { INTEL_BROADWELL_X, 0x01, 0x0b000025 }, ++ { INTEL_HASWELL_L, 0x01, 0x21 }, ++ { INTEL_HASWELL_G, 0x01, 0x18 }, ++ { INTEL_HASWELL, 0x03, 0x23 }, ++ { INTEL_HASWELL_X, 0x02, 0x3b }, ++ { INTEL_HASWELL_X, 0x04, 0x10 }, ++ { INTEL_IVYBRIDGE_X, 0x04, 0x42a }, + /* Observed in the wild */ +- { INTEL_FAM6_SANDYBRIDGE_X, 0x06, 0x61b }, +- { INTEL_FAM6_SANDYBRIDGE_X, 0x07, 0x712 }, ++ { INTEL_SANDYBRIDGE_X, 0x06, 0x61b }, ++ { INTEL_SANDYBRIDGE_X, 0x07, 0x712 }, + }; + + static bool bad_spectre_microcode(struct cpuinfo_x86 *c) +@@ -173,11 +173,8 @@ static bool bad_spectre_microcode(struct cpuinfo_x86 *c) + if (cpu_has(c, X86_FEATURE_HYPERVISOR)) + return false; + +- if (c->x86 != 6) +- return false; +- + for (i = 0; i < ARRAY_SIZE(spectre_bad_microcodes); i++) { +- if (c->x86_model == spectre_bad_microcodes[i].model && ++ if (c->x86_vfm == spectre_bad_microcodes[i].vfm && + c->x86_stepping == spectre_bad_microcodes[i].stepping) + return (c->microcode <= spectre_bad_microcodes[i].microcode); + } +@@ -312,7 +309,7 @@ static void early_init_intel(struct cpuinfo_x86 *c) + * need the microcode to have already been loaded... so if it is + * not, recommend a BIOS update and disable large pages. + */ +- if (c->x86 == 6 && c->x86_model == 0x1c && c->x86_stepping <= 2 && ++ if (c->x86_vfm == INTEL_ATOM_BONNELL && c->x86_stepping <= 2 && + c->microcode < 0x20e) { + pr_warn("Atom PSE erratum detected, BIOS microcode update recommended\n"); + clear_cpu_cap(c, X86_FEATURE_PSE); +@@ -344,17 +341,13 @@ static void early_init_intel(struct cpuinfo_x86 *c) + } + + /* Penwell and Cloverview have the TSC which doesn't sleep on S3 */ +- if (c->x86 == 6) { +- switch (c->x86_model) { +- case INTEL_FAM6_ATOM_SALTWELL_MID: +- case INTEL_FAM6_ATOM_SALTWELL_TABLET: +- case INTEL_FAM6_ATOM_SILVERMONT_MID: +- case INTEL_FAM6_ATOM_AIRMONT_NP: +- set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC_S3); +- break; +- default: +- break; +- } ++ switch (c->x86_vfm) { ++ case INTEL_ATOM_SALTWELL_MID: ++ case INTEL_ATOM_SALTWELL_TABLET: ++ case INTEL_ATOM_SILVERMONT_MID: ++ case INTEL_ATOM_AIRMONT_NP: ++ set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC_S3); ++ break; + } + + /* +@@ -393,7 +386,7 @@ static void early_init_intel(struct cpuinfo_x86 *c) + * should be false so that __flush_tlb_all() causes CR3 instead of CR4.PGE + * to be modified. + */ +- if (c->x86 == 5 && c->x86_model == 9) { ++ if (c->x86_vfm == INTEL_QUARK_X1000) { + pr_info("Disabling PGE capability bit\n"); + setup_clear_cpu_cap(X86_FEATURE_PGE); + } +@@ -663,12 +656,15 @@ static void init_intel(struct cpuinfo_x86 *c) + set_cpu_cap(c, X86_FEATURE_PEBS); + } + +- if (c->x86 == 6 && boot_cpu_has(X86_FEATURE_CLFLUSH) && +- (c->x86_model == 29 || c->x86_model == 46 || c->x86_model == 47)) ++ if (boot_cpu_has(X86_FEATURE_CLFLUSH) && ++ (c->x86_vfm == INTEL_CORE2_DUNNINGTON || ++ c->x86_vfm == INTEL_NEHALEM_EX || ++ c->x86_vfm == INTEL_WESTMERE_EX)) + set_cpu_bug(c, X86_BUG_CLFLUSH_MONITOR); + +- if (c->x86 == 6 && boot_cpu_has(X86_FEATURE_MWAIT) && +- ((c->x86_model == INTEL_FAM6_ATOM_GOLDMONT))) ++ if (boot_cpu_has(X86_FEATURE_MWAIT) && ++ (c->x86_vfm == INTEL_ATOM_GOLDMONT || ++ c->x86_vfm == INTEL_LUNARLAKE_M)) + set_cpu_bug(c, X86_BUG_MONITOR); + + #ifdef CONFIG_X86_64 +@@ -1285,9 +1281,9 @@ void handle_bus_lock(struct pt_regs *regs) + * feature even though they do not enumerate IA32_CORE_CAPABILITIES. + */ + static const struct x86_cpu_id split_lock_cpu_ids[] __initconst = { +- X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_X, 0), +- X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_L, 0), +- X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_D, 0), ++ X86_MATCH_VFM(INTEL_ICELAKE_X, 0), ++ X86_MATCH_VFM(INTEL_ICELAKE_L, 0), ++ X86_MATCH_VFM(INTEL_ICELAKE_D, 0), + {} + }; + +diff --git a/arch/x86/kernel/cpu/match.c b/arch/x86/kernel/cpu/match.c +index ae71b8ef909c9a..978a3094e8ff73 100644 +--- a/arch/x86/kernel/cpu/match.c ++++ b/arch/x86/kernel/cpu/match.c +@@ -17,8 +17,7 @@ + * + * A typical table entry would be to match a specific CPU + * +- * X86_MATCH_VENDOR_FAM_MODEL_FEATURE(INTEL, 6, INTEL_FAM6_BROADWELL, +- * X86_FEATURE_ANY, NULL); ++ * X86_MATCH_VFM_FEATURE(INTEL_BROADWELL, X86_FEATURE_ANY, NULL); + * + * Fields can be wildcarded with %X86_VENDOR_ANY, %X86_FAMILY_ANY, + * %X86_MODEL_ANY, %X86_FEATURE_ANY (except for vendor) +diff --git a/block/blk-mq.c b/block/blk-mq.c +index 6c71add013bfc2..5da948b07058b4 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -43,6 +43,7 @@ + + static DEFINE_PER_CPU(struct llist_head, blk_cpu_done); + static DEFINE_PER_CPU(call_single_data_t, blk_cpu_csd); ++static DEFINE_MUTEX(blk_mq_cpuhp_lock); + + static void blk_mq_insert_request(struct request *rq, blk_insert_t flags); + static void blk_mq_request_bypass_insert(struct request *rq, +@@ -3623,13 +3624,91 @@ static int blk_mq_hctx_notify_dead(unsigned int cpu, struct hlist_node *node) + return 0; + } + +-static void blk_mq_remove_cpuhp(struct blk_mq_hw_ctx *hctx) ++static void __blk_mq_remove_cpuhp(struct blk_mq_hw_ctx *hctx) + { +- if (!(hctx->flags & BLK_MQ_F_STACKING)) ++ lockdep_assert_held(&blk_mq_cpuhp_lock); ++ ++ if (!(hctx->flags & BLK_MQ_F_STACKING) && ++ !hlist_unhashed(&hctx->cpuhp_online)) { + cpuhp_state_remove_instance_nocalls(CPUHP_AP_BLK_MQ_ONLINE, + &hctx->cpuhp_online); +- cpuhp_state_remove_instance_nocalls(CPUHP_BLK_MQ_DEAD, +- &hctx->cpuhp_dead); ++ INIT_HLIST_NODE(&hctx->cpuhp_online); ++ } ++ ++ if (!hlist_unhashed(&hctx->cpuhp_dead)) { ++ cpuhp_state_remove_instance_nocalls(CPUHP_BLK_MQ_DEAD, ++ &hctx->cpuhp_dead); ++ INIT_HLIST_NODE(&hctx->cpuhp_dead); ++ } ++} ++ ++static void blk_mq_remove_cpuhp(struct blk_mq_hw_ctx *hctx) ++{ ++ mutex_lock(&blk_mq_cpuhp_lock); ++ __blk_mq_remove_cpuhp(hctx); ++ mutex_unlock(&blk_mq_cpuhp_lock); ++} ++ ++static void __blk_mq_add_cpuhp(struct blk_mq_hw_ctx *hctx) ++{ ++ lockdep_assert_held(&blk_mq_cpuhp_lock); ++ ++ if (!(hctx->flags & BLK_MQ_F_STACKING) && ++ hlist_unhashed(&hctx->cpuhp_online)) ++ cpuhp_state_add_instance_nocalls(CPUHP_AP_BLK_MQ_ONLINE, ++ &hctx->cpuhp_online); ++ ++ if (hlist_unhashed(&hctx->cpuhp_dead)) ++ cpuhp_state_add_instance_nocalls(CPUHP_BLK_MQ_DEAD, ++ &hctx->cpuhp_dead); ++} ++ ++static void __blk_mq_remove_cpuhp_list(struct list_head *head) ++{ ++ struct blk_mq_hw_ctx *hctx; ++ ++ lockdep_assert_held(&blk_mq_cpuhp_lock); ++ ++ list_for_each_entry(hctx, head, hctx_list) ++ __blk_mq_remove_cpuhp(hctx); ++} ++ ++/* ++ * Unregister cpuhp callbacks from exited hw queues ++ * ++ * Safe to call if this `request_queue` is live ++ */ ++static void blk_mq_remove_hw_queues_cpuhp(struct request_queue *q) ++{ ++ LIST_HEAD(hctx_list); ++ ++ spin_lock(&q->unused_hctx_lock); ++ list_splice_init(&q->unused_hctx_list, &hctx_list); ++ spin_unlock(&q->unused_hctx_lock); ++ ++ mutex_lock(&blk_mq_cpuhp_lock); ++ __blk_mq_remove_cpuhp_list(&hctx_list); ++ mutex_unlock(&blk_mq_cpuhp_lock); ++ ++ spin_lock(&q->unused_hctx_lock); ++ list_splice(&hctx_list, &q->unused_hctx_list); ++ spin_unlock(&q->unused_hctx_lock); ++} ++ ++/* ++ * Register cpuhp callbacks from all hw queues ++ * ++ * Safe to call if this `request_queue` is live ++ */ ++static void blk_mq_add_hw_queues_cpuhp(struct request_queue *q) ++{ ++ struct blk_mq_hw_ctx *hctx; ++ unsigned long i; ++ ++ mutex_lock(&blk_mq_cpuhp_lock); ++ queue_for_each_hw_ctx(q, hctx, i) ++ __blk_mq_add_cpuhp(hctx); ++ mutex_unlock(&blk_mq_cpuhp_lock); + } + + /* +@@ -3680,8 +3759,6 @@ static void blk_mq_exit_hctx(struct request_queue *q, + if (set->ops->exit_hctx) + set->ops->exit_hctx(hctx, hctx_idx); + +- blk_mq_remove_cpuhp(hctx); +- + xa_erase(&q->hctx_table, hctx_idx); + + spin_lock(&q->unused_hctx_lock); +@@ -3698,6 +3775,7 @@ static void blk_mq_exit_hw_queues(struct request_queue *q, + queue_for_each_hw_ctx(q, hctx, i) { + if (i == nr_queue) + break; ++ blk_mq_remove_cpuhp(hctx); + blk_mq_exit_hctx(q, set, hctx, i); + } + } +@@ -3708,16 +3786,11 @@ static int blk_mq_init_hctx(struct request_queue *q, + { + hctx->queue_num = hctx_idx; + +- if (!(hctx->flags & BLK_MQ_F_STACKING)) +- cpuhp_state_add_instance_nocalls(CPUHP_AP_BLK_MQ_ONLINE, +- &hctx->cpuhp_online); +- cpuhp_state_add_instance_nocalls(CPUHP_BLK_MQ_DEAD, &hctx->cpuhp_dead); +- + hctx->tags = set->tags[hctx_idx]; + + if (set->ops->init_hctx && + set->ops->init_hctx(hctx, set->driver_data, hctx_idx)) +- goto unregister_cpu_notifier; ++ goto fail; + + if (blk_mq_init_request(set, hctx->fq->flush_rq, hctx_idx, + hctx->numa_node)) +@@ -3734,8 +3807,7 @@ static int blk_mq_init_hctx(struct request_queue *q, + exit_hctx: + if (set->ops->exit_hctx) + set->ops->exit_hctx(hctx, hctx_idx); +- unregister_cpu_notifier: +- blk_mq_remove_cpuhp(hctx); ++ fail: + return -1; + } + +@@ -3761,6 +3833,8 @@ blk_mq_alloc_hctx(struct request_queue *q, struct blk_mq_tag_set *set, + INIT_DELAYED_WORK(&hctx->run_work, blk_mq_run_work_fn); + spin_lock_init(&hctx->lock); + INIT_LIST_HEAD(&hctx->dispatch); ++ INIT_HLIST_NODE(&hctx->cpuhp_dead); ++ INIT_HLIST_NODE(&hctx->cpuhp_online); + hctx->queue = q; + hctx->flags = set->flags & ~BLK_MQ_F_TAG_QUEUE_SHARED; + +@@ -4204,6 +4278,15 @@ struct gendisk *blk_mq_alloc_disk_for_queue(struct request_queue *q, + } + EXPORT_SYMBOL(blk_mq_alloc_disk_for_queue); + ++/* ++ * Only hctx removed from cpuhp list can be reused ++ */ ++static bool blk_mq_hctx_is_reusable(struct blk_mq_hw_ctx *hctx) ++{ ++ return hlist_unhashed(&hctx->cpuhp_online) && ++ hlist_unhashed(&hctx->cpuhp_dead); ++} ++ + static struct blk_mq_hw_ctx *blk_mq_alloc_and_init_hctx( + struct blk_mq_tag_set *set, struct request_queue *q, + int hctx_idx, int node) +@@ -4213,7 +4296,7 @@ static struct blk_mq_hw_ctx *blk_mq_alloc_and_init_hctx( + /* reuse dead hctx first */ + spin_lock(&q->unused_hctx_lock); + list_for_each_entry(tmp, &q->unused_hctx_list, hctx_list) { +- if (tmp->numa_node == node) { ++ if (tmp->numa_node == node && blk_mq_hctx_is_reusable(tmp)) { + hctx = tmp; + break; + } +@@ -4279,6 +4362,12 @@ static void blk_mq_realloc_hw_ctxs(struct blk_mq_tag_set *set, + xa_for_each_start(&q->hctx_table, j, hctx, j) + blk_mq_exit_hctx(q, set, hctx, j); + mutex_unlock(&q->sysfs_lock); ++ ++ /* unregister cpuhp callbacks for exited hctxs */ ++ blk_mq_remove_hw_queues_cpuhp(q); ++ ++ /* register cpuhp for new initialized hctxs */ ++ blk_mq_add_hw_queues_cpuhp(q); + } + + static void blk_mq_update_poll_flag(struct request_queue *q) +diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c +index 582564f8dde6f9..d9d339b8b57108 100644 +--- a/drivers/base/power/domain.c ++++ b/drivers/base/power/domain.c +@@ -2021,6 +2021,7 @@ static int genpd_alloc_data(struct generic_pm_domain *genpd) + + static void genpd_free_data(struct generic_pm_domain *genpd) + { ++ put_device(&genpd->dev); + if (genpd_is_cpu_domain(genpd)) + free_cpumask_var(genpd->cpus); + if (genpd->free_states) +diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c +index 1db04886def610..3011f7f9381b7f 100644 +--- a/drivers/base/regmap/regmap.c ++++ b/drivers/base/regmap/regmap.c +@@ -1062,13 +1062,13 @@ struct regmap *__regmap_init(struct device *dev, + + /* Sanity check */ + if (range_cfg->range_max < range_cfg->range_min) { +- dev_err(map->dev, "Invalid range %d: %d < %d\n", i, ++ dev_err(map->dev, "Invalid range %d: %u < %u\n", i, + range_cfg->range_max, range_cfg->range_min); + goto err_range; + } + + if (range_cfg->range_max > map->max_register) { +- dev_err(map->dev, "Invalid range %d: %d > %d\n", i, ++ dev_err(map->dev, "Invalid range %d: %u > %u\n", i, + range_cfg->range_max, map->max_register); + goto err_range; + } +diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c +index 997106fe73e49f..65a1f1576e55fb 100644 +--- a/drivers/block/virtio_blk.c ++++ b/drivers/block/virtio_blk.c +@@ -1624,9 +1624,12 @@ static void virtblk_remove(struct virtio_device *vdev) + static int virtblk_freeze(struct virtio_device *vdev) + { + struct virtio_blk *vblk = vdev->priv; ++ struct request_queue *q = vblk->disk->queue; + + /* Ensure no requests in virtqueues before deleting vqs. */ +- blk_mq_freeze_queue(vblk->disk->queue); ++ blk_mq_freeze_queue(q); ++ blk_mq_quiesce_queue_nowait(q); ++ blk_mq_unfreeze_queue(q); + + /* Ensure we don't receive any more interrupts */ + virtio_reset_device(vdev); +@@ -1650,8 +1653,8 @@ static int virtblk_restore(struct virtio_device *vdev) + return ret; + + virtio_device_ready(vdev); ++ blk_mq_unquiesce_queue(vblk->disk->queue); + +- blk_mq_unfreeze_queue(vblk->disk->queue); + return 0; + } + #endif +diff --git a/drivers/dma/apple-admac.c b/drivers/dma/apple-admac.c +index 356298e4dd22b3..5b1457f6e3bfc4 100644 +--- a/drivers/dma/apple-admac.c ++++ b/drivers/dma/apple-admac.c +@@ -153,6 +153,8 @@ static int admac_alloc_sram_carveout(struct admac_data *ad, + { + struct admac_sram *sram; + int i, ret = 0, nblocks; ++ ad->txcache.size = readl_relaxed(ad->base + REG_TX_SRAM_SIZE); ++ ad->rxcache.size = readl_relaxed(ad->base + REG_RX_SRAM_SIZE); + + if (dir == DMA_MEM_TO_DEV) + sram = &ad->txcache; +@@ -912,12 +914,7 @@ static int admac_probe(struct platform_device *pdev) + goto free_irq; + } + +- ad->txcache.size = readl_relaxed(ad->base + REG_TX_SRAM_SIZE); +- ad->rxcache.size = readl_relaxed(ad->base + REG_RX_SRAM_SIZE); +- + dev_info(&pdev->dev, "Audio DMA Controller\n"); +- dev_info(&pdev->dev, "imprint %x TX cache %u RX cache %u\n", +- readl_relaxed(ad->base + REG_IMPRINT), ad->txcache.size, ad->rxcache.size); + + return 0; + +diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c +index c3b37168b21f16..2d1ee284998ecd 100644 +--- a/drivers/dma/at_xdmac.c ++++ b/drivers/dma/at_xdmac.c +@@ -1363,6 +1363,8 @@ at_xdmac_prep_dma_memset(struct dma_chan *chan, dma_addr_t dest, int value, + return NULL; + + desc = at_xdmac_memset_create_desc(chan, atchan, dest, len, value); ++ if (!desc) ++ return NULL; + list_add_tail(&desc->desc_node, &desc->descs_list); + + desc->tx_dma_desc.cookie = -EBUSY; +diff --git a/drivers/dma/dw/acpi.c b/drivers/dma/dw/acpi.c +index c510c109d2c3ad..b6452fffa657ad 100644 +--- a/drivers/dma/dw/acpi.c ++++ b/drivers/dma/dw/acpi.c +@@ -8,13 +8,15 @@ + + static bool dw_dma_acpi_filter(struct dma_chan *chan, void *param) + { ++ struct dw_dma *dw = to_dw_dma(chan->device); ++ struct dw_dma_chip_pdata *data = dev_get_drvdata(dw->dma.dev); + struct acpi_dma_spec *dma_spec = param; + struct dw_dma_slave slave = { + .dma_dev = dma_spec->dev, + .src_id = dma_spec->slave_id, + .dst_id = dma_spec->slave_id, +- .m_master = 0, +- .p_master = 1, ++ .m_master = data->m_master, ++ .p_master = data->p_master, + }; + + return dw_dma_filter(chan, &slave); +diff --git a/drivers/dma/dw/internal.h b/drivers/dma/dw/internal.h +index 563ce73488db32..f1bd06a20cd611 100644 +--- a/drivers/dma/dw/internal.h ++++ b/drivers/dma/dw/internal.h +@@ -51,11 +51,15 @@ struct dw_dma_chip_pdata { + int (*probe)(struct dw_dma_chip *chip); + int (*remove)(struct dw_dma_chip *chip); + struct dw_dma_chip *chip; ++ u8 m_master; ++ u8 p_master; + }; + + static __maybe_unused const struct dw_dma_chip_pdata dw_dma_chip_pdata = { + .probe = dw_dma_probe, + .remove = dw_dma_remove, ++ .m_master = 0, ++ .p_master = 1, + }; + + static const struct dw_dma_platform_data idma32_pdata = { +@@ -72,6 +76,8 @@ static __maybe_unused const struct dw_dma_chip_pdata idma32_chip_pdata = { + .pdata = &idma32_pdata, + .probe = idma32_dma_probe, + .remove = idma32_dma_remove, ++ .m_master = 0, ++ .p_master = 0, + }; + + static const struct dw_dma_platform_data xbar_pdata = { +@@ -88,6 +94,8 @@ static __maybe_unused const struct dw_dma_chip_pdata xbar_chip_pdata = { + .pdata = &xbar_pdata, + .probe = idma32_dma_probe, + .remove = idma32_dma_remove, ++ .m_master = 0, ++ .p_master = 0, + }; + + #endif /* _DMA_DW_INTERNAL_H */ +diff --git a/drivers/dma/dw/pci.c b/drivers/dma/dw/pci.c +index ad2d4d012cf729..e8a0eb81726a56 100644 +--- a/drivers/dma/dw/pci.c ++++ b/drivers/dma/dw/pci.c +@@ -56,10 +56,10 @@ static int dw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid) + if (ret) + return ret; + +- dw_dma_acpi_controller_register(chip->dw); +- + pci_set_drvdata(pdev, data); + ++ dw_dma_acpi_controller_register(chip->dw); ++ + return 0; + } + +diff --git a/drivers/dma/fsl-edma-common.h b/drivers/dma/fsl-edma-common.h +index 6028389de408b0..8d4ef6eed3adbb 100644 +--- a/drivers/dma/fsl-edma-common.h ++++ b/drivers/dma/fsl-edma-common.h +@@ -151,6 +151,7 @@ struct fsl_edma_chan { + struct work_struct issue_worker; + struct platform_device *pdev; + struct device *pd_dev; ++ struct device_link *pd_dev_link; + u32 srcid; + struct clk *clk; + int priority; +diff --git a/drivers/dma/fsl-edma-main.c b/drivers/dma/fsl-edma-main.c +index 8a0ae90548997c..cd394eae47d179 100644 +--- a/drivers/dma/fsl-edma-main.c ++++ b/drivers/dma/fsl-edma-main.c +@@ -384,10 +384,33 @@ static const struct of_device_id fsl_edma_dt_ids[] = { + }; + MODULE_DEVICE_TABLE(of, fsl_edma_dt_ids); + ++static void fsl_edma3_detach_pd(struct fsl_edma_engine *fsl_edma) ++{ ++ struct fsl_edma_chan *fsl_chan; ++ int i; ++ ++ for (i = 0; i < fsl_edma->n_chans; i++) { ++ if (fsl_edma->chan_masked & BIT(i)) ++ continue; ++ fsl_chan = &fsl_edma->chans[i]; ++ if (fsl_chan->pd_dev_link) ++ device_link_del(fsl_chan->pd_dev_link); ++ if (fsl_chan->pd_dev) { ++ dev_pm_domain_detach(fsl_chan->pd_dev, false); ++ pm_runtime_dont_use_autosuspend(fsl_chan->pd_dev); ++ pm_runtime_set_suspended(fsl_chan->pd_dev); ++ } ++ } ++} ++ ++static void devm_fsl_edma3_detach_pd(void *data) ++{ ++ fsl_edma3_detach_pd(data); ++} ++ + static int fsl_edma3_attach_pd(struct platform_device *pdev, struct fsl_edma_engine *fsl_edma) + { + struct fsl_edma_chan *fsl_chan; +- struct device_link *link; + struct device *pd_chan; + struct device *dev; + int i; +@@ -403,15 +426,16 @@ static int fsl_edma3_attach_pd(struct platform_device *pdev, struct fsl_edma_eng + pd_chan = dev_pm_domain_attach_by_id(dev, i); + if (IS_ERR_OR_NULL(pd_chan)) { + dev_err(dev, "Failed attach pd %d\n", i); +- return -EINVAL; ++ goto detach; + } + +- link = device_link_add(dev, pd_chan, DL_FLAG_STATELESS | ++ fsl_chan->pd_dev_link = device_link_add(dev, pd_chan, DL_FLAG_STATELESS | + DL_FLAG_PM_RUNTIME | + DL_FLAG_RPM_ACTIVE); +- if (!link) { ++ if (!fsl_chan->pd_dev_link) { + dev_err(dev, "Failed to add device_link to %d\n", i); +- return -EINVAL; ++ dev_pm_domain_detach(pd_chan, false); ++ goto detach; + } + + fsl_chan->pd_dev = pd_chan; +@@ -422,6 +446,10 @@ static int fsl_edma3_attach_pd(struct platform_device *pdev, struct fsl_edma_eng + } + + return 0; ++ ++detach: ++ fsl_edma3_detach_pd(fsl_edma); ++ return -EINVAL; + } + + static int fsl_edma_probe(struct platform_device *pdev) +@@ -522,6 +550,9 @@ static int fsl_edma_probe(struct platform_device *pdev) + ret = fsl_edma3_attach_pd(pdev, fsl_edma); + if (ret) + return ret; ++ ret = devm_add_action_or_reset(&pdev->dev, devm_fsl_edma3_detach_pd, fsl_edma); ++ if (ret) ++ return ret; + } + + INIT_LIST_HEAD(&fsl_edma->dma_dev.channels); +diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c +index 23b232b5751844..ea48661e87ea70 100644 +--- a/drivers/dma/mv_xor.c ++++ b/drivers/dma/mv_xor.c +@@ -1393,6 +1393,7 @@ static int mv_xor_probe(struct platform_device *pdev) + irq = irq_of_parse_and_map(np, 0); + if (!irq) { + ret = -ENODEV; ++ of_node_put(np); + goto err_channel_add; + } + +@@ -1401,6 +1402,7 @@ static int mv_xor_probe(struct platform_device *pdev) + if (IS_ERR(chan)) { + ret = PTR_ERR(chan); + irq_dispose_mapping(irq); ++ of_node_put(np); + goto err_channel_add; + } + +diff --git a/drivers/dma/tegra186-gpc-dma.c b/drivers/dma/tegra186-gpc-dma.c +index 674cf630528383..029f45f7e37f4e 100644 +--- a/drivers/dma/tegra186-gpc-dma.c ++++ b/drivers/dma/tegra186-gpc-dma.c +@@ -231,6 +231,7 @@ struct tegra_dma_channel { + bool config_init; + char name[30]; + enum dma_transfer_direction sid_dir; ++ enum dma_status status; + int id; + int irq; + int slave_id; +@@ -393,6 +394,8 @@ static int tegra_dma_pause(struct tegra_dma_channel *tdc) + tegra_dma_dump_chan_regs(tdc); + } + ++ tdc->status = DMA_PAUSED; ++ + return ret; + } + +@@ -419,6 +422,8 @@ static void tegra_dma_resume(struct tegra_dma_channel *tdc) + val = tdc_read(tdc, TEGRA_GPCDMA_CHAN_CSRE); + val &= ~TEGRA_GPCDMA_CHAN_CSRE_PAUSE; + tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSRE, val); ++ ++ tdc->status = DMA_IN_PROGRESS; + } + + static int tegra_dma_device_resume(struct dma_chan *dc) +@@ -544,6 +549,7 @@ static void tegra_dma_xfer_complete(struct tegra_dma_channel *tdc) + + tegra_dma_sid_free(tdc); + tdc->dma_desc = NULL; ++ tdc->status = DMA_COMPLETE; + } + + static void tegra_dma_chan_decode_error(struct tegra_dma_channel *tdc, +@@ -716,6 +722,7 @@ static int tegra_dma_terminate_all(struct dma_chan *dc) + tdc->dma_desc = NULL; + } + ++ tdc->status = DMA_COMPLETE; + tegra_dma_sid_free(tdc); + vchan_get_all_descriptors(&tdc->vc, &head); + spin_unlock_irqrestore(&tdc->vc.lock, flags); +@@ -769,6 +776,9 @@ static enum dma_status tegra_dma_tx_status(struct dma_chan *dc, + if (ret == DMA_COMPLETE) + return ret; + ++ if (tdc->status == DMA_PAUSED) ++ ret = DMA_PAUSED; ++ + spin_lock_irqsave(&tdc->vc.lock, flags); + vd = vchan_find_desc(&tdc->vc, cookie); + if (vd) { +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +index af6c6d89e63afb..fbee10927bfb64 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +@@ -467,28 +467,6 @@ uint32_t amdgpu_amdkfd_get_max_engine_clock_in_mhz(struct amdgpu_device *adev) + return 100; + } + +-void amdgpu_amdkfd_get_cu_info(struct amdgpu_device *adev, struct kfd_cu_info *cu_info) +-{ +- struct amdgpu_cu_info acu_info = adev->gfx.cu_info; +- +- memset(cu_info, 0, sizeof(*cu_info)); +- if (sizeof(cu_info->cu_bitmap) != sizeof(acu_info.bitmap)) +- return; +- +- cu_info->cu_active_number = acu_info.number; +- cu_info->cu_ao_mask = acu_info.ao_cu_mask; +- memcpy(&cu_info->cu_bitmap[0], &acu_info.bitmap[0], +- sizeof(cu_info->cu_bitmap)); +- cu_info->num_shader_engines = adev->gfx.config.max_shader_engines; +- cu_info->num_shader_arrays_per_engine = adev->gfx.config.max_sh_per_se; +- cu_info->num_cu_per_sh = adev->gfx.config.max_cu_per_sh; +- cu_info->simd_per_cu = acu_info.simd_per_cu; +- cu_info->max_waves_per_simd = acu_info.max_waves_per_simd; +- cu_info->wave_front_size = acu_info.wave_front_size; +- cu_info->max_scratch_slots_per_cu = acu_info.max_scratch_slots_per_cu; +- cu_info->lds_size = acu_info.lds_size; +-} +- + int amdgpu_amdkfd_get_dmabuf_info(struct amdgpu_device *adev, int dma_buf_fd, + struct amdgpu_device **dmabuf_adev, + uint64_t *bo_size, void *metadata_buffer, +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +index 3134e6ad81d1d4..ff2b8ace438b62 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +@@ -235,8 +235,6 @@ void amdgpu_amdkfd_get_local_mem_info(struct amdgpu_device *adev, + uint64_t amdgpu_amdkfd_get_gpu_clock_counter(struct amdgpu_device *adev); + + uint32_t amdgpu_amdkfd_get_max_engine_clock_in_mhz(struct amdgpu_device *adev); +-void amdgpu_amdkfd_get_cu_info(struct amdgpu_device *adev, +- struct kfd_cu_info *cu_info); + int amdgpu_amdkfd_get_dmabuf_info(struct amdgpu_device *adev, int dma_buf_fd, + struct amdgpu_device **dmabuf_adev, + uint64_t *bo_size, void *metadata_buffer, +diff --git a/drivers/gpu/drm/amd/amdgpu/hdp_v4_0.c b/drivers/gpu/drm/amd/amdgpu/hdp_v4_0.c +index 71d1a2e3bac916..30210613dc5c47 100644 +--- a/drivers/gpu/drm/amd/amdgpu/hdp_v4_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/hdp_v4_0.c +@@ -40,10 +40,12 @@ + static void hdp_v4_0_flush_hdp(struct amdgpu_device *adev, + struct amdgpu_ring *ring) + { +- if (!ring || !ring->funcs->emit_wreg) +- WREG32_NO_KIQ((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0); +- else ++ if (!ring || !ring->funcs->emit_wreg) { ++ WREG32((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0); ++ RREG32((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2); ++ } else { + amdgpu_ring_emit_wreg(ring, (adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0); ++ } + } + + static void hdp_v4_0_invalidate_hdp(struct amdgpu_device *adev, +@@ -53,11 +55,13 @@ static void hdp_v4_0_invalidate_hdp(struct amdgpu_device *adev, + adev->ip_versions[HDP_HWIP][0] == IP_VERSION(4, 4, 2)) + return; + +- if (!ring || !ring->funcs->emit_wreg) ++ if (!ring || !ring->funcs->emit_wreg) { + WREG32_SOC15_NO_KIQ(HDP, 0, mmHDP_READ_CACHE_INVALIDATE, 1); +- else ++ RREG32_SOC15_NO_KIQ(HDP, 0, mmHDP_READ_CACHE_INVALIDATE); ++ } else { + amdgpu_ring_emit_wreg(ring, SOC15_REG_OFFSET( + HDP, 0, mmHDP_READ_CACHE_INVALIDATE), 1); ++ } + } + + static void hdp_v4_0_query_ras_error_count(struct amdgpu_device *adev, +diff --git a/drivers/gpu/drm/amd/amdgpu/hdp_v5_0.c b/drivers/gpu/drm/amd/amdgpu/hdp_v5_0.c +index a9ea23fa0def7f..d3962d46908811 100644 +--- a/drivers/gpu/drm/amd/amdgpu/hdp_v5_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/hdp_v5_0.c +@@ -31,10 +31,12 @@ + static void hdp_v5_0_flush_hdp(struct amdgpu_device *adev, + struct amdgpu_ring *ring) + { +- if (!ring || !ring->funcs->emit_wreg) +- WREG32_NO_KIQ((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0); +- else ++ if (!ring || !ring->funcs->emit_wreg) { ++ WREG32((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0); ++ RREG32((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2); ++ } else { + amdgpu_ring_emit_wreg(ring, (adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0); ++ } + } + + static void hdp_v5_0_invalidate_hdp(struct amdgpu_device *adev, +@@ -42,6 +44,7 @@ static void hdp_v5_0_invalidate_hdp(struct amdgpu_device *adev, + { + if (!ring || !ring->funcs->emit_wreg) { + WREG32_SOC15_NO_KIQ(HDP, 0, mmHDP_READ_CACHE_INVALIDATE, 1); ++ RREG32_SOC15_NO_KIQ(HDP, 0, mmHDP_READ_CACHE_INVALIDATE); + } else { + amdgpu_ring_emit_wreg(ring, SOC15_REG_OFFSET( + HDP, 0, mmHDP_READ_CACHE_INVALIDATE), 1); +diff --git a/drivers/gpu/drm/amd/amdgpu/hdp_v6_0.c b/drivers/gpu/drm/amd/amdgpu/hdp_v6_0.c +index 063eba619f2f6c..b6d71ec1debf9a 100644 +--- a/drivers/gpu/drm/amd/amdgpu/hdp_v6_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/hdp_v6_0.c +@@ -31,10 +31,12 @@ + static void hdp_v6_0_flush_hdp(struct amdgpu_device *adev, + struct amdgpu_ring *ring) + { +- if (!ring || !ring->funcs->emit_wreg) +- WREG32_NO_KIQ((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0); +- else ++ if (!ring || !ring->funcs->emit_wreg) { ++ WREG32((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0); ++ RREG32((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2); ++ } else { + amdgpu_ring_emit_wreg(ring, (adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0); ++ } + } + + static void hdp_v6_0_update_clock_gating(struct amdgpu_device *adev, +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c +index f76b7aee5c0a12..29a02c1752289c 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c +@@ -2037,11 +2037,12 @@ static int kfd_create_vcrat_image_gpu(void *pcrat_image, + uint32_t proximity_domain) + { + struct crat_header *crat_table = (struct crat_header *)pcrat_image; ++ struct amdgpu_gfx_config *gfx_info = &kdev->adev->gfx.config; ++ struct amdgpu_cu_info *cu_info = &kdev->adev->gfx.cu_info; + struct crat_subtype_generic *sub_type_hdr; + struct kfd_local_mem_info local_mem_info; + struct kfd_topology_device *peer_dev; + struct crat_subtype_computeunit *cu; +- struct kfd_cu_info cu_info; + int avail_size = *size; + uint32_t total_num_of_cu; + uint32_t nid = 0; +@@ -2085,21 +2086,20 @@ static int kfd_create_vcrat_image_gpu(void *pcrat_image, + cu->flags |= CRAT_CU_FLAGS_GPU_PRESENT; + cu->proximity_domain = proximity_domain; + +- amdgpu_amdkfd_get_cu_info(kdev->adev, &cu_info); +- cu->num_simd_per_cu = cu_info.simd_per_cu; +- cu->num_simd_cores = cu_info.simd_per_cu * +- (cu_info.cu_active_number / kdev->kfd->num_nodes); +- cu->max_waves_simd = cu_info.max_waves_per_simd; ++ cu->num_simd_per_cu = cu_info->simd_per_cu; ++ cu->num_simd_cores = cu_info->simd_per_cu * ++ (cu_info->number / kdev->kfd->num_nodes); ++ cu->max_waves_simd = cu_info->max_waves_per_simd; + +- cu->wave_front_size = cu_info.wave_front_size; +- cu->array_count = cu_info.num_shader_arrays_per_engine * +- cu_info.num_shader_engines; +- total_num_of_cu = (cu->array_count * cu_info.num_cu_per_sh); ++ cu->wave_front_size = cu_info->wave_front_size; ++ cu->array_count = gfx_info->max_sh_per_se * ++ gfx_info->max_shader_engines; ++ total_num_of_cu = (cu->array_count * gfx_info->max_cu_per_sh); + cu->processor_id_low = get_and_inc_gpu_processor_id(total_num_of_cu); +- cu->num_cu_per_array = cu_info.num_cu_per_sh; +- cu->max_slots_scatch_cu = cu_info.max_scratch_slots_per_cu; +- cu->num_banks = cu_info.num_shader_engines; +- cu->lds_size_in_kb = cu_info.lds_size; ++ cu->num_cu_per_array = gfx_info->max_cu_per_sh; ++ cu->max_slots_scatch_cu = cu_info->max_scratch_slots_per_cu; ++ cu->num_banks = gfx_info->max_shader_engines; ++ cu->lds_size_in_kb = cu_info->lds_size; + + cu->hsa_capability = 0; + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +index 4d9a406925e189..43fa260ddbcea0 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +@@ -197,6 +197,21 @@ static int add_queue_mes(struct device_queue_manager *dqm, struct queue *q, + if (dqm->is_hws_hang) + return -EIO; + ++ if (!pdd->proc_ctx_cpu_ptr) { ++ r = amdgpu_amdkfd_alloc_gtt_mem(adev, ++ AMDGPU_MES_PROC_CTX_SIZE, ++ &pdd->proc_ctx_bo, ++ &pdd->proc_ctx_gpu_addr, ++ &pdd->proc_ctx_cpu_ptr, ++ false); ++ if (r) { ++ dev_err(adev->dev, ++ "failed to allocate process context bo\n"); ++ return r; ++ } ++ memset(pdd->proc_ctx_cpu_ptr, 0, AMDGPU_MES_PROC_CTX_SIZE); ++ } ++ + memset(&queue_input, 0x0, sizeof(struct mes_add_queue_input)); + queue_input.process_id = qpd->pqm->process->pasid; + queue_input.page_table_base_addr = qpd->page_table_base; +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c b/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c +index 6604a3f99c5ecf..b22a036523b7e4 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c +@@ -373,7 +373,8 @@ int kfd_init_apertures(struct kfd_process *process) + + pdd = kfd_create_process_device_data(dev, process); + if (!pdd) { +- pr_err("Failed to create process device data\n"); ++ dev_err(dev->adev->dev, ++ "Failed to create process device data\n"); + return -ENOMEM; + } + /* +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c +index 68d13c4fac8f4f..2c529339ff6572 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c +@@ -68,7 +68,7 @@ static bool kq_initialize(struct kernel_queue *kq, struct kfd_node *dev, + kq->mqd_mgr = dev->dqm->mqd_mgrs[KFD_MQD_TYPE_HIQ]; + break; + default: +- pr_err("Invalid queue type %d\n", type); ++ dev_err(dev->adev->dev, "Invalid queue type %d\n", type); + return false; + } + +@@ -78,13 +78,14 @@ static bool kq_initialize(struct kernel_queue *kq, struct kfd_node *dev, + prop.doorbell_ptr = kfd_get_kernel_doorbell(dev->kfd, &prop.doorbell_off); + + if (!prop.doorbell_ptr) { +- pr_err("Failed to initialize doorbell"); ++ dev_err(dev->adev->dev, "Failed to initialize doorbell"); + goto err_get_kernel_doorbell; + } + + retval = kfd_gtt_sa_allocate(dev, queue_size, &kq->pq); + if (retval != 0) { +- pr_err("Failed to init pq queues size %d\n", queue_size); ++ dev_err(dev->adev->dev, "Failed to init pq queues size %d\n", ++ queue_size); + goto err_pq_allocate_vidmem; + } + +@@ -332,7 +333,7 @@ struct kernel_queue *kernel_queue_init(struct kfd_node *dev, + if (kq_initialize(kq, dev, type, KFD_KERNEL_QUEUE_SIZE)) + return kq; + +- pr_err("Failed to init kernel queue\n"); ++ dev_err(dev->adev->dev, "Failed to init kernel queue\n"); + + kfree(kq); + return NULL; +@@ -351,26 +352,26 @@ static __attribute__((unused)) void test_kq(struct kfd_node *dev) + uint32_t *buffer, i; + int retval; + +- pr_err("Starting kernel queue test\n"); ++ dev_err(dev->adev->dev, "Starting kernel queue test\n"); + + kq = kernel_queue_init(dev, KFD_QUEUE_TYPE_HIQ); + if (unlikely(!kq)) { +- pr_err(" Failed to initialize HIQ\n"); +- pr_err("Kernel queue test failed\n"); ++ dev_err(dev->adev->dev, " Failed to initialize HIQ\n"); ++ dev_err(dev->adev->dev, "Kernel queue test failed\n"); + return; + } + + retval = kq_acquire_packet_buffer(kq, 5, &buffer); + if (unlikely(retval != 0)) { +- pr_err(" Failed to acquire packet buffer\n"); +- pr_err("Kernel queue test failed\n"); ++ dev_err(dev->adev->dev, " Failed to acquire packet buffer\n"); ++ dev_err(dev->adev->dev, "Kernel queue test failed\n"); + return; + } + for (i = 0; i < 5; i++) + buffer[i] = kq->nop_packet; + kq_submit_packet(kq); + +- pr_err("Ending kernel queue test\n"); ++ dev_err(dev->adev->dev, "Ending kernel queue test\n"); + } + + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c +index 4c3f379803117e..0edae9ded68a99 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c +@@ -99,7 +99,8 @@ void mqd_symmetrically_map_cu_mask(struct mqd_manager *mm, + const uint32_t *cu_mask, uint32_t cu_mask_count, + uint32_t *se_mask, uint32_t inst) + { +- struct kfd_cu_info cu_info; ++ struct amdgpu_cu_info *cu_info = &mm->dev->adev->gfx.cu_info; ++ struct amdgpu_gfx_config *gfx_info = &mm->dev->adev->gfx.config; + uint32_t cu_per_sh[KFD_MAX_NUM_SE][KFD_MAX_NUM_SH_PER_SE] = {0}; + bool wgp_mode_req = KFD_GC_VERSION(mm->dev) >= IP_VERSION(10, 0, 0); + uint32_t en_mask = wgp_mode_req ? 0x3 : 0x1; +@@ -108,9 +109,7 @@ void mqd_symmetrically_map_cu_mask(struct mqd_manager *mm, + int inc = cu_inc * NUM_XCC(mm->dev->xcc_mask); + int xcc_inst = inst + ffs(mm->dev->xcc_mask) - 1; + +- amdgpu_amdkfd_get_cu_info(mm->dev->adev, &cu_info); +- +- cu_active_per_node = cu_info.cu_active_number / mm->dev->kfd->num_nodes; ++ cu_active_per_node = cu_info->number / mm->dev->kfd->num_nodes; + if (cu_mask_count > cu_active_per_node) + cu_mask_count = cu_active_per_node; + +@@ -118,13 +117,16 @@ void mqd_symmetrically_map_cu_mask(struct mqd_manager *mm, + * Returning with no CU's enabled will hang the queue, which should be + * attention grabbing. + */ +- if (cu_info.num_shader_engines > KFD_MAX_NUM_SE) { +- pr_err("Exceeded KFD_MAX_NUM_SE, chip reports %d\n", cu_info.num_shader_engines); ++ if (gfx_info->max_shader_engines > KFD_MAX_NUM_SE) { ++ dev_err(mm->dev->adev->dev, ++ "Exceeded KFD_MAX_NUM_SE, chip reports %d\n", ++ gfx_info->max_shader_engines); + return; + } +- if (cu_info.num_shader_arrays_per_engine > KFD_MAX_NUM_SH_PER_SE) { +- pr_err("Exceeded KFD_MAX_NUM_SH, chip reports %d\n", +- cu_info.num_shader_arrays_per_engine * cu_info.num_shader_engines); ++ if (gfx_info->max_sh_per_se > KFD_MAX_NUM_SH_PER_SE) { ++ dev_err(mm->dev->adev->dev, ++ "Exceeded KFD_MAX_NUM_SH, chip reports %d\n", ++ gfx_info->max_sh_per_se * gfx_info->max_shader_engines); + return; + } + +@@ -142,10 +144,10 @@ void mqd_symmetrically_map_cu_mask(struct mqd_manager *mm, + * See note on Arcturus cu_bitmap layout in gfx_v9_0_get_cu_info. + * See note on GFX11 cu_bitmap layout in gfx_v11_0_get_cu_info. + */ +- for (se = 0; se < cu_info.num_shader_engines; se++) +- for (sh = 0; sh < cu_info.num_shader_arrays_per_engine; sh++) ++ for (se = 0; se < gfx_info->max_shader_engines; se++) ++ for (sh = 0; sh < gfx_info->max_sh_per_se; sh++) + cu_per_sh[se][sh] = hweight32( +- cu_info.cu_bitmap[xcc_inst][se % 4][sh + (se / 4) * ++ cu_info->bitmap[xcc_inst][se % 4][sh + (se / 4) * + cu_bitmap_sh_mul]); + + /* Symmetrically map cu_mask to all SEs & SHs: +@@ -184,13 +186,13 @@ void mqd_symmetrically_map_cu_mask(struct mqd_manager *mm, + * + * First ensure all CUs are disabled, then enable user specified CUs. + */ +- for (i = 0; i < cu_info.num_shader_engines; i++) ++ for (i = 0; i < gfx_info->max_shader_engines; i++) + se_mask[i] = 0; + + i = inst; + for (cu = 0; cu < 16; cu += cu_inc) { +- for (sh = 0; sh < cu_info.num_shader_arrays_per_engine; sh++) { +- for (se = 0; se < cu_info.num_shader_engines; se++) { ++ for (sh = 0; sh < gfx_info->max_sh_per_se; sh++) { ++ for (se = 0; se < gfx_info->max_shader_engines; se++) { + if (cu_per_sh[se][sh] > cu) { + if (cu_mask[i / 32] & (en_mask << (i % 32))) + se_mask[se] |= en_mask << (cu + sh * 16); +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c +index 401096c103b2f1..ecb38a6e8013cd 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c +@@ -45,7 +45,8 @@ static void pm_calc_rlib_size(struct packet_manager *pm, + unsigned int process_count, queue_count, compute_queue_count, gws_queue_count; + unsigned int map_queue_size; + unsigned int max_proc_per_quantum = 1; +- struct kfd_node *dev = pm->dqm->dev; ++ struct kfd_node *node = pm->dqm->dev; ++ struct device *dev = node->adev->dev; + + process_count = pm->dqm->processes_count; + queue_count = pm->dqm->active_queue_count; +@@ -59,14 +60,14 @@ static void pm_calc_rlib_size(struct packet_manager *pm, + */ + *over_subscription = false; + +- if (dev->max_proc_per_quantum > 1) +- max_proc_per_quantum = dev->max_proc_per_quantum; ++ if (node->max_proc_per_quantum > 1) ++ max_proc_per_quantum = node->max_proc_per_quantum; + + if ((process_count > max_proc_per_quantum) || + compute_queue_count > get_cp_queues_num(pm->dqm) || + gws_queue_count > 1) { + *over_subscription = true; +- pr_debug("Over subscribed runlist\n"); ++ dev_dbg(dev, "Over subscribed runlist\n"); + } + + map_queue_size = pm->pmf->map_queues_size; +@@ -81,7 +82,7 @@ static void pm_calc_rlib_size(struct packet_manager *pm, + if (*over_subscription) + *rlib_size += pm->pmf->runlist_size; + +- pr_debug("runlist ib size %d\n", *rlib_size); ++ dev_dbg(dev, "runlist ib size %d\n", *rlib_size); + } + + static int pm_allocate_runlist_ib(struct packet_manager *pm, +@@ -90,6 +91,8 @@ static int pm_allocate_runlist_ib(struct packet_manager *pm, + unsigned int *rl_buffer_size, + bool *is_over_subscription) + { ++ struct kfd_node *node = pm->dqm->dev; ++ struct device *dev = node->adev->dev; + int retval; + + if (WARN_ON(pm->allocated)) +@@ -99,11 +102,10 @@ static int pm_allocate_runlist_ib(struct packet_manager *pm, + + mutex_lock(&pm->lock); + +- retval = kfd_gtt_sa_allocate(pm->dqm->dev, *rl_buffer_size, +- &pm->ib_buffer_obj); ++ retval = kfd_gtt_sa_allocate(node, *rl_buffer_size, &pm->ib_buffer_obj); + + if (retval) { +- pr_err("Failed to allocate runlist IB\n"); ++ dev_err(dev, "Failed to allocate runlist IB\n"); + goto out; + } + +@@ -125,6 +127,8 @@ static int pm_create_runlist_ib(struct packet_manager *pm, + { + unsigned int alloc_size_bytes; + unsigned int *rl_buffer, rl_wptr, i; ++ struct kfd_node *node = pm->dqm->dev; ++ struct device *dev = node->adev->dev; + int retval, processes_mapped; + struct device_process_node *cur; + struct qcm_process_device *qpd; +@@ -142,7 +146,7 @@ static int pm_create_runlist_ib(struct packet_manager *pm, + *rl_size_bytes = alloc_size_bytes; + pm->ib_size_bytes = alloc_size_bytes; + +- pr_debug("Building runlist ib process count: %d queues count %d\n", ++ dev_dbg(dev, "Building runlist ib process count: %d queues count %d\n", + pm->dqm->processes_count, pm->dqm->active_queue_count); + + /* build the run list ib packet */ +@@ -150,7 +154,7 @@ static int pm_create_runlist_ib(struct packet_manager *pm, + qpd = cur->qpd; + /* build map process packet */ + if (processes_mapped >= pm->dqm->processes_count) { +- pr_debug("Not enough space left in runlist IB\n"); ++ dev_dbg(dev, "Not enough space left in runlist IB\n"); + pm_release_ib(pm); + return -ENOMEM; + } +@@ -167,7 +171,8 @@ static int pm_create_runlist_ib(struct packet_manager *pm, + if (!kq->queue->properties.is_active) + continue; + +- pr_debug("static_queue, mapping kernel q %d, is debug status %d\n", ++ dev_dbg(dev, ++ "static_queue, mapping kernel q %d, is debug status %d\n", + kq->queue->queue, qpd->is_debug); + + retval = pm->pmf->map_queues(pm, +@@ -186,7 +191,8 @@ static int pm_create_runlist_ib(struct packet_manager *pm, + if (!q->properties.is_active) + continue; + +- pr_debug("static_queue, mapping user queue %d, is debug status %d\n", ++ dev_dbg(dev, ++ "static_queue, mapping user queue %d, is debug status %d\n", + q->queue, qpd->is_debug); + + retval = pm->pmf->map_queues(pm, +@@ -203,11 +209,13 @@ static int pm_create_runlist_ib(struct packet_manager *pm, + } + } + +- pr_debug("Finished map process and queues to runlist\n"); ++ dev_dbg(dev, "Finished map process and queues to runlist\n"); + + if (is_over_subscription) { + if (!pm->is_over_subscription) +- pr_warn("Runlist is getting oversubscribed. Expect reduced ROCm performance.\n"); ++ dev_warn( ++ dev, ++ "Runlist is getting oversubscribed. Expect reduced ROCm performance.\n"); + retval = pm->pmf->runlist(pm, &rl_buffer[rl_wptr], + *rl_gpu_addr, + alloc_size_bytes / sizeof(uint32_t), +@@ -272,6 +280,8 @@ void pm_uninit(struct packet_manager *pm, bool hanging) + int pm_send_set_resources(struct packet_manager *pm, + struct scheduling_resources *res) + { ++ struct kfd_node *node = pm->dqm->dev; ++ struct device *dev = node->adev->dev; + uint32_t *buffer, size; + int retval = 0; + +@@ -281,7 +291,7 @@ int pm_send_set_resources(struct packet_manager *pm, + size / sizeof(uint32_t), + (unsigned int **)&buffer); + if (!buffer) { +- pr_err("Failed to allocate buffer on kernel queue\n"); ++ dev_err(dev, "Failed to allocate buffer on kernel queue\n"); + retval = -ENOMEM; + goto out; + } +@@ -343,6 +353,8 @@ int pm_send_runlist(struct packet_manager *pm, struct list_head *dqm_queues) + int pm_send_query_status(struct packet_manager *pm, uint64_t fence_address, + uint64_t fence_value) + { ++ struct kfd_node *node = pm->dqm->dev; ++ struct device *dev = node->adev->dev; + uint32_t *buffer, size; + int retval = 0; + +@@ -354,7 +366,7 @@ int pm_send_query_status(struct packet_manager *pm, uint64_t fence_address, + kq_acquire_packet_buffer(pm->priv_queue, + size / sizeof(uint32_t), (unsigned int **)&buffer); + if (!buffer) { +- pr_err("Failed to allocate buffer on kernel queue\n"); ++ dev_err(dev, "Failed to allocate buffer on kernel queue\n"); + retval = -ENOMEM; + goto out; + } +@@ -372,6 +384,8 @@ int pm_send_query_status(struct packet_manager *pm, uint64_t fence_address, + + int pm_update_grace_period(struct packet_manager *pm, uint32_t grace_period) + { ++ struct kfd_node *node = pm->dqm->dev; ++ struct device *dev = node->adev->dev; + int retval = 0; + uint32_t *buffer, size; + +@@ -385,7 +399,8 @@ int pm_update_grace_period(struct packet_manager *pm, uint32_t grace_period) + (unsigned int **)&buffer); + + if (!buffer) { +- pr_err("Failed to allocate buffer on kernel queue\n"); ++ dev_err(dev, ++ "Failed to allocate buffer on kernel queue\n"); + retval = -ENOMEM; + goto out; + } +@@ -406,6 +421,8 @@ int pm_send_unmap_queue(struct packet_manager *pm, + enum kfd_unmap_queues_filter filter, + uint32_t filter_param, bool reset) + { ++ struct kfd_node *node = pm->dqm->dev; ++ struct device *dev = node->adev->dev; + uint32_t *buffer, size; + int retval = 0; + +@@ -414,7 +431,7 @@ int pm_send_unmap_queue(struct packet_manager *pm, + kq_acquire_packet_buffer(pm->priv_queue, + size / sizeof(uint32_t), (unsigned int **)&buffer); + if (!buffer) { +- pr_err("Failed to allocate buffer on kernel queue\n"); ++ dev_err(dev, "Failed to allocate buffer on kernel queue\n"); + retval = -ENOMEM; + goto out; + } +@@ -463,6 +480,8 @@ int pm_debugfs_runlist(struct seq_file *m, void *data) + + int pm_debugfs_hang_hws(struct packet_manager *pm) + { ++ struct kfd_node *node = pm->dqm->dev; ++ struct device *dev = node->adev->dev; + uint32_t *buffer, size; + int r = 0; + +@@ -474,16 +493,16 @@ int pm_debugfs_hang_hws(struct packet_manager *pm) + kq_acquire_packet_buffer(pm->priv_queue, + size / sizeof(uint32_t), (unsigned int **)&buffer); + if (!buffer) { +- pr_err("Failed to allocate buffer on kernel queue\n"); ++ dev_err(dev, "Failed to allocate buffer on kernel queue\n"); + r = -ENOMEM; + goto out; + } + memset(buffer, 0x55, size); + kq_submit_packet(pm->priv_queue); + +- pr_info("Submitting %x %x %x %x %x %x %x to HIQ to hang the HWS.", +- buffer[0], buffer[1], buffer[2], buffer[3], +- buffer[4], buffer[5], buffer[6]); ++ dev_info(dev, "Submitting %x %x %x %x %x %x %x to HIQ to hang the HWS.", ++ buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], ++ buffer[5], buffer[6]); + out: + mutex_unlock(&pm->lock); + return r; +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c +index fd640a061c96a8..64346c71c62a30 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c +@@ -1046,7 +1046,8 @@ static void kfd_process_destroy_pdds(struct kfd_process *p) + + kfd_free_process_doorbells(pdd->dev->kfd, pdd); + +- if (pdd->dev->kfd->shared_resources.enable_mes) ++ if (pdd->dev->kfd->shared_resources.enable_mes && ++ pdd->proc_ctx_cpu_ptr) + amdgpu_amdkfd_free_gtt_mem(pdd->dev->adev, + &pdd->proc_ctx_bo); + /* +@@ -1308,7 +1309,8 @@ int kfd_process_init_cwsr_apu(struct kfd_process *p, struct file *filep) + if (IS_ERR_VALUE(qpd->tba_addr)) { + int err = qpd->tba_addr; + +- pr_err("Failure to set tba address. error %d.\n", err); ++ dev_err(dev->adev->dev, ++ "Failure to set tba address. error %d.\n", err); + qpd->tba_addr = 0; + qpd->cwsr_kaddr = NULL; + return err; +@@ -1571,7 +1573,6 @@ struct kfd_process_device *kfd_create_process_device_data(struct kfd_node *dev, + struct kfd_process *p) + { + struct kfd_process_device *pdd = NULL; +- int retval = 0; + + if (WARN_ON_ONCE(p->n_pdds >= MAX_GPU_INSTANCE)) + return NULL; +@@ -1595,20 +1596,6 @@ struct kfd_process_device *kfd_create_process_device_data(struct kfd_node *dev, + pdd->user_gpu_id = dev->id; + atomic64_set(&pdd->evict_duration_counter, 0); + +- if (dev->kfd->shared_resources.enable_mes) { +- retval = amdgpu_amdkfd_alloc_gtt_mem(dev->adev, +- AMDGPU_MES_PROC_CTX_SIZE, +- &pdd->proc_ctx_bo, +- &pdd->proc_ctx_gpu_addr, +- &pdd->proc_ctx_cpu_ptr, +- false); +- if (retval) { +- pr_err("failed to allocate process context bo\n"); +- goto err_free_pdd; +- } +- memset(pdd->proc_ctx_cpu_ptr, 0, AMDGPU_MES_PROC_CTX_SIZE); +- } +- + p->pdds[p->n_pdds++] = pdd; + if (kfd_dbg_is_per_vmid_supported(pdd->dev)) + pdd->spi_dbg_override = pdd->dev->kfd2kgd->disable_debug_trap( +@@ -1620,10 +1607,6 @@ struct kfd_process_device *kfd_create_process_device_data(struct kfd_node *dev, + idr_init(&pdd->alloc_idr); + + return pdd; +- +-err_free_pdd: +- kfree(pdd); +- return NULL; + } + + /** +@@ -1667,7 +1650,7 @@ int kfd_process_device_init_vm(struct kfd_process_device *pdd, + &p->kgd_process_info, + &p->ef); + if (ret) { +- pr_err("Failed to create process VM object\n"); ++ dev_err(dev->adev->dev, "Failed to create process VM object\n"); + return ret; + } + pdd->drm_priv = drm_file->private_data; +@@ -1714,7 +1697,7 @@ struct kfd_process_device *kfd_bind_process_to_device(struct kfd_node *dev, + + pdd = kfd_get_process_device_data(dev, p); + if (!pdd) { +- pr_err("Process device data doesn't exist\n"); ++ dev_err(dev->adev->dev, "Process device data doesn't exist\n"); + return ERR_PTR(-ENOMEM); + } + +@@ -1824,6 +1807,7 @@ int kfd_process_evict_queues(struct kfd_process *p, uint32_t trigger) + + for (i = 0; i < p->n_pdds; i++) { + struct kfd_process_device *pdd = p->pdds[i]; ++ struct device *dev = pdd->dev->adev->dev; + + kfd_smi_event_queue_eviction(pdd->dev, p->lead_thread->pid, + trigger); +@@ -1835,7 +1819,7 @@ int kfd_process_evict_queues(struct kfd_process *p, uint32_t trigger) + * them been add back since they actually not be saved right now. + */ + if (r && r != -EIO) { +- pr_err("Failed to evict process queues\n"); ++ dev_err(dev, "Failed to evict process queues\n"); + goto fail; + } + n_evicted++; +@@ -1857,7 +1841,8 @@ int kfd_process_evict_queues(struct kfd_process *p, uint32_t trigger) + + if (pdd->dev->dqm->ops.restore_process_queues(pdd->dev->dqm, + &pdd->qpd)) +- pr_err("Failed to restore queues\n"); ++ dev_err(pdd->dev->adev->dev, ++ "Failed to restore queues\n"); + + n_evicted--; + } +@@ -1873,13 +1858,14 @@ int kfd_process_restore_queues(struct kfd_process *p) + + for (i = 0; i < p->n_pdds; i++) { + struct kfd_process_device *pdd = p->pdds[i]; ++ struct device *dev = pdd->dev->adev->dev; + + kfd_smi_event_queue_restore(pdd->dev, p->lead_thread->pid); + + r = pdd->dev->dqm->ops.restore_process_queues(pdd->dev->dqm, + &pdd->qpd); + if (r) { +- pr_err("Failed to restore process queues\n"); ++ dev_err(dev, "Failed to restore process queues\n"); + if (!ret) + ret = r; + } +@@ -2039,7 +2025,7 @@ int kfd_reserved_mem_mmap(struct kfd_node *dev, struct kfd_process *process, + struct qcm_process_device *qpd; + + if ((vma->vm_end - vma->vm_start) != KFD_CWSR_TBA_TMA_SIZE) { +- pr_err("Incorrect CWSR mapping size.\n"); ++ dev_err(dev->adev->dev, "Incorrect CWSR mapping size.\n"); + return -EINVAL; + } + +@@ -2051,7 +2037,8 @@ int kfd_reserved_mem_mmap(struct kfd_node *dev, struct kfd_process *process, + qpd->cwsr_kaddr = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, + get_order(KFD_CWSR_TBA_TMA_SIZE)); + if (!qpd->cwsr_kaddr) { +- pr_err("Error allocating per process CWSR buffer.\n"); ++ dev_err(dev->adev->dev, ++ "Error allocating per process CWSR buffer.\n"); + return -ENOMEM; + } + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c +index 8362a71ab70752..3885bb53f0191e 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c +@@ -1537,7 +1537,6 @@ static int kfd_dev_create_p2p_links(void) + /* Helper function. See kfd_fill_gpu_cache_info for parameter description */ + static int fill_in_l1_pcache(struct kfd_cache_properties **props_ext, + struct kfd_gpu_cache_info *pcache_info, +- struct kfd_cu_info *cu_info, + int cu_bitmask, + int cache_type, unsigned int cu_processor_id, + int cu_block) +@@ -1599,7 +1598,8 @@ static int fill_in_l1_pcache(struct kfd_cache_properties **props_ext, + /* Helper function. See kfd_fill_gpu_cache_info for parameter description */ + static int fill_in_l2_l3_pcache(struct kfd_cache_properties **props_ext, + struct kfd_gpu_cache_info *pcache_info, +- struct kfd_cu_info *cu_info, ++ struct amdgpu_cu_info *cu_info, ++ struct amdgpu_gfx_config *gfx_info, + int cache_type, unsigned int cu_processor_id, + struct kfd_node *knode) + { +@@ -1610,7 +1610,7 @@ static int fill_in_l2_l3_pcache(struct kfd_cache_properties **props_ext, + + start = ffs(knode->xcc_mask) - 1; + end = start + NUM_XCC(knode->xcc_mask); +- cu_sibling_map_mask = cu_info->cu_bitmap[start][0][0]; ++ cu_sibling_map_mask = cu_info->bitmap[start][0][0]; + cu_sibling_map_mask &= + ((1 << pcache_info[cache_type].num_cu_shared) - 1); + first_active_cu = ffs(cu_sibling_map_mask); +@@ -1646,15 +1646,15 @@ static int fill_in_l2_l3_pcache(struct kfd_cache_properties **props_ext, + k = 0; + + for (xcc = start; xcc < end; xcc++) { +- for (i = 0; i < cu_info->num_shader_engines; i++) { +- for (j = 0; j < cu_info->num_shader_arrays_per_engine; j++) { ++ for (i = 0; i < gfx_info->max_shader_engines; i++) { ++ for (j = 0; j < gfx_info->max_sh_per_se; j++) { + pcache->sibling_map[k] = (uint8_t)(cu_sibling_map_mask & 0xFF); + pcache->sibling_map[k+1] = (uint8_t)((cu_sibling_map_mask >> 8) & 0xFF); + pcache->sibling_map[k+2] = (uint8_t)((cu_sibling_map_mask >> 16) & 0xFF); + pcache->sibling_map[k+3] = (uint8_t)((cu_sibling_map_mask >> 24) & 0xFF); + k += 4; + +- cu_sibling_map_mask = cu_info->cu_bitmap[xcc][i % 4][j + i / 4]; ++ cu_sibling_map_mask = cu_info->bitmap[xcc][i % 4][j + i / 4]; + cu_sibling_map_mask &= ((1 << pcache_info[cache_type].num_cu_shared) - 1); + } + } +@@ -1679,16 +1679,14 @@ static void kfd_fill_cache_non_crat_info(struct kfd_topology_device *dev, struct + unsigned int cu_processor_id; + int ret; + unsigned int num_cu_shared; +- struct kfd_cu_info cu_info; +- struct kfd_cu_info *pcu_info; ++ struct amdgpu_cu_info *cu_info = &kdev->adev->gfx.cu_info; ++ struct amdgpu_gfx_config *gfx_info = &kdev->adev->gfx.config; + int gpu_processor_id; + struct kfd_cache_properties *props_ext; + int num_of_entries = 0; + int num_of_cache_types = 0; + struct kfd_gpu_cache_info cache_info[KFD_MAX_CACHE_TYPES]; + +- amdgpu_amdkfd_get_cu_info(kdev->adev, &cu_info); +- pcu_info = &cu_info; + + gpu_processor_id = dev->node_props.simd_id_base; + +@@ -1715,12 +1713,12 @@ static void kfd_fill_cache_non_crat_info(struct kfd_topology_device *dev, struct + cu_processor_id = gpu_processor_id; + if (pcache_info[ct].cache_level == 1) { + for (xcc = start; xcc < end; xcc++) { +- for (i = 0; i < pcu_info->num_shader_engines; i++) { +- for (j = 0; j < pcu_info->num_shader_arrays_per_engine; j++) { +- for (k = 0; k < pcu_info->num_cu_per_sh; k += pcache_info[ct].num_cu_shared) { ++ for (i = 0; i < gfx_info->max_shader_engines; i++) { ++ for (j = 0; j < gfx_info->max_sh_per_se; j++) { ++ for (k = 0; k < gfx_info->max_cu_per_sh; k += pcache_info[ct].num_cu_shared) { + +- ret = fill_in_l1_pcache(&props_ext, pcache_info, pcu_info, +- pcu_info->cu_bitmap[xcc][i % 4][j + i / 4], ct, ++ ret = fill_in_l1_pcache(&props_ext, pcache_info, ++ cu_info->bitmap[xcc][i % 4][j + i / 4], ct, + cu_processor_id, k); + + if (ret < 0) +@@ -1733,9 +1731,9 @@ static void kfd_fill_cache_non_crat_info(struct kfd_topology_device *dev, struct + + /* Move to next CU block */ + num_cu_shared = ((k + pcache_info[ct].num_cu_shared) <= +- pcu_info->num_cu_per_sh) ? ++ gfx_info->max_cu_per_sh) ? + pcache_info[ct].num_cu_shared : +- (pcu_info->num_cu_per_sh - k); ++ (gfx_info->max_cu_per_sh - k); + cu_processor_id += num_cu_shared; + } + } +@@ -1743,7 +1741,7 @@ static void kfd_fill_cache_non_crat_info(struct kfd_topology_device *dev, struct + } + } else { + ret = fill_in_l2_l3_pcache(&props_ext, pcache_info, +- pcu_info, ct, cu_processor_id, kdev); ++ cu_info, gfx_info, ct, cu_processor_id, kdev); + + if (ret < 0) + break; +@@ -1922,10 +1920,11 @@ int kfd_topology_add_device(struct kfd_node *gpu) + { + uint32_t gpu_id; + struct kfd_topology_device *dev; +- struct kfd_cu_info cu_info; + int res = 0; + int i; + const char *asic_name = amdgpu_asic_name[gpu->adev->asic_type]; ++ struct amdgpu_gfx_config *gfx_info = &gpu->adev->gfx.config; ++ struct amdgpu_cu_info *cu_info = &gpu->adev->gfx.cu_info; + + gpu_id = kfd_generate_gpu_id(gpu); + if (gpu->xcp && !gpu->xcp->ddev) { +@@ -1963,9 +1962,6 @@ int kfd_topology_add_device(struct kfd_node *gpu) + /* Fill-in additional information that is not available in CRAT but + * needed for the topology + */ +- +- amdgpu_amdkfd_get_cu_info(dev->gpu->adev, &cu_info); +- + for (i = 0; i < KFD_TOPOLOGY_PUBLIC_NAME_SIZE-1; i++) { + dev->node_props.name[i] = __tolower(asic_name[i]); + if (asic_name[i] == '\0') +@@ -1974,7 +1970,7 @@ int kfd_topology_add_device(struct kfd_node *gpu) + dev->node_props.name[i] = '\0'; + + dev->node_props.simd_arrays_per_engine = +- cu_info.num_shader_arrays_per_engine; ++ gfx_info->max_sh_per_se; + + dev->node_props.gfx_target_version = + gpu->kfd->device_info.gfx_target_version; +@@ -2055,7 +2051,7 @@ int kfd_topology_add_device(struct kfd_node *gpu) + */ + if (dev->gpu->adev->asic_type == CHIP_CARRIZO) { + dev->node_props.simd_count = +- cu_info.simd_per_cu * cu_info.cu_active_number; ++ cu_info->simd_per_cu * cu_info->number; + dev->node_props.max_waves_per_simd = 10; + } + +diff --git a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h +index 3b5a56585c4b72..c653a7f4d5e55b 100644 +--- a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h ++++ b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h +@@ -57,20 +57,6 @@ struct kfd_vm_fault_info { + bool prot_exec; + }; + +-struct kfd_cu_info { +- uint32_t num_shader_engines; +- uint32_t num_shader_arrays_per_engine; +- uint32_t num_cu_per_sh; +- uint32_t cu_active_number; +- uint32_t cu_ao_mask; +- uint32_t simd_per_cu; +- uint32_t max_waves_per_simd; +- uint32_t wave_front_size; +- uint32_t max_scratch_slots_per_cu; +- uint32_t lds_size; +- uint32_t cu_bitmap[AMDGPU_MAX_GC_INSTANCES][4][4]; +-}; +- + /* For getting GPU local memory information from KGD */ + struct kfd_local_mem_info { + uint64_t local_mem_size_private; +diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c +index 90bfb1e988fb31..d6c5de190c2742 100644 +--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c ++++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c +@@ -4033,9 +4033,10 @@ static void drm_dp_mst_up_req_work(struct work_struct *work) + static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr) + { + struct drm_dp_pending_up_req *up_req; ++ struct drm_dp_mst_branch *mst_primary; + + if (!drm_dp_get_one_sb_msg(mgr, true, NULL)) +- goto out; ++ goto out_clear_reply; + + if (!mgr->up_req_recv.have_eomt) + return 0; +@@ -4053,10 +4054,19 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr) + drm_dbg_kms(mgr->dev, "Received unknown up req type, ignoring: %x\n", + up_req->msg.req_type); + kfree(up_req); +- goto out; ++ goto out_clear_reply; ++ } ++ ++ mutex_lock(&mgr->lock); ++ mst_primary = mgr->mst_primary; ++ if (!mst_primary || !drm_dp_mst_topology_try_get_mstb(mst_primary)) { ++ mutex_unlock(&mgr->lock); ++ kfree(up_req); ++ goto out_clear_reply; + } ++ mutex_unlock(&mgr->lock); + +- drm_dp_send_up_ack_reply(mgr, mgr->mst_primary, up_req->msg.req_type, ++ drm_dp_send_up_ack_reply(mgr, mst_primary, up_req->msg.req_type, + false); + + if (up_req->msg.req_type == DP_CONNECTION_STATUS_NOTIFY) { +@@ -4073,13 +4083,13 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr) + conn_stat->peer_device_type); + + mutex_lock(&mgr->probe_lock); +- handle_csn = mgr->mst_primary->link_address_sent; ++ handle_csn = mst_primary->link_address_sent; + mutex_unlock(&mgr->probe_lock); + + if (!handle_csn) { + drm_dbg_kms(mgr->dev, "Got CSN before finish topology probing. Skip it."); + kfree(up_req); +- goto out; ++ goto out_put_primary; + } + } else if (up_req->msg.req_type == DP_RESOURCE_STATUS_NOTIFY) { + const struct drm_dp_resource_status_notify *res_stat = +@@ -4096,7 +4106,9 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr) + mutex_unlock(&mgr->up_req_lock); + queue_work(system_long_wq, &mgr->up_req_work); + +-out: ++out_put_primary: ++ drm_dp_mst_topology_put_mstb(mst_primary); ++out_clear_reply: + memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx)); + return 0; + } +diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c +index 0951bfdc89cfa5..913823a063c9ae 100644 +--- a/drivers/i2c/busses/i2c-imx.c ++++ b/drivers/i2c/busses/i2c-imx.c +@@ -286,6 +286,7 @@ static const struct of_device_id i2c_imx_dt_ids[] = { + { .compatible = "fsl,imx6sll-i2c", .data = &imx6_i2c_hwdata, }, + { .compatible = "fsl,imx6sx-i2c", .data = &imx6_i2c_hwdata, }, + { .compatible = "fsl,imx6ul-i2c", .data = &imx6_i2c_hwdata, }, ++ { .compatible = "fsl,imx7d-i2c", .data = &imx6_i2c_hwdata, }, + { .compatible = "fsl,imx7s-i2c", .data = &imx6_i2c_hwdata, }, + { .compatible = "fsl,imx8mm-i2c", .data = &imx6_i2c_hwdata, }, + { .compatible = "fsl,imx8mn-i2c", .data = &imx6_i2c_hwdata, }, +diff --git a/drivers/i2c/busses/i2c-microchip-corei2c.c b/drivers/i2c/busses/i2c-microchip-corei2c.c +index 0b0a1c4d17caef..b0a51695138ad0 100644 +--- a/drivers/i2c/busses/i2c-microchip-corei2c.c ++++ b/drivers/i2c/busses/i2c-microchip-corei2c.c +@@ -93,27 +93,35 @@ + * @base: pointer to register struct + * @dev: device reference + * @i2c_clk: clock reference for i2c input clock ++ * @msg_queue: pointer to the messages requiring sending + * @buf: pointer to msg buffer for easier use + * @msg_complete: xfer completion object + * @adapter: core i2c abstraction + * @msg_err: error code for completed message + * @bus_clk_rate: current i2c bus clock rate + * @isr_status: cached copy of local ISR status ++ * @total_num: total number of messages to be sent/received ++ * @current_num: index of the current message being sent/received + * @msg_len: number of bytes transferred in msg + * @addr: address of the current slave ++ * @restart_needed: whether or not a repeated start is required after current message + */ + struct mchp_corei2c_dev { + void __iomem *base; + struct device *dev; + struct clk *i2c_clk; ++ struct i2c_msg *msg_queue; + u8 *buf; + struct completion msg_complete; + struct i2c_adapter adapter; + int msg_err; ++ int total_num; ++ int current_num; + u32 bus_clk_rate; + u32 isr_status; + u16 msg_len; + u8 addr; ++ bool restart_needed; + }; + + static void mchp_corei2c_core_disable(struct mchp_corei2c_dev *idev) +@@ -222,6 +230,47 @@ static int mchp_corei2c_fill_tx(struct mchp_corei2c_dev *idev) + return 0; + } + ++static void mchp_corei2c_next_msg(struct mchp_corei2c_dev *idev) ++{ ++ struct i2c_msg *this_msg; ++ u8 ctrl; ++ ++ if (idev->current_num >= idev->total_num) { ++ complete(&idev->msg_complete); ++ return; ++ } ++ ++ /* ++ * If there's been an error, the isr needs to return control ++ * to the "main" part of the driver, so as not to keep sending ++ * messages once it completes and clears the SI bit. ++ */ ++ if (idev->msg_err) { ++ complete(&idev->msg_complete); ++ return; ++ } ++ ++ this_msg = idev->msg_queue++; ++ ++ if (idev->current_num < (idev->total_num - 1)) { ++ struct i2c_msg *next_msg = idev->msg_queue; ++ ++ idev->restart_needed = next_msg->flags & I2C_M_RD; ++ } else { ++ idev->restart_needed = false; ++ } ++ ++ idev->addr = i2c_8bit_addr_from_msg(this_msg); ++ idev->msg_len = this_msg->len; ++ idev->buf = this_msg->buf; ++ ++ ctrl = readb(idev->base + CORE_I2C_CTRL); ++ ctrl |= CTRL_STA; ++ writeb(ctrl, idev->base + CORE_I2C_CTRL); ++ ++ idev->current_num++; ++} ++ + static irqreturn_t mchp_corei2c_handle_isr(struct mchp_corei2c_dev *idev) + { + u32 status = idev->isr_status; +@@ -238,8 +287,6 @@ static irqreturn_t mchp_corei2c_handle_isr(struct mchp_corei2c_dev *idev) + ctrl &= ~CTRL_STA; + writeb(idev->addr, idev->base + CORE_I2C_DATA); + writeb(ctrl, idev->base + CORE_I2C_CTRL); +- if (idev->msg_len == 0) +- finished = true; + break; + case STATUS_M_ARB_LOST: + idev->msg_err = -EAGAIN; +@@ -247,10 +294,14 @@ static irqreturn_t mchp_corei2c_handle_isr(struct mchp_corei2c_dev *idev) + break; + case STATUS_M_SLAW_ACK: + case STATUS_M_TX_DATA_ACK: +- if (idev->msg_len > 0) ++ if (idev->msg_len > 0) { + mchp_corei2c_fill_tx(idev); +- else +- last_byte = true; ++ } else { ++ if (idev->restart_needed) ++ finished = true; ++ else ++ last_byte = true; ++ } + break; + case STATUS_M_TX_DATA_NACK: + case STATUS_M_SLAR_NACK: +@@ -287,7 +338,7 @@ static irqreturn_t mchp_corei2c_handle_isr(struct mchp_corei2c_dev *idev) + mchp_corei2c_stop(idev); + + if (last_byte || finished) +- complete(&idev->msg_complete); ++ mchp_corei2c_next_msg(idev); + + return IRQ_HANDLED; + } +@@ -311,21 +362,48 @@ static irqreturn_t mchp_corei2c_isr(int irq, void *_dev) + return ret; + } + +-static int mchp_corei2c_xfer_msg(struct mchp_corei2c_dev *idev, +- struct i2c_msg *msg) ++static int mchp_corei2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, ++ int num) + { +- u8 ctrl; ++ struct mchp_corei2c_dev *idev = i2c_get_adapdata(adap); ++ struct i2c_msg *this_msg = msgs; + unsigned long time_left; ++ u8 ctrl; ++ ++ mchp_corei2c_core_enable(idev); ++ ++ /* ++ * The isr controls the flow of a transfer, this info needs to be saved ++ * to a location that it can access the queue information from. ++ */ ++ idev->restart_needed = false; ++ idev->msg_queue = msgs; ++ idev->total_num = num; ++ idev->current_num = 0; + +- idev->addr = i2c_8bit_addr_from_msg(msg); +- idev->msg_len = msg->len; +- idev->buf = msg->buf; ++ /* ++ * But the first entry to the isr is triggered by the start in this ++ * function, so the first message needs to be "dequeued". ++ */ ++ idev->addr = i2c_8bit_addr_from_msg(this_msg); ++ idev->msg_len = this_msg->len; ++ idev->buf = this_msg->buf; + idev->msg_err = 0; + +- reinit_completion(&idev->msg_complete); ++ if (idev->total_num > 1) { ++ struct i2c_msg *next_msg = msgs + 1; + +- mchp_corei2c_core_enable(idev); ++ idev->restart_needed = next_msg->flags & I2C_M_RD; ++ } + ++ idev->current_num++; ++ idev->msg_queue++; ++ ++ reinit_completion(&idev->msg_complete); ++ ++ /* ++ * Send the first start to pass control to the isr ++ */ + ctrl = readb(idev->base + CORE_I2C_CTRL); + ctrl |= CTRL_STA; + writeb(ctrl, idev->base + CORE_I2C_CTRL); +@@ -335,20 +413,8 @@ static int mchp_corei2c_xfer_msg(struct mchp_corei2c_dev *idev, + if (!time_left) + return -ETIMEDOUT; + +- return idev->msg_err; +-} +- +-static int mchp_corei2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, +- int num) +-{ +- struct mchp_corei2c_dev *idev = i2c_get_adapdata(adap); +- int i, ret; +- +- for (i = 0; i < num; i++) { +- ret = mchp_corei2c_xfer_msg(idev, msgs++); +- if (ret) +- return ret; +- } ++ if (idev->msg_err) ++ return idev->msg_err; + + return num; + } +diff --git a/drivers/media/dvb-frontends/dib3000mb.c b/drivers/media/dvb-frontends/dib3000mb.c +index c598b2a6332565..7c452ddd9e40fa 100644 +--- a/drivers/media/dvb-frontends/dib3000mb.c ++++ b/drivers/media/dvb-frontends/dib3000mb.c +@@ -51,7 +51,7 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe (|-a + static int dib3000_read_reg(struct dib3000_state *state, u16 reg) + { + u8 wb[] = { ((reg >> 8) | 0x80) & 0xff, reg & 0xff }; +- u8 rb[2]; ++ u8 rb[2] = {}; + struct i2c_msg msg[] = { + { .addr = state->config.demod_address, .flags = 0, .buf = wb, .len = 2 }, + { .addr = state->config.demod_address, .flags = I2C_M_RD, .buf = rb, .len = 2 }, +diff --git a/drivers/mtd/nand/raw/arasan-nand-controller.c b/drivers/mtd/nand/raw/arasan-nand-controller.c +index a492051c46f596..bde396b359c321 100644 +--- a/drivers/mtd/nand/raw/arasan-nand-controller.c ++++ b/drivers/mtd/nand/raw/arasan-nand-controller.c +@@ -1410,8 +1410,8 @@ static int anfc_parse_cs(struct arasan_nfc *nfc) + * case, the "not" chosen CS is assigned to nfc->spare_cs and selected + * whenever a GPIO CS must be asserted. + */ +- if (nfc->cs_array && nfc->ncs > 2) { +- if (!nfc->cs_array[0] && !nfc->cs_array[1]) { ++ if (nfc->cs_array) { ++ if (nfc->ncs > 2 && !nfc->cs_array[0] && !nfc->cs_array[1]) { + dev_err(nfc->dev, + "Assign a single native CS when using GPIOs\n"); + return -EINVAL; +@@ -1479,8 +1479,15 @@ static int anfc_probe(struct platform_device *pdev) + + static void anfc_remove(struct platform_device *pdev) + { ++ int i; + struct arasan_nfc *nfc = platform_get_drvdata(pdev); + ++ for (i = 0; i < nfc->ncs; i++) { ++ if (nfc->cs_array[i]) { ++ gpiod_put(nfc->cs_array[i]); ++ } ++ } ++ + anfc_chips_cleanup(nfc); + } + +diff --git a/drivers/mtd/nand/raw/atmel/pmecc.c b/drivers/mtd/nand/raw/atmel/pmecc.c +index a22aab4ed4e8ab..3c7dee1be21df1 100644 +--- a/drivers/mtd/nand/raw/atmel/pmecc.c ++++ b/drivers/mtd/nand/raw/atmel/pmecc.c +@@ -380,10 +380,8 @@ atmel_pmecc_create_user(struct atmel_pmecc *pmecc, + user->delta = user->dmu + req->ecc.strength + 1; + + gf_tables = atmel_pmecc_get_gf_tables(req); +- if (IS_ERR(gf_tables)) { +- kfree(user); ++ if (IS_ERR(gf_tables)) + return ERR_CAST(gf_tables); +- } + + user->gf_tables = gf_tables; + +diff --git a/drivers/mtd/nand/raw/diskonchip.c b/drivers/mtd/nand/raw/diskonchip.c +index 2068025d56396a..594e13a852c497 100644 +--- a/drivers/mtd/nand/raw/diskonchip.c ++++ b/drivers/mtd/nand/raw/diskonchip.c +@@ -1098,7 +1098,7 @@ static inline int __init inftl_partscan(struct mtd_info *mtd, struct mtd_partiti + (i == 0) && (ip->firstUnit > 0)) { + parts[0].name = " DiskOnChip IPL / Media Header partition"; + parts[0].offset = 0; +- parts[0].size = mtd->erasesize * ip->firstUnit; ++ parts[0].size = (uint64_t)mtd->erasesize * ip->firstUnit; + numparts = 1; + } + +diff --git a/drivers/pci/msi/irqdomain.c b/drivers/pci/msi/irqdomain.c +index cfd84a899c82d8..dfc15e7507f9b9 100644 +--- a/drivers/pci/msi/irqdomain.c ++++ b/drivers/pci/msi/irqdomain.c +@@ -330,8 +330,11 @@ bool pci_msi_domain_supports(struct pci_dev *pdev, unsigned int feature_mask, + + domain = dev_get_msi_domain(&pdev->dev); + +- if (!domain || !irq_domain_is_hierarchy(domain)) +- return mode == ALLOW_LEGACY; ++ if (!domain || !irq_domain_is_hierarchy(domain)) { ++ if (IS_ENABLED(CONFIG_PCI_MSI_ARCH_FALLBACKS)) ++ return mode == ALLOW_LEGACY; ++ return false; ++ } + + if (!irq_domain_is_msi_parent(domain)) { + /* +diff --git a/drivers/pci/msi/msi.c b/drivers/pci/msi/msi.c +index 2d117cb74832be..053bb9fac6e3e1 100644 +--- a/drivers/pci/msi/msi.c ++++ b/drivers/pci/msi/msi.c +@@ -429,6 +429,10 @@ int __pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec, + if (WARN_ON_ONCE(dev->msi_enabled)) + return -EINVAL; + ++ /* Test for the availability of MSI support */ ++ if (!pci_msi_domain_supports(dev, 0, ALLOW_LEGACY)) ++ return -ENOTSUPP; ++ + nvec = pci_msi_vec_count(dev); + if (nvec < 0) + return nvec; +diff --git a/drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c b/drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c +index 4c10cafded4e93..530b571607c013 100644 +--- a/drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c ++++ b/drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c +@@ -323,6 +323,12 @@ static void usb_init_common_7216(struct brcm_usb_init_params *params) + void __iomem *ctrl = params->regs[BRCM_REGS_CTRL]; + + USB_CTRL_UNSET(ctrl, USB_PM, XHC_S2_CLK_SWITCH_EN); ++ ++ /* ++ * The PHY might be in a bad state if it is already powered ++ * up. Toggle the power just in case. ++ */ ++ USB_CTRL_SET(ctrl, USB_PM, USB_PWRDN); + USB_CTRL_UNSET(ctrl, USB_PM, USB_PWRDN); + + /* 1 millisecond - for USB clocks to settle down */ +diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c +index 96a0b1e111f349..a892e1d7e2d024 100644 +--- a/drivers/phy/phy-core.c ++++ b/drivers/phy/phy-core.c +@@ -140,8 +140,10 @@ static struct phy_provider *of_phy_provider_lookup(struct device_node *node) + return phy_provider; + + for_each_child_of_node(phy_provider->children, child) +- if (child == node) ++ if (child == node) { ++ of_node_put(child); + return phy_provider; ++ } + } + + return ERR_PTR(-EPROBE_DEFER); +@@ -577,8 +579,10 @@ static struct phy *_of_phy_get(struct device_node *np, int index) + return ERR_PTR(-ENODEV); + + /* This phy type handled by the usb-phy subsystem for now */ +- if (of_device_is_compatible(args.np, "usb-nop-xceiv")) +- return ERR_PTR(-ENODEV); ++ if (of_device_is_compatible(args.np, "usb-nop-xceiv")) { ++ phy = ERR_PTR(-ENODEV); ++ goto out_put_node; ++ } + + mutex_lock(&phy_provider_mutex); + phy_provider = of_phy_provider_lookup(args.np); +@@ -600,6 +604,7 @@ static struct phy *_of_phy_get(struct device_node *np, int index) + + out_unlock: + mutex_unlock(&phy_provider_mutex); ++out_put_node: + of_node_put(args.np); + + return phy; +@@ -685,7 +690,7 @@ void devm_phy_put(struct device *dev, struct phy *phy) + if (!phy) + return; + +- r = devres_destroy(dev, devm_phy_release, devm_phy_match, phy); ++ r = devres_release(dev, devm_phy_release, devm_phy_match, phy); + dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n"); + } + EXPORT_SYMBOL_GPL(devm_phy_put); +@@ -1069,7 +1074,7 @@ void devm_phy_destroy(struct device *dev, struct phy *phy) + { + int r; + +- r = devres_destroy(dev, devm_phy_consume, devm_phy_match, phy); ++ r = devres_release(dev, devm_phy_consume, devm_phy_match, phy); + dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n"); + } + EXPORT_SYMBOL_GPL(devm_phy_destroy); +@@ -1207,12 +1212,12 @@ EXPORT_SYMBOL_GPL(of_phy_provider_unregister); + * of_phy_provider_unregister to unregister the phy provider. + */ + void devm_of_phy_provider_unregister(struct device *dev, +- struct phy_provider *phy_provider) ++ struct phy_provider *phy_provider) + { + int r; + +- r = devres_destroy(dev, devm_phy_provider_release, devm_phy_match, +- phy_provider); ++ r = devres_release(dev, devm_phy_provider_release, devm_phy_match, ++ phy_provider); + dev_WARN_ONCE(dev, r, "couldn't find PHY provider device resource\n"); + } + EXPORT_SYMBOL_GPL(devm_of_phy_provider_unregister); +diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c +index d5a726c13e39d1..c697d01b2a2a1e 100644 +--- a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c ++++ b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c +@@ -1088,7 +1088,7 @@ static const struct qmp_phy_init_tbl sc8280xp_usb3_uniphy_rx_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), +- QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FO_GAIN, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL1, 0x54), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL2, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), +diff --git a/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c b/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c +index 26b157f53f3da0..9c231094ba3594 100644 +--- a/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c ++++ b/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c +@@ -309,7 +309,7 @@ static int rockchip_combphy_parse_dt(struct device *dev, struct rockchip_combphy + + priv->ext_refclk = device_property_present(dev, "rockchip,ext-refclk"); + +- priv->phy_rst = devm_reset_control_array_get_exclusive(dev); ++ priv->phy_rst = devm_reset_control_get(dev, "phy"); + if (IS_ERR(priv->phy_rst)) + return dev_err_probe(dev, PTR_ERR(priv->phy_rst), "failed to get phy reset\n"); + +diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c +index af3da303e2b15a..cba515ce3444df 100644 +--- a/drivers/platform/x86/asus-nb-wmi.c ++++ b/drivers/platform/x86/asus-nb-wmi.c +@@ -590,6 +590,7 @@ static const struct key_entry asus_nb_wmi_keymap[] = { + { KE_KEY, 0xC4, { KEY_KBDILLUMUP } }, + { KE_KEY, 0xC5, { KEY_KBDILLUMDOWN } }, + { KE_IGNORE, 0xC6, }, /* Ambient Light Sensor notification */ ++ { KE_IGNORE, 0xCF, }, /* AC mode */ + { KE_KEY, 0xFA, { KEY_PROG2 } }, /* Lid flip action */ + { KE_KEY, 0xBD, { KEY_PROG2 } }, /* Lid flip action on ROG xflow laptops */ + { KE_END, 0}, +diff --git a/drivers/power/supply/gpio-charger.c b/drivers/power/supply/gpio-charger.c +index 68212b39785bea..6139f736ecbe4f 100644 +--- a/drivers/power/supply/gpio-charger.c ++++ b/drivers/power/supply/gpio-charger.c +@@ -67,6 +67,14 @@ static int set_charge_current_limit(struct gpio_charger *gpio_charger, int val) + if (gpio_charger->current_limit_map[i].limit_ua <= val) + break; + } ++ ++ /* ++ * If a valid charge current limit isn't found, default to smallest ++ * current limitation for safety reasons. ++ */ ++ if (i >= gpio_charger->current_limit_map_size) ++ i = gpio_charger->current_limit_map_size - 1; ++ + mapping = gpio_charger->current_limit_map[i]; + + for (i = 0; i < ndescs; i++) { +diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c +index 3d4f13da1ae873..4cc93cb79b8b0a 100644 +--- a/drivers/scsi/megaraid/megaraid_sas_base.c ++++ b/drivers/scsi/megaraid/megaraid_sas_base.c +@@ -8904,8 +8904,11 @@ megasas_aen_polling(struct work_struct *work) + (ld_target_id / MEGASAS_MAX_DEV_PER_CHANNEL), + (ld_target_id % MEGASAS_MAX_DEV_PER_CHANNEL), + 0); +- if (sdev1) ++ if (sdev1) { ++ mutex_unlock(&instance->reset_mutex); + megasas_remove_scsi_device(sdev1); ++ mutex_lock(&instance->reset_mutex); ++ } + + event_type = SCAN_VD_CHANNEL; + break; +diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c +index 8acf586dc8b2ed..a5d12b95fbd09f 100644 +--- a/drivers/scsi/mpt3sas/mpt3sas_base.c ++++ b/drivers/scsi/mpt3sas/mpt3sas_base.c +@@ -7050,11 +7050,12 @@ _base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER *ioc, int request_bytes, + int i; + u8 failed; + __le32 *mfp; ++ int ret_val; + + /* make sure doorbell is not in use */ + if ((ioc->base_readl_ext_retry(&ioc->chip->Doorbell) & MPI2_DOORBELL_USED)) { + ioc_err(ioc, "doorbell is in use (line=%d)\n", __LINE__); +- return -EFAULT; ++ goto doorbell_diag_reset; + } + + /* clear pending doorbell interrupts from previous state changes */ +@@ -7144,6 +7145,10 @@ _base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER *ioc, int request_bytes, + le32_to_cpu(mfp[i])); + } + return 0; ++ ++doorbell_diag_reset: ++ ret_val = _base_diag_reset(ioc); ++ return ret_val; + } + + /** +diff --git a/drivers/scsi/qla1280.h b/drivers/scsi/qla1280.h +index d309e2ca14deb3..dea2290b37d4d7 100644 +--- a/drivers/scsi/qla1280.h ++++ b/drivers/scsi/qla1280.h +@@ -116,12 +116,12 @@ struct device_reg { + uint16_t id_h; /* ID high */ + uint16_t cfg_0; /* Configuration 0 */ + #define ISP_CFG0_HWMSK 0x000f /* Hardware revision mask */ +-#define ISP_CFG0_1020 BIT_0 /* ISP1020 */ +-#define ISP_CFG0_1020A BIT_1 /* ISP1020A */ +-#define ISP_CFG0_1040 BIT_2 /* ISP1040 */ +-#define ISP_CFG0_1040A BIT_3 /* ISP1040A */ +-#define ISP_CFG0_1040B BIT_4 /* ISP1040B */ +-#define ISP_CFG0_1040C BIT_5 /* ISP1040C */ ++#define ISP_CFG0_1020 1 /* ISP1020 */ ++#define ISP_CFG0_1020A 2 /* ISP1020A */ ++#define ISP_CFG0_1040 3 /* ISP1040 */ ++#define ISP_CFG0_1040A 4 /* ISP1040A */ ++#define ISP_CFG0_1040B 5 /* ISP1040B */ ++#define ISP_CFG0_1040C 6 /* ISP1040C */ + uint16_t cfg_1; /* Configuration 1 */ + #define ISP_CFG1_F128 BIT_6 /* 128-byte FIFO threshold */ + #define ISP_CFG1_F64 BIT_4|BIT_5 /* 128-byte FIFO threshold */ +diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c +index 7ceb982040a5df..d0b55c1fa908a5 100644 +--- a/drivers/scsi/storvsc_drv.c ++++ b/drivers/scsi/storvsc_drv.c +@@ -149,6 +149,8 @@ struct hv_fc_wwn_packet { + */ + static int vmstor_proto_version; + ++static bool hv_dev_is_fc(struct hv_device *hv_dev); ++ + #define STORVSC_LOGGING_NONE 0 + #define STORVSC_LOGGING_ERROR 1 + #define STORVSC_LOGGING_WARN 2 +@@ -1138,6 +1140,7 @@ static void storvsc_on_io_completion(struct storvsc_device *stor_device, + * not correctly handle: + * INQUIRY command with page code parameter set to 0x80 + * MODE_SENSE command with cmd[2] == 0x1c ++ * MAINTENANCE_IN is not supported by HyperV FC passthrough + * + * Setup srb and scsi status so this won't be fatal. + * We do this so we can distinguish truly fatal failues +@@ -1145,7 +1148,9 @@ static void storvsc_on_io_completion(struct storvsc_device *stor_device, + */ + + if ((stor_pkt->vm_srb.cdb[0] == INQUIRY) || +- (stor_pkt->vm_srb.cdb[0] == MODE_SENSE)) { ++ (stor_pkt->vm_srb.cdb[0] == MODE_SENSE) || ++ (stor_pkt->vm_srb.cdb[0] == MAINTENANCE_IN && ++ hv_dev_is_fc(device))) { + vstor_packet->vm_srb.scsi_status = 0; + vstor_packet->vm_srb.srb_status = SRB_STATUS_SUCCESS; + } +diff --git a/drivers/spi/spi-intel-pci.c b/drivers/spi/spi-intel-pci.c +index 4337ca51d7aa21..5c0dec90eec1df 100644 +--- a/drivers/spi/spi-intel-pci.c ++++ b/drivers/spi/spi-intel-pci.c +@@ -86,6 +86,8 @@ static const struct pci_device_id intel_spi_pci_ids[] = { + { PCI_VDEVICE(INTEL, 0xa324), (unsigned long)&cnl_info }, + { PCI_VDEVICE(INTEL, 0xa3a4), (unsigned long)&cnl_info }, + { PCI_VDEVICE(INTEL, 0xa823), (unsigned long)&cnl_info }, ++ { PCI_VDEVICE(INTEL, 0xe323), (unsigned long)&cnl_info }, ++ { PCI_VDEVICE(INTEL, 0xe423), (unsigned long)&cnl_info }, + { }, + }; + MODULE_DEVICE_TABLE(pci, intel_spi_pci_ids); +diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c +index ddf1c684bcc7d8..3cfd262c1abc25 100644 +--- a/drivers/spi/spi-omap2-mcspi.c ++++ b/drivers/spi/spi-omap2-mcspi.c +@@ -1521,10 +1521,10 @@ static int omap2_mcspi_probe(struct platform_device *pdev) + } + + mcspi->ref_clk = devm_clk_get_optional_enabled(&pdev->dev, NULL); +- if (mcspi->ref_clk) +- mcspi->ref_clk_hz = clk_get_rate(mcspi->ref_clk); +- else ++ if (IS_ERR(mcspi->ref_clk)) + mcspi->ref_clk_hz = OMAP2_MCSPI_MAX_FREQ; ++ else ++ mcspi->ref_clk_hz = clk_get_rate(mcspi->ref_clk); + ctlr->max_speed_hz = mcspi->ref_clk_hz; + ctlr->min_speed_hz = mcspi->ref_clk_hz >> 15; + +diff --git a/drivers/watchdog/it87_wdt.c b/drivers/watchdog/it87_wdt.c +index 843f9f8e391776..239947df613db1 100644 +--- a/drivers/watchdog/it87_wdt.c ++++ b/drivers/watchdog/it87_wdt.c +@@ -20,6 +20,8 @@ + + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + ++#include ++#include + #include + #include + #include +@@ -40,6 +42,7 @@ + #define VAL 0x2f + + /* Logical device Numbers LDN */ ++#define EC 0x04 + #define GPIO 0x07 + + /* Configuration Registers and Functions */ +@@ -71,6 +74,12 @@ + #define IT8784_ID 0x8784 + #define IT8786_ID 0x8786 + ++/* Environment Controller Configuration Registers LDN=0x04 */ ++#define SCR1 0xfa ++ ++/* Environment Controller Bits SCR1 */ ++#define WDT_PWRGD 0x20 ++ + /* GPIO Configuration Registers LDN=0x07 */ + #define WDTCTRL 0x71 + #define WDTCFG 0x72 +@@ -233,6 +242,21 @@ static int wdt_set_timeout(struct watchdog_device *wdd, unsigned int t) + return ret; + } + ++enum { ++ IT87_WDT_OUTPUT_THROUGH_PWRGD = BIT(0), ++}; ++ ++static const struct dmi_system_id it87_quirks[] = { ++ { ++ /* Qotom Q30900P (IT8786) */ ++ .matches = { ++ DMI_EXACT_MATCH(DMI_BOARD_NAME, "QCML04"), ++ }, ++ .driver_data = (void *)IT87_WDT_OUTPUT_THROUGH_PWRGD, ++ }, ++ {} ++}; ++ + static const struct watchdog_info ident = { + .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, + .firmware_version = 1, +@@ -254,8 +278,10 @@ static struct watchdog_device wdt_dev = { + + static int __init it87_wdt_init(void) + { ++ const struct dmi_system_id *dmi_id; + u8 chip_rev; + u8 ctrl; ++ int quirks = 0; + int rc; + + rc = superio_enter(); +@@ -266,6 +292,10 @@ static int __init it87_wdt_init(void) + chip_rev = superio_inb(CHIPREV) & 0x0f; + superio_exit(); + ++ dmi_id = dmi_first_match(it87_quirks); ++ if (dmi_id) ++ quirks = (long)dmi_id->driver_data; ++ + switch (chip_type) { + case IT8702_ID: + max_units = 255; +@@ -326,6 +356,15 @@ static int __init it87_wdt_init(void) + superio_outb(0x00, WDTCTRL); + } + ++ if (quirks & IT87_WDT_OUTPUT_THROUGH_PWRGD) { ++ superio_select(EC); ++ ctrl = superio_inb(SCR1); ++ if (!(ctrl & WDT_PWRGD)) { ++ ctrl |= WDT_PWRGD; ++ superio_outb(ctrl, SCR1); ++ } ++ } ++ + superio_exit(); + + if (timeout < 1 || timeout > max_units * 60) { +diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c +index 0559d9f2d97b36..66bb68ceb14cf6 100644 +--- a/drivers/watchdog/mtk_wdt.c ++++ b/drivers/watchdog/mtk_wdt.c +@@ -10,6 +10,7 @@ + */ + + #include ++#include + #include + #include + #include +@@ -81,6 +82,10 @@ static const struct mtk_wdt_data mt2712_data = { + .toprgu_sw_rst_num = MT2712_TOPRGU_SW_RST_NUM, + }; + ++static const struct mtk_wdt_data mt6735_data = { ++ .toprgu_sw_rst_num = MT6735_TOPRGU_RST_NUM, ++}; ++ + static const struct mtk_wdt_data mt6795_data = { + .toprgu_sw_rst_num = MT6795_TOPRGU_SW_RST_NUM, + }; +@@ -448,6 +453,7 @@ static int mtk_wdt_resume(struct device *dev) + static const struct of_device_id mtk_wdt_dt_ids[] = { + { .compatible = "mediatek,mt2712-wdt", .data = &mt2712_data }, + { .compatible = "mediatek,mt6589-wdt" }, ++ { .compatible = "mediatek,mt6735-wdt", .data = &mt6735_data }, + { .compatible = "mediatek,mt6795-wdt", .data = &mt6795_data }, + { .compatible = "mediatek,mt7986-wdt", .data = &mt7986_data }, + { .compatible = "mediatek,mt8183-wdt", .data = &mt8183_data }, +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index 035815c4394985..d6767f728c079d 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -7153,6 +7153,8 @@ noinline int can_nocow_extent(struct inode *inode, u64 offset, u64 *len, + ret = -EAGAIN; + goto out; + } ++ ++ cond_resched(); + } + + if (orig_start) +diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c +index c9198723e4cb73..512d4cbac1ca0b 100644 +--- a/fs/btrfs/sysfs.c ++++ b/fs/btrfs/sysfs.c +@@ -1022,7 +1022,7 @@ static ssize_t btrfs_nodesize_show(struct kobject *kobj, + { + struct btrfs_fs_info *fs_info = to_fs_info(kobj); + +- return sysfs_emit(buf, "%u\n", fs_info->super_copy->nodesize); ++ return sysfs_emit(buf, "%u\n", fs_info->nodesize); + } + + BTRFS_ATTR(, nodesize, btrfs_nodesize_show); +@@ -1032,7 +1032,7 @@ static ssize_t btrfs_sectorsize_show(struct kobject *kobj, + { + struct btrfs_fs_info *fs_info = to_fs_info(kobj); + +- return sysfs_emit(buf, "%u\n", fs_info->super_copy->sectorsize); ++ return sysfs_emit(buf, "%u\n", fs_info->sectorsize); + } + + BTRFS_ATTR(, sectorsize, btrfs_sectorsize_show); +@@ -1084,7 +1084,7 @@ static ssize_t btrfs_clone_alignment_show(struct kobject *kobj, + { + struct btrfs_fs_info *fs_info = to_fs_info(kobj); + +- return sysfs_emit(buf, "%u\n", fs_info->super_copy->sectorsize); ++ return sysfs_emit(buf, "%u\n", fs_info->sectorsize); + } + + BTRFS_ATTR(, clone_alignment, btrfs_clone_alignment_show); +diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c +index 1a2776025e9861..2c92de964c5a2e 100644 +--- a/fs/ceph/addr.c ++++ b/fs/ceph/addr.c +@@ -355,6 +355,7 @@ static void ceph_netfs_issue_read(struct netfs_io_subrequest *subreq) + u64 len = subreq->len; + bool sparse = IS_ENCRYPTED(inode) || ceph_test_mount_opt(fsc, SPARSEREAD); + u64 off = subreq->start; ++ int extent_cnt; + + if (ceph_inode_is_shutdown(inode)) { + err = -EIO; +@@ -377,7 +378,8 @@ static void ceph_netfs_issue_read(struct netfs_io_subrequest *subreq) + } + + if (sparse) { +- err = ceph_alloc_sparse_ext_map(&req->r_ops[0]); ++ extent_cnt = __ceph_sparse_read_ext_count(inode, len); ++ err = ceph_alloc_sparse_ext_map(&req->r_ops[0], extent_cnt); + if (err) + goto out; + } +diff --git a/fs/ceph/file.c b/fs/ceph/file.c +index 813974244a9d37..a03b11cf788721 100644 +--- a/fs/ceph/file.c ++++ b/fs/ceph/file.c +@@ -1001,6 +1001,7 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos, + struct ceph_osd_req_op *op; + u64 read_off = off; + u64 read_len = len; ++ int extent_cnt; + + /* determine new offset/length if encrypted */ + ceph_fscrypt_adjust_off_and_len(inode, &read_off, &read_len); +@@ -1025,6 +1026,16 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos, + len = read_off + read_len - off; + more = len < iov_iter_count(to); + ++ op = &req->r_ops[0]; ++ if (sparse) { ++ extent_cnt = __ceph_sparse_read_ext_count(inode, read_len); ++ ret = ceph_alloc_sparse_ext_map(op, extent_cnt); ++ if (ret) { ++ ceph_osdc_put_request(req); ++ break; ++ } ++ } ++ + num_pages = calc_pages_for(read_off, read_len); + page_off = offset_in_page(off); + pages = ceph_alloc_page_vector(num_pages, GFP_KERNEL); +@@ -1038,15 +1049,6 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos, + offset_in_page(read_off), + false, true); + +- op = &req->r_ops[0]; +- if (sparse) { +- ret = ceph_alloc_sparse_ext_map(op); +- if (ret) { +- ceph_osdc_put_request(req); +- break; +- } +- } +- + ceph_osdc_start_request(osdc, req); + ret = ceph_osdc_wait_request(osdc, req); + +@@ -1431,6 +1433,7 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter, + ssize_t len; + struct ceph_osd_req_op *op; + int readop = sparse ? CEPH_OSD_OP_SPARSE_READ : CEPH_OSD_OP_READ; ++ int extent_cnt; + + if (write) + size = min_t(u64, size, fsc->mount_options->wsize); +@@ -1451,6 +1454,16 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter, + break; + } + ++ op = &req->r_ops[0]; ++ if (!write && sparse) { ++ extent_cnt = __ceph_sparse_read_ext_count(inode, size); ++ ret = ceph_alloc_sparse_ext_map(op, extent_cnt); ++ if (ret) { ++ ceph_osdc_put_request(req); ++ break; ++ } ++ } ++ + len = iter_get_bvecs_alloc(iter, size, &bvecs, &num_pages); + if (len < 0) { + ceph_osdc_put_request(req); +@@ -1460,6 +1473,8 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter, + if (len != size) + osd_req_op_extent_update(req, 0, len); + ++ osd_req_op_extent_osd_data_bvecs(req, 0, bvecs, num_pages, len); ++ + /* + * To simplify error handling, allow AIO when IO within i_size + * or IO can be satisfied by single OSD request. +@@ -1491,16 +1506,6 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter, + req->r_mtime = mtime; + } + +- osd_req_op_extent_osd_data_bvecs(req, 0, bvecs, num_pages, len); +- op = &req->r_ops[0]; +- if (sparse) { +- ret = ceph_alloc_sparse_ext_map(op); +- if (ret) { +- ceph_osdc_put_request(req); +- break; +- } +- } +- + if (aio_req) { + aio_req->total_len += len; + aio_req->num_reqs++; +diff --git a/fs/ceph/super.h b/fs/ceph/super.h +index 8efd4ba6077448..5903e3fb6d7506 100644 +--- a/fs/ceph/super.h ++++ b/fs/ceph/super.h +@@ -3,6 +3,7 @@ + #define _FS_CEPH_SUPER_H + + #include ++#include + + #include + #include +@@ -1401,6 +1402,19 @@ static inline void __ceph_update_quota(struct ceph_inode_info *ci, + ceph_adjust_quota_realms_count(&ci->netfs.inode, has_quota); + } + ++static inline int __ceph_sparse_read_ext_count(struct inode *inode, u64 len) ++{ ++ int cnt = 0; ++ ++ if (IS_ENCRYPTED(inode)) { ++ cnt = len >> CEPH_FSCRYPT_BLOCK_SHIFT; ++ if (cnt > CEPH_SPARSE_EXT_ARRAY_INITIAL) ++ cnt = 0; ++ } ++ ++ return cnt; ++} ++ + extern void ceph_handle_quota(struct ceph_mds_client *mdsc, + struct ceph_mds_session *session, + struct ceph_msg *msg); +diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c +index d4d3ec58047e82..4b5d998cbc2f44 100644 +--- a/fs/nfsd/export.c ++++ b/fs/nfsd/export.c +@@ -40,24 +40,15 @@ + #define EXPKEY_HASHMAX (1 << EXPKEY_HASHBITS) + #define EXPKEY_HASHMASK (EXPKEY_HASHMAX -1) + +-static void expkey_put_work(struct work_struct *work) ++static void expkey_put(struct kref *ref) + { +- struct svc_expkey *key = +- container_of(to_rcu_work(work), struct svc_expkey, ek_rcu_work); ++ struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref); + + if (test_bit(CACHE_VALID, &key->h.flags) && + !test_bit(CACHE_NEGATIVE, &key->h.flags)) + path_put(&key->ek_path); + auth_domain_put(key->ek_client); +- kfree(key); +-} +- +-static void expkey_put(struct kref *ref) +-{ +- struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref); +- +- INIT_RCU_WORK(&key->ek_rcu_work, expkey_put_work); +- queue_rcu_work(system_wq, &key->ek_rcu_work); ++ kfree_rcu(key, ek_rcu); + } + + static int expkey_upcall(struct cache_detail *cd, struct cache_head *h) +@@ -360,26 +351,16 @@ static void export_stats_destroy(struct export_stats *stats) + EXP_STATS_COUNTERS_NUM); + } + +-static void svc_export_put_work(struct work_struct *work) ++static void svc_export_put(struct kref *ref) + { +- struct svc_export *exp = +- container_of(to_rcu_work(work), struct svc_export, ex_rcu_work); +- ++ struct svc_export *exp = container_of(ref, struct svc_export, h.ref); + path_put(&exp->ex_path); + auth_domain_put(exp->ex_client); + nfsd4_fslocs_free(&exp->ex_fslocs); + export_stats_destroy(exp->ex_stats); + kfree(exp->ex_stats); + kfree(exp->ex_uuid); +- kfree(exp); +-} +- +-static void svc_export_put(struct kref *ref) +-{ +- struct svc_export *exp = container_of(ref, struct svc_export, h.ref); +- +- INIT_RCU_WORK(&exp->ex_rcu_work, svc_export_put_work); +- queue_rcu_work(system_wq, &exp->ex_rcu_work); ++ kfree_rcu(exp, ex_rcu); + } + + static int svc_export_upcall(struct cache_detail *cd, struct cache_head *h) +diff --git a/fs/nfsd/export.h b/fs/nfsd/export.h +index 9d895570ceba05..ca9dc230ae3d0b 100644 +--- a/fs/nfsd/export.h ++++ b/fs/nfsd/export.h +@@ -75,7 +75,7 @@ struct svc_export { + u32 ex_layout_types; + struct nfsd4_deviceid_map *ex_devid_map; + struct cache_detail *cd; +- struct rcu_work ex_rcu_work; ++ struct rcu_head ex_rcu; + unsigned long ex_xprtsec_modes; + struct export_stats *ex_stats; + }; +@@ -92,7 +92,7 @@ struct svc_expkey { + u32 ek_fsid[6]; + + struct path ek_path; +- struct rcu_work ek_rcu_work; ++ struct rcu_head ek_rcu; + }; + + #define EX_ISSYNC(exp) (!((exp)->ex_flags & NFSEXP_ASYNC)) +diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c +index 49a49529c6b8fb..54ffadf02e034f 100644 +--- a/fs/nfsd/nfs4callback.c ++++ b/fs/nfsd/nfs4callback.c +@@ -986,7 +986,7 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c + args.authflavor = clp->cl_cred.cr_flavor; + clp->cl_cb_ident = conn->cb_ident; + } else { +- if (!conn->cb_xprt) ++ if (!conn->cb_xprt || !ses) + return -EINVAL; + clp->cl_cb_session = ses; + args.bc_xprt = conn->cb_xprt; +@@ -1379,8 +1379,6 @@ static void nfsd4_process_cb_update(struct nfsd4_callback *cb) + ses = c->cn_session; + } + spin_unlock(&clp->cl_lock); +- if (!c) +- return; + + err = setup_callback_client(clp, &conn, ses); + if (err) { +diff --git a/fs/smb/server/smb_common.c b/fs/smb/server/smb_common.c +index 663b014b9d1886..23537e1b346858 100644 +--- a/fs/smb/server/smb_common.c ++++ b/fs/smb/server/smb_common.c +@@ -18,8 +18,8 @@ + #include "mgmt/share_config.h" + + /*for shortname implementation */ +-static const char basechars[43] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_-!@#$%"; +-#define MANGLE_BASE (sizeof(basechars) / sizeof(char) - 1) ++static const char *basechars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_-!@#$%"; ++#define MANGLE_BASE (strlen(basechars) - 1) + #define MAGIC_CHAR '~' + #define PERIOD '.' + #define mangle(V) ((char)(basechars[(V) % MANGLE_BASE])) +diff --git a/fs/udf/namei.c b/fs/udf/namei.c +index 605f182da42cbb..b3f57ad2b869ff 100644 +--- a/fs/udf/namei.c ++++ b/fs/udf/namei.c +@@ -521,7 +521,11 @@ static int udf_rmdir(struct inode *dir, struct dentry *dentry) + inode->i_nlink); + clear_nlink(inode); + inode->i_size = 0; +- inode_dec_link_count(dir); ++ if (dir->i_nlink >= 3) ++ inode_dec_link_count(dir); ++ else ++ udf_warn(inode->i_sb, "parent dir link count too low (%u)\n", ++ dir->i_nlink); + udf_add_fid_counter(dir->i_sb, true, -1); + dir->i_mtime = inode_set_ctime_to_ts(dir, + inode_set_ctime_current(inode)); +diff --git a/include/linux/ceph/osd_client.h b/include/linux/ceph/osd_client.h +index f703fb8030de26..50e409e8446659 100644 +--- a/include/linux/ceph/osd_client.h ++++ b/include/linux/ceph/osd_client.h +@@ -573,9 +573,12 @@ int __ceph_alloc_sparse_ext_map(struct ceph_osd_req_op *op, int cnt); + */ + #define CEPH_SPARSE_EXT_ARRAY_INITIAL 16 + +-static inline int ceph_alloc_sparse_ext_map(struct ceph_osd_req_op *op) ++static inline int ceph_alloc_sparse_ext_map(struct ceph_osd_req_op *op, int cnt) + { +- return __ceph_alloc_sparse_ext_map(op, CEPH_SPARSE_EXT_ARRAY_INITIAL); ++ if (!cnt) ++ cnt = CEPH_SPARSE_EXT_ARRAY_INITIAL; ++ ++ return __ceph_alloc_sparse_ext_map(op, cnt); + } + + extern void ceph_osdc_get_request(struct ceph_osd_request *req); +diff --git a/include/linux/sched.h b/include/linux/sched.h +index 4809f27b520172..d4f9d82c69e0b0 100644 +--- a/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -1683,8 +1683,9 @@ static inline unsigned int __task_state_index(unsigned int tsk_state, + * We're lying here, but rather than expose a completely new task state + * to userspace, we can make this appear as if the task has gone through + * a regular rt_mutex_lock() call. ++ * Report frozen tasks as uninterruptible. + */ +- if (tsk_state & TASK_RTLOCK_WAIT) ++ if ((tsk_state & TASK_RTLOCK_WAIT) || (tsk_state & TASK_FROZEN)) + state = TASK_UNINTERRUPTIBLE; + + return fls(state); +diff --git a/include/linux/sched/task_stack.h b/include/linux/sched/task_stack.h +index f158b025c17509..d2117e1c8fa581 100644 +--- a/include/linux/sched/task_stack.h ++++ b/include/linux/sched/task_stack.h +@@ -8,6 +8,7 @@ + + #include + #include ++#include + + #ifdef CONFIG_THREAD_INFO_IN_TASK + +@@ -88,6 +89,7 @@ static inline int object_is_on_stack(const void *obj) + { + void *stack = task_stack_page(current); + ++ obj = kasan_reset_tag(obj); + return (obj >= stack) && (obj < (stack + THREAD_SIZE)); + } + +diff --git a/include/linux/skmsg.h b/include/linux/skmsg.h +index 062fe440f5d095..6ccfd9236387c6 100644 +--- a/include/linux/skmsg.h ++++ b/include/linux/skmsg.h +@@ -308,17 +308,22 @@ static inline void sock_drop(struct sock *sk, struct sk_buff *skb) + kfree_skb(skb); + } + +-static inline void sk_psock_queue_msg(struct sk_psock *psock, ++static inline bool sk_psock_queue_msg(struct sk_psock *psock, + struct sk_msg *msg) + { ++ bool ret; ++ + spin_lock_bh(&psock->ingress_lock); +- if (sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED)) ++ if (sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED)) { + list_add_tail(&msg->list, &psock->ingress_msg); +- else { ++ ret = true; ++ } else { + sk_msg_free(psock->sk, msg); + kfree(msg); ++ ret = false; + } + spin_unlock_bh(&psock->ingress_lock); ++ return ret; + } + + static inline struct sk_msg *sk_psock_dequeue_msg(struct sk_psock *psock) +diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h +index 9d799777c333c0..9df2524fff33ae 100644 +--- a/include/linux/trace_events.h ++++ b/include/linux/trace_events.h +@@ -369,7 +369,7 @@ struct trace_event_call { + struct list_head list; + struct trace_event_class *class; + union { +- char *name; ++ const char *name; + /* Set TRACE_EVENT_FL_TRACEPOINT flag when using "tp" */ + struct tracepoint *tp; + }; +diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h +index fed855bae6d8e8..3219b368db79cc 100644 +--- a/include/linux/vmstat.h ++++ b/include/linux/vmstat.h +@@ -519,7 +519,7 @@ static inline const char *node_stat_name(enum node_stat_item item) + + static inline const char *lru_list_name(enum lru_list lru) + { +- return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_" ++ return node_stat_name(NR_LRU_BASE + (enum node_stat_item)lru) + 3; // skip "nr_" + } + + static inline const char *writeback_stat_name(enum writeback_stat_item item) +diff --git a/include/net/sock.h b/include/net/sock.h +index a6b795ec7c9cb6..dc625f94ee37b7 100644 +--- a/include/net/sock.h ++++ b/include/net/sock.h +@@ -1635,7 +1635,7 @@ static inline bool sk_wmem_schedule(struct sock *sk, int size) + } + + static inline bool +-sk_rmem_schedule(struct sock *sk, struct sk_buff *skb, int size) ++__sk_rmem_schedule(struct sock *sk, int size, bool pfmemalloc) + { + int delta; + +@@ -1643,7 +1643,13 @@ sk_rmem_schedule(struct sock *sk, struct sk_buff *skb, int size) + return true; + delta = size - sk->sk_forward_alloc; + return delta <= 0 || __sk_mem_schedule(sk, delta, SK_MEM_RECV) || +- skb_pfmemalloc(skb); ++ pfmemalloc; ++} ++ ++static inline bool ++sk_rmem_schedule(struct sock *sk, struct sk_buff *skb, int size) ++{ ++ return __sk_rmem_schedule(sk, size, skb_pfmemalloc(skb)); + } + + static inline int sk_unused_reserved_mem(const struct sock *sk) +diff --git a/include/uapi/linux/stddef.h b/include/uapi/linux/stddef.h +index 2ec6f35cda32e9..473ad86706d837 100644 +--- a/include/uapi/linux/stddef.h ++++ b/include/uapi/linux/stddef.h +@@ -8,6 +8,13 @@ + #define __always_inline inline + #endif + ++/* Not all C++ standards support type declarations inside an anonymous union */ ++#ifndef __cplusplus ++#define __struct_group_tag(TAG) TAG ++#else ++#define __struct_group_tag(TAG) ++#endif ++ + /** + * __struct_group() - Create a mirrored named and anonyomous struct + * +@@ -20,13 +27,13 @@ + * and size: one anonymous and one named. The former's members can be used + * normally without sub-struct naming, and the latter can be used to + * reason about the start, end, and size of the group of struct members. +- * The named struct can also be explicitly tagged for layer reuse, as well +- * as both having struct attributes appended. ++ * The named struct can also be explicitly tagged for layer reuse (C only), ++ * as well as both having struct attributes appended. + */ + #define __struct_group(TAG, NAME, ATTRS, MEMBERS...) \ + union { \ + struct { MEMBERS } ATTRS; \ +- struct TAG { MEMBERS } ATTRS NAME; \ ++ struct __struct_group_tag(TAG) { MEMBERS } ATTRS NAME; \ + } ATTRS + + #ifdef __cplusplus +diff --git a/io_uring/sqpoll.c b/io_uring/sqpoll.c +index cdf8b567cb9443..489e66647e0795 100644 +--- a/io_uring/sqpoll.c ++++ b/io_uring/sqpoll.c +@@ -352,6 +352,7 @@ void io_sqpoll_wait_sq(struct io_ring_ctx *ctx) + __cold int io_sq_offload_create(struct io_ring_ctx *ctx, + struct io_uring_params *p) + { ++ struct task_struct *task_to_put = NULL; + int ret; + + /* Retain compatibility with failing for an invalid attach attempt */ +@@ -432,6 +433,7 @@ __cold int io_sq_offload_create(struct io_ring_ctx *ctx, + } + + sqd->thread = tsk; ++ task_to_put = get_task_struct(tsk); + ret = io_uring_alloc_task_context(tsk, ctx); + wake_up_new_task(tsk); + if (ret) +@@ -442,11 +444,15 @@ __cold int io_sq_offload_create(struct io_ring_ctx *ctx, + goto err; + } + ++ if (task_to_put) ++ put_task_struct(task_to_put); + return 0; + err_sqpoll: + complete(&ctx->sq_data->exited); + err: + io_sq_thread_finish(ctx); ++ if (task_to_put) ++ put_task_struct(task_to_put); + return ret; + } + +diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c +index ecd869ed27670c..220903117c5139 100644 +--- a/kernel/trace/trace.c ++++ b/kernel/trace/trace.c +@@ -5331,6 +5331,9 @@ tracing_cpumask_write(struct file *filp, const char __user *ubuf, + cpumask_var_t tracing_cpumask_new; + int err; + ++ if (count == 0 || count > KMALLOC_MAX_SIZE) ++ return -EINVAL; ++ + if (!zalloc_cpumask_var(&tracing_cpumask_new, GFP_KERNEL)) + return -ENOMEM; + +diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c +index 94cb09d44115ae..508c10414a9343 100644 +--- a/kernel/trace/trace_kprobe.c ++++ b/kernel/trace/trace_kprobe.c +@@ -702,7 +702,7 @@ static int trace_kprobe_module_callback(struct notifier_block *nb, + + static struct notifier_block trace_kprobe_module_nb = { + .notifier_call = trace_kprobe_module_callback, +- .priority = 1 /* Invoked after kprobe module callback */ ++ .priority = 2 /* Invoked after kprobe and jump_label module callback */ + }; + + static int count_symbols(void *data, unsigned long unused) +diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c +index 3babcd5e65e16d..0b6a8bb0642f25 100644 +--- a/net/ceph/osd_client.c ++++ b/net/ceph/osd_client.c +@@ -1173,6 +1173,8 @@ EXPORT_SYMBOL(ceph_osdc_new_request); + + int __ceph_alloc_sparse_ext_map(struct ceph_osd_req_op *op, int cnt) + { ++ WARN_ON(op->op != CEPH_OSD_OP_SPARSE_READ); ++ + op->extent.sparse_ext_cnt = cnt; + op->extent.sparse_ext = kmalloc_array(cnt, + sizeof(*op->extent.sparse_ext), +diff --git a/net/core/filter.c b/net/core/filter.c +index bc52ab3374f3ac..34320ce70096ac 100644 +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -3731,13 +3731,22 @@ static const struct bpf_func_proto bpf_skb_adjust_room_proto = { + + static u32 __bpf_skb_min_len(const struct sk_buff *skb) + { +- u32 min_len = skb_network_offset(skb); ++ int offset = skb_network_offset(skb); ++ u32 min_len = 0; + +- if (skb_transport_header_was_set(skb)) +- min_len = skb_transport_offset(skb); +- if (skb->ip_summed == CHECKSUM_PARTIAL) +- min_len = skb_checksum_start_offset(skb) + +- skb->csum_offset + sizeof(__sum16); ++ if (offset > 0) ++ min_len = offset; ++ if (skb_transport_header_was_set(skb)) { ++ offset = skb_transport_offset(skb); ++ if (offset > 0) ++ min_len = offset; ++ } ++ if (skb->ip_summed == CHECKSUM_PARTIAL) { ++ offset = skb_checksum_start_offset(skb) + ++ skb->csum_offset + sizeof(__sum16); ++ if (offset > 0) ++ min_len = offset; ++ } + return min_len; + } + +diff --git a/net/core/skmsg.c b/net/core/skmsg.c +index 846fd672f0e529..902098e221b396 100644 +--- a/net/core/skmsg.c ++++ b/net/core/skmsg.c +@@ -445,8 +445,10 @@ int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg, + if (likely(!peek)) { + sge->offset += copy; + sge->length -= copy; +- if (!msg_rx->skb) ++ if (!msg_rx->skb) { + sk_mem_uncharge(sk, copy); ++ atomic_sub(copy, &sk->sk_rmem_alloc); ++ } + msg_rx->sg.size -= copy; + + if (!sge->length) { +@@ -772,6 +774,8 @@ static void __sk_psock_purge_ingress_msg(struct sk_psock *psock) + + list_for_each_entry_safe(msg, tmp, &psock->ingress_msg, list) { + list_del(&msg->list); ++ if (!msg->skb) ++ atomic_sub(msg->sg.size, &psock->sk->sk_rmem_alloc); + sk_msg_free(psock->sk, msg); + kfree(msg); + } +diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c +index 0a42d73c0850e0..f882054fae5ee1 100644 +--- a/net/ipv4/tcp_bpf.c ++++ b/net/ipv4/tcp_bpf.c +@@ -49,13 +49,14 @@ static int bpf_tcp_ingress(struct sock *sk, struct sk_psock *psock, + sge = sk_msg_elem(msg, i); + size = (apply && apply_bytes < sge->length) ? + apply_bytes : sge->length; +- if (!sk_wmem_schedule(sk, size)) { ++ if (!__sk_rmem_schedule(sk, size, false)) { + if (!copied) + ret = -ENOMEM; + break; + } + + sk_mem_charge(sk, size); ++ atomic_add(size, &sk->sk_rmem_alloc); + sk_msg_xfer(tmp, msg, i, size); + copied += size; + if (sge->length) +@@ -74,7 +75,8 @@ static int bpf_tcp_ingress(struct sock *sk, struct sk_psock *psock, + + if (!ret) { + msg->sg.start = i; +- sk_psock_queue_msg(psock, tmp); ++ if (!sk_psock_queue_msg(psock, tmp)) ++ atomic_sub(copied, &sk->sk_rmem_alloc); + sk_psock_data_ready(sk, psock); + } else { + sk_msg_free(sk, tmp); +diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c +index b3208b068dd809..989ce0fb62919f 100644 +--- a/sound/pci/hda/patch_conexant.c ++++ b/sound/pci/hda/patch_conexant.c +@@ -311,6 +311,7 @@ enum { + CXT_FIXUP_HP_MIC_NO_PRESENCE, + CXT_PINCFG_SWS_JS201D, + CXT_PINCFG_TOP_SPEAKER, ++ CXT_FIXUP_HP_A_U, + }; + + /* for hda_fixup_thinkpad_acpi() */ +@@ -778,6 +779,18 @@ static void cxt_setup_mute_led(struct hda_codec *codec, + } + } + ++static void cxt_setup_gpio_unmute(struct hda_codec *codec, ++ unsigned int gpio_mute_mask) ++{ ++ if (gpio_mute_mask) { ++ // set gpio data to 0. ++ snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 0); ++ snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_MASK, gpio_mute_mask); ++ snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DIRECTION, gpio_mute_mask); ++ snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_STICKY_MASK, 0); ++ } ++} ++ + static void cxt_fixup_mute_led_gpio(struct hda_codec *codec, + const struct hda_fixup *fix, int action) + { +@@ -792,6 +805,15 @@ static void cxt_fixup_hp_zbook_mute_led(struct hda_codec *codec, + cxt_setup_mute_led(codec, 0x10, 0x20); + } + ++static void cxt_fixup_hp_a_u(struct hda_codec *codec, ++ const struct hda_fixup *fix, int action) ++{ ++ // Init vers in BIOS mute the spk/hp by set gpio high to avoid pop noise, ++ // so need to unmute once by clearing the gpio data when runs into the system. ++ if (action == HDA_FIXUP_ACT_INIT) ++ cxt_setup_gpio_unmute(codec, 0x2); ++} ++ + /* ThinkPad X200 & co with cxt5051 */ + static const struct hda_pintbl cxt_pincfg_lenovo_x200[] = { + { 0x16, 0x042140ff }, /* HP (seq# overridden) */ +@@ -1002,6 +1024,10 @@ static const struct hda_fixup cxt_fixups[] = { + { } + }, + }, ++ [CXT_FIXUP_HP_A_U] = { ++ .type = HDA_FIXUP_FUNC, ++ .v.func = cxt_fixup_hp_a_u, ++ }, + }; + + static const struct hda_quirk cxt5045_fixups[] = { +@@ -1076,6 +1102,7 @@ static const struct hda_quirk cxt5066_fixups[] = { + SND_PCI_QUIRK(0x103c, 0x8457, "HP Z2 G4 mini", CXT_FIXUP_HP_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x103c, 0x8458, "HP Z2 G4 mini premium", CXT_FIXUP_HP_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1043, 0x138d, "Asus", CXT_FIXUP_HEADPHONE_MIC_PIN), ++ SND_PCI_QUIRK(0x14f1, 0x0252, "MBX-Z60MR100", CXT_FIXUP_HP_A_U), + SND_PCI_QUIRK(0x14f1, 0x0265, "SWS JS201D", CXT_PINCFG_SWS_JS201D), + SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT_FIXUP_OLPC_XO), + SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400", CXT_PINCFG_LENOVO_TP410), +@@ -1121,6 +1148,7 @@ static const struct hda_model_fixup cxt5066_fixup_models[] = { + { .id = CXT_PINCFG_LENOVO_NOTEBOOK, .name = "lenovo-20149" }, + { .id = CXT_PINCFG_SWS_JS201D, .name = "sws-js201d" }, + { .id = CXT_PINCFG_TOP_SPEAKER, .name = "sirius-top-speaker" }, ++ { .id = CXT_FIXUP_HP_A_U, .name = "HP-U-support" }, + {} + }; + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index d61c317b49ead1..29d7eb8c6bec3e 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -10054,6 +10054,13 @@ static const struct hda_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x103c, 0x8ca4, "HP ZBook Fury", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x8ca7, "HP ZBook Fury", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x8cf5, "HP ZBook Studio 16", ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED), ++ SND_PCI_QUIRK(0x103c, 0x8d01, "HP ZBook Power 14 G12", ALC285_FIXUP_HP_GPIO_LED), ++ SND_PCI_QUIRK(0x103c, 0x8d84, "HP EliteBook X G1i", ALC285_FIXUP_HP_GPIO_LED), ++ SND_PCI_QUIRK(0x103c, 0x8d91, "HP ZBook Firefly 14 G12", ALC285_FIXUP_HP_GPIO_LED), ++ SND_PCI_QUIRK(0x103c, 0x8d92, "HP ZBook Firefly 16 G12", ALC285_FIXUP_HP_GPIO_LED), ++ SND_PCI_QUIRK(0x103c, 0x8e18, "HP ZBook Firefly 14 G12A", ALC285_FIXUP_HP_GPIO_LED), ++ SND_PCI_QUIRK(0x103c, 0x8e19, "HP ZBook Firefly 14 G12A", ALC285_FIXUP_HP_GPIO_LED), ++ SND_PCI_QUIRK(0x103c, 0x8e1a, "HP ZBook Firefly 14 G12A", ALC285_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC), + SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300), + SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), +diff --git a/sound/sh/sh_dac_audio.c b/sound/sh/sh_dac_audio.c +index 95ba3abd4e47eb..13fe6a76005ec4 100644 +--- a/sound/sh/sh_dac_audio.c ++++ b/sound/sh/sh_dac_audio.c +@@ -163,7 +163,7 @@ static int snd_sh_dac_pcm_copy(struct snd_pcm_substream *substream, + /* channel is not used (interleaved data) */ + struct snd_sh_dac *chip = snd_pcm_substream_chip(substream); + +- if (copy_from_iter_toio(chip->data_buffer + pos, src, count)) ++ if (copy_from_iter(chip->data_buffer + pos, count, src) != count) + return -EFAULT; + chip->buffer_end = chip->data_buffer + pos + count; + +@@ -182,7 +182,7 @@ static int snd_sh_dac_pcm_silence(struct snd_pcm_substream *substream, + /* channel is not used (interleaved data) */ + struct snd_sh_dac *chip = snd_pcm_substream_chip(substream); + +- memset_io(chip->data_buffer + pos, 0, count); ++ memset(chip->data_buffer + pos, 0, count); + chip->buffer_end = chip->data_buffer + pos + count; + + if (chip->empty) { +@@ -211,7 +211,6 @@ static const struct snd_pcm_ops snd_sh_dac_pcm_ops = { + .pointer = snd_sh_dac_pcm_pointer, + .copy = snd_sh_dac_pcm_copy, + .fill_silence = snd_sh_dac_pcm_silence, +- .mmap = snd_pcm_lib_mmap_iomem, + }; + + static int snd_sh_dac_pcm(struct snd_sh_dac *chip, int device) +diff --git a/tools/include/uapi/linux/stddef.h b/tools/include/uapi/linux/stddef.h +index bb6ea517efb511..c53cde425406b7 100644 +--- a/tools/include/uapi/linux/stddef.h ++++ b/tools/include/uapi/linux/stddef.h +@@ -8,6 +8,13 @@ + #define __always_inline __inline__ + #endif + ++/* Not all C++ standards support type declarations inside an anonymous union */ ++#ifndef __cplusplus ++#define __struct_group_tag(TAG) TAG ++#else ++#define __struct_group_tag(TAG) ++#endif ++ + /** + * __struct_group() - Create a mirrored named and anonyomous struct + * +@@ -20,14 +27,14 @@ + * and size: one anonymous and one named. The former's members can be used + * normally without sub-struct naming, and the latter can be used to + * reason about the start, end, and size of the group of struct members. +- * The named struct can also be explicitly tagged for layer reuse, as well +- * as both having struct attributes appended. ++ * The named struct can also be explicitly tagged for layer reuse (C only), ++ * as well as both having struct attributes appended. + */ + #define __struct_group(TAG, NAME, ATTRS, MEMBERS...) \ + union { \ + struct { MEMBERS } ATTRS; \ +- struct TAG { MEMBERS } ATTRS NAME; \ +- } ++ struct __struct_group_tag(TAG) { MEMBERS } ATTRS NAME; \ ++ } ATTRS + + /** + * __DECLARE_FLEX_ARRAY() - Declare a flexible array usable in a union diff --git a/patch/kernel/archive/odroidxu4-6.6/patch-6.6.69-70.patch b/patch/kernel/archive/odroidxu4-6.6/patch-6.6.69-70.patch new file mode 100644 index 0000000000..0ccd04cd7a --- /dev/null +++ b/patch/kernel/archive/odroidxu4-6.6/patch-6.6.69-70.patch @@ -0,0 +1,12214 @@ +diff --git a/Documentation/admin-guide/media/building.rst b/Documentation/admin-guide/media/building.rst +index a0647342991637..7a413ba07f93bb 100644 +--- a/Documentation/admin-guide/media/building.rst ++++ b/Documentation/admin-guide/media/building.rst +@@ -15,7 +15,7 @@ Please notice, however, that, if: + + you should use the main media development tree ``master`` branch: + +- https://git.linuxtv.org/media_tree.git/ ++ https://git.linuxtv.org/media.git/ + + In this case, you may find some useful information at the + `LinuxTv wiki pages `_: +diff --git a/Documentation/admin-guide/media/saa7134.rst b/Documentation/admin-guide/media/saa7134.rst +index 51eae7eb5ab7f4..18d7cbc897db4b 100644 +--- a/Documentation/admin-guide/media/saa7134.rst ++++ b/Documentation/admin-guide/media/saa7134.rst +@@ -67,7 +67,7 @@ Changes / Fixes + Please mail to linux-media AT vger.kernel.org unified diffs against + the linux media git tree: + +- https://git.linuxtv.org/media_tree.git/ ++ https://git.linuxtv.org/media.git/ + + This is done by committing a patch at a clone of the git tree and + submitting the patch using ``git send-email``. Don't forget to +diff --git a/Documentation/arch/arm64/silicon-errata.rst b/Documentation/arch/arm64/silicon-errata.rst +index 3cf806733083c7..8209c7a7c3970e 100644 +--- a/Documentation/arch/arm64/silicon-errata.rst ++++ b/Documentation/arch/arm64/silicon-errata.rst +@@ -244,8 +244,9 @@ stable kernels. + +----------------+-----------------+-----------------+-----------------------------+ + | Hisilicon | Hip08 SMMU PMCG | #162001800 | N/A | + +----------------+-----------------+-----------------+-----------------------------+ +-| Hisilicon | Hip08 SMMU PMCG | #162001900 | N/A | +-| | Hip09 SMMU PMCG | | | ++| Hisilicon | Hip{08,09,09A,10| #162001900 | N/A | ++| | ,10C,11} | | | ++| | SMMU PMCG | | | + +----------------+-----------------+-----------------+-----------------------------+ + +----------------+-----------------+-----------------+-----------------------------+ + | Qualcomm Tech. | Kryo/Falkor v1 | E1003 | QCOM_FALKOR_ERRATUM_1003 | +diff --git a/Documentation/devicetree/bindings/display/bridge/adi,adv7533.yaml b/Documentation/devicetree/bindings/display/bridge/adi,adv7533.yaml +index 987aa83c264943..e956f524e379dc 100644 +--- a/Documentation/devicetree/bindings/display/bridge/adi,adv7533.yaml ++++ b/Documentation/devicetree/bindings/display/bridge/adi,adv7533.yaml +@@ -87,7 +87,7 @@ properties: + adi,dsi-lanes: + description: Number of DSI data lanes connected to the DSI host. + $ref: /schemas/types.yaml#/definitions/uint32 +- enum: [ 1, 2, 3, 4 ] ++ enum: [ 2, 3, 4 ] + + ports: + description: +diff --git a/Documentation/i2c/busses/i2c-i801.rst b/Documentation/i2c/busses/i2c-i801.rst +index 10eced6c2e4625..47e8ac5b7099f7 100644 +--- a/Documentation/i2c/busses/i2c-i801.rst ++++ b/Documentation/i2c/busses/i2c-i801.rst +@@ -48,6 +48,8 @@ Supported adapters: + * Intel Raptor Lake (PCH) + * Intel Meteor Lake (SOC and PCH) + * Intel Birch Stream (SOC) ++ * Intel Arrow Lake (SOC) ++ * Intel Panther Lake (SOC) + + Datasheets: Publicly available at the Intel website + +diff --git a/Makefile b/Makefile +index ec4d9d1d9b7ae7..4c0dd62e02e465 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 6 + PATCHLEVEL = 6 +-SUBLEVEL = 69 ++SUBLEVEL = 70 + EXTRAVERSION = + NAME = Pinguïn Aangedreven + +diff --git a/arch/arc/Makefile b/arch/arc/Makefile +index 2390dd042e3636..fb98478ed1ab09 100644 +--- a/arch/arc/Makefile ++++ b/arch/arc/Makefile +@@ -6,7 +6,7 @@ + KBUILD_DEFCONFIG := haps_hs_smp_defconfig + + ifeq ($(CROSS_COMPILE),) +-CROSS_COMPILE := $(call cc-cross-prefix, arc-linux- arceb-linux-) ++CROSS_COMPILE := $(call cc-cross-prefix, arc-linux- arceb-linux- arc-linux-gnu-) + endif + + cflags-y += -fno-common -pipe -fno-builtin -mmedium-calls -D__linux__ +diff --git a/arch/loongarch/kernel/numa.c b/arch/loongarch/kernel/numa.c +index 6e65ff12d5c7dc..8fe21f868f72d4 100644 +--- a/arch/loongarch/kernel/numa.c ++++ b/arch/loongarch/kernel/numa.c +@@ -226,32 +226,6 @@ static void __init node_mem_init(unsigned int node) + + #ifdef CONFIG_ACPI_NUMA + +-/* +- * Sanity check to catch more bad NUMA configurations (they are amazingly +- * common). Make sure the nodes cover all memory. +- */ +-static bool __init numa_meminfo_cover_memory(const struct numa_meminfo *mi) +-{ +- int i; +- u64 numaram, biosram; +- +- numaram = 0; +- for (i = 0; i < mi->nr_blks; i++) { +- u64 s = mi->blk[i].start >> PAGE_SHIFT; +- u64 e = mi->blk[i].end >> PAGE_SHIFT; +- +- numaram += e - s; +- numaram -= __absent_pages_in_range(mi->blk[i].nid, s, e); +- if ((s64)numaram < 0) +- numaram = 0; +- } +- max_pfn = max_low_pfn; +- biosram = max_pfn - absent_pages_in_range(0, max_pfn); +- +- BUG_ON((s64)(biosram - numaram) >= (1 << (20 - PAGE_SHIFT))); +- return true; +-} +- + static void __init add_node_intersection(u32 node, u64 start, u64 size, u32 type) + { + static unsigned long num_physpages; +@@ -396,7 +370,7 @@ int __init init_numa_memory(void) + return -EINVAL; + + init_node_memblock(); +- if (numa_meminfo_cover_memory(&numa_meminfo) == false) ++ if (!memblock_validate_numa_coverage(SZ_1M)) + return -EINVAL; + + for_each_node_mask(node, node_possible_map) { +diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c +index d43db8150767be..dddf4f31c219ac 100644 +--- a/arch/powerpc/kernel/setup-common.c ++++ b/arch/powerpc/kernel/setup-common.c +@@ -601,7 +601,6 @@ struct seq_buf ppc_hw_desc __initdata = { + .buffer = ppc_hw_desc_buf, + .size = sizeof(ppc_hw_desc_buf), + .len = 0, +- .readpos = 0, + }; + + static __init void probe_machine(void) +diff --git a/arch/x86/entry/vsyscall/vsyscall_64.c b/arch/x86/entry/vsyscall/vsyscall_64.c +index 1245000a8792fd..2fb7d53cf3338d 100644 +--- a/arch/x86/entry/vsyscall/vsyscall_64.c ++++ b/arch/x86/entry/vsyscall/vsyscall_64.c +@@ -76,7 +76,7 @@ static void warn_bad_vsyscall(const char *level, struct pt_regs *regs, + if (!show_unhandled_signals) + return; + +- printk_ratelimited("%s%s[%d] %s ip:%lx cs:%lx sp:%lx ax:%lx si:%lx di:%lx\n", ++ printk_ratelimited("%s%s[%d] %s ip:%lx cs:%x sp:%lx ax:%lx si:%lx di:%lx\n", + level, current->comm, task_pid_nr(current), + message, regs->ip, regs->cs, + regs->sp, regs->ax, regs->si, regs->di); +diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h +index f4db78b09c8f0b..5a83fbd9bc0b44 100644 +--- a/arch/x86/include/asm/ptrace.h ++++ b/arch/x86/include/asm/ptrace.h +@@ -56,18 +56,64 @@ struct pt_regs { + + #else /* __i386__ */ + ++struct fred_cs { ++ /* CS selector */ ++ u64 cs : 16, ++ /* Stack level at event time */ ++ sl : 2, ++ /* IBT in WAIT_FOR_ENDBRANCH state */ ++ wfe : 1, ++ : 45; ++}; ++ ++struct fred_ss { ++ /* SS selector */ ++ u64 ss : 16, ++ /* STI state */ ++ sti : 1, ++ /* Set if syscall, sysenter or INT n */ ++ swevent : 1, ++ /* Event is NMI type */ ++ nmi : 1, ++ : 13, ++ /* Event vector */ ++ vector : 8, ++ : 8, ++ /* Event type */ ++ type : 4, ++ : 4, ++ /* Event was incident to enclave execution */ ++ enclave : 1, ++ /* CPU was in long mode */ ++ lm : 1, ++ /* ++ * Nested exception during FRED delivery, not set ++ * for #DF. ++ */ ++ nested : 1, ++ : 1, ++ /* ++ * The length of the instruction causing the event. ++ * Only set for INTO, INT1, INT3, INT n, SYSCALL ++ * and SYSENTER. 0 otherwise. ++ */ ++ insnlen : 4; ++}; ++ + struct pt_regs { +-/* +- * C ABI says these regs are callee-preserved. They aren't saved on kernel entry +- * unless syscall needs a complete, fully filled "struct pt_regs". +- */ ++ /* ++ * C ABI says these regs are callee-preserved. They aren't saved on ++ * kernel entry unless syscall needs a complete, fully filled ++ * "struct pt_regs". ++ */ + unsigned long r15; + unsigned long r14; + unsigned long r13; + unsigned long r12; + unsigned long bp; + unsigned long bx; +-/* These regs are callee-clobbered. Always saved on kernel entry. */ ++ ++ /* These regs are callee-clobbered. Always saved on kernel entry. */ + unsigned long r11; + unsigned long r10; + unsigned long r9; +@@ -77,18 +123,50 @@ struct pt_regs { + unsigned long dx; + unsigned long si; + unsigned long di; +-/* +- * On syscall entry, this is syscall#. On CPU exception, this is error code. +- * On hw interrupt, it's IRQ number: +- */ ++ ++ /* ++ * orig_ax is used on entry for: ++ * - the syscall number (syscall, sysenter, int80) ++ * - error_code stored by the CPU on traps and exceptions ++ * - the interrupt number for device interrupts ++ * ++ * A FRED stack frame starts here: ++ * 1) It _always_ includes an error code; ++ * ++ * 2) The return frame for ERET[US] starts here, but ++ * the content of orig_ax is ignored. ++ */ + unsigned long orig_ax; +-/* Return frame for iretq */ ++ ++ /* The IRETQ return frame starts here */ + unsigned long ip; +- unsigned long cs; ++ ++ union { ++ /* CS selector */ ++ u16 cs; ++ /* The extended 64-bit data slot containing CS */ ++ u64 csx; ++ /* The FRED CS extension */ ++ struct fred_cs fred_cs; ++ }; ++ + unsigned long flags; + unsigned long sp; +- unsigned long ss; +-/* top of stack page */ ++ ++ union { ++ /* SS selector */ ++ u16 ss; ++ /* The extended 64-bit data slot containing SS */ ++ u64 ssx; ++ /* The FRED SS extension */ ++ struct fred_ss fred_ss; ++ }; ++ ++ /* ++ * Top of stack on IDT systems, while FRED systems have extra fields ++ * defined above for storing exception related information, e.g. CR2 or ++ * DR6. ++ */ + }; + + #endif /* !__i386__ */ +diff --git a/arch/x86/include/asm/tlb.h b/arch/x86/include/asm/tlb.h +index 580636cdc257b7..4d3c9d00d6b6b2 100644 +--- a/arch/x86/include/asm/tlb.h ++++ b/arch/x86/include/asm/tlb.h +@@ -34,4 +34,8 @@ static inline void __tlb_remove_table(void *table) + free_page_and_swap_cache(table); + } + ++static inline void invlpg(unsigned long addr) ++{ ++ asm volatile("invlpg (%0)" ::"r" (addr) : "memory"); ++} + #endif /* _ASM_X86_TLB_H */ +diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile +index 3269a0e23d3ab8..15fc9fc3dcf052 100644 +--- a/arch/x86/kernel/Makefile ++++ b/arch/x86/kernel/Makefile +@@ -99,9 +99,9 @@ obj-$(CONFIG_TRACING) += trace.o + obj-$(CONFIG_RETHOOK) += rethook.o + obj-$(CONFIG_CRASH_CORE) += crash_core_$(BITS).o + obj-$(CONFIG_KEXEC_CORE) += machine_kexec_$(BITS).o +-obj-$(CONFIG_KEXEC_CORE) += relocate_kernel_$(BITS).o crash.o ++obj-$(CONFIG_KEXEC_CORE) += relocate_kernel_$(BITS).o + obj-$(CONFIG_KEXEC_FILE) += kexec-bzimage64.o +-obj-$(CONFIG_CRASH_DUMP) += crash_dump_$(BITS).o ++obj-$(CONFIG_CRASH_DUMP) += crash_dump_$(BITS).o crash.o + obj-y += kprobes/ + obj-$(CONFIG_MODULES) += module.o + obj-$(CONFIG_X86_32) += doublefault_32.o +diff --git a/arch/x86/kernel/cet.c b/arch/x86/kernel/cet.c +index d2c732a34e5d90..303bf74d175b30 100644 +--- a/arch/x86/kernel/cet.c ++++ b/arch/x86/kernel/cet.c +@@ -81,6 +81,34 @@ static void do_user_cp_fault(struct pt_regs *regs, unsigned long error_code) + + static __ro_after_init bool ibt_fatal = true; + ++/* ++ * By definition, all missing-ENDBRANCH #CPs are a result of WFE && !ENDBR. ++ * ++ * For the kernel IBT no ENDBR selftest where #CPs are deliberately triggered, ++ * the WFE state of the interrupted context needs to be cleared to let execution ++ * continue. Otherwise when the CPU resumes from the instruction that just ++ * caused the previous #CP, another missing-ENDBRANCH #CP is raised and the CPU ++ * enters a dead loop. ++ * ++ * This is not a problem with IDT because it doesn't preserve WFE and IRET doesn't ++ * set WFE. But FRED provides space on the entry stack (in an expanded CS area) ++ * to save and restore the WFE state, thus the WFE state is no longer clobbered, ++ * so software must clear it. ++ */ ++static void ibt_clear_fred_wfe(struct pt_regs *regs) ++{ ++ /* ++ * No need to do any FRED checks. ++ * ++ * For IDT event delivery, the high-order 48 bits of CS are pushed ++ * as 0s into the stack, and later IRET ignores these bits. ++ * ++ * For FRED, a test to check if fred_cs.wfe is set would be dropped ++ * by compilers. ++ */ ++ regs->fred_cs.wfe = 0; ++} ++ + static void do_kernel_cp_fault(struct pt_regs *regs, unsigned long error_code) + { + if ((error_code & CP_EC) != CP_ENDBR) { +@@ -90,6 +118,7 @@ static void do_kernel_cp_fault(struct pt_regs *regs, unsigned long error_code) + + if (unlikely(regs->ip == (unsigned long)&ibt_selftest_noendbr)) { + regs->ax = 0; ++ ibt_clear_fred_wfe(regs); + return; + } + +@@ -97,6 +126,7 @@ static void do_kernel_cp_fault(struct pt_regs *regs, unsigned long error_code) + if (!ibt_fatal) { + printk(KERN_DEFAULT CUT_HERE); + __warn(__FILE__, __LINE__, (void *)regs->ip, TAINT_WARN, regs, NULL); ++ ibt_clear_fred_wfe(regs); + return; + } + BUG(); +diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c +index bcb2d640a0cd85..6328cf56e59be2 100644 +--- a/arch/x86/kernel/cpu/mshyperv.c ++++ b/arch/x86/kernel/cpu/mshyperv.c +@@ -209,7 +209,9 @@ static void hv_machine_shutdown(void) + if (kexec_in_progress) + hyperv_cleanup(); + } ++#endif /* CONFIG_KEXEC_CORE */ + ++#ifdef CONFIG_CRASH_DUMP + static void hv_machine_crash_shutdown(struct pt_regs *regs) + { + if (hv_crash_handler) +@@ -221,7 +223,64 @@ static void hv_machine_crash_shutdown(struct pt_regs *regs) + /* Disable the hypercall page when there is only 1 active CPU. */ + hyperv_cleanup(); + } +-#endif /* CONFIG_KEXEC_CORE */ ++#endif /* CONFIG_CRASH_DUMP */ ++ ++static u64 hv_ref_counter_at_suspend; ++static void (*old_save_sched_clock_state)(void); ++static void (*old_restore_sched_clock_state)(void); ++ ++/* ++ * Hyper-V clock counter resets during hibernation. Save and restore clock ++ * offset during suspend/resume, while also considering the time passed ++ * before suspend. This is to make sure that sched_clock using hv tsc page ++ * based clocksource, proceeds from where it left off during suspend and ++ * it shows correct time for the timestamps of kernel messages after resume. ++ */ ++static void save_hv_clock_tsc_state(void) ++{ ++ hv_ref_counter_at_suspend = hv_read_reference_counter(); ++} ++ ++static void restore_hv_clock_tsc_state(void) ++{ ++ /* ++ * Adjust the offsets used by hv tsc clocksource to ++ * account for the time spent before hibernation. ++ * adjusted value = reference counter (time) at suspend ++ * - reference counter (time) now. ++ */ ++ hv_adj_sched_clock_offset(hv_ref_counter_at_suspend - hv_read_reference_counter()); ++} ++ ++/* ++ * Functions to override save_sched_clock_state and restore_sched_clock_state ++ * functions of x86_platform. The Hyper-V clock counter is reset during ++ * suspend-resume and the offset used to measure time needs to be ++ * corrected, post resume. ++ */ ++static void hv_save_sched_clock_state(void) ++{ ++ old_save_sched_clock_state(); ++ save_hv_clock_tsc_state(); ++} ++ ++static void hv_restore_sched_clock_state(void) ++{ ++ restore_hv_clock_tsc_state(); ++ old_restore_sched_clock_state(); ++} ++ ++static void __init x86_setup_ops_for_tsc_pg_clock(void) ++{ ++ if (!(ms_hyperv.features & HV_MSR_REFERENCE_TSC_AVAILABLE)) ++ return; ++ ++ old_save_sched_clock_state = x86_platform.save_sched_clock_state; ++ x86_platform.save_sched_clock_state = hv_save_sched_clock_state; ++ ++ old_restore_sched_clock_state = x86_platform.restore_sched_clock_state; ++ x86_platform.restore_sched_clock_state = hv_restore_sched_clock_state; ++} + #endif /* CONFIG_HYPERV */ + + static uint32_t __init ms_hyperv_platform(void) +@@ -493,9 +552,13 @@ static void __init ms_hyperv_init_platform(void) + no_timer_check = 1; + #endif + +-#if IS_ENABLED(CONFIG_HYPERV) && defined(CONFIG_KEXEC_CORE) ++#if IS_ENABLED(CONFIG_HYPERV) ++#if defined(CONFIG_KEXEC_CORE) + machine_ops.shutdown = hv_machine_shutdown; ++#endif ++#if defined(CONFIG_CRASH_DUMP) + machine_ops.crash_shutdown = hv_machine_crash_shutdown; ++#endif + #endif + if (ms_hyperv.features & HV_ACCESS_TSC_INVARIANT) { + /* +@@ -572,6 +635,7 @@ static void __init ms_hyperv_init_platform(void) + + /* Register Hyper-V specific clocksource */ + hv_init_clocksource(); ++ x86_setup_ops_for_tsc_pg_clock(); + hv_vtl_init_platform(); + #endif + /* +diff --git a/arch/x86/kernel/kexec-bzimage64.c b/arch/x86/kernel/kexec-bzimage64.c +index a61c12c0127097..0de509c02d18b9 100644 +--- a/arch/x86/kernel/kexec-bzimage64.c ++++ b/arch/x86/kernel/kexec-bzimage64.c +@@ -263,11 +263,13 @@ setup_boot_parameters(struct kimage *image, struct boot_params *params, + memset(¶ms->hd0_info, 0, sizeof(params->hd0_info)); + memset(¶ms->hd1_info, 0, sizeof(params->hd1_info)); + ++#ifdef CONFIG_CRASH_DUMP + if (image->type == KEXEC_TYPE_CRASH) { + ret = crash_setup_memmap_entries(image, params); + if (ret) + return ret; + } else ++#endif + setup_e820_entries(params); + + nr_e820_entries = params->e820_entries; +@@ -428,12 +430,14 @@ static void *bzImage64_load(struct kimage *image, char *kernel, + return ERR_PTR(-EINVAL); + } + ++#ifdef CONFIG_CRASH_DUMP + /* Allocate and load backup region */ + if (image->type == KEXEC_TYPE_CRASH) { + ret = crash_load_segments(image); + if (ret) + return ERR_PTR(ret); + } ++#endif + + /* + * Load purgatory. For 64bit entry point, purgatory code can be +diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c +index b8ab9ee5896c19..38d88c8b56ec07 100644 +--- a/arch/x86/kernel/kvm.c ++++ b/arch/x86/kernel/kvm.c +@@ -769,7 +769,7 @@ static struct notifier_block kvm_pv_reboot_nb = { + * won't be valid. In cases like kexec, in which you install a new kernel, this + * means a random memory location will be kept being written. + */ +-#ifdef CONFIG_KEXEC_CORE ++#ifdef CONFIG_CRASH_DUMP + static void kvm_crash_shutdown(struct pt_regs *regs) + { + kvm_guest_cpu_offline(true); +@@ -852,7 +852,7 @@ static void __init kvm_guest_init(void) + kvm_guest_cpu_init(); + #endif + +-#ifdef CONFIG_KEXEC_CORE ++#ifdef CONFIG_CRASH_DUMP + machine_ops.crash_shutdown = kvm_crash_shutdown; + #endif + +diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c +index 2fa12d1dc67602..aaeac2deb85dc6 100644 +--- a/arch/x86/kernel/machine_kexec_64.c ++++ b/arch/x86/kernel/machine_kexec_64.c +@@ -545,6 +545,8 @@ int arch_kimage_file_post_load_cleanup(struct kimage *image) + } + #endif /* CONFIG_KEXEC_FILE */ + ++#ifdef CONFIG_CRASH_DUMP ++ + static int + kexec_mark_range(unsigned long start, unsigned long end, bool protect) + { +@@ -589,6 +591,7 @@ void arch_kexec_unprotect_crashkres(void) + { + kexec_mark_crashkres(false); + } ++#endif + + /* + * During a traditional boot under SME, SME will encrypt the kernel, +diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c +index d595ef7c1de05e..dd19a4db741afd 100644 +--- a/arch/x86/kernel/process_64.c ++++ b/arch/x86/kernel/process_64.c +@@ -117,7 +117,7 @@ void __show_regs(struct pt_regs *regs, enum show_regs_mode mode, + + printk("%sFS: %016lx(%04x) GS:%016lx(%04x) knlGS:%016lx\n", + log_lvl, fs, fsindex, gs, gsindex, shadowgs); +- printk("%sCS: %04lx DS: %04x ES: %04x CR0: %016lx\n", ++ printk("%sCS: %04x DS: %04x ES: %04x CR0: %016lx\n", + log_lvl, regs->cs, ds, es, cr0); + printk("%sCR2: %016lx CR3: %016lx CR4: %016lx\n", + log_lvl, cr2, cr3, cr4); +diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c +index 830425e6d38e2f..f3130f762784a1 100644 +--- a/arch/x86/kernel/reboot.c ++++ b/arch/x86/kernel/reboot.c +@@ -796,7 +796,7 @@ struct machine_ops machine_ops __ro_after_init = { + .emergency_restart = native_machine_emergency_restart, + .restart = native_machine_restart, + .halt = native_machine_halt, +-#ifdef CONFIG_KEXEC_CORE ++#ifdef CONFIG_CRASH_DUMP + .crash_shutdown = native_machine_crash_shutdown, + #endif + }; +@@ -826,7 +826,7 @@ void machine_halt(void) + machine_ops.halt(); + } + +-#ifdef CONFIG_KEXEC_CORE ++#ifdef CONFIG_CRASH_DUMP + void machine_crash_shutdown(struct pt_regs *regs) + { + machine_ops.crash_shutdown(regs); +diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c +index eb129277dcdd64..8bcecabd475bdf 100644 +--- a/arch/x86/kernel/setup.c ++++ b/arch/x86/kernel/setup.c +@@ -547,7 +547,7 @@ static void __init reserve_crashkernel(void) + bool high = false; + int ret; + +- if (!IS_ENABLED(CONFIG_KEXEC_CORE)) ++ if (!IS_ENABLED(CONFIG_CRASH_RESERVE)) + return; + + total_mem = memblock_phys_mem_size(); +diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c +index 96a771f9f930a6..52c3823b721191 100644 +--- a/arch/x86/kernel/smp.c ++++ b/arch/x86/kernel/smp.c +@@ -282,7 +282,7 @@ struct smp_ops smp_ops = { + .smp_cpus_done = native_smp_cpus_done, + + .stop_other_cpus = native_stop_other_cpus, +-#if defined(CONFIG_KEXEC_CORE) ++#if defined(CONFIG_CRASH_DUMP) + .crash_stop_other_cpus = kdump_nmi_shootdown_cpus, + #endif + .smp_send_reschedule = native_smp_send_reschedule, +diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c +index c7fa5396c0f05c..2c67bfc3cf3204 100644 +--- a/arch/x86/mm/numa.c ++++ b/arch/x86/mm/numa.c +@@ -448,37 +448,6 @@ int __node_distance(int from, int to) + } + EXPORT_SYMBOL(__node_distance); + +-/* +- * Sanity check to catch more bad NUMA configurations (they are amazingly +- * common). Make sure the nodes cover all memory. +- */ +-static bool __init numa_meminfo_cover_memory(const struct numa_meminfo *mi) +-{ +- u64 numaram, e820ram; +- int i; +- +- numaram = 0; +- for (i = 0; i < mi->nr_blks; i++) { +- u64 s = mi->blk[i].start >> PAGE_SHIFT; +- u64 e = mi->blk[i].end >> PAGE_SHIFT; +- numaram += e - s; +- numaram -= __absent_pages_in_range(mi->blk[i].nid, s, e); +- if ((s64)numaram < 0) +- numaram = 0; +- } +- +- e820ram = max_pfn - absent_pages_in_range(0, max_pfn); +- +- /* We seem to lose 3 pages somewhere. Allow 1M of slack. */ +- if ((s64)(e820ram - numaram) >= (1 << (20 - PAGE_SHIFT))) { +- printk(KERN_ERR "NUMA: nodes only cover %LuMB of your %LuMB e820 RAM. Not used.\n", +- (numaram << PAGE_SHIFT) >> 20, +- (e820ram << PAGE_SHIFT) >> 20); +- return false; +- } +- return true; +-} +- + /* + * Mark all currently memblock-reserved physical memory (which covers the + * kernel's own memory ranges) as hot-unswappable. +@@ -584,7 +553,8 @@ static int __init numa_register_memblks(struct numa_meminfo *mi) + return -EINVAL; + } + } +- if (!numa_meminfo_cover_memory(mi)) ++ ++ if (!memblock_validate_numa_coverage(SZ_1M)) + return -EINVAL; + + /* Finally register nodes. */ +diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c +index 2fbae48f0b470a..64f594826a2822 100644 +--- a/arch/x86/mm/tlb.c ++++ b/arch/x86/mm/tlb.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + + #include "mm_internal.h" + +@@ -1145,7 +1146,7 @@ STATIC_NOPV void native_flush_tlb_one_user(unsigned long addr) + bool cpu_pcide; + + /* Flush 'addr' from the kernel PCID: */ +- asm volatile("invlpg (%0)" ::"r" (addr) : "memory"); ++ invlpg(addr); + + /* If PTI is off there is no user PCID and nothing to flush. */ + if (!static_cpu_has(X86_FEATURE_PTI)) +diff --git a/arch/x86/xen/enlighten_hvm.c b/arch/x86/xen/enlighten_hvm.c +index 70be57e8f51caa..ade22feee7aeb1 100644 +--- a/arch/x86/xen/enlighten_hvm.c ++++ b/arch/x86/xen/enlighten_hvm.c +@@ -141,7 +141,9 @@ static void xen_hvm_shutdown(void) + if (kexec_in_progress) + xen_reboot(SHUTDOWN_soft_reset); + } ++#endif + ++#ifdef CONFIG_CRASH_DUMP + static void xen_hvm_crash_shutdown(struct pt_regs *regs) + { + native_machine_crash_shutdown(regs); +@@ -229,6 +231,8 @@ static void __init xen_hvm_guest_init(void) + + #ifdef CONFIG_KEXEC_CORE + machine_ops.shutdown = xen_hvm_shutdown; ++#endif ++#ifdef CONFIG_CRASH_DUMP + machine_ops.crash_shutdown = xen_hvm_crash_shutdown; + #endif + } +diff --git a/arch/x86/xen/mmu_pv.c b/arch/x86/xen/mmu_pv.c +index 6b201e64d8abc8..bfd57d07f4b5ee 100644 +--- a/arch/x86/xen/mmu_pv.c ++++ b/arch/x86/xen/mmu_pv.c +@@ -2517,7 +2517,7 @@ int xen_remap_pfn(struct vm_area_struct *vma, unsigned long addr, + } + EXPORT_SYMBOL_GPL(xen_remap_pfn); + +-#ifdef CONFIG_KEXEC_CORE ++#ifdef CONFIG_VMCORE_INFO + phys_addr_t paddr_vmcoreinfo_note(void) + { + if (xen_pv_domain()) +diff --git a/crypto/ecc.c b/crypto/ecc.c +index f53fb4d6af992b..21504280aca2e5 100644 +--- a/crypto/ecc.c ++++ b/crypto/ecc.c +@@ -66,6 +66,28 @@ const struct ecc_curve *ecc_get_curve(unsigned int curve_id) + } + EXPORT_SYMBOL(ecc_get_curve); + ++void ecc_digits_from_bytes(const u8 *in, unsigned int nbytes, ++ u64 *out, unsigned int ndigits) ++{ ++ int diff = ndigits - DIV_ROUND_UP(nbytes, sizeof(u64)); ++ unsigned int o = nbytes & 7; ++ __be64 msd = 0; ++ ++ /* diff > 0: not enough input bytes: set most significant digits to 0 */ ++ if (diff > 0) { ++ ndigits -= diff; ++ memset(&out[ndigits - 1], 0, diff * sizeof(u64)); ++ } ++ ++ if (o) { ++ memcpy((u8 *)&msd + sizeof(msd) - o, in, o); ++ out[--ndigits] = be64_to_cpu(msd); ++ in += o; ++ } ++ ecc_swap_digits(in, out, ndigits); ++} ++EXPORT_SYMBOL(ecc_digits_from_bytes); ++ + static u64 *ecc_alloc_digits_space(unsigned int ndigits) + { + size_t len = ndigits * sizeof(u64); +diff --git a/crypto/ecdsa.c b/crypto/ecdsa.c +index 3f9ec273a121fd..da04df3c8ecf4d 100644 +--- a/crypto/ecdsa.c ++++ b/crypto/ecdsa.c +@@ -35,40 +35,27 @@ struct ecdsa_signature_ctx { + static int ecdsa_get_signature_rs(u64 *dest, size_t hdrlen, unsigned char tag, + const void *value, size_t vlen, unsigned int ndigits) + { +- size_t keylen = ndigits * sizeof(u64); +- ssize_t diff = vlen - keylen; ++ size_t bufsize = ndigits * sizeof(u64); + const char *d = value; +- u8 rs[ECC_MAX_BYTES]; + +- if (!value || !vlen) ++ if (!value || !vlen || vlen > bufsize + 1) + return -EINVAL; + +- /* diff = 0: 'value' has exacly the right size +- * diff > 0: 'value' has too many bytes; one leading zero is allowed that +- * makes the value a positive integer; error on more +- * diff < 0: 'value' is missing leading zeros, which we add ++ /* ++ * vlen may be 1 byte larger than bufsize due to a leading zero byte ++ * (necessary if the most significant bit of the integer is set). + */ +- if (diff > 0) { ++ if (vlen > bufsize) { + /* skip over leading zeros that make 'value' a positive int */ + if (*d == 0) { + vlen -= 1; +- diff--; + d++; +- } +- if (diff) ++ } else { + return -EINVAL; ++ } + } +- if (-diff >= keylen) +- return -EINVAL; +- +- if (diff) { +- /* leading zeros not given in 'value' */ +- memset(rs, 0, -diff); +- } +- +- memcpy(&rs[-diff], d, vlen); + +- ecc_swap_digits((u64 *)rs, dest, ndigits); ++ ecc_digits_from_bytes(d, vlen, dest, ndigits); + + return 0; + } +@@ -138,7 +125,7 @@ static int ecdsa_verify(struct akcipher_request *req) + { + struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); + struct ecc_ctx *ctx = akcipher_tfm_ctx(tfm); +- size_t keylen = ctx->curve->g.ndigits * sizeof(u64); ++ size_t bufsize = ctx->curve->g.ndigits * sizeof(u64); + struct ecdsa_signature_ctx sig_ctx = { + .curve = ctx->curve, + }; +@@ -165,14 +152,14 @@ static int ecdsa_verify(struct akcipher_request *req) + goto error; + + /* if the hash is shorter then we will add leading zeros to fit to ndigits */ +- diff = keylen - req->dst_len; ++ diff = bufsize - req->dst_len; + if (diff >= 0) { + if (diff) + memset(rawhash, 0, diff); + memcpy(&rawhash[diff], buffer + req->src_len, req->dst_len); + } else if (diff < 0) { + /* given hash is longer, we take the left-most bytes */ +- memcpy(&rawhash, buffer + req->src_len, keylen); ++ memcpy(&rawhash, buffer + req->src_len, bufsize); + } + + ecc_swap_digits((u64 *)rawhash, hash, ctx->curve->g.ndigits); +@@ -222,9 +209,8 @@ static int ecdsa_ecc_ctx_reset(struct ecc_ctx *ctx) + static int ecdsa_set_pub_key(struct crypto_akcipher *tfm, const void *key, unsigned int keylen) + { + struct ecc_ctx *ctx = akcipher_tfm_ctx(tfm); ++ unsigned int digitlen, ndigits; + const unsigned char *d = key; +- const u64 *digits = (const u64 *)&d[1]; +- unsigned int ndigits; + int ret; + + ret = ecdsa_ecc_ctx_reset(ctx); +@@ -238,12 +224,17 @@ static int ecdsa_set_pub_key(struct crypto_akcipher *tfm, const void *key, unsig + return -EINVAL; + + keylen--; +- ndigits = (keylen >> 1) / sizeof(u64); ++ digitlen = keylen >> 1; ++ ++ ndigits = DIV_ROUND_UP(digitlen, sizeof(u64)); + if (ndigits != ctx->curve->g.ndigits) + return -EINVAL; + +- ecc_swap_digits(digits, ctx->pub_key.x, ndigits); +- ecc_swap_digits(&digits[ndigits], ctx->pub_key.y, ndigits); ++ d++; ++ ++ ecc_digits_from_bytes(d, digitlen, ctx->pub_key.x, ndigits); ++ ecc_digits_from_bytes(&d[digitlen], digitlen, ctx->pub_key.y, ndigits); ++ + ret = ecc_is_pubkey_valid_full(ctx->curve, &ctx->pub_key); + + ctx->pub_key_set = ret == 0; +diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c +index 6496ff5a6ba20d..1a31106a14e446 100644 +--- a/drivers/acpi/arm64/iort.c ++++ b/drivers/acpi/arm64/iort.c +@@ -1712,6 +1712,15 @@ static struct acpi_platform_list pmcg_plat_info[] __initdata = { + /* HiSilicon Hip09 Platform */ + {"HISI ", "HIP09 ", 0, ACPI_SIG_IORT, greater_than_or_equal, + "Erratum #162001900", IORT_SMMU_V3_PMCG_HISI_HIP09}, ++ {"HISI ", "HIP09A ", 0, ACPI_SIG_IORT, greater_than_or_equal, ++ "Erratum #162001900", IORT_SMMU_V3_PMCG_HISI_HIP09}, ++ /* HiSilicon Hip10/11 Platform uses the same SMMU IP with Hip09 */ ++ {"HISI ", "HIP10 ", 0, ACPI_SIG_IORT, greater_than_or_equal, ++ "Erratum #162001900", IORT_SMMU_V3_PMCG_HISI_HIP09}, ++ {"HISI ", "HIP10C ", 0, ACPI_SIG_IORT, greater_than_or_equal, ++ "Erratum #162001900", IORT_SMMU_V3_PMCG_HISI_HIP09}, ++ {"HISI ", "HIP11 ", 0, ACPI_SIG_IORT, greater_than_or_equal, ++ "Erratum #162001900", IORT_SMMU_V3_PMCG_HISI_HIP09}, + { } + }; + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index fe5e30662017de..c80b5aa7628ae9 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -620,6 +620,9 @@ static const struct usb_device_id quirks_table[] = { + { USB_DEVICE(0x0e8d, 0x0608), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH | + BTUSB_VALID_LE_STATES }, ++ { USB_DEVICE(0x13d3, 0x3606), .driver_info = BTUSB_MEDIATEK | ++ BTUSB_WIDEBAND_SPEECH | ++ BTUSB_VALID_LE_STATES }, + + /* MediaTek MT7922A Bluetooth devices */ + { USB_DEVICE(0x0489, 0xe0d8), .driver_info = BTUSB_MEDIATEK | +@@ -658,6 +661,37 @@ static const struct usb_device_id quirks_table[] = { + { USB_DEVICE(0x04ca, 0x3804), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH | + BTUSB_VALID_LE_STATES }, ++ { USB_DEVICE(0x35f5, 0x7922), .driver_info = BTUSB_MEDIATEK | ++ BTUSB_WIDEBAND_SPEECH | ++ BTUSB_VALID_LE_STATES }, ++ { USB_DEVICE(0x13d3, 0x3614), .driver_info = BTUSB_MEDIATEK | ++ BTUSB_WIDEBAND_SPEECH | ++ BTUSB_VALID_LE_STATES }, ++ { USB_DEVICE(0x13d3, 0x3615), .driver_info = BTUSB_MEDIATEK | ++ BTUSB_WIDEBAND_SPEECH | ++ BTUSB_VALID_LE_STATES }, ++ { USB_DEVICE(0x04ca, 0x38e4), .driver_info = BTUSB_MEDIATEK | ++ BTUSB_WIDEBAND_SPEECH | ++ BTUSB_VALID_LE_STATES }, ++ { USB_DEVICE(0x13d3, 0x3605), .driver_info = BTUSB_MEDIATEK | ++ BTUSB_WIDEBAND_SPEECH | ++ BTUSB_VALID_LE_STATES }, ++ { USB_DEVICE(0x13d3, 0x3607), .driver_info = BTUSB_MEDIATEK | ++ BTUSB_WIDEBAND_SPEECH | ++ BTUSB_VALID_LE_STATES }, ++ ++ /* Additional MediaTek MT7925 Bluetooth devices */ ++ { USB_DEVICE(0x0489, 0xe111), .driver_info = BTUSB_MEDIATEK | ++ BTUSB_WIDEBAND_SPEECH }, ++ { USB_DEVICE(0x0489, 0xe113), .driver_info = BTUSB_MEDIATEK | ++ BTUSB_WIDEBAND_SPEECH | ++ BTUSB_VALID_LE_STATES }, ++ { USB_DEVICE(0x13d3, 0x3602), .driver_info = BTUSB_MEDIATEK | ++ BTUSB_WIDEBAND_SPEECH | ++ BTUSB_VALID_LE_STATES }, ++ { USB_DEVICE(0x13d3, 0x3603), .driver_info = BTUSB_MEDIATEK | ++ BTUSB_WIDEBAND_SPEECH | ++ BTUSB_VALID_LE_STATES }, + + /* Additional Realtek 8723AE Bluetooth devices */ + { USB_DEVICE(0x0930, 0x021d), .driver_info = BTUSB_REALTEK }, +@@ -858,6 +892,10 @@ struct btusb_data { + + int (*setup_on_usb)(struct hci_dev *hdev); + ++ int (*suspend)(struct hci_dev *hdev); ++ int (*resume)(struct hci_dev *hdev); ++ int (*disconnect)(struct hci_dev *hdev); ++ + int oob_wake_irq; /* irq for out-of-band wake-on-bt */ + unsigned cmd_timeout_cnt; + +@@ -4609,6 +4647,9 @@ static void btusb_disconnect(struct usb_interface *intf) + if (data->diag) + usb_set_intfdata(data->diag, NULL); + ++ if (data->disconnect) ++ data->disconnect(hdev); ++ + hci_unregister_dev(hdev); + + if (intf == data->intf) { +@@ -4657,6 +4698,9 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message) + + cancel_work_sync(&data->work); + ++ if (data->suspend) ++ data->suspend(data->hdev); ++ + btusb_stop_traffic(data); + usb_kill_anchored_urbs(&data->tx_anchor); + +@@ -4760,6 +4804,9 @@ static int btusb_resume(struct usb_interface *intf) + btusb_submit_isoc_urb(hdev, GFP_NOIO); + } + ++ if (data->resume) ++ data->resume(hdev); ++ + spin_lock_irq(&data->txlock); + play_deferred(data); + clear_bit(BTUSB_SUSPENDING, &data->flags); +diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c +index 8b3e5f84e89a77..ce44dbfd47e275 100644 +--- a/drivers/clk/qcom/clk-alpha-pll.c ++++ b/drivers/clk/qcom/clk-alpha-pll.c +@@ -52,6 +52,7 @@ + #define PLL_CONFIG_CTL(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL]) + #define PLL_CONFIG_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL_U]) + #define PLL_CONFIG_CTL_U1(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL_U1]) ++#define PLL_CONFIG_CTL_U2(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL_U2]) + #define PLL_TEST_CTL(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL]) + #define PLL_TEST_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL_U]) + #define PLL_TEST_CTL_U1(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL_U1]) +@@ -227,6 +228,32 @@ const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = { + [PLL_OFF_ALPHA_VAL] = 0x24, + [PLL_OFF_ALPHA_VAL_U] = 0x28, + }, ++ [CLK_ALPHA_PLL_TYPE_ZONDA_OLE] = { ++ [PLL_OFF_L_VAL] = 0x04, ++ [PLL_OFF_ALPHA_VAL] = 0x08, ++ [PLL_OFF_USER_CTL] = 0x0c, ++ [PLL_OFF_USER_CTL_U] = 0x10, ++ [PLL_OFF_CONFIG_CTL] = 0x14, ++ [PLL_OFF_CONFIG_CTL_U] = 0x18, ++ [PLL_OFF_CONFIG_CTL_U1] = 0x1c, ++ [PLL_OFF_CONFIG_CTL_U2] = 0x20, ++ [PLL_OFF_TEST_CTL] = 0x24, ++ [PLL_OFF_TEST_CTL_U] = 0x28, ++ [PLL_OFF_TEST_CTL_U1] = 0x2c, ++ [PLL_OFF_OPMODE] = 0x30, ++ [PLL_OFF_STATUS] = 0x3c, ++ }, ++ [CLK_ALPHA_PLL_TYPE_NSS_HUAYRA] = { ++ [PLL_OFF_L_VAL] = 0x04, ++ [PLL_OFF_ALPHA_VAL] = 0x08, ++ [PLL_OFF_TEST_CTL] = 0x0c, ++ [PLL_OFF_TEST_CTL_U] = 0x10, ++ [PLL_OFF_USER_CTL] = 0x14, ++ [PLL_OFF_CONFIG_CTL] = 0x18, ++ [PLL_OFF_CONFIG_CTL_U] = 0x1c, ++ [PLL_OFF_STATUS] = 0x20, ++ }, ++ + }; + EXPORT_SYMBOL_GPL(clk_alpha_pll_regs); + +diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h +index 3fd0ef41c72c89..52dc5b9b546a15 100644 +--- a/drivers/clk/qcom/clk-alpha-pll.h ++++ b/drivers/clk/qcom/clk-alpha-pll.h +@@ -21,6 +21,7 @@ enum { + CLK_ALPHA_PLL_TYPE_LUCID = CLK_ALPHA_PLL_TYPE_TRION, + CLK_ALPHA_PLL_TYPE_AGERA, + CLK_ALPHA_PLL_TYPE_ZONDA, ++ CLK_ALPHA_PLL_TYPE_ZONDA_OLE, + CLK_ALPHA_PLL_TYPE_LUCID_EVO, + CLK_ALPHA_PLL_TYPE_LUCID_OLE, + CLK_ALPHA_PLL_TYPE_RIVIAN_EVO, +@@ -28,6 +29,7 @@ enum { + CLK_ALPHA_PLL_TYPE_BRAMMO_EVO, + CLK_ALPHA_PLL_TYPE_STROMER, + CLK_ALPHA_PLL_TYPE_STROMER_PLUS, ++ CLK_ALPHA_PLL_TYPE_NSS_HUAYRA, + CLK_ALPHA_PLL_TYPE_MAX, + }; + +@@ -42,6 +44,7 @@ enum { + PLL_OFF_CONFIG_CTL, + PLL_OFF_CONFIG_CTL_U, + PLL_OFF_CONFIG_CTL_U1, ++ PLL_OFF_CONFIG_CTL_U2, + PLL_OFF_TEST_CTL, + PLL_OFF_TEST_CTL_U, + PLL_OFF_TEST_CTL_U1, +@@ -119,6 +122,7 @@ struct alpha_pll_config { + u32 config_ctl_val; + u32 config_ctl_hi_val; + u32 config_ctl_hi1_val; ++ u32 config_ctl_hi2_val; + u32 user_ctl_val; + u32 user_ctl_hi_val; + u32 user_ctl_hi1_val; +@@ -173,6 +177,7 @@ extern const struct clk_ops clk_alpha_pll_postdiv_lucid_5lpe_ops; + + extern const struct clk_ops clk_alpha_pll_zonda_ops; + #define clk_alpha_pll_postdiv_zonda_ops clk_alpha_pll_postdiv_fabia_ops ++#define clk_alpha_pll_zonda_ole_ops clk_alpha_pll_zonda_ops + + extern const struct clk_ops clk_alpha_pll_lucid_evo_ops; + extern const struct clk_ops clk_alpha_pll_reset_lucid_evo_ops; +diff --git a/drivers/clocksource/hyperv_timer.c b/drivers/clocksource/hyperv_timer.c +index 8ff7cd4e20bb11..5eec1457e13967 100644 +--- a/drivers/clocksource/hyperv_timer.c ++++ b/drivers/clocksource/hyperv_timer.c +@@ -27,7 +27,8 @@ + #include + + static struct clock_event_device __percpu *hv_clock_event; +-static u64 hv_sched_clock_offset __ro_after_init; ++/* Note: offset can hold negative values after hibernation. */ ++static u64 hv_sched_clock_offset __read_mostly; + + /* + * If false, we're using the old mechanism for stimer0 interrupts +@@ -456,6 +457,17 @@ static void resume_hv_clock_tsc(struct clocksource *arg) + hv_set_register(HV_REGISTER_REFERENCE_TSC, tsc_msr.as_uint64); + } + ++/* ++ * Called during resume from hibernation, from overridden ++ * x86_platform.restore_sched_clock_state routine. This is to adjust offsets ++ * used to calculate time for hv tsc page based sched_clock, to account for ++ * time spent before hibernation. ++ */ ++void hv_adj_sched_clock_offset(u64 offset) ++{ ++ hv_sched_clock_offset -= offset; ++} ++ + #ifdef HAVE_VDSO_CLOCKMODE_HVCLOCK + static int hv_cs_enable(struct clocksource *cs) + { +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c +index 3263b5fa182d20..f99e3b812ee44b 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c +@@ -319,7 +319,7 @@ svm_migrate_copy_to_vram(struct kfd_node *node, struct svm_range *prange, + spage = migrate_pfn_to_page(migrate->src[i]); + if (spage && !is_zone_device_page(spage)) { + src[i] = dma_map_page(dev, spage, 0, PAGE_SIZE, +- DMA_TO_DEVICE); ++ DMA_BIDIRECTIONAL); + r = dma_mapping_error(dev, src[i]); + if (r) { + dev_err(dev, "%s: fail %d dma_map_page\n", +@@ -634,7 +634,7 @@ svm_migrate_copy_to_ram(struct amdgpu_device *adev, struct svm_range *prange, + goto out_oom; + } + +- dst[i] = dma_map_page(dev, dpage, 0, PAGE_SIZE, DMA_FROM_DEVICE); ++ dst[i] = dma_map_page(dev, dpage, 0, PAGE_SIZE, DMA_BIDIRECTIONAL); + r = dma_mapping_error(dev, dst[i]); + if (r) { + dev_err(adev->dev, "%s: fail %d dma_map_page\n", __func__, r); +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +index 9ec9792f115a8a..385a5a75fdf873 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +@@ -1219,10 +1219,6 @@ static bool is_dsc_need_re_compute( + if (dc_link->type != dc_connection_mst_branch) + return false; + +- if (!(dc_link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_SUPPORT || +- dc_link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_PASSTHROUGH_SUPPORT)) +- return false; +- + for (i = 0; i < MAX_PIPES; i++) + stream_on_link[i] = NULL; + +@@ -1243,6 +1239,18 @@ static bool is_dsc_need_re_compute( + if (!aconnector) + continue; + ++ /* ++ * Check if cached virtual MST DSC caps are available and DSC is supported ++ * this change takes care of newer MST DSC capable devices that report their ++ * DPCD caps as per specifications in their Virtual DPCD registers. ++ ++ * TODO: implement the check for older MST DSC devices that do not conform to ++ * specifications. ++ */ ++ if (!(aconnector->dc_sink->dsc_caps.dsc_dec_caps.is_dsc_supported || ++ aconnector->dc_link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_PASSTHROUGH_SUPPORT)) ++ continue; ++ + stream_on_link[new_stream_on_link_num] = aconnector; + new_stream_on_link_num++; + +diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c b/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c +index 61f4a38e7d2bf6..8f786592143b6c 100644 +--- a/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c ++++ b/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c +@@ -153,7 +153,16 @@ static int adv7511_hdmi_hw_params(struct device *dev, void *data, + ADV7511_AUDIO_CFG3_LEN_MASK, len); + regmap_update_bits(adv7511->regmap, ADV7511_REG_I2C_FREQ_ID_CFG, + ADV7511_I2C_FREQ_ID_CFG_RATE_MASK, rate << 4); +- regmap_write(adv7511->regmap, 0x73, 0x1); ++ ++ /* send current Audio infoframe values while updating */ ++ regmap_update_bits(adv7511->regmap, ADV7511_REG_INFOFRAME_UPDATE, ++ BIT(5), BIT(5)); ++ ++ regmap_write(adv7511->regmap, ADV7511_REG_AUDIO_INFOFRAME(0), 0x1); ++ ++ /* use Audio infoframe updated info */ ++ regmap_update_bits(adv7511->regmap, ADV7511_REG_INFOFRAME_UPDATE, ++ BIT(5), 0); + + return 0; + } +@@ -184,8 +193,9 @@ static int audio_startup(struct device *dev, void *data) + regmap_update_bits(adv7511->regmap, ADV7511_REG_GC(0), + BIT(7) | BIT(6), BIT(7)); + /* use Audio infoframe updated info */ +- regmap_update_bits(adv7511->regmap, ADV7511_REG_GC(1), ++ regmap_update_bits(adv7511->regmap, ADV7511_REG_INFOFRAME_UPDATE, + BIT(5), 0); ++ + /* enable SPDIF receiver */ + if (adv7511->audio_source == ADV7511_AUDIO_SOURCE_SPDIF) + regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CONFIG, +diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +index ef2b6ce544d0a8..1aa4153b40e0c1 100644 +--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c ++++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +@@ -1225,8 +1225,10 @@ static int adv7511_probe(struct i2c_client *i2c) + return ret; + + ret = adv7511_init_regulators(adv7511); +- if (ret) +- return dev_err_probe(dev, ret, "failed to init regulators\n"); ++ if (ret) { ++ dev_err_probe(dev, ret, "failed to init regulators\n"); ++ goto err_of_node_put; ++ } + + /* + * The power down GPIO is optional. If present, toggle it from active to +@@ -1346,6 +1348,8 @@ static int adv7511_probe(struct i2c_client *i2c) + i2c_unregister_device(adv7511->i2c_edid); + uninit_regulators: + adv7511_uninit_regulators(adv7511); ++err_of_node_put: ++ of_node_put(adv7511->host_node); + + return ret; + } +@@ -1354,6 +1358,8 @@ static void adv7511_remove(struct i2c_client *i2c) + { + struct adv7511 *adv7511 = i2c_get_clientdata(i2c); + ++ of_node_put(adv7511->host_node); ++ + adv7511_uninit_regulators(adv7511); + + drm_bridge_remove(&adv7511->bridge); +diff --git a/drivers/gpu/drm/bridge/adv7511/adv7533.c b/drivers/gpu/drm/bridge/adv7511/adv7533.c +index 7e3e56441aedc5..6a4733c7082700 100644 +--- a/drivers/gpu/drm/bridge/adv7511/adv7533.c ++++ b/drivers/gpu/drm/bridge/adv7511/adv7533.c +@@ -175,7 +175,7 @@ int adv7533_parse_dt(struct device_node *np, struct adv7511 *adv) + + of_property_read_u32(np, "adi,dsi-lanes", &num_lanes); + +- if (num_lanes < 1 || num_lanes > 4) ++ if (num_lanes < 2 || num_lanes > 4) + return -EINVAL; + + adv->num_dsi_lanes = num_lanes; +@@ -184,8 +184,6 @@ int adv7533_parse_dt(struct device_node *np, struct adv7511 *adv) + if (!adv->host_node) + return -ENODEV; + +- of_node_put(adv->host_node); +- + adv->use_timing_gen = !of_property_read_bool(np, + "adi,disable-timing-generator"); + +diff --git a/drivers/gpu/drm/i915/gt/intel_rc6.c b/drivers/gpu/drm/i915/gt/intel_rc6.c +index 9e113e9473260a..6e8c182b2559e7 100644 +--- a/drivers/gpu/drm/i915/gt/intel_rc6.c ++++ b/drivers/gpu/drm/i915/gt/intel_rc6.c +@@ -133,7 +133,7 @@ static void gen11_rc6_enable(struct intel_rc6 *rc6) + GEN9_MEDIA_PG_ENABLE | + GEN11_MEDIA_SAMPLER_PG_ENABLE; + +- if (GRAPHICS_VER(gt->i915) >= 12) { ++ if (GRAPHICS_VER(gt->i915) >= 12 && !IS_DG1(gt->i915)) { + for (i = 0; i < I915_MAX_VCS; i++) + if (HAS_ENGINE(gt, _VCS(i))) + pg_enable |= (VDN_HCP_POWERGATE_ENABLE(i) | +diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig +index 97d27e01a6ee27..982007a112c2a0 100644 +--- a/drivers/i2c/busses/Kconfig ++++ b/drivers/i2c/busses/Kconfig +@@ -159,6 +159,8 @@ config I2C_I801 + Raptor Lake (PCH) + Meteor Lake (SOC and PCH) + Birch Stream (SOC) ++ Arrow Lake (SOC) ++ Panther Lake (SOC) + + This driver can also be built as a module. If so, the module + will be called i2c-i801. +diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c +index 2b8bcd121ffa5d..18c04f5e41d9c5 100644 +--- a/drivers/i2c/busses/i2c-i801.c ++++ b/drivers/i2c/busses/i2c-i801.c +@@ -80,6 +80,9 @@ + * Meteor Lake SoC-S (SOC) 0xae22 32 hard yes yes yes + * Meteor Lake PCH-S (PCH) 0x7f23 32 hard yes yes yes + * Birch Stream (SOC) 0x5796 32 hard yes yes yes ++ * Arrow Lake-H (SOC) 0x7722 32 hard yes yes yes ++ * Panther Lake-H (SOC) 0xe322 32 hard yes yes yes ++ * Panther Lake-P (SOC) 0xe422 32 hard yes yes yes + * + * Features supported by this driver: + * Software PEC no +@@ -234,6 +237,7 @@ + #define PCI_DEVICE_ID_INTEL_ALDER_LAKE_M_SMBUS 0x54a3 + #define PCI_DEVICE_ID_INTEL_BIRCH_STREAM_SMBUS 0x5796 + #define PCI_DEVICE_ID_INTEL_BROXTON_SMBUS 0x5ad4 ++#define PCI_DEVICE_ID_INTEL_ARROW_LAKE_H_SMBUS 0x7722 + #define PCI_DEVICE_ID_INTEL_RAPTOR_LAKE_S_SMBUS 0x7a23 + #define PCI_DEVICE_ID_INTEL_ALDER_LAKE_S_SMBUS 0x7aa3 + #define PCI_DEVICE_ID_INTEL_METEOR_LAKE_P_SMBUS 0x7e22 +@@ -256,6 +260,8 @@ + #define PCI_DEVICE_ID_INTEL_CANNONLAKE_H_SMBUS 0xa323 + #define PCI_DEVICE_ID_INTEL_COMETLAKE_V_SMBUS 0xa3a3 + #define PCI_DEVICE_ID_INTEL_METEOR_LAKE_SOC_S_SMBUS 0xae22 ++#define PCI_DEVICE_ID_INTEL_PANTHER_LAKE_H_SMBUS 0xe322 ++#define PCI_DEVICE_ID_INTEL_PANTHER_LAKE_P_SMBUS 0xe422 + + struct i801_mux_config { + char *gpio_chip; +@@ -1046,6 +1052,9 @@ static const struct pci_device_id i801_ids[] = { + { PCI_DEVICE_DATA(INTEL, METEOR_LAKE_SOC_S_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, METEOR_LAKE_PCH_S_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, BIRCH_STREAM_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, ++ { PCI_DEVICE_DATA(INTEL, ARROW_LAKE_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, ++ { PCI_DEVICE_DATA(INTEL, PANTHER_LAKE_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, ++ { PCI_DEVICE_DATA(INTEL, PANTHER_LAKE_P_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { 0, } + }; + +diff --git a/drivers/i2c/busses/i2c-xgene-slimpro.c b/drivers/i2c/busses/i2c-xgene-slimpro.c +index fbc1ffbd2fa7d6..658396c9eeabf9 100644 +--- a/drivers/i2c/busses/i2c-xgene-slimpro.c ++++ b/drivers/i2c/busses/i2c-xgene-slimpro.c +@@ -91,14 +91,6 @@ + + #define SLIMPRO_IIC_MSG_DWORD_COUNT 3 + +-/* PCC related defines */ +-#define PCC_SIGNATURE 0x50424300 +-#define PCC_STS_CMD_COMPLETE BIT(0) +-#define PCC_STS_SCI_DOORBELL BIT(1) +-#define PCC_STS_ERR BIT(2) +-#define PCC_STS_PLAT_NOTIFY BIT(3) +-#define PCC_CMD_GENERATE_DB_INT BIT(15) +- + struct slimpro_i2c_dev { + struct i2c_adapter adapter; + struct device *dev; +@@ -160,11 +152,11 @@ static void slimpro_i2c_pcc_rx_cb(struct mbox_client *cl, void *msg) + + /* Check if platform sends interrupt */ + if (!xgene_word_tst_and_clr(&generic_comm_base->status, +- PCC_STS_SCI_DOORBELL)) ++ PCC_STATUS_SCI_DOORBELL)) + return; + + if (xgene_word_tst_and_clr(&generic_comm_base->status, +- PCC_STS_CMD_COMPLETE)) { ++ PCC_STATUS_CMD_COMPLETE)) { + msg = generic_comm_base + 1; + + /* Response message msg[1] contains the return value. */ +@@ -186,10 +178,10 @@ static void slimpro_i2c_pcc_tx_prepare(struct slimpro_i2c_dev *ctx, u32 *msg) + cpu_to_le32(PCC_SIGNATURE | ctx->mbox_idx)); + + WRITE_ONCE(generic_comm_base->command, +- cpu_to_le16(SLIMPRO_MSG_TYPE(msg[0]) | PCC_CMD_GENERATE_DB_INT)); ++ cpu_to_le16(SLIMPRO_MSG_TYPE(msg[0]) | PCC_CMD_GENERATE_DB_INTR)); + + status = le16_to_cpu(READ_ONCE(generic_comm_base->status)); +- status &= ~PCC_STS_CMD_COMPLETE; ++ status &= ~PCC_STATUS_CMD_COMPLETE; + WRITE_ONCE(generic_comm_base->status, cpu_to_le16(status)); + + /* Copy the message to the PCC comm space */ +diff --git a/drivers/iio/adc/ad7192.c b/drivers/iio/adc/ad7192.c +index b64fd365f83fb8..fa6810aa6a4a7a 100644 +--- a/drivers/iio/adc/ad7192.c ++++ b/drivers/iio/adc/ad7192.c +@@ -16,7 +16,9 @@ + #include + #include + #include +-#include ++#include ++#include ++#include + + #include + #include +@@ -360,19 +362,19 @@ static inline bool ad7192_valid_external_frequency(u32 freq) + freq <= AD7192_EXT_FREQ_MHZ_MAX); + } + +-static int ad7192_of_clock_select(struct ad7192_state *st) ++static int ad7192_clock_select(struct ad7192_state *st) + { +- struct device_node *np = st->sd.spi->dev.of_node; ++ struct device *dev = &st->sd.spi->dev; + unsigned int clock_sel; + + clock_sel = AD7192_CLK_INT; + + /* use internal clock */ + if (!st->mclk) { +- if (of_property_read_bool(np, "adi,int-clock-output-enable")) ++ if (device_property_read_bool(dev, "adi,int-clock-output-enable")) + clock_sel = AD7192_CLK_INT_CO; + } else { +- if (of_property_read_bool(np, "adi,clock-xtal")) ++ if (device_property_read_bool(dev, "adi,clock-xtal")) + clock_sel = AD7192_CLK_EXT_MCLK1_2; + else + clock_sel = AD7192_CLK_EXT_MCLK2; +@@ -381,7 +383,7 @@ static int ad7192_of_clock_select(struct ad7192_state *st) + return clock_sel; + } + +-static int ad7192_setup(struct iio_dev *indio_dev, struct device_node *np) ++static int ad7192_setup(struct iio_dev *indio_dev, struct device *dev) + { + struct ad7192_state *st = iio_priv(indio_dev); + bool rej60_en, refin2_en; +@@ -403,7 +405,7 @@ static int ad7192_setup(struct iio_dev *indio_dev, struct device_node *np) + id &= AD7192_ID_MASK; + + if (id != st->chip_info->chip_id) +- dev_warn(&st->sd.spi->dev, "device ID query failed (0x%X != 0x%X)\n", ++ dev_warn(dev, "device ID query failed (0x%X != 0x%X)\n", + id, st->chip_info->chip_id); + + st->mode = AD7192_MODE_SEL(AD7192_MODE_IDLE) | +@@ -412,31 +414,31 @@ static int ad7192_setup(struct iio_dev *indio_dev, struct device_node *np) + + st->conf = AD7192_CONF_GAIN(0); + +- rej60_en = of_property_read_bool(np, "adi,rejection-60-Hz-enable"); ++ rej60_en = device_property_read_bool(dev, "adi,rejection-60-Hz-enable"); + if (rej60_en) + st->mode |= AD7192_MODE_REJ60; + +- refin2_en = of_property_read_bool(np, "adi,refin2-pins-enable"); ++ refin2_en = device_property_read_bool(dev, "adi,refin2-pins-enable"); + if (refin2_en && st->chip_info->chip_id != CHIPID_AD7195) + st->conf |= AD7192_CONF_REFSEL; + + st->conf &= ~AD7192_CONF_CHOP; + st->f_order = AD7192_NO_SYNC_FILTER; + +- buf_en = of_property_read_bool(np, "adi,buffer-enable"); ++ buf_en = device_property_read_bool(dev, "adi,buffer-enable"); + if (buf_en) + st->conf |= AD7192_CONF_BUF; + +- bipolar = of_property_read_bool(np, "bipolar"); ++ bipolar = device_property_read_bool(dev, "bipolar"); + if (!bipolar) + st->conf |= AD7192_CONF_UNIPOLAR; + +- burnout_curr_en = of_property_read_bool(np, +- "adi,burnout-currents-enable"); ++ burnout_curr_en = device_property_read_bool(dev, ++ "adi,burnout-currents-enable"); + if (burnout_curr_en && buf_en) { + st->conf |= AD7192_CONF_BURN; + } else if (burnout_curr_en) { +- dev_warn(&st->sd.spi->dev, ++ dev_warn(dev, + "Can't enable burnout currents: see CHOP or buffer\n"); + } + +@@ -1036,9 +1038,10 @@ static int ad7192_probe(struct spi_device *spi) + } + st->int_vref_mv = ret / 1000; + +- st->chip_info = of_device_get_match_data(&spi->dev); ++ st->chip_info = spi_get_device_match_data(spi); + if (!st->chip_info) +- st->chip_info = (void *)spi_get_device_id(spi)->driver_data; ++ return -ENODEV; ++ + indio_dev->name = st->chip_info->name; + indio_dev->modes = INDIO_DIRECT_MODE; + +@@ -1065,7 +1068,7 @@ static int ad7192_probe(struct spi_device *spi) + if (IS_ERR(st->mclk)) + return PTR_ERR(st->mclk); + +- st->clock_sel = ad7192_of_clock_select(st); ++ st->clock_sel = ad7192_clock_select(st); + + if (st->clock_sel == AD7192_CLK_EXT_MCLK1_2 || + st->clock_sel == AD7192_CLK_EXT_MCLK2) { +@@ -1077,7 +1080,7 @@ static int ad7192_probe(struct spi_device *spi) + } + } + +- ret = ad7192_setup(indio_dev, spi->dev.of_node); ++ ret = ad7192_setup(indio_dev, &spi->dev); + if (ret) + return ret; + +diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c +index e836c9c477f675..c6053e82ecf6f3 100644 +--- a/drivers/infiniband/core/uverbs_cmd.c ++++ b/drivers/infiniband/core/uverbs_cmd.c +@@ -161,7 +161,7 @@ static const void __user *uverbs_request_next_ptr(struct uverbs_req_iter *iter, + { + const void __user *res = iter->cur; + +- if (iter->cur + len > iter->end) ++ if (len > iter->end - iter->cur) + return (void __force __user *)ERR_PTR(-ENOSPC); + iter->cur += len; + return res; +@@ -2009,11 +2009,13 @@ static int ib_uverbs_post_send(struct uverbs_attr_bundle *attrs) + ret = uverbs_request_start(attrs, &iter, &cmd, sizeof(cmd)); + if (ret) + return ret; +- wqes = uverbs_request_next_ptr(&iter, cmd.wqe_size * cmd.wr_count); ++ wqes = uverbs_request_next_ptr(&iter, size_mul(cmd.wqe_size, ++ cmd.wr_count)); + if (IS_ERR(wqes)) + return PTR_ERR(wqes); +- sgls = uverbs_request_next_ptr( +- &iter, cmd.sge_count * sizeof(struct ib_uverbs_sge)); ++ sgls = uverbs_request_next_ptr(&iter, ++ size_mul(cmd.sge_count, ++ sizeof(struct ib_uverbs_sge))); + if (IS_ERR(sgls)) + return PTR_ERR(sgls); + ret = uverbs_request_finish(&iter); +@@ -2199,11 +2201,11 @@ ib_uverbs_unmarshall_recv(struct uverbs_req_iter *iter, u32 wr_count, + if (wqe_size < sizeof(struct ib_uverbs_recv_wr)) + return ERR_PTR(-EINVAL); + +- wqes = uverbs_request_next_ptr(iter, wqe_size * wr_count); ++ wqes = uverbs_request_next_ptr(iter, size_mul(wqe_size, wr_count)); + if (IS_ERR(wqes)) + return ERR_CAST(wqes); +- sgls = uverbs_request_next_ptr( +- iter, sge_count * sizeof(struct ib_uverbs_sge)); ++ sgls = uverbs_request_next_ptr(iter, size_mul(sge_count, ++ sizeof(struct ib_uverbs_sge))); + if (IS_ERR(sgls)) + return ERR_CAST(sgls); + ret = uverbs_request_finish(iter); +diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c +index df589726060144..13c65ec5825687 100644 +--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c ++++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c +@@ -147,7 +147,7 @@ int bnxt_re_query_device(struct ib_device *ibdev, + + ib_attr->vendor_id = rdev->en_dev->pdev->vendor; + ib_attr->vendor_part_id = rdev->en_dev->pdev->device; +- ib_attr->hw_ver = rdev->en_dev->pdev->subsystem_device; ++ ib_attr->hw_ver = rdev->en_dev->pdev->revision; + ib_attr->max_qp = dev_attr->max_qp; + ib_attr->max_qp_wr = dev_attr->max_qp_wqes; + ib_attr->device_cap_flags = +@@ -992,23 +992,22 @@ static int bnxt_re_setup_swqe_size(struct bnxt_re_qp *qp, + align = sizeof(struct sq_send_hdr); + ilsize = ALIGN(init_attr->cap.max_inline_data, align); + +- sq->wqe_size = bnxt_re_get_wqe_size(ilsize, sq->max_sge); +- if (sq->wqe_size > bnxt_re_get_swqe_size(dev_attr->max_qp_sges)) +- return -EINVAL; +- /* For gen p4 and gen p5 backward compatibility mode +- * wqe size is fixed to 128 bytes ++ /* For gen p4 and gen p5 fixed wqe compatibility mode ++ * wqe size is fixed to 128 bytes - ie 6 SGEs + */ +- if (sq->wqe_size < bnxt_re_get_swqe_size(dev_attr->max_qp_sges) && +- qplqp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC) +- sq->wqe_size = bnxt_re_get_swqe_size(dev_attr->max_qp_sges); ++ if (qplqp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC) { ++ sq->wqe_size = bnxt_re_get_swqe_size(BNXT_STATIC_MAX_SGE); ++ sq->max_sge = BNXT_STATIC_MAX_SGE; ++ } else { ++ sq->wqe_size = bnxt_re_get_wqe_size(ilsize, sq->max_sge); ++ if (sq->wqe_size > bnxt_re_get_swqe_size(dev_attr->max_qp_sges)) ++ return -EINVAL; ++ } + + if (init_attr->cap.max_inline_data) { + qplqp->max_inline_data = sq->wqe_size - + sizeof(struct sq_send_hdr); + init_attr->cap.max_inline_data = qplqp->max_inline_data; +- if (qplqp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC) +- sq->max_sge = qplqp->max_inline_data / +- sizeof(struct sq_sge); + } + + return 0; +@@ -1154,6 +1153,7 @@ static struct bnxt_re_qp *bnxt_re_create_shadow_qp + /* Shadow QP SQ depth should be same as QP1 RQ depth */ + qp->qplib_qp.sq.wqe_size = bnxt_re_get_wqe_size(0, 6); + qp->qplib_qp.sq.max_wqe = qp1_qp->rq.max_wqe; ++ qp->qplib_qp.sq.max_sw_wqe = qp1_qp->rq.max_wqe; + qp->qplib_qp.sq.max_sge = 2; + /* Q full delta can be 1 since it is internal QP */ + qp->qplib_qp.sq.q_full_delta = 1; +@@ -1165,6 +1165,7 @@ static struct bnxt_re_qp *bnxt_re_create_shadow_qp + + qp->qplib_qp.rq.wqe_size = bnxt_re_get_rwqe_size(6); + qp->qplib_qp.rq.max_wqe = qp1_qp->rq.max_wqe; ++ qp->qplib_qp.rq.max_sw_wqe = qp1_qp->rq.max_wqe; + qp->qplib_qp.rq.max_sge = qp1_qp->rq.max_sge; + /* Q full delta can be 1 since it is internal QP */ + qp->qplib_qp.rq.q_full_delta = 1; +@@ -1226,6 +1227,7 @@ static int bnxt_re_init_rq_attr(struct bnxt_re_qp *qp, + */ + entries = bnxt_re_init_depth(init_attr->cap.max_recv_wr + 1, uctx); + rq->max_wqe = min_t(u32, entries, dev_attr->max_qp_wqes + 1); ++ rq->max_sw_wqe = rq->max_wqe; + rq->q_full_delta = 0; + rq->sg_info.pgsize = PAGE_SIZE; + rq->sg_info.pgshft = PAGE_SHIFT; +@@ -1285,6 +1287,7 @@ static int bnxt_re_init_sq_attr(struct bnxt_re_qp *qp, + 0 : BNXT_QPLIB_RESERVED_QP_WRS; + entries = bnxt_re_init_depth(entries + diff + 1, uctx); + sq->max_wqe = min_t(u32, entries, dev_attr->max_qp_wqes + diff + 1); ++ sq->max_sw_wqe = bnxt_qplib_get_depth(sq, qplqp->wqe_mode, true); + sq->q_full_delta = diff + 1; + /* + * Reserving one slot for Phantom WQE. Application can +@@ -2055,18 +2058,20 @@ int bnxt_re_modify_qp(struct ib_qp *ib_qp, struct ib_qp_attr *qp_attr, + } + } + +- if (qp_attr_mask & IB_QP_PATH_MTU) { +- qp->qplib_qp.modify_flags |= +- CMDQ_MODIFY_QP_MODIFY_MASK_PATH_MTU; +- qp->qplib_qp.path_mtu = __from_ib_mtu(qp_attr->path_mtu); +- qp->qplib_qp.mtu = ib_mtu_enum_to_int(qp_attr->path_mtu); +- } else if (qp_attr->qp_state == IB_QPS_RTR) { +- qp->qplib_qp.modify_flags |= +- CMDQ_MODIFY_QP_MODIFY_MASK_PATH_MTU; +- qp->qplib_qp.path_mtu = +- __from_ib_mtu(iboe_get_mtu(rdev->netdev->mtu)); +- qp->qplib_qp.mtu = +- ib_mtu_enum_to_int(iboe_get_mtu(rdev->netdev->mtu)); ++ if (qp_attr->qp_state == IB_QPS_RTR) { ++ enum ib_mtu qpmtu; ++ ++ qpmtu = iboe_get_mtu(rdev->netdev->mtu); ++ if (qp_attr_mask & IB_QP_PATH_MTU) { ++ if (ib_mtu_enum_to_int(qp_attr->path_mtu) > ++ ib_mtu_enum_to_int(qpmtu)) ++ return -EINVAL; ++ qpmtu = qp_attr->path_mtu; ++ } ++ ++ qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_PATH_MTU; ++ qp->qplib_qp.path_mtu = __from_ib_mtu(qpmtu); ++ qp->qplib_qp.mtu = ib_mtu_enum_to_int(qpmtu); + } + + if (qp_attr_mask & IB_QP_TIMEOUT) { +@@ -2153,6 +2158,7 @@ int bnxt_re_modify_qp(struct ib_qp *ib_qp, struct ib_qp_attr *qp_attr, + entries = bnxt_re_init_depth(qp_attr->cap.max_recv_wr, uctx); + qp->qplib_qp.rq.max_wqe = + min_t(u32, entries, dev_attr->max_qp_wqes + 1); ++ qp->qplib_qp.rq.max_sw_wqe = qp->qplib_qp.rq.max_wqe; + qp->qplib_qp.rq.q_full_delta = qp->qplib_qp.rq.max_wqe - + qp_attr->cap.max_recv_wr; + qp->qplib_qp.rq.max_sge = qp_attr->cap.max_recv_sge; +@@ -2710,7 +2716,8 @@ static int bnxt_re_post_send_shadow_qp(struct bnxt_re_dev *rdev, + wr = wr->next; + } + bnxt_qplib_post_send_db(&qp->qplib_qp); +- bnxt_ud_qp_hw_stall_workaround(qp); ++ if (!bnxt_qplib_is_chip_gen_p5_p7(qp->rdev->chip_ctx)) ++ bnxt_ud_qp_hw_stall_workaround(qp); + spin_unlock_irqrestore(&qp->sq_lock, flags); + return rc; + } +@@ -2822,7 +2829,8 @@ int bnxt_re_post_send(struct ib_qp *ib_qp, const struct ib_send_wr *wr, + wr = wr->next; + } + bnxt_qplib_post_send_db(&qp->qplib_qp); +- bnxt_ud_qp_hw_stall_workaround(qp); ++ if (!bnxt_qplib_is_chip_gen_p5_p7(qp->rdev->chip_ctx)) ++ bnxt_ud_qp_hw_stall_workaround(qp); + spin_unlock_irqrestore(&qp->sq_lock, flags); + + return rc; +@@ -4167,9 +4175,6 @@ int bnxt_re_alloc_ucontext(struct ib_ucontext *ctx, struct ib_udata *udata) + resp.cqe_sz = sizeof(struct cq_base); + resp.max_cqd = dev_attr->max_cq_wqes; + +- resp.comp_mask |= BNXT_RE_UCNTX_CMASK_HAVE_MODE; +- resp.mode = rdev->chip_ctx->modes.wqe_mode; +- + if (rdev->chip_ctx->modes.db_push) + resp.comp_mask |= BNXT_RE_UCNTX_CMASK_WC_DPI_ENABLED; + +diff --git a/drivers/infiniband/hw/bnxt_re/main.c b/drivers/infiniband/hw/bnxt_re/main.c +index 0373d0e9db6329..c7e51cc2ea2687 100644 +--- a/drivers/infiniband/hw/bnxt_re/main.c ++++ b/drivers/infiniband/hw/bnxt_re/main.c +@@ -128,13 +128,13 @@ static void bnxt_re_set_db_offset(struct bnxt_re_dev *rdev) + } + } + +-static void bnxt_re_set_drv_mode(struct bnxt_re_dev *rdev, u8 mode) ++static void bnxt_re_set_drv_mode(struct bnxt_re_dev *rdev) + { + struct bnxt_qplib_chip_ctx *cctx; + + cctx = rdev->chip_ctx; +- cctx->modes.wqe_mode = bnxt_qplib_is_chip_gen_p5_p7(rdev->chip_ctx) ? +- mode : BNXT_QPLIB_WQE_MODE_STATIC; ++ cctx->modes.wqe_mode = bnxt_qplib_is_chip_gen_p7(rdev->chip_ctx) ? ++ BNXT_QPLIB_WQE_MODE_VARIABLE : BNXT_QPLIB_WQE_MODE_STATIC; + if (bnxt_re_hwrm_qcaps(rdev)) + dev_err(rdev_to_dev(rdev), + "Failed to query hwrm qcaps\n"); +@@ -155,7 +155,7 @@ static void bnxt_re_destroy_chip_ctx(struct bnxt_re_dev *rdev) + kfree(chip_ctx); + } + +-static int bnxt_re_setup_chip_ctx(struct bnxt_re_dev *rdev, u8 wqe_mode) ++static int bnxt_re_setup_chip_ctx(struct bnxt_re_dev *rdev) + { + struct bnxt_qplib_chip_ctx *chip_ctx; + struct bnxt_en_dev *en_dev; +@@ -177,7 +177,7 @@ static int bnxt_re_setup_chip_ctx(struct bnxt_re_dev *rdev, u8 wqe_mode) + rdev->qplib_res.dattr = &rdev->dev_attr; + rdev->qplib_res.is_vf = BNXT_EN_VF(en_dev); + +- bnxt_re_set_drv_mode(rdev, wqe_mode); ++ bnxt_re_set_drv_mode(rdev); + + bnxt_re_set_db_offset(rdev); + rc = bnxt_qplib_map_db_bar(&rdev->qplib_res); +@@ -1440,7 +1440,7 @@ static void bnxt_re_worker(struct work_struct *work) + schedule_delayed_work(&rdev->worker, msecs_to_jiffies(30000)); + } + +-static int bnxt_re_dev_init(struct bnxt_re_dev *rdev, u8 wqe_mode) ++static int bnxt_re_dev_init(struct bnxt_re_dev *rdev) + { + struct bnxt_re_ring_attr rattr = {}; + struct bnxt_qplib_creq_ctx *creq; +@@ -1458,7 +1458,7 @@ static int bnxt_re_dev_init(struct bnxt_re_dev *rdev, u8 wqe_mode) + } + set_bit(BNXT_RE_FLAG_NETDEV_REGISTERED, &rdev->flags); + +- rc = bnxt_re_setup_chip_ctx(rdev, wqe_mode); ++ rc = bnxt_re_setup_chip_ctx(rdev); + if (rc) { + bnxt_unregister_dev(rdev->en_dev); + clear_bit(BNXT_RE_FLAG_NETDEV_REGISTERED, &rdev->flags); +@@ -1609,7 +1609,7 @@ static int bnxt_re_dev_init(struct bnxt_re_dev *rdev, u8 wqe_mode) + return rc; + } + +-static int bnxt_re_add_device(struct auxiliary_device *adev, u8 wqe_mode) ++static int bnxt_re_add_device(struct auxiliary_device *adev) + { + struct bnxt_aux_priv *aux_priv = + container_of(adev, struct bnxt_aux_priv, aux_dev); +@@ -1626,7 +1626,7 @@ static int bnxt_re_add_device(struct auxiliary_device *adev, u8 wqe_mode) + goto exit; + } + +- rc = bnxt_re_dev_init(rdev, wqe_mode); ++ rc = bnxt_re_dev_init(rdev); + if (rc) + goto re_dev_dealloc; + +@@ -1756,7 +1756,8 @@ static int bnxt_re_probe(struct auxiliary_device *adev, + int rc; + + mutex_lock(&bnxt_re_mutex); +- rc = bnxt_re_add_device(adev, BNXT_QPLIB_WQE_MODE_STATIC); ++ ++ rc = bnxt_re_add_device(adev); + if (rc) { + mutex_unlock(&bnxt_re_mutex); + return rc; +diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.c b/drivers/infiniband/hw/bnxt_re/qplib_fp.c +index b624c255eee6fa..871a49315c880f 100644 +--- a/drivers/infiniband/hw/bnxt_re/qplib_fp.c ++++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.c +@@ -639,13 +639,6 @@ int bnxt_qplib_create_srq(struct bnxt_qplib_res *res, + rc = bnxt_qplib_alloc_init_hwq(&srq->hwq, &hwq_attr); + if (rc) + return rc; +- +- srq->swq = kcalloc(srq->hwq.max_elements, sizeof(*srq->swq), +- GFP_KERNEL); +- if (!srq->swq) { +- rc = -ENOMEM; +- goto fail; +- } + srq->dbinfo.flags = 0; + bnxt_qplib_rcfw_cmd_prep((struct cmdq_base *)&req, + CMDQ_BASE_OPCODE_CREATE_SRQ, +@@ -674,9 +667,17 @@ int bnxt_qplib_create_srq(struct bnxt_qplib_res *res, + spin_lock_init(&srq->lock); + srq->start_idx = 0; + srq->last_idx = srq->hwq.max_elements - 1; +- for (idx = 0; idx < srq->hwq.max_elements; idx++) +- srq->swq[idx].next_idx = idx + 1; +- srq->swq[srq->last_idx].next_idx = -1; ++ if (!srq->hwq.is_user) { ++ srq->swq = kcalloc(srq->hwq.max_elements, sizeof(*srq->swq), ++ GFP_KERNEL); ++ if (!srq->swq) { ++ rc = -ENOMEM; ++ goto fail; ++ } ++ for (idx = 0; idx < srq->hwq.max_elements; idx++) ++ srq->swq[idx].next_idx = idx + 1; ++ srq->swq[srq->last_idx].next_idx = -1; ++ } + + srq->id = le32_to_cpu(resp.xid); + srq->dbinfo.hwq = &srq->hwq; +@@ -806,13 +807,13 @@ static int bnxt_qplib_alloc_init_swq(struct bnxt_qplib_q *que) + { + int indx; + +- que->swq = kcalloc(que->max_wqe, sizeof(*que->swq), GFP_KERNEL); ++ que->swq = kcalloc(que->max_sw_wqe, sizeof(*que->swq), GFP_KERNEL); + if (!que->swq) + return -ENOMEM; + + que->swq_start = 0; +- que->swq_last = que->max_wqe - 1; +- for (indx = 0; indx < que->max_wqe; indx++) ++ que->swq_last = que->max_sw_wqe - 1; ++ for (indx = 0; indx < que->max_sw_wqe; indx++) + que->swq[indx].next_idx = indx + 1; + que->swq[que->swq_last].next_idx = 0; /* Make it circular */ + que->swq_last = 0; +@@ -848,7 +849,7 @@ int bnxt_qplib_create_qp1(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) + hwq_attr.res = res; + hwq_attr.sginfo = &sq->sg_info; + hwq_attr.stride = sizeof(struct sq_sge); +- hwq_attr.depth = bnxt_qplib_get_depth(sq); ++ hwq_attr.depth = bnxt_qplib_get_depth(sq, qp->wqe_mode, false); + hwq_attr.type = HWQ_TYPE_QUEUE; + rc = bnxt_qplib_alloc_init_hwq(&sq->hwq, &hwq_attr); + if (rc) +@@ -876,7 +877,7 @@ int bnxt_qplib_create_qp1(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) + hwq_attr.res = res; + hwq_attr.sginfo = &rq->sg_info; + hwq_attr.stride = sizeof(struct sq_sge); +- hwq_attr.depth = bnxt_qplib_get_depth(rq); ++ hwq_attr.depth = bnxt_qplib_get_depth(rq, qp->wqe_mode, false); + hwq_attr.type = HWQ_TYPE_QUEUE; + rc = bnxt_qplib_alloc_init_hwq(&rq->hwq, &hwq_attr); + if (rc) +@@ -980,9 +981,7 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) + u32 tbl_indx; + u16 nsge; + +- if (res->dattr) +- qp->dev_cap_flags = res->dattr->dev_cap_flags; +- ++ qp->is_host_msn_tbl = _is_host_msn_table(res->dattr->dev_cap_flags2); + sq->dbinfo.flags = 0; + bnxt_qplib_rcfw_cmd_prep((struct cmdq_base *)&req, + CMDQ_BASE_OPCODE_CREATE_QP, +@@ -999,7 +998,7 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) + sizeof(struct sq_psn_search_ext) : + sizeof(struct sq_psn_search); + +- if (BNXT_RE_HW_RETX(qp->dev_cap_flags)) { ++ if (qp->is_host_msn_tbl) { + psn_sz = sizeof(struct sq_msn_search); + qp->msn = 0; + } +@@ -1008,13 +1007,18 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) + hwq_attr.res = res; + hwq_attr.sginfo = &sq->sg_info; + hwq_attr.stride = sizeof(struct sq_sge); +- hwq_attr.depth = bnxt_qplib_get_depth(sq); ++ hwq_attr.depth = bnxt_qplib_get_depth(sq, qp->wqe_mode, true); + hwq_attr.aux_stride = psn_sz; + hwq_attr.aux_depth = psn_sz ? bnxt_qplib_set_sq_size(sq, qp->wqe_mode) + : 0; + /* Update msn tbl size */ +- if (BNXT_RE_HW_RETX(qp->dev_cap_flags) && psn_sz) { +- hwq_attr.aux_depth = roundup_pow_of_two(bnxt_qplib_set_sq_size(sq, qp->wqe_mode)); ++ if (qp->is_host_msn_tbl && psn_sz) { ++ if (qp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC) ++ hwq_attr.aux_depth = ++ roundup_pow_of_two(bnxt_qplib_set_sq_size(sq, qp->wqe_mode)); ++ else ++ hwq_attr.aux_depth = ++ roundup_pow_of_two(bnxt_qplib_set_sq_size(sq, qp->wqe_mode)) / 2; + qp->msn_tbl_sz = hwq_attr.aux_depth; + qp->msn = 0; + } +@@ -1024,13 +1028,14 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) + if (rc) + return rc; + +- rc = bnxt_qplib_alloc_init_swq(sq); +- if (rc) +- goto fail_sq; +- +- if (psn_sz) +- bnxt_qplib_init_psn_ptr(qp, psn_sz); ++ if (!sq->hwq.is_user) { ++ rc = bnxt_qplib_alloc_init_swq(sq); ++ if (rc) ++ goto fail_sq; + ++ if (psn_sz) ++ bnxt_qplib_init_psn_ptr(qp, psn_sz); ++ } + req.sq_size = cpu_to_le32(bnxt_qplib_set_sq_size(sq, qp->wqe_mode)); + pbl = &sq->hwq.pbl[PBL_LVL_0]; + req.sq_pbl = cpu_to_le64(pbl->pg_map_arr[0]); +@@ -1049,16 +1054,18 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) + hwq_attr.res = res; + hwq_attr.sginfo = &rq->sg_info; + hwq_attr.stride = sizeof(struct sq_sge); +- hwq_attr.depth = bnxt_qplib_get_depth(rq); ++ hwq_attr.depth = bnxt_qplib_get_depth(rq, qp->wqe_mode, false); + hwq_attr.aux_stride = 0; + hwq_attr.aux_depth = 0; + hwq_attr.type = HWQ_TYPE_QUEUE; + rc = bnxt_qplib_alloc_init_hwq(&rq->hwq, &hwq_attr); + if (rc) + goto sq_swq; +- rc = bnxt_qplib_alloc_init_swq(rq); +- if (rc) +- goto fail_rq; ++ if (!rq->hwq.is_user) { ++ rc = bnxt_qplib_alloc_init_swq(rq); ++ if (rc) ++ goto fail_rq; ++ } + + req.rq_size = cpu_to_le32(rq->max_wqe); + pbl = &rq->hwq.pbl[PBL_LVL_0]; +@@ -1154,9 +1161,11 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) + rq->dbinfo.db = qp->dpi->dbr; + rq->dbinfo.max_slot = bnxt_qplib_set_rq_max_slot(rq->wqe_size); + } ++ spin_lock_bh(&rcfw->tbl_lock); + tbl_indx = map_qp_id_to_tbl_indx(qp->id, rcfw); + rcfw->qp_tbl[tbl_indx].qp_id = qp->id; + rcfw->qp_tbl[tbl_indx].qp_handle = (void *)qp; ++ spin_unlock_bh(&rcfw->tbl_lock); + + return 0; + fail: +@@ -1638,7 +1647,7 @@ static void bnxt_qplib_fill_psn_search(struct bnxt_qplib_qp *qp, + if (!swq->psn_search) + return; + /* Handle MSN differently on cap flags */ +- if (BNXT_RE_HW_RETX(qp->dev_cap_flags)) { ++ if (qp->is_host_msn_tbl) { + bnxt_qplib_fill_msn_search(qp, wqe, swq); + return; + } +@@ -1820,7 +1829,7 @@ int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp, + } + + swq = bnxt_qplib_get_swqe(sq, &wqe_idx); +- bnxt_qplib_pull_psn_buff(qp, sq, swq, BNXT_RE_HW_RETX(qp->dev_cap_flags)); ++ bnxt_qplib_pull_psn_buff(qp, sq, swq, qp->is_host_msn_tbl); + + idx = 0; + swq->slot_idx = hwq->prod; +@@ -2010,7 +2019,7 @@ int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp, + rc = -EINVAL; + goto done; + } +- if (!BNXT_RE_HW_RETX(qp->dev_cap_flags) || msn_update) { ++ if (!qp->is_host_msn_tbl || msn_update) { + swq->next_psn = sq->psn & BTH_PSN_MASK; + bnxt_qplib_fill_psn_search(qp, wqe, swq); + } +@@ -2491,7 +2500,7 @@ static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq, + } + sq = &qp->sq; + +- cqe_sq_cons = le16_to_cpu(hwcqe->sq_cons_idx) % sq->max_wqe; ++ cqe_sq_cons = le16_to_cpu(hwcqe->sq_cons_idx) % sq->max_sw_wqe; + if (qp->sq.flushed) { + dev_dbg(&cq->hwq.pdev->dev, + "%s: QP in Flush QP = %p\n", __func__, qp); +@@ -2534,10 +2543,12 @@ static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq, + bnxt_qplib_add_flush_qp(qp); + } else { + /* Before we complete, do WA 9060 */ +- if (do_wa9060(qp, cq, cq_cons, sq->swq_last, +- cqe_sq_cons)) { +- *lib_qp = qp; +- goto out; ++ if (!bnxt_qplib_is_chip_gen_p5_p7(qp->cctx)) { ++ if (do_wa9060(qp, cq, cq_cons, sq->swq_last, ++ cqe_sq_cons)) { ++ *lib_qp = qp; ++ goto out; ++ } + } + if (swq->flags & SQ_SEND_FLAGS_SIGNAL_COMP) { + cqe->status = CQ_REQ_STATUS_OK; +@@ -2881,7 +2892,7 @@ static int bnxt_qplib_cq_process_terminal(struct bnxt_qplib_cq *cq, + cqe_cons = le16_to_cpu(hwcqe->sq_cons_idx); + if (cqe_cons == 0xFFFF) + goto do_rq; +- cqe_cons %= sq->max_wqe; ++ cqe_cons %= sq->max_sw_wqe; + + if (qp->sq.flushed) { + dev_dbg(&cq->hwq.pdev->dev, +diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.h b/drivers/infiniband/hw/bnxt_re/qplib_fp.h +index 5d4c49089a20f4..b5c53e864fbb39 100644 +--- a/drivers/infiniband/hw/bnxt_re/qplib_fp.h ++++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.h +@@ -113,7 +113,6 @@ struct bnxt_qplib_sge { + u32 size; + }; + +-#define BNXT_QPLIB_QP_MAX_SGL 6 + struct bnxt_qplib_swq { + u64 wr_id; + int next_idx; +@@ -153,7 +152,7 @@ struct bnxt_qplib_swqe { + #define BNXT_QPLIB_SWQE_FLAGS_UC_FENCE BIT(2) + #define BNXT_QPLIB_SWQE_FLAGS_SOLICIT_EVENT BIT(3) + #define BNXT_QPLIB_SWQE_FLAGS_INLINE BIT(4) +- struct bnxt_qplib_sge sg_list[BNXT_QPLIB_QP_MAX_SGL]; ++ struct bnxt_qplib_sge sg_list[BNXT_VAR_MAX_SGE]; + int num_sge; + /* Max inline data is 96 bytes */ + u32 inline_len; +@@ -251,6 +250,7 @@ struct bnxt_qplib_q { + struct bnxt_qplib_db_info dbinfo; + struct bnxt_qplib_sg_info sg_info; + u32 max_wqe; ++ u32 max_sw_wqe; + u16 wqe_size; + u16 q_full_delta; + u16 max_sge; +@@ -340,7 +340,7 @@ struct bnxt_qplib_qp { + struct list_head rq_flush; + u32 msn; + u32 msn_tbl_sz; +- u16 dev_cap_flags; ++ bool is_host_msn_tbl; + }; + + #define BNXT_QPLIB_MAX_CQE_ENTRY_SIZE sizeof(struct cq_base) +@@ -585,15 +585,22 @@ static inline void bnxt_qplib_swq_mod_start(struct bnxt_qplib_q *que, u32 idx) + que->swq_start = que->swq[idx].next_idx; + } + +-static inline u32 bnxt_qplib_get_depth(struct bnxt_qplib_q *que) ++static inline u32 bnxt_qplib_get_depth(struct bnxt_qplib_q *que, u8 wqe_mode, bool is_sq) + { +- return (que->wqe_size * que->max_wqe) / sizeof(struct sq_sge); ++ u32 slots; ++ ++ /* Queue depth is the number of slots. */ ++ slots = (que->wqe_size * que->max_wqe) / sizeof(struct sq_sge); ++ /* For variable WQE mode, need to align the slots to 256 */ ++ if (wqe_mode == BNXT_QPLIB_WQE_MODE_VARIABLE && is_sq) ++ slots = ALIGN(slots, BNXT_VAR_MAX_SLOT_ALIGN); ++ return slots; + } + + static inline u32 bnxt_qplib_set_sq_size(struct bnxt_qplib_q *que, u8 wqe_mode) + { + return (wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC) ? +- que->max_wqe : bnxt_qplib_get_depth(que); ++ que->max_wqe : bnxt_qplib_get_depth(que, wqe_mode, true); + } + + static inline u32 bnxt_qplib_set_sq_max_slot(u8 wqe_mode) +diff --git a/drivers/infiniband/hw/bnxt_re/qplib_res.h b/drivers/infiniband/hw/bnxt_re/qplib_res.h +index f9e7aa3757cfb2..c2152122a4329d 100644 +--- a/drivers/infiniband/hw/bnxt_re/qplib_res.h ++++ b/drivers/infiniband/hw/bnxt_re/qplib_res.h +@@ -523,6 +523,12 @@ static inline bool _is_hw_retx_supported(u16 dev_cap_flags) + + #define BNXT_RE_HW_RETX(a) _is_hw_retx_supported((a)) + ++static inline bool _is_host_msn_table(u16 dev_cap_ext_flags2) ++{ ++ return (dev_cap_ext_flags2 & CREQ_QUERY_FUNC_RESP_SB_REQ_RETRANSMISSION_SUPPORT_MASK) == ++ CREQ_QUERY_FUNC_RESP_SB_REQ_RETRANSMISSION_SUPPORT_HOST_MSN_TABLE; ++} ++ + static inline u8 bnxt_qplib_dbr_pacing_en(struct bnxt_qplib_chip_ctx *cctx) + { + return cctx->modes.dbr_pacing; +diff --git a/drivers/infiniband/hw/bnxt_re/qplib_sp.c b/drivers/infiniband/hw/bnxt_re/qplib_sp.c +index 0b98577cd7082e..74c3f6b26c4d3a 100644 +--- a/drivers/infiniband/hw/bnxt_re/qplib_sp.c ++++ b/drivers/infiniband/hw/bnxt_re/qplib_sp.c +@@ -95,11 +95,13 @@ int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw, + struct bnxt_qplib_cmdqmsg msg = {}; + struct creq_query_func_resp_sb *sb; + struct bnxt_qplib_rcfw_sbuf sbuf; ++ struct bnxt_qplib_chip_ctx *cctx; + struct cmdq_query_func req = {}; + u8 *tqm_alloc; + int i, rc; + u32 temp; + ++ cctx = rcfw->res->cctx; + bnxt_qplib_rcfw_cmd_prep((struct cmdq_base *)&req, + CMDQ_BASE_OPCODE_QUERY_FUNC, + sizeof(req)); +@@ -127,14 +129,21 @@ int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw, + attr->max_qp_init_rd_atom = + sb->max_qp_init_rd_atom > BNXT_QPLIB_MAX_OUT_RD_ATOM ? + BNXT_QPLIB_MAX_OUT_RD_ATOM : sb->max_qp_init_rd_atom; +- attr->max_qp_wqes = le16_to_cpu(sb->max_qp_wr); +- /* +- * 128 WQEs needs to be reserved for the HW (8916). Prevent +- * reporting the max number +- */ +- attr->max_qp_wqes -= BNXT_QPLIB_RESERVED_QP_WRS + 1; +- attr->max_qp_sges = bnxt_qplib_is_chip_gen_p5_p7(rcfw->res->cctx) ? +- 6 : sb->max_sge; ++ attr->max_qp_wqes = le16_to_cpu(sb->max_qp_wr) - 1; ++ if (!bnxt_qplib_is_chip_gen_p5_p7(rcfw->res->cctx)) { ++ /* ++ * 128 WQEs needs to be reserved for the HW (8916). Prevent ++ * reporting the max number on legacy devices ++ */ ++ attr->max_qp_wqes -= BNXT_QPLIB_RESERVED_QP_WRS + 1; ++ } ++ ++ /* Adjust for max_qp_wqes for variable wqe */ ++ if (cctx->modes.wqe_mode == BNXT_QPLIB_WQE_MODE_VARIABLE) ++ attr->max_qp_wqes = BNXT_VAR_MAX_WQE - 1; ++ ++ attr->max_qp_sges = cctx->modes.wqe_mode == BNXT_QPLIB_WQE_MODE_VARIABLE ? ++ min_t(u32, sb->max_sge_var_wqe, BNXT_VAR_MAX_SGE) : 6; + attr->max_cq = le32_to_cpu(sb->max_cq); + attr->max_cq_wqes = le32_to_cpu(sb->max_cqe); + if (!bnxt_qplib_is_chip_gen_p7(rcfw->res->cctx)) +@@ -165,6 +174,7 @@ int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw, + attr->max_sgid = le32_to_cpu(sb->max_gid); + attr->max_sgid = min_t(u32, BNXT_QPLIB_NUM_GIDS_SUPPORTED, 2 * attr->max_sgid); + attr->dev_cap_flags = le16_to_cpu(sb->dev_cap_flags); ++ attr->dev_cap_flags2 = le16_to_cpu(sb->dev_cap_ext_flags_2); + + bnxt_qplib_query_version(rcfw, attr->fw_ver); + +diff --git a/drivers/infiniband/hw/bnxt_re/qplib_sp.h b/drivers/infiniband/hw/bnxt_re/qplib_sp.h +index 755765e68eaab2..aeacd0a9a92cc4 100644 +--- a/drivers/infiniband/hw/bnxt_re/qplib_sp.h ++++ b/drivers/infiniband/hw/bnxt_re/qplib_sp.h +@@ -40,6 +40,7 @@ + #ifndef __BNXT_QPLIB_SP_H__ + #define __BNXT_QPLIB_SP_H__ + ++#include + #define BNXT_QPLIB_RESERVED_QP_WRS 128 + + struct bnxt_qplib_dev_attr { +@@ -73,6 +74,7 @@ struct bnxt_qplib_dev_attr { + u8 tqm_alloc_reqs[MAX_TQM_ALLOC_REQ]; + bool is_atomic; + u16 dev_cap_flags; ++ u16 dev_cap_flags2; + u32 max_dpi; + }; + +@@ -351,4 +353,11 @@ int bnxt_qplib_qext_stat(struct bnxt_qplib_rcfw *rcfw, u32 fid, + int bnxt_qplib_modify_cc(struct bnxt_qplib_res *res, + struct bnxt_qplib_cc_param *cc_param); + ++#define BNXT_VAR_MAX_WQE 4352 ++#define BNXT_VAR_MAX_SLOT_ALIGN 256 ++#define BNXT_VAR_MAX_SGE 13 ++#define BNXT_RE_MAX_RQ_WQES 65536 ++ ++#define BNXT_STATIC_MAX_SGE 6 ++ + #endif /* __BNXT_QPLIB_SP_H__*/ +diff --git a/drivers/infiniband/hw/bnxt_re/roce_hsi.h b/drivers/infiniband/hw/bnxt_re/roce_hsi.h +index 2909608f4b5de4..cb4e7e19fbaf08 100644 +--- a/drivers/infiniband/hw/bnxt_re/roce_hsi.h ++++ b/drivers/infiniband/hw/bnxt_re/roce_hsi.h +@@ -2157,8 +2157,36 @@ struct creq_query_func_resp_sb { + __le32 tqm_alloc_reqs[12]; + __le32 max_dpi; + u8 max_sge_var_wqe; +- u8 reserved_8; ++ u8 dev_cap_ext_flags; ++ #define CREQ_QUERY_FUNC_RESP_SB_ATOMIC_OPS_NOT_SUPPORTED 0x1UL ++ #define CREQ_QUERY_FUNC_RESP_SB_DRV_VERSION_RGTR_SUPPORTED 0x2UL ++ #define CREQ_QUERY_FUNC_RESP_SB_CREATE_QP_BATCH_SUPPORTED 0x4UL ++ #define CREQ_QUERY_FUNC_RESP_SB_DESTROY_QP_BATCH_SUPPORTED 0x8UL ++ #define CREQ_QUERY_FUNC_RESP_SB_ROCE_STATS_EXT_CTX_SUPPORTED 0x10UL ++ #define CREQ_QUERY_FUNC_RESP_SB_CREATE_SRQ_SGE_SUPPORTED 0x20UL ++ #define CREQ_QUERY_FUNC_RESP_SB_FIXED_SIZE_WQE_DISABLED 0x40UL ++ #define CREQ_QUERY_FUNC_RESP_SB_DCN_SUPPORTED 0x80UL + __le16 max_inline_data_var_wqe; ++ __le32 start_qid; ++ u8 max_msn_table_size; ++ u8 reserved8_1; ++ __le16 dev_cap_ext_flags_2; ++ #define CREQ_QUERY_FUNC_RESP_SB_OPTIMIZE_MODIFY_QP_SUPPORTED 0x1UL ++ #define CREQ_QUERY_FUNC_RESP_SB_CHANGE_UDP_SRC_PORT_WQE_SUPPORTED 0x2UL ++ #define CREQ_QUERY_FUNC_RESP_SB_CQ_COALESCING_SUPPORTED 0x4UL ++ #define CREQ_QUERY_FUNC_RESP_SB_MEMORY_REGION_RO_SUPPORTED 0x8UL ++ #define CREQ_QUERY_FUNC_RESP_SB_REQ_RETRANSMISSION_SUPPORT_MASK 0x30UL ++ #define CREQ_QUERY_FUNC_RESP_SB_REQ_RETRANSMISSION_SUPPORT_SFT 4 ++ #define CREQ_QUERY_FUNC_RESP_SB_REQ_RETRANSMISSION_SUPPORT_HOST_PSN_TABLE (0x0UL << 4) ++ #define CREQ_QUERY_FUNC_RESP_SB_REQ_RETRANSMISSION_SUPPORT_HOST_MSN_TABLE (0x1UL << 4) ++ #define CREQ_QUERY_FUNC_RESP_SB_REQ_RETRANSMISSION_SUPPORT_IQM_MSN_TABLE (0x2UL << 4) ++ #define CREQ_QUERY_FUNC_RESP_SB_REQ_RETRANSMISSION_SUPPORT_LAST \ ++ CREQ_QUERY_FUNC_RESP_SB_REQ_RETRANSMISSION_SUPPORT_IQM_MSN_TABLE ++ __le16 max_xp_qp_size; ++ __le16 create_qp_batch_size; ++ __le16 destroy_qp_batch_size; ++ __le16 reserved16; ++ __le64 reserved64; + }; + + /* cmdq_set_func_resources (size:448b/56B) */ +diff --git a/drivers/infiniband/hw/hns/hns_roce_alloc.c b/drivers/infiniband/hw/hns/hns_roce_alloc.c +index 11a78ceae56891..950c133d4220e7 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_alloc.c ++++ b/drivers/infiniband/hw/hns/hns_roce_alloc.c +@@ -153,8 +153,7 @@ int hns_roce_get_kmem_bufs(struct hns_roce_dev *hr_dev, dma_addr_t *bufs, + return total; + } + +-int hns_roce_get_umem_bufs(struct hns_roce_dev *hr_dev, dma_addr_t *bufs, +- int buf_cnt, struct ib_umem *umem, ++int hns_roce_get_umem_bufs(dma_addr_t *bufs, int buf_cnt, struct ib_umem *umem, + unsigned int page_shift) + { + struct ib_block_iter biter; +diff --git a/drivers/infiniband/hw/hns/hns_roce_cq.c b/drivers/infiniband/hw/hns/hns_roce_cq.c +index 9b91731a620795..5e0d78f4e54548 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_cq.c ++++ b/drivers/infiniband/hw/hns/hns_roce_cq.c +@@ -133,14 +133,12 @@ static int alloc_cqc(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq) + struct hns_roce_cq_table *cq_table = &hr_dev->cq_table; + struct ib_device *ibdev = &hr_dev->ib_dev; + u64 mtts[MTT_MIN_COUNT] = {}; +- dma_addr_t dma_handle; + int ret; + +- ret = hns_roce_mtr_find(hr_dev, &hr_cq->mtr, 0, mtts, ARRAY_SIZE(mtts), +- &dma_handle); +- if (!ret) { ++ ret = hns_roce_mtr_find(hr_dev, &hr_cq->mtr, 0, mtts, ARRAY_SIZE(mtts)); ++ if (ret) { + ibdev_err(ibdev, "failed to find CQ mtr, ret = %d.\n", ret); +- return -EINVAL; ++ return ret; + } + + /* Get CQC memory HEM(Hardware Entry Memory) table */ +@@ -157,7 +155,8 @@ static int alloc_cqc(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq) + goto err_put; + } + +- ret = hns_roce_create_cqc(hr_dev, hr_cq, mtts, dma_handle); ++ ret = hns_roce_create_cqc(hr_dev, hr_cq, mtts, ++ hns_roce_get_mtr_ba(&hr_cq->mtr)); + if (ret) + goto err_xa; + +diff --git a/drivers/infiniband/hw/hns/hns_roce_device.h b/drivers/infiniband/hw/hns/hns_roce_device.h +index 21ef00fdb65631..03b6546f63cdc6 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_device.h ++++ b/drivers/infiniband/hw/hns/hns_roce_device.h +@@ -892,8 +892,7 @@ struct hns_roce_hw { + int (*rereg_write_mtpt)(struct hns_roce_dev *hr_dev, + struct hns_roce_mr *mr, int flags, + void *mb_buf); +- int (*frmr_write_mtpt)(struct hns_roce_dev *hr_dev, void *mb_buf, +- struct hns_roce_mr *mr); ++ int (*frmr_write_mtpt)(void *mb_buf, struct hns_roce_mr *mr); + int (*mw_write_mtpt)(void *mb_buf, struct hns_roce_mw *mw); + void (*write_cqc)(struct hns_roce_dev *hr_dev, + struct hns_roce_cq *hr_cq, void *mb_buf, u64 *mtts, +@@ -1129,8 +1128,13 @@ void hns_roce_cmd_use_polling(struct hns_roce_dev *hr_dev); + + /* hns roce hw need current block and next block addr from mtt */ + #define MTT_MIN_COUNT 2 ++static inline dma_addr_t hns_roce_get_mtr_ba(struct hns_roce_mtr *mtr) ++{ ++ return mtr->hem_cfg.root_ba; ++} ++ + int hns_roce_mtr_find(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr, +- u32 offset, u64 *mtt_buf, int mtt_max, u64 *base_addr); ++ u32 offset, u64 *mtt_buf, int mtt_max); + int hns_roce_mtr_create(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr, + struct hns_roce_buf_attr *buf_attr, + unsigned int page_shift, struct ib_udata *udata, +@@ -1188,7 +1192,7 @@ struct hns_roce_buf *hns_roce_buf_alloc(struct hns_roce_dev *hr_dev, u32 size, + int hns_roce_get_kmem_bufs(struct hns_roce_dev *hr_dev, dma_addr_t *bufs, + int buf_cnt, struct hns_roce_buf *buf, + unsigned int page_shift); +-int hns_roce_get_umem_bufs(struct hns_roce_dev *hr_dev, dma_addr_t *bufs, ++int hns_roce_get_umem_bufs(dma_addr_t *bufs, + int buf_cnt, struct ib_umem *umem, + unsigned int page_shift); + +diff --git a/drivers/infiniband/hw/hns/hns_roce_hem.c b/drivers/infiniband/hw/hns/hns_roce_hem.c +index 0ab514c49d5e6e..51ab6041ca91bc 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hem.c ++++ b/drivers/infiniband/hw/hns/hns_roce_hem.c +@@ -986,6 +986,7 @@ struct hns_roce_hem_item { + size_t count; /* max ba numbers */ + int start; /* start buf offset in this hem */ + int end; /* end buf offset in this hem */ ++ bool exist_bt; + }; + + /* All HEM items are linked in a tree structure */ +@@ -1014,6 +1015,7 @@ hem_list_alloc_item(struct hns_roce_dev *hr_dev, int start, int end, int count, + } + } + ++ hem->exist_bt = exist_bt; + hem->count = count; + hem->start = start; + hem->end = end; +@@ -1024,34 +1026,32 @@ hem_list_alloc_item(struct hns_roce_dev *hr_dev, int start, int end, int count, + } + + static void hem_list_free_item(struct hns_roce_dev *hr_dev, +- struct hns_roce_hem_item *hem, bool exist_bt) ++ struct hns_roce_hem_item *hem) + { +- if (exist_bt) ++ if (hem->exist_bt) + dma_free_coherent(hr_dev->dev, hem->count * BA_BYTE_LEN, + hem->addr, hem->dma_addr); + kfree(hem); + } + + static void hem_list_free_all(struct hns_roce_dev *hr_dev, +- struct list_head *head, bool exist_bt) ++ struct list_head *head) + { + struct hns_roce_hem_item *hem, *temp_hem; + + list_for_each_entry_safe(hem, temp_hem, head, list) { + list_del(&hem->list); +- hem_list_free_item(hr_dev, hem, exist_bt); ++ hem_list_free_item(hr_dev, hem); + } + } + +-static void hem_list_link_bt(struct hns_roce_dev *hr_dev, void *base_addr, +- u64 table_addr) ++static void hem_list_link_bt(void *base_addr, u64 table_addr) + { + *(u64 *)(base_addr) = table_addr; + } + + /* assign L0 table address to hem from root bt */ +-static void hem_list_assign_bt(struct hns_roce_dev *hr_dev, +- struct hns_roce_hem_item *hem, void *cpu_addr, ++static void hem_list_assign_bt(struct hns_roce_hem_item *hem, void *cpu_addr, + u64 phy_addr) + { + hem->addr = cpu_addr; +@@ -1141,6 +1141,10 @@ int hns_roce_hem_list_calc_root_ba(const struct hns_roce_buf_region *regions, + + for (i = 0; i < region_cnt; i++) { + r = (struct hns_roce_buf_region *)®ions[i]; ++ /* when r->hopnum = 0, the region should not occupy root_ba. */ ++ if (!r->hopnum) ++ continue; ++ + if (r->hopnum > 1) { + step = hem_list_calc_ba_range(r->hopnum, 1, unit); + if (step > 0) +@@ -1222,8 +1226,7 @@ static int hem_list_alloc_mid_bt(struct hns_roce_dev *hr_dev, + if (level > 1) { + pre = hem_ptrs[level - 1]; + step = (cur->start - pre->start) / step * BA_BYTE_LEN; +- hem_list_link_bt(hr_dev, pre->addr + step, +- cur->dma_addr); ++ hem_list_link_bt(pre->addr + step, cur->dma_addr); + } + } + +@@ -1235,7 +1238,7 @@ static int hem_list_alloc_mid_bt(struct hns_roce_dev *hr_dev, + + err_exit: + for (level = 1; level < hopnum; level++) +- hem_list_free_all(hr_dev, &temp_list[level], true); ++ hem_list_free_all(hr_dev, &temp_list[level]); + + return ret; + } +@@ -1276,16 +1279,26 @@ static int alloc_fake_root_bt(struct hns_roce_dev *hr_dev, void *cpu_base, + { + struct hns_roce_hem_item *hem; + ++ /* This is on the has_mtt branch, if r->hopnum ++ * is 0, there is no root_ba to reuse for the ++ * region's fake hem, so a dma_alloc request is ++ * necessary here. ++ */ + hem = hem_list_alloc_item(hr_dev, r->offset, r->offset + r->count - 1, +- r->count, false); ++ r->count, !r->hopnum); + if (!hem) + return -ENOMEM; + +- hem_list_assign_bt(hr_dev, hem, cpu_base, phy_base); ++ /* The root_ba can be reused only when r->hopnum > 0. */ ++ if (r->hopnum) ++ hem_list_assign_bt(hem, cpu_base, phy_base); + list_add(&hem->list, branch_head); + list_add(&hem->sibling, leaf_head); + +- return r->count; ++ /* If r->hopnum == 0, 0 is returned, ++ * so that the root_bt entry is not occupied. ++ */ ++ return r->hopnum ? r->count : 0; + } + + static int setup_middle_bt(struct hns_roce_dev *hr_dev, void *cpu_base, +@@ -1304,7 +1317,7 @@ static int setup_middle_bt(struct hns_roce_dev *hr_dev, void *cpu_base, + /* if exist mid bt, link L1 to L0 */ + list_for_each_entry_safe(hem, temp_hem, branch_head, list) { + offset = (hem->start - r->offset) / step * BA_BYTE_LEN; +- hem_list_link_bt(hr_dev, cpu_base + offset, hem->dma_addr); ++ hem_list_link_bt(cpu_base + offset, hem->dma_addr); + total++; + } + +@@ -1329,7 +1342,7 @@ setup_root_hem(struct hns_roce_dev *hr_dev, struct hns_roce_hem_list *hem_list, + return -ENOMEM; + + total = 0; +- for (i = 0; i < region_cnt && total < max_ba_num; i++) { ++ for (i = 0; i < region_cnt && total <= max_ba_num; i++) { + r = ®ions[i]; + if (!r->count) + continue; +@@ -1395,9 +1408,9 @@ static int hem_list_alloc_root_bt(struct hns_roce_dev *hr_dev, + region_cnt); + if (ret) { + for (i = 0; i < region_cnt; i++) +- hem_list_free_all(hr_dev, &head.branch[i], false); ++ hem_list_free_all(hr_dev, &head.branch[i]); + +- hem_list_free_all(hr_dev, &head.root, true); ++ hem_list_free_all(hr_dev, &head.root); + } + + return ret; +@@ -1460,10 +1473,9 @@ void hns_roce_hem_list_release(struct hns_roce_dev *hr_dev, + + for (i = 0; i < HNS_ROCE_MAX_BT_REGION; i++) + for (j = 0; j < HNS_ROCE_MAX_BT_LEVEL; j++) +- hem_list_free_all(hr_dev, &hem_list->mid_bt[i][j], +- j != 0); ++ hem_list_free_all(hr_dev, &hem_list->mid_bt[i][j]); + +- hem_list_free_all(hr_dev, &hem_list->root_bt, true); ++ hem_list_free_all(hr_dev, &hem_list->root_bt); + INIT_LIST_HEAD(&hem_list->btm_bt); + hem_list->root_ba = 0; + } +diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +index 2824d390ec3161..aded0a7f42838d 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c ++++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +@@ -471,7 +471,7 @@ static inline int set_ud_wqe(struct hns_roce_qp *qp, + valid_num_sge = calc_wr_sge_num(wr, &msg_len); + + ret = set_ud_opcode(ud_sq_wqe, wr); +- if (WARN_ON(ret)) ++ if (WARN_ON_ONCE(ret)) + return ret; + + ud_sq_wqe->msg_len = cpu_to_le32(msg_len); +@@ -575,7 +575,7 @@ static inline int set_rc_wqe(struct hns_roce_qp *qp, + rc_sq_wqe->msg_len = cpu_to_le32(msg_len); + + ret = set_rc_opcode(hr_dev, rc_sq_wqe, wr); +- if (WARN_ON(ret)) ++ if (WARN_ON_ONCE(ret)) + return ret; + + hr_reg_write(rc_sq_wqe, RC_SEND_WQE_SO, +@@ -673,6 +673,10 @@ static void write_dwqe(struct hns_roce_dev *hr_dev, struct hns_roce_qp *qp, + #define HNS_ROCE_SL_SHIFT 2 + struct hns_roce_v2_rc_send_wqe *rc_sq_wqe = wqe; + ++ if (unlikely(qp->state == IB_QPS_ERR)) { ++ flush_cqe(hr_dev, qp); ++ return; ++ } + /* All kinds of DirectWQE have the same header field layout */ + hr_reg_enable(rc_sq_wqe, RC_SEND_WQE_FLAG); + hr_reg_write(rc_sq_wqe, RC_SEND_WQE_DB_SL_L, qp->sl); +@@ -3181,21 +3185,22 @@ static int set_mtpt_pbl(struct hns_roce_dev *hr_dev, + u64 pages[HNS_ROCE_V2_MAX_INNER_MTPT_NUM] = { 0 }; + struct ib_device *ibdev = &hr_dev->ib_dev; + dma_addr_t pbl_ba; +- int i, count; ++ int ret; ++ int i; + +- count = hns_roce_mtr_find(hr_dev, &mr->pbl_mtr, 0, pages, +- min_t(int, ARRAY_SIZE(pages), mr->npages), +- &pbl_ba); +- if (count < 1) { +- ibdev_err(ibdev, "failed to find PBL mtr, count = %d.\n", +- count); +- return -ENOBUFS; ++ ret = hns_roce_mtr_find(hr_dev, &mr->pbl_mtr, 0, pages, ++ min_t(int, ARRAY_SIZE(pages), mr->npages)); ++ if (ret) { ++ ibdev_err(ibdev, "failed to find PBL mtr, ret = %d.\n", ret); ++ return ret; + } + + /* Aligned to the hardware address access unit */ +- for (i = 0; i < count; i++) ++ for (i = 0; i < ARRAY_SIZE(pages); i++) + pages[i] >>= 6; + ++ pbl_ba = hns_roce_get_mtr_ba(&mr->pbl_mtr); ++ + mpt_entry->pbl_size = cpu_to_le32(mr->npages); + mpt_entry->pbl_ba_l = cpu_to_le32(pbl_ba >> 3); + hr_reg_write(mpt_entry, MPT_PBL_BA_H, upper_32_bits(pbl_ba >> 3)); +@@ -3291,21 +3296,14 @@ static int hns_roce_v2_rereg_write_mtpt(struct hns_roce_dev *hr_dev, + return ret; + } + +-static int hns_roce_v2_frmr_write_mtpt(struct hns_roce_dev *hr_dev, +- void *mb_buf, struct hns_roce_mr *mr) ++static int hns_roce_v2_frmr_write_mtpt(void *mb_buf, struct hns_roce_mr *mr) + { +- struct ib_device *ibdev = &hr_dev->ib_dev; ++ dma_addr_t pbl_ba = hns_roce_get_mtr_ba(&mr->pbl_mtr); + struct hns_roce_v2_mpt_entry *mpt_entry; +- dma_addr_t pbl_ba = 0; + + mpt_entry = mb_buf; + memset(mpt_entry, 0, sizeof(*mpt_entry)); + +- if (hns_roce_mtr_find(hr_dev, &mr->pbl_mtr, 0, NULL, 0, &pbl_ba) < 0) { +- ibdev_err(ibdev, "failed to find frmr mtr.\n"); +- return -ENOBUFS; +- } +- + hr_reg_write(mpt_entry, MPT_ST, V2_MPT_ST_FREE); + hr_reg_write(mpt_entry, MPT_PD, mr->pd); + +@@ -4213,8 +4211,7 @@ static void set_access_flags(struct hns_roce_qp *hr_qp, + } + + static void set_qpc_wqe_cnt(struct hns_roce_qp *hr_qp, +- struct hns_roce_v2_qp_context *context, +- struct hns_roce_v2_qp_context *qpc_mask) ++ struct hns_roce_v2_qp_context *context) + { + hr_reg_write(context, QPC_SGE_SHIFT, + to_hr_hem_entries_shift(hr_qp->sge.sge_cnt, +@@ -4236,7 +4233,6 @@ static inline int get_pdn(struct ib_pd *ib_pd) + } + + static void modify_qp_reset_to_init(struct ib_qp *ibqp, +- const struct ib_qp_attr *attr, + struct hns_roce_v2_qp_context *context, + struct hns_roce_v2_qp_context *qpc_mask) + { +@@ -4255,7 +4251,7 @@ static void modify_qp_reset_to_init(struct ib_qp *ibqp, + + hr_reg_write(context, QPC_RQWS, ilog2(hr_qp->rq.max_gs)); + +- set_qpc_wqe_cnt(hr_qp, context, qpc_mask); ++ set_qpc_wqe_cnt(hr_qp, context); + + /* No VLAN need to set 0xFFF */ + hr_reg_write(context, QPC_VLAN_ID, 0xfff); +@@ -4296,7 +4292,6 @@ static void modify_qp_reset_to_init(struct ib_qp *ibqp, + } + + static void modify_qp_init_to_init(struct ib_qp *ibqp, +- const struct ib_qp_attr *attr, + struct hns_roce_v2_qp_context *context, + struct hns_roce_v2_qp_context *qpc_mask) + { +@@ -4333,17 +4328,20 @@ static int config_qp_rq_buf(struct hns_roce_dev *hr_dev, + { + u64 mtts[MTT_MIN_COUNT] = { 0 }; + u64 wqe_sge_ba; +- int count; ++ int ret; + + /* Search qp buf's mtts */ +- count = hns_roce_mtr_find(hr_dev, &hr_qp->mtr, hr_qp->rq.offset, mtts, +- MTT_MIN_COUNT, &wqe_sge_ba); +- if (hr_qp->rq.wqe_cnt && count < 1) { ++ ret = hns_roce_mtr_find(hr_dev, &hr_qp->mtr, hr_qp->rq.offset, mtts, ++ MTT_MIN_COUNT); ++ if (hr_qp->rq.wqe_cnt && ret) { + ibdev_err(&hr_dev->ib_dev, +- "failed to find RQ WQE, QPN = 0x%lx.\n", hr_qp->qpn); +- return -EINVAL; ++ "failed to find QP(0x%lx) RQ WQE buf, ret = %d.\n", ++ hr_qp->qpn, ret); ++ return ret; + } + ++ wqe_sge_ba = hns_roce_get_mtr_ba(&hr_qp->mtr); ++ + context->wqe_sge_ba = cpu_to_le32(wqe_sge_ba >> 3); + qpc_mask->wqe_sge_ba = 0; + +@@ -4407,23 +4405,23 @@ static int config_qp_sq_buf(struct hns_roce_dev *hr_dev, + struct ib_device *ibdev = &hr_dev->ib_dev; + u64 sge_cur_blk = 0; + u64 sq_cur_blk = 0; +- int count; ++ int ret; + + /* search qp buf's mtts */ +- count = hns_roce_mtr_find(hr_dev, &hr_qp->mtr, 0, &sq_cur_blk, 1, NULL); +- if (count < 1) { +- ibdev_err(ibdev, "failed to find QP(0x%lx) SQ buf.\n", +- hr_qp->qpn); +- return -EINVAL; ++ ret = hns_roce_mtr_find(hr_dev, &hr_qp->mtr, hr_qp->sq.offset, ++ &sq_cur_blk, 1); ++ if (ret) { ++ ibdev_err(ibdev, "failed to find QP(0x%lx) SQ WQE buf, ret = %d.\n", ++ hr_qp->qpn, ret); ++ return ret; + } + if (hr_qp->sge.sge_cnt > 0) { +- count = hns_roce_mtr_find(hr_dev, &hr_qp->mtr, +- hr_qp->sge.offset, +- &sge_cur_blk, 1, NULL); +- if (count < 1) { +- ibdev_err(ibdev, "failed to find QP(0x%lx) SGE buf.\n", +- hr_qp->qpn); +- return -EINVAL; ++ ret = hns_roce_mtr_find(hr_dev, &hr_qp->mtr, ++ hr_qp->sge.offset, &sge_cur_blk, 1); ++ if (ret) { ++ ibdev_err(ibdev, "failed to find QP(0x%lx) SGE buf, ret = %d.\n", ++ hr_qp->qpn, ret); ++ return ret; + } + } + +@@ -4614,8 +4612,7 @@ static int modify_qp_init_to_rtr(struct ib_qp *ibqp, + return 0; + } + +-static int modify_qp_rtr_to_rts(struct ib_qp *ibqp, +- const struct ib_qp_attr *attr, int attr_mask, ++static int modify_qp_rtr_to_rts(struct ib_qp *ibqp, int attr_mask, + struct hns_roce_v2_qp_context *context, + struct hns_roce_v2_qp_context *qpc_mask) + { +@@ -4984,15 +4981,14 @@ static int hns_roce_v2_set_abs_fields(struct ib_qp *ibqp, + + if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT) { + memset(qpc_mask, 0, hr_dev->caps.qpc_sz); +- modify_qp_reset_to_init(ibqp, attr, context, qpc_mask); ++ modify_qp_reset_to_init(ibqp, context, qpc_mask); + } else if (cur_state == IB_QPS_INIT && new_state == IB_QPS_INIT) { +- modify_qp_init_to_init(ibqp, attr, context, qpc_mask); ++ modify_qp_init_to_init(ibqp, context, qpc_mask); + } else if (cur_state == IB_QPS_INIT && new_state == IB_QPS_RTR) { + ret = modify_qp_init_to_rtr(ibqp, attr, attr_mask, context, + qpc_mask, udata); + } else if (cur_state == IB_QPS_RTR && new_state == IB_QPS_RTS) { +- ret = modify_qp_rtr_to_rts(ibqp, attr, attr_mask, context, +- qpc_mask); ++ ret = modify_qp_rtr_to_rts(ibqp, attr_mask, context, qpc_mask); + } + + return ret; +@@ -5550,18 +5546,20 @@ static int hns_roce_v2_write_srqc_index_queue(struct hns_roce_srq *srq, + struct ib_device *ibdev = srq->ibsrq.device; + struct hns_roce_dev *hr_dev = to_hr_dev(ibdev); + u64 mtts_idx[MTT_MIN_COUNT] = {}; +- dma_addr_t dma_handle_idx = 0; ++ dma_addr_t dma_handle_idx; + int ret; + + /* Get physical address of idx que buf */ + ret = hns_roce_mtr_find(hr_dev, &idx_que->mtr, 0, mtts_idx, +- ARRAY_SIZE(mtts_idx), &dma_handle_idx); +- if (ret < 1) { ++ ARRAY_SIZE(mtts_idx)); ++ if (ret) { + ibdev_err(ibdev, "failed to find mtr for SRQ idx, ret = %d.\n", + ret); +- return -ENOBUFS; ++ return ret; + } + ++ dma_handle_idx = hns_roce_get_mtr_ba(&idx_que->mtr); ++ + hr_reg_write(ctx, SRQC_IDX_HOP_NUM, + to_hr_hem_hopnum(hr_dev->caps.idx_hop_num, srq->wqe_cnt)); + +@@ -5593,20 +5591,22 @@ static int hns_roce_v2_write_srqc(struct hns_roce_srq *srq, void *mb_buf) + struct hns_roce_dev *hr_dev = to_hr_dev(ibdev); + struct hns_roce_srq_context *ctx = mb_buf; + u64 mtts_wqe[MTT_MIN_COUNT] = {}; +- dma_addr_t dma_handle_wqe = 0; ++ dma_addr_t dma_handle_wqe; + int ret; + + memset(ctx, 0, sizeof(*ctx)); + + /* Get the physical address of srq buf */ + ret = hns_roce_mtr_find(hr_dev, &srq->buf_mtr, 0, mtts_wqe, +- ARRAY_SIZE(mtts_wqe), &dma_handle_wqe); +- if (ret < 1) { ++ ARRAY_SIZE(mtts_wqe)); ++ if (ret) { + ibdev_err(ibdev, "failed to find mtr for SRQ WQE, ret = %d.\n", + ret); +- return -ENOBUFS; ++ return ret; + } + ++ dma_handle_wqe = hns_roce_get_mtr_ba(&srq->buf_mtr); ++ + hr_reg_write(ctx, SRQC_SRQ_ST, 1); + hr_reg_write_bool(ctx, SRQC_SRQ_TYPE, + srq->ibsrq.srq_type == IB_SRQT_XRC); +@@ -6327,7 +6327,7 @@ static int config_eqc(struct hns_roce_dev *hr_dev, struct hns_roce_eq *eq, + u64 eqe_ba[MTT_MIN_COUNT] = { 0 }; + struct hns_roce_eq_context *eqc; + u64 bt_ba = 0; +- int count; ++ int ret; + + eqc = mb_buf; + memset(eqc, 0, sizeof(struct hns_roce_eq_context)); +@@ -6335,13 +6335,15 @@ static int config_eqc(struct hns_roce_dev *hr_dev, struct hns_roce_eq *eq, + init_eq_config(hr_dev, eq); + + /* if not multi-hop, eqe buffer only use one trunk */ +- count = hns_roce_mtr_find(hr_dev, &eq->mtr, 0, eqe_ba, MTT_MIN_COUNT, +- &bt_ba); +- if (count < 1) { +- dev_err(hr_dev->dev, "failed to find EQE mtr\n"); +- return -ENOBUFS; ++ ret = hns_roce_mtr_find(hr_dev, &eq->mtr, 0, eqe_ba, ++ ARRAY_SIZE(eqe_ba)); ++ if (ret) { ++ dev_err(hr_dev->dev, "failed to find EQE mtr, ret = %d\n", ret); ++ return ret; + } + ++ bt_ba = hns_roce_get_mtr_ba(&eq->mtr); ++ + hr_reg_write(eqc, EQC_EQ_ST, HNS_ROCE_V2_EQ_STATE_VALID); + hr_reg_write(eqc, EQC_EQE_HOP_NUM, eq->hop_num); + hr_reg_write(eqc, EQC_OVER_IGNORE, eq->over_ignore); +diff --git a/drivers/infiniband/hw/hns/hns_roce_mr.c b/drivers/infiniband/hw/hns/hns_roce_mr.c +index 7f29a55d378f02..408ef2a9614927 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_mr.c ++++ b/drivers/infiniband/hw/hns/hns_roce_mr.c +@@ -154,7 +154,7 @@ static int hns_roce_mr_enable(struct hns_roce_dev *hr_dev, + if (mr->type != MR_TYPE_FRMR) + ret = hr_dev->hw->write_mtpt(hr_dev, mailbox->buf, mr); + else +- ret = hr_dev->hw->frmr_write_mtpt(hr_dev, mailbox->buf, mr); ++ ret = hr_dev->hw->frmr_write_mtpt(mailbox->buf, mr); + if (ret) { + dev_err(dev, "failed to write mtpt, ret = %d.\n", ret); + goto err_page; +@@ -714,7 +714,7 @@ static int mtr_map_bufs(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr, + return -ENOMEM; + + if (mtr->umem) +- npage = hns_roce_get_umem_bufs(hr_dev, pages, page_count, ++ npage = hns_roce_get_umem_bufs(pages, page_count, + mtr->umem, page_shift); + else + npage = hns_roce_get_kmem_bufs(hr_dev, pages, page_count, +@@ -767,11 +767,6 @@ int hns_roce_mtr_map(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr, + for (i = 0, mapped_cnt = 0; i < mtr->hem_cfg.region_count && + mapped_cnt < page_cnt; i++) { + r = &mtr->hem_cfg.region[i]; +- /* if hopnum is 0, no need to map pages in this region */ +- if (!r->hopnum) { +- mapped_cnt += r->count; +- continue; +- } + + if (r->offset + r->count > page_cnt) { + ret = -EINVAL; +@@ -802,47 +797,53 @@ int hns_roce_mtr_map(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr, + return ret; + } + +-int hns_roce_mtr_find(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr, +- u32 offset, u64 *mtt_buf, int mtt_max, u64 *base_addr) ++static int hns_roce_get_direct_addr_mtt(struct hns_roce_hem_cfg *cfg, ++ u32 start_index, u64 *mtt_buf, ++ int mtt_cnt) + { +- struct hns_roce_hem_cfg *cfg = &mtr->hem_cfg; +- int mtt_count, left; +- u32 start_index; ++ int mtt_count; + int total = 0; +- __le64 *mtts; + u32 npage; + u64 addr; + +- if (!mtt_buf || mtt_max < 1) +- goto done; +- +- /* no mtt memory in direct mode, so just return the buffer address */ +- if (cfg->is_direct) { +- start_index = offset >> HNS_HW_PAGE_SHIFT; +- for (mtt_count = 0; mtt_count < cfg->region_count && +- total < mtt_max; mtt_count++) { +- npage = cfg->region[mtt_count].offset; +- if (npage < start_index) +- continue; ++ if (mtt_cnt > cfg->region_count) ++ return -EINVAL; + +- addr = cfg->root_ba + (npage << HNS_HW_PAGE_SHIFT); +- mtt_buf[total] = addr; ++ for (mtt_count = 0; mtt_count < cfg->region_count && total < mtt_cnt; ++ mtt_count++) { ++ npage = cfg->region[mtt_count].offset; ++ if (npage < start_index) ++ continue; + +- total++; +- } ++ addr = cfg->root_ba + (npage << HNS_HW_PAGE_SHIFT); ++ mtt_buf[total] = addr; + +- goto done; ++ total++; + } + +- start_index = offset >> cfg->buf_pg_shift; +- left = mtt_max; ++ if (!total) ++ return -ENOENT; ++ ++ return 0; ++} ++ ++static int hns_roce_get_mhop_mtt(struct hns_roce_dev *hr_dev, ++ struct hns_roce_mtr *mtr, u32 start_index, ++ u64 *mtt_buf, int mtt_cnt) ++{ ++ int left = mtt_cnt; ++ int total = 0; ++ int mtt_count; ++ __le64 *mtts; ++ u32 npage; ++ + while (left > 0) { + mtt_count = 0; + mtts = hns_roce_hem_list_find_mtt(hr_dev, &mtr->hem_list, + start_index + total, + &mtt_count); + if (!mtts || !mtt_count) +- goto done; ++ break; + + npage = min(mtt_count, left); + left -= npage; +@@ -850,11 +851,33 @@ int hns_roce_mtr_find(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr, + mtt_buf[total++] = le64_to_cpu(mtts[mtt_count]); + } + +-done: +- if (base_addr) +- *base_addr = cfg->root_ba; ++ if (!total) ++ return -ENOENT; ++ ++ return 0; ++} + +- return total; ++int hns_roce_mtr_find(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr, ++ u32 offset, u64 *mtt_buf, int mtt_max) ++{ ++ struct hns_roce_hem_cfg *cfg = &mtr->hem_cfg; ++ u32 start_index; ++ int ret; ++ ++ if (!mtt_buf || mtt_max < 1) ++ return -EINVAL; ++ ++ /* no mtt memory in direct mode, so just return the buffer address */ ++ if (cfg->is_direct) { ++ start_index = offset >> HNS_HW_PAGE_SHIFT; ++ ret = hns_roce_get_direct_addr_mtt(cfg, start_index, ++ mtt_buf, mtt_max); ++ } else { ++ start_index = offset >> cfg->buf_pg_shift; ++ ret = hns_roce_get_mhop_mtt(hr_dev, mtr, start_index, ++ mtt_buf, mtt_max); ++ } ++ return ret; + } + + static int mtr_init_buf_cfg(struct hns_roce_dev *hr_dev, +diff --git a/drivers/infiniband/hw/hns/hns_roce_qp.c b/drivers/infiniband/hw/hns/hns_roce_qp.c +index 88a4777d29f8b8..97d79c8d5cd069 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_qp.c ++++ b/drivers/infiniband/hw/hns/hns_roce_qp.c +@@ -1075,7 +1075,6 @@ static int set_qp_param(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp, + } + + static int hns_roce_create_qp_common(struct hns_roce_dev *hr_dev, +- struct ib_pd *ib_pd, + struct ib_qp_init_attr *init_attr, + struct ib_udata *udata, + struct hns_roce_qp *hr_qp) +@@ -1229,7 +1228,6 @@ int hns_roce_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *init_attr, + struct ib_device *ibdev = qp->device; + struct hns_roce_dev *hr_dev = to_hr_dev(ibdev); + struct hns_roce_qp *hr_qp = to_hr_qp(qp); +- struct ib_pd *pd = qp->pd; + int ret; + + ret = check_qp_type(hr_dev, init_attr->qp_type, !!udata); +@@ -1244,7 +1242,7 @@ int hns_roce_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *init_attr, + hr_qp->phy_port = hr_dev->iboe.phy_port[hr_qp->port]; + } + +- ret = hns_roce_create_qp_common(hr_dev, pd, init_attr, udata, hr_qp); ++ ret = hns_roce_create_qp_common(hr_dev, init_attr, udata, hr_qp); + if (ret) + ibdev_err(ibdev, "create QP type 0x%x failed(%d)\n", + init_attr->qp_type, ret); +diff --git a/drivers/infiniband/hw/hns/hns_roce_srq.c b/drivers/infiniband/hw/hns/hns_roce_srq.c +index 652508b660a060..80fcb1b0e8fdcf 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_srq.c ++++ b/drivers/infiniband/hw/hns/hns_roce_srq.c +@@ -249,7 +249,7 @@ static void free_srq_wqe_buf(struct hns_roce_dev *hr_dev, + hns_roce_mtr_destroy(hr_dev, &srq->buf_mtr); + } + +-static int alloc_srq_wrid(struct hns_roce_dev *hr_dev, struct hns_roce_srq *srq) ++static int alloc_srq_wrid(struct hns_roce_srq *srq) + { + srq->wrid = kvmalloc_array(srq->wqe_cnt, sizeof(u64), GFP_KERNEL); + if (!srq->wrid) +@@ -365,7 +365,7 @@ static int alloc_srq_buf(struct hns_roce_dev *hr_dev, struct hns_roce_srq *srq, + goto err_idx; + + if (!udata) { +- ret = alloc_srq_wrid(hr_dev, srq); ++ ret = alloc_srq_wrid(srq); + if (ret) + goto err_wqe_buf; + } +diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c +index c510484e024b1a..ada7dbf8eb1cf5 100644 +--- a/drivers/infiniband/hw/mlx5/main.c ++++ b/drivers/infiniband/hw/mlx5/main.c +@@ -3372,7 +3372,8 @@ static int mlx5_ib_init_multiport_master(struct mlx5_ib_dev *dev) + list_for_each_entry(mpi, &mlx5_ib_unaffiliated_port_list, + list) { + if (dev->sys_image_guid == mpi->sys_image_guid && +- (mlx5_core_native_port_num(mpi->mdev) - 1) == i) { ++ (mlx5_core_native_port_num(mpi->mdev) - 1) == i && ++ mlx5_core_same_coredev_type(dev->mdev, mpi->mdev)) { + bound = mlx5_ib_bind_slave_port(dev, mpi); + } + +@@ -4406,7 +4407,8 @@ static int mlx5r_mp_probe(struct auxiliary_device *adev, + + mutex_lock(&mlx5_ib_multiport_mutex); + list_for_each_entry(dev, &mlx5_ib_dev_list, ib_dev_list) { +- if (dev->sys_image_guid == mpi->sys_image_guid) ++ if (dev->sys_image_guid == mpi->sys_image_guid && ++ mlx5_core_same_coredev_type(dev->mdev, mpi->mdev)) + bound = mlx5_ib_bind_slave_port(dev, mpi); + + if (bound) { +diff --git a/drivers/infiniband/ulp/rtrs/rtrs-srv.c b/drivers/infiniband/ulp/rtrs/rtrs-srv.c +index 758a3d9c2844d1..84d1654148d764 100644 +--- a/drivers/infiniband/ulp/rtrs/rtrs-srv.c ++++ b/drivers/infiniband/ulp/rtrs/rtrs-srv.c +@@ -346,6 +346,7 @@ static int send_io_resp_imm(struct rtrs_srv_con *con, struct rtrs_srv_op *id, + struct rtrs_srv_mr *srv_mr; + bool need_inval = false; + enum ib_send_flags flags; ++ struct ib_sge list; + u32 imm; + int err; + +@@ -398,7 +399,6 @@ static int send_io_resp_imm(struct rtrs_srv_con *con, struct rtrs_srv_op *id, + imm = rtrs_to_io_rsp_imm(id->msg_id, errno, need_inval); + imm_wr.wr.next = NULL; + if (always_invalidate) { +- struct ib_sge list; + struct rtrs_msg_rkey_rsp *msg; + + srv_mr = &srv_path->mrs[id->msg_id]; +diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c +index 412196a7dad587..2c6c50348afd19 100644 +--- a/drivers/irqchip/irq-gic.c ++++ b/drivers/irqchip/irq-gic.c +@@ -64,7 +64,7 @@ static void gic_check_cpu_features(void) + + union gic_base { + void __iomem *common_base; +- void __percpu * __iomem *percpu_base; ++ void __iomem * __percpu *percpu_base; + }; + + struct gic_chip_data { +diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c +index a44d4b3e5beb22..82102a4c5d6883 100644 +--- a/drivers/mailbox/pcc.c ++++ b/drivers/mailbox/pcc.c +@@ -91,6 +91,14 @@ struct pcc_chan_reg { + * @cmd_update: PCC register bundle for the command complete update register + * @error: PCC register bundle for the error status register + * @plat_irq: platform interrupt ++ * @type: PCC subspace type ++ * @plat_irq_flags: platform interrupt flags ++ * @chan_in_use: this flag is used just to check if the interrupt needs ++ * handling when it is shared. Since only one transfer can occur ++ * at a time and mailbox takes care of locking, this flag can be ++ * accessed without a lock. Note: the type only support the ++ * communication from OSPM to Platform, like type3, use it, and ++ * other types completely ignore it. + */ + struct pcc_chan_info { + struct pcc_mbox_chan chan; +@@ -100,12 +108,17 @@ struct pcc_chan_info { + struct pcc_chan_reg cmd_update; + struct pcc_chan_reg error; + int plat_irq; ++ u8 type; ++ unsigned int plat_irq_flags; ++ bool chan_in_use; + }; + + #define to_pcc_chan_info(c) container_of(c, struct pcc_chan_info, chan) + static struct pcc_chan_info *chan_info; + static int pcc_chan_count; + ++static int pcc_send_data(struct mbox_chan *chan, void *data); ++ + /* + * PCC can be used with perf critical drivers such as CPPC + * So it makes sense to locally cache the virtual address and +@@ -221,6 +234,70 @@ static int pcc_map_interrupt(u32 interrupt, u32 flags) + return acpi_register_gsi(NULL, interrupt, trigger, polarity); + } + ++static bool pcc_chan_plat_irq_can_be_shared(struct pcc_chan_info *pchan) ++{ ++ return (pchan->plat_irq_flags & ACPI_PCCT_INTERRUPT_MODE) == ++ ACPI_LEVEL_SENSITIVE; ++} ++ ++static bool pcc_mbox_cmd_complete_check(struct pcc_chan_info *pchan) ++{ ++ u64 val; ++ int ret; ++ ++ ret = pcc_chan_reg_read(&pchan->cmd_complete, &val); ++ if (ret) ++ return false; ++ ++ if (!pchan->cmd_complete.gas) ++ return true; ++ ++ /* ++ * Judge if the channel respond the interrupt based on the value of ++ * command complete. ++ */ ++ val &= pchan->cmd_complete.status_mask; ++ ++ /* ++ * If this is PCC slave subspace channel, and the command complete ++ * bit 0 indicates that Platform is sending a notification and OSPM ++ * needs to respond this interrupt to process this command. ++ */ ++ if (pchan->type == ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE) ++ return !val; ++ ++ return !!val; ++} ++ ++static void check_and_ack(struct pcc_chan_info *pchan, struct mbox_chan *chan) ++{ ++ struct acpi_pcct_ext_pcc_shared_memory pcc_hdr; ++ ++ if (pchan->type != ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE) ++ return; ++ /* If the memory region has not been mapped, we cannot ++ * determine if we need to send the message, but we still ++ * need to set the cmd_update flag before returning. ++ */ ++ if (pchan->chan.shmem == NULL) { ++ pcc_chan_reg_read_modify_write(&pchan->cmd_update); ++ return; ++ } ++ memcpy_fromio(&pcc_hdr, pchan->chan.shmem, ++ sizeof(struct acpi_pcct_ext_pcc_shared_memory)); ++ /* ++ * The PCC slave subspace channel needs to set the command complete bit ++ * after processing message. If the PCC_ACK_FLAG is set, it should also ++ * ring the doorbell. ++ * ++ * The PCC master subspace channel clears chan_in_use to free channel. ++ */ ++ if (le32_to_cpup(&pcc_hdr.flags) & PCC_ACK_FLAG_MASK) ++ pcc_send_data(chan, NULL); ++ else ++ pcc_chan_reg_read_modify_write(&pchan->cmd_update); ++} ++ + /** + * pcc_mbox_irq - PCC mailbox interrupt handler + * @irq: interrupt number +@@ -236,16 +313,12 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p) + int ret; + + pchan = chan->con_priv; +- +- ret = pcc_chan_reg_read(&pchan->cmd_complete, &val); +- if (ret) ++ if (pchan->type == ACPI_PCCT_TYPE_EXT_PCC_MASTER_SUBSPACE && ++ !pchan->chan_in_use) + return IRQ_NONE; + +- if (val) { /* Ensure GAS exists and value is non-zero */ +- val &= pchan->cmd_complete.status_mask; +- if (!val) +- return IRQ_NONE; +- } ++ if (!pcc_mbox_cmd_complete_check(pchan)) ++ return IRQ_NONE; + + ret = pcc_chan_reg_read(&pchan->error, &val); + if (ret) +@@ -262,6 +335,9 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p) + + mbox_chan_received_data(chan, NULL); + ++ check_and_ack(pchan, chan); ++ pchan->chan_in_use = false; ++ + return IRQ_HANDLED; + } + +@@ -311,14 +387,37 @@ EXPORT_SYMBOL_GPL(pcc_mbox_request_channel); + void pcc_mbox_free_channel(struct pcc_mbox_chan *pchan) + { + struct mbox_chan *chan = pchan->mchan; ++ struct pcc_chan_info *pchan_info; ++ struct pcc_mbox_chan *pcc_mbox_chan; + + if (!chan || !chan->cl) + return; ++ pchan_info = chan->con_priv; ++ pcc_mbox_chan = &pchan_info->chan; ++ if (pcc_mbox_chan->shmem) { ++ iounmap(pcc_mbox_chan->shmem); ++ pcc_mbox_chan->shmem = NULL; ++ } + + mbox_free_channel(chan); + } + EXPORT_SYMBOL_GPL(pcc_mbox_free_channel); + ++int pcc_mbox_ioremap(struct mbox_chan *chan) ++{ ++ struct pcc_chan_info *pchan_info; ++ struct pcc_mbox_chan *pcc_mbox_chan; ++ ++ if (!chan || !chan->cl) ++ return -1; ++ pchan_info = chan->con_priv; ++ pcc_mbox_chan = &pchan_info->chan; ++ pcc_mbox_chan->shmem = ioremap(pcc_mbox_chan->shmem_base_addr, ++ pcc_mbox_chan->shmem_size); ++ return 0; ++} ++EXPORT_SYMBOL_GPL(pcc_mbox_ioremap); ++ + /** + * pcc_send_data - Called from Mailbox Controller code. Used + * here only to ring the channel doorbell. The PCC client +@@ -340,7 +439,11 @@ static int pcc_send_data(struct mbox_chan *chan, void *data) + if (ret) + return ret; + +- return pcc_chan_reg_read_modify_write(&pchan->db); ++ ret = pcc_chan_reg_read_modify_write(&pchan->db); ++ if (!ret && pchan->plat_irq > 0) ++ pchan->chan_in_use = true; ++ ++ return ret; + } + + /** +@@ -353,11 +456,14 @@ static int pcc_send_data(struct mbox_chan *chan, void *data) + static int pcc_startup(struct mbox_chan *chan) + { + struct pcc_chan_info *pchan = chan->con_priv; ++ unsigned long irqflags; + int rc; + + if (pchan->plat_irq > 0) { +- rc = devm_request_irq(chan->mbox->dev, pchan->plat_irq, pcc_mbox_irq, 0, +- MBOX_IRQ_NAME, chan); ++ irqflags = pcc_chan_plat_irq_can_be_shared(pchan) ? ++ IRQF_SHARED | IRQF_ONESHOT : 0; ++ rc = devm_request_irq(chan->mbox->dev, pchan->plat_irq, pcc_mbox_irq, ++ irqflags, MBOX_IRQ_NAME, chan); + if (unlikely(rc)) { + dev_err(chan->mbox->dev, "failed to register PCC interrupt %d\n", + pchan->plat_irq); +@@ -463,6 +569,7 @@ static int pcc_parse_subspace_irq(struct pcc_chan_info *pchan, + pcct_ss->platform_interrupt); + return -EINVAL; + } ++ pchan->plat_irq_flags = pcct_ss->flags; + + if (pcct_ss->header.type == ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE_TYPE2) { + struct acpi_pcct_hw_reduced_type2 *pcct2_ss = (void *)pcct_ss; +@@ -484,6 +591,12 @@ static int pcc_parse_subspace_irq(struct pcc_chan_info *pchan, + "PLAT IRQ ACK"); + } + ++ if (pcc_chan_plat_irq_can_be_shared(pchan) && ++ !pchan->plat_irq_ack.gas) { ++ pr_err("PCC subspace has level IRQ with no ACK register\n"); ++ return -EINVAL; ++ } ++ + return ret; + } + +@@ -698,6 +811,7 @@ static int pcc_mbox_probe(struct platform_device *pdev) + + pcc_parse_subspace_shmem(pchan, pcct_entry); + ++ pchan->type = pcct_entry->type; + pcct_entry = (struct acpi_subtable_header *) + ((unsigned long) pcct_entry + pcct_entry->length); + } +diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c +index 5a3e933df63352..1b05890f99f4f4 100644 +--- a/drivers/media/usb/uvc/uvc_driver.c ++++ b/drivers/media/usb/uvc/uvc_driver.c +@@ -2519,6 +2519,28 @@ static const struct usb_device_id uvc_ids[] = { + .bInterfaceSubClass = 1, + .bInterfaceProtocol = UVC_PC_PROTOCOL_15, + .driver_info = (kernel_ulong_t)&uvc_ctrl_power_line_limited }, ++ /* Quanta ACER HD User Facing */ ++ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE ++ | USB_DEVICE_ID_MATCH_INT_INFO, ++ .idVendor = 0x0408, ++ .idProduct = 0x4033, ++ .bInterfaceClass = USB_CLASS_VIDEO, ++ .bInterfaceSubClass = 1, ++ .bInterfaceProtocol = UVC_PC_PROTOCOL_15, ++ .driver_info = (kernel_ulong_t)&(const struct uvc_device_info){ ++ .uvc_version = 0x010a, ++ } }, ++ /* Quanta ACER HD User Facing */ ++ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE ++ | USB_DEVICE_ID_MATCH_INT_INFO, ++ .idVendor = 0x0408, ++ .idProduct = 0x4035, ++ .bInterfaceClass = USB_CLASS_VIDEO, ++ .bInterfaceSubClass = 1, ++ .bInterfaceProtocol = UVC_PC_PROTOCOL_15, ++ .driver_info = (kernel_ulong_t)&(const struct uvc_device_info){ ++ .uvc_version = 0x010a, ++ } }, + /* LogiLink Wireless Webcam */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, +diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c +index e113b99a3eab59..8716004fcf6c90 100644 +--- a/drivers/mmc/host/sdhci-msm.c ++++ b/drivers/mmc/host/sdhci-msm.c +@@ -1867,20 +1867,20 @@ static int sdhci_msm_program_key(struct cqhci_host *cq_host, + struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host); + union cqhci_crypto_cap_entry cap; + ++ if (!(cfg->config_enable & CQHCI_CRYPTO_CONFIGURATION_ENABLE)) ++ return qcom_ice_evict_key(msm_host->ice, slot); ++ + /* Only AES-256-XTS has been tested so far. */ + cap = cq_host->crypto_cap_array[cfg->crypto_cap_idx]; + if (cap.algorithm_id != CQHCI_CRYPTO_ALG_AES_XTS || + cap.key_size != CQHCI_CRYPTO_KEY_SIZE_256) + return -EINVAL; + +- if (cfg->config_enable & CQHCI_CRYPTO_CONFIGURATION_ENABLE) +- return qcom_ice_program_key(msm_host->ice, +- QCOM_ICE_CRYPTO_ALG_AES_XTS, +- QCOM_ICE_CRYPTO_KEY_SIZE_256, +- cfg->crypto_key, +- cfg->data_unit_size, slot); +- else +- return qcom_ice_evict_key(msm_host->ice, slot); ++ return qcom_ice_program_key(msm_host->ice, ++ QCOM_ICE_CRYPTO_ALG_AES_XTS, ++ QCOM_ICE_CRYPTO_KEY_SIZE_256, ++ cfg->crypto_key, ++ cfg->data_unit_size, slot); + } + + #else /* CONFIG_MMC_CRYPTO */ +diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c +index a7e8fcdf25768b..59134d117846d1 100644 +--- a/drivers/net/dsa/microchip/ksz9477.c ++++ b/drivers/net/dsa/microchip/ksz9477.c +@@ -2,7 +2,7 @@ + /* + * Microchip KSZ9477 switch driver main logic + * +- * Copyright (C) 2017-2019 Microchip Technology Inc. ++ * Copyright (C) 2017-2024 Microchip Technology Inc. + */ + + #include +@@ -916,26 +916,51 @@ void ksz9477_get_caps(struct ksz_device *dev, int port, + int ksz9477_set_ageing_time(struct ksz_device *dev, unsigned int msecs) + { + u32 secs = msecs / 1000; +- u8 value; +- u8 data; ++ u8 data, mult, value; ++ u32 max_val; + int ret; + +- value = FIELD_GET(SW_AGE_PERIOD_7_0_M, secs); ++#define MAX_TIMER_VAL ((1 << 8) - 1) + +- ret = ksz_write8(dev, REG_SW_LUE_CTRL_3, value); +- if (ret < 0) +- return ret; ++ /* The aging timer comprises a 3-bit multiplier and an 8-bit second ++ * value. Either of them cannot be zero. The maximum timer is then ++ * 7 * 255 = 1785 seconds. ++ */ ++ if (!secs) ++ secs = 1; + +- data = FIELD_GET(SW_AGE_PERIOD_10_8_M, secs); ++ /* Return error if too large. */ ++ else if (secs > 7 * MAX_TIMER_VAL) ++ return -EINVAL; + + ret = ksz_read8(dev, REG_SW_LUE_CTRL_0, &value); + if (ret < 0) + return ret; + +- value &= ~SW_AGE_CNT_M; +- value |= FIELD_PREP(SW_AGE_CNT_M, data); ++ /* Check whether there is need to update the multiplier. */ ++ mult = FIELD_GET(SW_AGE_CNT_M, value); ++ max_val = MAX_TIMER_VAL; ++ if (mult > 0) { ++ /* Try to use the same multiplier already in the register as ++ * the hardware default uses multiplier 4 and 75 seconds for ++ * 300 seconds. ++ */ ++ max_val = DIV_ROUND_UP(secs, mult); ++ if (max_val > MAX_TIMER_VAL || max_val * mult != secs) ++ max_val = MAX_TIMER_VAL; ++ } ++ ++ data = DIV_ROUND_UP(secs, max_val); ++ if (mult != data) { ++ value &= ~SW_AGE_CNT_M; ++ value |= FIELD_PREP(SW_AGE_CNT_M, data); ++ ret = ksz_write8(dev, REG_SW_LUE_CTRL_0, value); ++ if (ret < 0) ++ return ret; ++ } + +- return ksz_write8(dev, REG_SW_LUE_CTRL_0, value); ++ value = DIV_ROUND_UP(secs, data); ++ return ksz_write8(dev, REG_SW_LUE_CTRL_3, value); + } + + void ksz9477_port_queue_split(struct ksz_device *dev, int port) +diff --git a/drivers/net/dsa/microchip/ksz9477_reg.h b/drivers/net/dsa/microchip/ksz9477_reg.h +index a2ef4b18349c41..d0886ed984c578 100644 +--- a/drivers/net/dsa/microchip/ksz9477_reg.h ++++ b/drivers/net/dsa/microchip/ksz9477_reg.h +@@ -2,7 +2,7 @@ + /* + * Microchip KSZ9477 register definitions + * +- * Copyright (C) 2017-2018 Microchip Technology Inc. ++ * Copyright (C) 2017-2024 Microchip Technology Inc. + */ + + #ifndef __KSZ9477_REGS_H +@@ -190,8 +190,6 @@ + #define SW_VLAN_ENABLE BIT(7) + #define SW_DROP_INVALID_VID BIT(6) + #define SW_AGE_CNT_M GENMASK(5, 3) +-#define SW_AGE_CNT_S 3 +-#define SW_AGE_PERIOD_10_8_M GENMASK(10, 8) + #define SW_RESV_MCAST_ENABLE BIT(2) + #define SW_HASH_OPTION_M 0x03 + #define SW_HASH_OPTION_CRC 1 +diff --git a/drivers/net/dsa/microchip/lan937x_main.c b/drivers/net/dsa/microchip/lan937x_main.c +index b479a628b1ae56..dde37e61faa359 100644 +--- a/drivers/net/dsa/microchip/lan937x_main.c ++++ b/drivers/net/dsa/microchip/lan937x_main.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /* Microchip LAN937X switch driver main logic +- * Copyright (C) 2019-2022 Microchip Technology Inc. ++ * Copyright (C) 2019-2024 Microchip Technology Inc. + */ + #include + #include +@@ -257,10 +257,66 @@ int lan937x_change_mtu(struct ksz_device *dev, int port, int new_mtu) + + int lan937x_set_ageing_time(struct ksz_device *dev, unsigned int msecs) + { +- u32 secs = msecs / 1000; +- u32 value; ++ u8 data, mult, value8; ++ bool in_msec = false; ++ u32 max_val, value; ++ u32 secs = msecs; + int ret; + ++#define MAX_TIMER_VAL ((1 << 20) - 1) ++ ++ /* The aging timer comprises a 3-bit multiplier and a 20-bit second ++ * value. Either of them cannot be zero. The maximum timer is then ++ * 7 * 1048575 = 7340025 seconds. As this value is too large for ++ * practical use it can be interpreted as microseconds, making the ++ * maximum timer 7340 seconds with finer control. This allows for ++ * maximum 122 minutes compared to 29 minutes in KSZ9477 switch. ++ */ ++ if (msecs % 1000) ++ in_msec = true; ++ else ++ secs /= 1000; ++ if (!secs) ++ secs = 1; ++ ++ /* Return error if too large. */ ++ else if (secs > 7 * MAX_TIMER_VAL) ++ return -EINVAL; ++ ++ /* Configure how to interpret the number value. */ ++ ret = ksz_rmw8(dev, REG_SW_LUE_CTRL_2, SW_AGE_CNT_IN_MICROSEC, ++ in_msec ? SW_AGE_CNT_IN_MICROSEC : 0); ++ if (ret < 0) ++ return ret; ++ ++ ret = ksz_read8(dev, REG_SW_LUE_CTRL_0, &value8); ++ if (ret < 0) ++ return ret; ++ ++ /* Check whether there is need to update the multiplier. */ ++ mult = FIELD_GET(SW_AGE_CNT_M, value8); ++ max_val = MAX_TIMER_VAL; ++ if (mult > 0) { ++ /* Try to use the same multiplier already in the register as ++ * the hardware default uses multiplier 4 and 75 seconds for ++ * 300 seconds. ++ */ ++ max_val = DIV_ROUND_UP(secs, mult); ++ if (max_val > MAX_TIMER_VAL || max_val * mult != secs) ++ max_val = MAX_TIMER_VAL; ++ } ++ ++ data = DIV_ROUND_UP(secs, max_val); ++ if (mult != data) { ++ value8 &= ~SW_AGE_CNT_M; ++ value8 |= FIELD_PREP(SW_AGE_CNT_M, data); ++ ret = ksz_write8(dev, REG_SW_LUE_CTRL_0, value8); ++ if (ret < 0) ++ return ret; ++ } ++ ++ secs = DIV_ROUND_UP(secs, data); ++ + value = FIELD_GET(SW_AGE_PERIOD_7_0_M, secs); + + ret = ksz_write8(dev, REG_SW_AGE_PERIOD__1, value); +diff --git a/drivers/net/dsa/microchip/lan937x_reg.h b/drivers/net/dsa/microchip/lan937x_reg.h +index 45b606b6429f65..b3e536e7c68694 100644 +--- a/drivers/net/dsa/microchip/lan937x_reg.h ++++ b/drivers/net/dsa/microchip/lan937x_reg.h +@@ -1,6 +1,6 @@ + /* SPDX-License-Identifier: GPL-2.0 */ + /* Microchip LAN937X switch register definitions +- * Copyright (C) 2019-2021 Microchip Technology Inc. ++ * Copyright (C) 2019-2024 Microchip Technology Inc. + */ + #ifndef __LAN937X_REG_H + #define __LAN937X_REG_H +@@ -48,8 +48,7 @@ + + #define SW_VLAN_ENABLE BIT(7) + #define SW_DROP_INVALID_VID BIT(6) +-#define SW_AGE_CNT_M 0x7 +-#define SW_AGE_CNT_S 3 ++#define SW_AGE_CNT_M GENMASK(5, 3) + #define SW_RESV_MCAST_ENABLE BIT(2) + + #define REG_SW_LUE_CTRL_1 0x0311 +@@ -62,6 +61,10 @@ + #define SW_FAST_AGING BIT(1) + #define SW_LINK_AUTO_AGING BIT(0) + ++#define REG_SW_LUE_CTRL_2 0x0312 ++ ++#define SW_AGE_CNT_IN_MICROSEC BIT(7) ++ + #define REG_SW_AGE_PERIOD__1 0x0313 + #define SW_AGE_PERIOD_7_0_M GENMASK(7, 0) + +diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c +index 49e890a7e04a37..23cc2d85994e42 100644 +--- a/drivers/net/ethernet/broadcom/bcmsysport.c ++++ b/drivers/net/ethernet/broadcom/bcmsysport.c +@@ -1967,7 +1967,11 @@ static int bcm_sysport_open(struct net_device *dev) + unsigned int i; + int ret; + +- clk_prepare_enable(priv->clk); ++ ret = clk_prepare_enable(priv->clk); ++ if (ret) { ++ netdev_err(dev, "could not enable priv clock\n"); ++ return ret; ++ } + + /* Reset UniMAC */ + umac_reset(priv); +@@ -2625,7 +2629,11 @@ static int bcm_sysport_probe(struct platform_device *pdev) + goto err_deregister_notifier; + } + +- clk_prepare_enable(priv->clk); ++ ret = clk_prepare_enable(priv->clk); ++ if (ret) { ++ dev_err(&pdev->dev, "could not enable priv clock\n"); ++ goto err_deregister_netdev; ++ } + + priv->rev = topctrl_readl(priv, REV_CNTL) & REV_MASK; + dev_info(&pdev->dev, +@@ -2639,6 +2647,8 @@ static int bcm_sysport_probe(struct platform_device *pdev) + + return 0; + ++err_deregister_netdev: ++ unregister_netdev(dev); + err_deregister_notifier: + unregister_netdevice_notifier(&priv->netdev_notifier); + err_deregister_fixed_link: +@@ -2810,7 +2820,12 @@ static int __maybe_unused bcm_sysport_resume(struct device *d) + if (!netif_running(dev)) + return 0; + +- clk_prepare_enable(priv->clk); ++ ret = clk_prepare_enable(priv->clk); ++ if (ret) { ++ netdev_err(dev, "could not enable priv clock\n"); ++ return ret; ++ } ++ + if (priv->wolopts) + clk_disable_unprepare(priv->wol_clk); + +diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c +index 5703240474e5b2..d70305654e7d07 100644 +--- a/drivers/net/ethernet/google/gve/gve_main.c ++++ b/drivers/net/ethernet/google/gve/gve_main.c +@@ -1528,8 +1528,8 @@ static int gve_xsk_pool_enable(struct net_device *dev, + if (err) + return err; + +- /* If XDP prog is not installed, return */ +- if (!priv->xdp_prog) ++ /* If XDP prog is not installed or interface is down, return. */ ++ if (!priv->xdp_prog || !netif_running(dev)) + return 0; + + rx = &priv->rx[qid]; +@@ -1574,21 +1574,16 @@ static int gve_xsk_pool_disable(struct net_device *dev, + if (qid >= priv->rx_cfg.num_queues) + return -EINVAL; + +- /* If XDP prog is not installed, unmap DMA and return */ +- if (!priv->xdp_prog) +- goto done; +- +- tx_qid = gve_xdp_tx_queue_id(priv, qid); +- if (!netif_running(dev)) { +- priv->rx[qid].xsk_pool = NULL; +- xdp_rxq_info_unreg(&priv->rx[qid].xsk_rxq); +- priv->tx[tx_qid].xsk_pool = NULL; ++ /* If XDP prog is not installed or interface is down, unmap DMA and ++ * return. ++ */ ++ if (!priv->xdp_prog || !netif_running(dev)) + goto done; +- } + + napi_rx = &priv->ntfy_blocks[priv->rx[qid].ntfy_id].napi; + napi_disable(napi_rx); /* make sure current rx poll is done */ + ++ tx_qid = gve_xdp_tx_queue_id(priv, qid); + napi_tx = &priv->ntfy_blocks[priv->tx[tx_qid].ntfy_id].napi; + napi_disable(napi_tx); /* make sure current tx poll is done */ + +@@ -1616,6 +1611,9 @@ static int gve_xsk_wakeup(struct net_device *dev, u32 queue_id, u32 flags) + struct gve_priv *priv = netdev_priv(dev); + int tx_queue_id = gve_xdp_tx_queue_id(priv, queue_id); + ++ if (!gve_get_napi_enabled(priv)) ++ return -ENETDOWN; ++ + if (queue_id >= priv->rx_cfg.num_queues || !priv->xdp_prog) + return -EINVAL; + +@@ -1757,6 +1755,9 @@ static void gve_turndown(struct gve_priv *priv) + + gve_clear_napi_enabled(priv); + gve_clear_report_stats(priv); ++ ++ /* Make sure that all traffic is finished processing. */ ++ synchronize_net(); + } + + static void gve_turnup(struct gve_priv *priv) +diff --git a/drivers/net/ethernet/google/gve/gve_tx.c b/drivers/net/ethernet/google/gve/gve_tx.c +index 2ae891a62875c7..29987624791a68 100644 +--- a/drivers/net/ethernet/google/gve/gve_tx.c ++++ b/drivers/net/ethernet/google/gve/gve_tx.c +@@ -777,9 +777,12 @@ int gve_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames, + struct gve_tx_ring *tx; + int i, err = 0, qid; + +- if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK)) ++ if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK) || !priv->xdp_prog) + return -EINVAL; + ++ if (!gve_get_napi_enabled(priv)) ++ return -ENETDOWN; ++ + qid = gve_xdp_tx_queue_id(priv, + smp_processor_id() % priv->num_xdp_queues); + +diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c +index 3b129a1c338152..07e5051171a48a 100644 +--- a/drivers/net/ethernet/marvell/mv643xx_eth.c ++++ b/drivers/net/ethernet/marvell/mv643xx_eth.c +@@ -2708,9 +2708,15 @@ static struct platform_device *port_platdev[3]; + + static void mv643xx_eth_shared_of_remove(void) + { ++ struct mv643xx_eth_platform_data *pd; + int n; + + for (n = 0; n < 3; n++) { ++ if (!port_platdev[n]) ++ continue; ++ pd = dev_get_platdata(&port_platdev[n]->dev); ++ if (pd) ++ of_node_put(pd->phy_node); + platform_device_del(port_platdev[n]); + port_platdev[n] = NULL; + } +@@ -2773,8 +2779,10 @@ static int mv643xx_eth_shared_of_add_port(struct platform_device *pdev, + } + + ppdev = platform_device_alloc(MV643XX_ETH_NAME, dev_num); +- if (!ppdev) +- return -ENOMEM; ++ if (!ppdev) { ++ ret = -ENOMEM; ++ goto put_err; ++ } + ppdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); + ppdev->dev.of_node = pnp; + +@@ -2796,6 +2804,8 @@ static int mv643xx_eth_shared_of_add_port(struct platform_device *pdev, + + port_err: + platform_device_put(ppdev); ++put_err: ++ of_node_put(ppd.phy_node); + return ret; + } + +diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c +index 07720841a8d700..dd3d93720358bd 100644 +--- a/drivers/net/ethernet/marvell/sky2.c ++++ b/drivers/net/ethernet/marvell/sky2.c +@@ -129,6 +129,7 @@ static const struct pci_device_id sky2_id_table[] = { + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436C) }, /* 88E8072 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436D) }, /* 88E8055 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4370) }, /* 88E8075 */ ++ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4373) }, /* 88E8075 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4380) }, /* 88E8057 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4381) }, /* 88E8059 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4382) }, /* 88E8079 */ +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c +index cc9bcc42003242..6ab02f3fc29123 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c +@@ -339,9 +339,13 @@ static int mlx5e_macsec_init_sa_fs(struct macsec_context *ctx, + { + struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev); + struct mlx5_macsec_fs *macsec_fs = priv->mdev->macsec_fs; ++ const struct macsec_tx_sc *tx_sc = &ctx->secy->tx_sc; + struct mlx5_macsec_rule_attrs rule_attrs; + union mlx5_macsec_rule *macsec_rule; + ++ if (is_tx && tx_sc->encoding_sa != sa->assoc_num) ++ return 0; ++ + rule_attrs.macsec_obj_id = sa->macsec_obj_id; + rule_attrs.sci = sa->sci; + rule_attrs.assoc_num = sa->assoc_num; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c +index 13b5916b64e224..eed8fcde261384 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c +@@ -150,11 +150,11 @@ void mlx5_esw_ipsec_restore_dest_uplink(struct mlx5_core_dev *mdev) + unsigned long i; + int err; + +- xa_for_each(&esw->offloads.vport_reps, i, rep) { +- rpriv = rep->rep_data[REP_ETH].priv; +- if (!rpriv || !rpriv->netdev) ++ mlx5_esw_for_each_rep(esw, i, rep) { ++ if (atomic_read(&rep->rep_data[REP_ETH].state) != REP_LOADED) + continue; + ++ rpriv = rep->rep_data[REP_ETH].priv; + rhashtable_walk_enter(&rpriv->tc_ht, &iter); + rhashtable_walk_start(&iter); + while ((flow = rhashtable_walk_next(&iter)) != NULL) { +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +index 9b771b572593b5..3e58e731b5697c 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +@@ -713,6 +713,9 @@ void mlx5e_tc_clean_fdb_peer_flows(struct mlx5_eswitch *esw); + MLX5_CAP_GEN_2((esw->dev), ec_vf_vport_base) +\ + (last) - 1) + ++#define mlx5_esw_for_each_rep(esw, i, rep) \ ++ xa_for_each(&((esw)->offloads.vport_reps), i, rep) ++ + struct mlx5_eswitch *__must_check + mlx5_devlink_eswitch_get(struct devlink *devlink); + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +index 58529d1a98b37b..7eba3a5bb97cae 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +@@ -52,9 +52,6 @@ + #include "lag/lag.h" + #include "en/tc/post_meter.h" + +-#define mlx5_esw_for_each_rep(esw, i, rep) \ +- xa_for_each(&((esw)->offloads.vport_reps), i, rep) +- + /* There are two match-all miss flows, one for unicast dst mac and + * one for multicast. + */ +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +index 991250f44c2ed1..474e63d02ba492 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +@@ -3478,6 +3478,7 @@ void mlx5_fs_core_free(struct mlx5_core_dev *dev) + int mlx5_fs_core_alloc(struct mlx5_core_dev *dev) + { + struct mlx5_flow_steering *steering; ++ char name[80]; + int err = 0; + + err = mlx5_init_fc_stats(dev); +@@ -3502,10 +3503,12 @@ int mlx5_fs_core_alloc(struct mlx5_core_dev *dev) + else + steering->mode = MLX5_FLOW_STEERING_MODE_DMFS; + +- steering->fgs_cache = kmem_cache_create("mlx5_fs_fgs", ++ snprintf(name, sizeof(name), "%s-mlx5_fs_fgs", dev_name(dev->device)); ++ steering->fgs_cache = kmem_cache_create(name, + sizeof(struct mlx5_flow_group), 0, + 0, NULL); +- steering->ftes_cache = kmem_cache_create("mlx5_fs_ftes", sizeof(struct fs_fte), 0, ++ snprintf(name, sizeof(name), "%s-mlx5_fs_ftes", dev_name(dev->device)); ++ steering->ftes_cache = kmem_cache_create(name, sizeof(struct fs_fte), 0, + 0, NULL); + if (!steering->ftes_cache || !steering->fgs_cache) { + err = -ENOMEM; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c +index 6fa06ba2d34653..f57c84e5128bc7 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c +@@ -1067,7 +1067,6 @@ static struct mlx5dr_cq *dr_create_cq(struct mlx5_core_dev *mdev, + int inlen, err, eqn; + void *cqc, *in; + __be64 *pas; +- int vector; + u32 i; + + cq = kzalloc(sizeof(*cq), GFP_KERNEL); +@@ -1096,8 +1095,7 @@ static struct mlx5dr_cq *dr_create_cq(struct mlx5_core_dev *mdev, + if (!in) + goto err_cqwq; + +- vector = raw_smp_processor_id() % mlx5_comp_vectors_max(mdev); +- err = mlx5_comp_eqn_get(mdev, vector, &eqn); ++ err = mlx5_comp_eqn_get(mdev, 0, &eqn); + if (err) { + kvfree(in); + goto err_cqwq; +diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c +index dcd198104141f1..fa3fef2b74db0d 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c +@@ -423,8 +423,7 @@ mlxsw_sp_span_gretap4_route(const struct net_device *to_dev, + + parms = mlxsw_sp_ipip_netdev_parms4(to_dev); + ip_tunnel_init_flow(&fl4, parms.iph.protocol, *daddrp, *saddrp, +- 0, 0, dev_net(to_dev), parms.link, tun->fwmark, 0, +- 0); ++ 0, 0, tun->net, parms.link, tun->fwmark, 0, 0); + + rt = ip_route_output_key(tun->net, &fl4); + if (IS_ERR(rt)) +diff --git a/drivers/net/ethernet/renesas/rswitch.c b/drivers/net/ethernet/renesas/rswitch.c +index 54aa56c841334c..2f483531d95cb7 100644 +--- a/drivers/net/ethernet/renesas/rswitch.c ++++ b/drivers/net/ethernet/renesas/rswitch.c +@@ -1632,8 +1632,9 @@ static netdev_tx_t rswitch_start_xmit(struct sk_buff *skb, struct net_device *nd + if (dma_mapping_error(ndev->dev.parent, dma_addr_orig)) + goto err_kfree; + +- gq->skbs[gq->cur] = skb; +- gq->unmap_addrs[gq->cur] = dma_addr_orig; ++ /* Stored the skb at the last descriptor to avoid skb free before hardware completes send */ ++ gq->skbs[(gq->cur + nr_desc - 1) % gq->ring_size] = skb; ++ gq->unmap_addrs[(gq->cur + nr_desc - 1) % gq->ring_size] = dma_addr_orig; + + dma_wmb(); + +diff --git a/drivers/net/ethernet/sfc/tc_conntrack.c b/drivers/net/ethernet/sfc/tc_conntrack.c +index 44bb57670340da..109d2aa34ae332 100644 +--- a/drivers/net/ethernet/sfc/tc_conntrack.c ++++ b/drivers/net/ethernet/sfc/tc_conntrack.c +@@ -16,7 +16,7 @@ static int efx_tc_flow_block(enum tc_setup_type type, void *type_data, + void *cb_priv); + + static const struct rhashtable_params efx_tc_ct_zone_ht_params = { +- .key_len = offsetof(struct efx_tc_ct_zone, linkage), ++ .key_len = sizeof_field(struct efx_tc_ct_zone, zone), + .key_offset = 0, + .head_offset = offsetof(struct efx_tc_ct_zone, linkage), + }; +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +index b4fdd40be63cb4..4d570efd9d4bbe 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +@@ -296,62 +296,80 @@ static int stmmac_mtl_setup(struct platform_device *pdev, + } + + /** +- * stmmac_dt_phy - parse device-tree driver parameters to allocate PHY resources +- * @plat: driver data platform structure +- * @np: device tree node +- * @dev: device pointer +- * Description: +- * The mdio bus will be allocated in case of a phy transceiver is on board; +- * it will be NULL if the fixed-link is configured. +- * If there is the "snps,dwmac-mdio" sub-node the mdio will be allocated +- * in any case (for DSA, mdio must be registered even if fixed-link). +- * The table below sums the supported configurations: +- * ------------------------------- +- * snps,phy-addr | Y +- * ------------------------------- +- * phy-handle | Y +- * ------------------------------- +- * fixed-link | N +- * ------------------------------- +- * snps,dwmac-mdio | +- * even if | Y +- * fixed-link | +- * ------------------------------- ++ * stmmac_of_get_mdio() - Gets the MDIO bus from the devicetree. ++ * @np: devicetree node ++ * ++ * The MDIO bus will be searched for in the following ways: ++ * 1. The compatible is "snps,dwc-qos-ethernet-4.10" && a "mdio" named ++ * child node exists ++ * 2. A child node with the "snps,dwmac-mdio" compatible is present + * +- * It returns 0 in case of success otherwise -ENODEV. ++ * Return: The MDIO node if present otherwise NULL + */ +-static int stmmac_dt_phy(struct plat_stmmacenet_data *plat, +- struct device_node *np, struct device *dev) ++static struct device_node *stmmac_of_get_mdio(struct device_node *np) + { +- bool mdio = !of_phy_is_fixed_link(np); + static const struct of_device_id need_mdio_ids[] = { + { .compatible = "snps,dwc-qos-ethernet-4.10" }, + {}, + }; ++ struct device_node *mdio_node = NULL; + + if (of_match_node(need_mdio_ids, np)) { +- plat->mdio_node = of_get_child_by_name(np, "mdio"); ++ mdio_node = of_get_child_by_name(np, "mdio"); + } else { + /** + * If snps,dwmac-mdio is passed from DT, always register + * the MDIO + */ +- for_each_child_of_node(np, plat->mdio_node) { +- if (of_device_is_compatible(plat->mdio_node, ++ for_each_child_of_node(np, mdio_node) { ++ if (of_device_is_compatible(mdio_node, + "snps,dwmac-mdio")) + break; + } + } + +- if (plat->mdio_node) { ++ return mdio_node; ++} ++ ++/** ++ * stmmac_mdio_setup() - Populate platform related MDIO structures. ++ * @plat: driver data platform structure ++ * @np: devicetree node ++ * @dev: device pointer ++ * ++ * This searches for MDIO information from the devicetree. ++ * If an MDIO node is found, it's assigned to plat->mdio_node and ++ * plat->mdio_bus_data is allocated. ++ * If no connection can be determined, just plat->mdio_bus_data is allocated ++ * to indicate a bus should be created and scanned for a phy. ++ * If it's determined there's no MDIO bus needed, both are left NULL. ++ * ++ * This expects that plat->phy_node has already been searched for. ++ * ++ * Return: 0 on success, errno otherwise. ++ */ ++static int stmmac_mdio_setup(struct plat_stmmacenet_data *plat, ++ struct device_node *np, struct device *dev) ++{ ++ bool legacy_mdio; ++ ++ plat->mdio_node = stmmac_of_get_mdio(np); ++ if (plat->mdio_node) + dev_dbg(dev, "Found MDIO subnode\n"); +- mdio = true; +- } + +- if (mdio) { +- plat->mdio_bus_data = +- devm_kzalloc(dev, sizeof(struct stmmac_mdio_bus_data), +- GFP_KERNEL); ++ /* Legacy devicetrees allowed for no MDIO bus description and expect ++ * the bus to be scanned for devices. If there's no phy or fixed-link ++ * described assume this is the case since there must be something ++ * connected to the MAC. ++ */ ++ legacy_mdio = !of_phy_is_fixed_link(np) && !plat->phy_node; ++ if (legacy_mdio) ++ dev_info(dev, "Deprecated MDIO bus assumption used\n"); ++ ++ if (plat->mdio_node || legacy_mdio) { ++ plat->mdio_bus_data = devm_kzalloc(dev, ++ sizeof(*plat->mdio_bus_data), ++ GFP_KERNEL); + if (!plat->mdio_bus_data) + return -ENOMEM; + +@@ -455,10 +473,11 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac) + if (of_property_read_u32(np, "snps,phy-addr", &plat->phy_addr) == 0) + dev_warn(&pdev->dev, "snps,phy-addr property is deprecated\n"); + +- /* To Configure PHY by using all device-tree supported properties */ +- rc = stmmac_dt_phy(plat, np, &pdev->dev); +- if (rc) +- return ERR_PTR(rc); ++ rc = stmmac_mdio_setup(plat, np, &pdev->dev); ++ if (rc) { ++ ret = ERR_PTR(rc); ++ goto error_put_phy; ++ } + + of_property_read_u32(np, "tx-fifo-depth", &plat->tx_fifo_size); + +@@ -547,8 +566,8 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac) + dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg), + GFP_KERNEL); + if (!dma_cfg) { +- stmmac_remove_config_dt(pdev, plat); +- return ERR_PTR(-ENOMEM); ++ ret = ERR_PTR(-ENOMEM); ++ goto error_put_mdio; + } + plat->dma_cfg = dma_cfg; + +@@ -576,8 +595,8 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac) + + rc = stmmac_mtl_setup(pdev, plat); + if (rc) { +- stmmac_remove_config_dt(pdev, plat); +- return ERR_PTR(rc); ++ ret = ERR_PTR(rc); ++ goto error_put_mdio; + } + + /* clock setup */ +@@ -629,6 +648,10 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac) + clk_disable_unprepare(plat->pclk); + error_pclk_get: + clk_disable_unprepare(plat->stmmac_clk); ++error_put_mdio: ++ of_node_put(plat->mdio_node); ++error_put_phy: ++ of_node_put(plat->phy_node); + + return ret; + } +@@ -637,16 +660,17 @@ static void devm_stmmac_remove_config_dt(void *data) + { + struct plat_stmmacenet_data *plat = data; + +- /* Platform data argument is unused */ +- stmmac_remove_config_dt(NULL, plat); ++ clk_disable_unprepare(plat->stmmac_clk); ++ clk_disable_unprepare(plat->pclk); ++ of_node_put(plat->mdio_node); ++ of_node_put(plat->phy_node); + } + + /** + * devm_stmmac_probe_config_dt + * @pdev: platform_device structure + * @mac: MAC address to use +- * Description: Devres variant of stmmac_probe_config_dt(). Does not require +- * the user to call stmmac_remove_config_dt() at driver detach. ++ * Description: Devres variant of stmmac_probe_config_dt(). + */ + struct plat_stmmacenet_data * + devm_stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac) +diff --git a/drivers/net/ethernet/ti/icssg/icss_iep.c b/drivers/net/ethernet/ti/icssg/icss_iep.c +index 3025e9c189702b..f06cdec14ed7a1 100644 +--- a/drivers/net/ethernet/ti/icssg/icss_iep.c ++++ b/drivers/net/ethernet/ti/icssg/icss_iep.c +@@ -290,6 +290,9 @@ static void icss_iep_enable_shadow_mode(struct icss_iep *iep) + for (cmp = IEP_MIN_CMP; cmp < IEP_MAX_CMP; cmp++) { + regmap_update_bits(iep->map, ICSS_IEP_CMP_STAT_REG, + IEP_CMP_STATUS(cmp), IEP_CMP_STATUS(cmp)); ++ ++ regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG, ++ IEP_CMP_CFG_CMP_EN(cmp), 0); + } + + /* enable reset counter on CMP0 event */ +@@ -808,6 +811,11 @@ int icss_iep_exit(struct icss_iep *iep) + } + icss_iep_disable(iep); + ++ if (iep->pps_enabled) ++ icss_iep_pps_enable(iep, false); ++ else if (iep->perout_enabled) ++ icss_iep_perout_enable(iep, NULL, false); ++ + return 0; + } + EXPORT_SYMBOL_GPL(icss_iep_exit); +diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c +index 89775b6d0699a0..8e30df676ededb 100644 +--- a/drivers/net/usb/qmi_wwan.c ++++ b/drivers/net/usb/qmi_wwan.c +@@ -1373,6 +1373,9 @@ static const struct usb_device_id products[] = { + {QMI_QUIRK_SET_DTR(0x1bc7, 0x10a0, 0)}, /* Telit FN920C04 */ + {QMI_QUIRK_SET_DTR(0x1bc7, 0x10a4, 0)}, /* Telit FN920C04 */ + {QMI_QUIRK_SET_DTR(0x1bc7, 0x10a9, 0)}, /* Telit FN920C04 */ ++ {QMI_QUIRK_SET_DTR(0x1bc7, 0x10c0, 0)}, /* Telit FE910C04 */ ++ {QMI_QUIRK_SET_DTR(0x1bc7, 0x10c4, 0)}, /* Telit FE910C04 */ ++ {QMI_QUIRK_SET_DTR(0x1bc7, 0x10c8, 0)}, /* Telit FE910C04 */ + {QMI_FIXED_INTF(0x1bc7, 0x1100, 3)}, /* Telit ME910 */ + {QMI_FIXED_INTF(0x1bc7, 0x1101, 3)}, /* Telit ME910 dual modem */ + {QMI_FIXED_INTF(0x1bc7, 0x1200, 5)}, /* Telit LE920 */ +diff --git a/drivers/net/wireless/ath/ath10k/bmi.c b/drivers/net/wireless/ath/ath10k/bmi.c +index af6546572df26b..9a4f8e815412cb 100644 +--- a/drivers/net/wireless/ath/ath10k/bmi.c ++++ b/drivers/net/wireless/ath/ath10k/bmi.c +@@ -2,6 +2,7 @@ + /* + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2014,2016-2017 Qualcomm Atheros, Inc. ++ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #include "bmi.h" +diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c +index c27b8204718a6d..afae4a8027f833 100644 +--- a/drivers/net/wireless/ath/ath10k/ce.c ++++ b/drivers/net/wireless/ath/ath10k/ce.c +@@ -3,6 +3,7 @@ + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. + * Copyright (c) 2018 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #include "hif.h" +diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c +index 81058be3598f15..c3a8b3496be2a5 100644 +--- a/drivers/net/wireless/ath/ath10k/core.c ++++ b/drivers/net/wireless/ath/ath10k/core.c +@@ -3,6 +3,7 @@ + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #include +diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h +index 4b5239de401840..cb2359d2ee0b04 100644 +--- a/drivers/net/wireless/ath/ath10k/core.h ++++ b/drivers/net/wireless/ath/ath10k/core.h +@@ -3,6 +3,7 @@ + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #ifndef _CORE_H_ +diff --git a/drivers/net/wireless/ath/ath10k/coredump.c b/drivers/net/wireless/ath/ath10k/coredump.c +index 2d1634a890dde3..bb3a276b7ed584 100644 +--- a/drivers/net/wireless/ath/ath10k/coredump.c ++++ b/drivers/net/wireless/ath/ath10k/coredump.c +@@ -2,6 +2,7 @@ + /* + * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. + * Copyright (c) 2018, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #include "coredump.h" +diff --git a/drivers/net/wireless/ath/ath10k/coredump.h b/drivers/net/wireless/ath/ath10k/coredump.h +index 437b9759f05d3d..e5ef0352e319c7 100644 +--- a/drivers/net/wireless/ath/ath10k/coredump.h ++++ b/drivers/net/wireless/ath/ath10k/coredump.h +@@ -1,6 +1,7 @@ + /* SPDX-License-Identifier: ISC */ + /* + * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. ++ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #ifndef _COREDUMP_H_ +diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c +index fe89bc61e5317d..92ad0a04bcc738 100644 +--- a/drivers/net/wireless/ath/ath10k/debug.c ++++ b/drivers/net/wireless/ath/ath10k/debug.c +@@ -3,6 +3,7 @@ + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. + * Copyright (c) 2018, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #include +diff --git a/drivers/net/wireless/ath/ath10k/debugfs_sta.c b/drivers/net/wireless/ath/ath10k/debugfs_sta.c +index 5598cf706daabc..0f6de862c3a9ba 100644 +--- a/drivers/net/wireless/ath/ath10k/debugfs_sta.c ++++ b/drivers/net/wireless/ath/ath10k/debugfs_sta.c +@@ -2,6 +2,7 @@ + /* + * Copyright (c) 2014-2017 Qualcomm Atheros, Inc. + * Copyright (c) 2018, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #include "core.h" +diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c +index 5bfeecb95fca23..a6e21ce90bad64 100644 +--- a/drivers/net/wireless/ath/ath10k/htc.c ++++ b/drivers/net/wireless/ath/ath10k/htc.c +@@ -2,6 +2,7 @@ + /* + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. ++ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #include "core.h" +diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h +index 7b24297146e72a..52f6dc6b81c5ee 100644 +--- a/drivers/net/wireless/ath/ath10k/htt.h ++++ b/drivers/net/wireless/ath/ath10k/htt.h +@@ -3,6 +3,7 @@ + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. + * Copyright (c) 2018, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2021, 2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #ifndef _HTT_H_ +diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c +index 438b0caaceb79e..51855f23ea2664 100644 +--- a/drivers/net/wireless/ath/ath10k/htt_rx.c ++++ b/drivers/net/wireless/ath/ath10k/htt_rx.c +@@ -3,6 +3,7 @@ + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. + * Copyright (c) 2018, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #include "core.h" +diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c +index bd603feb795314..60425d22d70790 100644 +--- a/drivers/net/wireless/ath/ath10k/htt_tx.c ++++ b/drivers/net/wireless/ath/ath10k/htt_tx.c +@@ -2,6 +2,7 @@ + /* + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. ++ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #include +diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c +index 6d32b43a4da65e..8fafe096adff53 100644 +--- a/drivers/net/wireless/ath/ath10k/hw.c ++++ b/drivers/net/wireless/ath/ath10k/hw.c +@@ -1,6 +1,7 @@ + // SPDX-License-Identifier: ISC + /* + * Copyright (c) 2014-2017 Qualcomm Atheros, Inc. ++ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #include +diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h +index 7ecdd0011cfa48..afd336282615c6 100644 +--- a/drivers/net/wireless/ath/ath10k/hw.h ++++ b/drivers/net/wireless/ath/ath10k/hw.h +@@ -3,6 +3,7 @@ + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. + * Copyright (c) 2018 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #ifndef _HW_H_ +diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c +index d5e6e11f630b95..655fb5cdf01f86 100644 +--- a/drivers/net/wireless/ath/ath10k/mac.c ++++ b/drivers/net/wireless/ath/ath10k/mac.c +@@ -3,6 +3,7 @@ + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #include "mac.h" +diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c +index 23f36622193908..aaa240f3c08a9f 100644 +--- a/drivers/net/wireless/ath/ath10k/pci.c ++++ b/drivers/net/wireless/ath/ath10k/pci.c +@@ -2,6 +2,7 @@ + /* + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. ++ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #include +diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h +index 480cd97ab739de..27bb4cf2dfea93 100644 +--- a/drivers/net/wireless/ath/ath10k/pci.h ++++ b/drivers/net/wireless/ath/ath10k/pci.h +@@ -2,6 +2,7 @@ + /* + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. ++ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #ifndef _PCI_H_ +diff --git a/drivers/net/wireless/ath/ath10k/qmi.c b/drivers/net/wireless/ath/ath10k/qmi.c +index 52c1a3de8da60a..38e939f572a9ed 100644 +--- a/drivers/net/wireless/ath/ath10k/qmi.c ++++ b/drivers/net/wireless/ath/ath10k/qmi.c +@@ -1,6 +1,7 @@ + // SPDX-License-Identifier: ISC + /* + * Copyright (c) 2018 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #include +diff --git a/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.c b/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.c +index 1c81e454f943fd..0e85c75d227836 100644 +--- a/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.c ++++ b/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.c +@@ -1,6 +1,7 @@ + // SPDX-License-Identifier: ISC + /* + * Copyright (c) 2018 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #include +diff --git a/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.h b/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.h +index f0db991408dc26..9f311f3bc9e7f9 100644 +--- a/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.h ++++ b/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.h +@@ -1,6 +1,7 @@ + /* SPDX-License-Identifier: ISC */ + /* + * Copyright (c) 2018 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #ifndef WCN3990_QMI_SVC_V01_H +diff --git a/drivers/net/wireless/ath/ath10k/rx_desc.h b/drivers/net/wireless/ath/ath10k/rx_desc.h +index 777e53aa69dc86..564293df1e9acf 100644 +--- a/drivers/net/wireless/ath/ath10k/rx_desc.h ++++ b/drivers/net/wireless/ath/ath10k/rx_desc.h +@@ -2,6 +2,7 @@ + /* + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. ++ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #ifndef _RX_DESC_H_ +diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c +index 56fbcfb80bf886..850d999615a2c3 100644 +--- a/drivers/net/wireless/ath/ath10k/sdio.c ++++ b/drivers/net/wireless/ath/ath10k/sdio.c +@@ -3,6 +3,7 @@ + * Copyright (c) 2004-2011 Atheros Communications Inc. + * Copyright (c) 2011-2012,2017 Qualcomm Atheros, Inc. + * Copyright (c) 2016-2017 Erik Stromdahl ++ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #include +@@ -2647,9 +2648,9 @@ static void ath10k_sdio_remove(struct sdio_func *func) + + netif_napi_del(&ar->napi); + +- ath10k_core_destroy(ar); +- + destroy_workqueue(ar_sdio->workqueue); ++ ++ ath10k_core_destroy(ar); + } + + static const struct sdio_device_id ath10k_sdio_devices[] = { +diff --git a/drivers/net/wireless/ath/ath10k/thermal.c b/drivers/net/wireless/ath/ath10k/thermal.c +index cefd97323dfe50..31c8d7fbb0955b 100644 +--- a/drivers/net/wireless/ath/ath10k/thermal.c ++++ b/drivers/net/wireless/ath/ath10k/thermal.c +@@ -1,6 +1,7 @@ + // SPDX-License-Identifier: ISC + /* + * Copyright (c) 2014-2015 Qualcomm Atheros, Inc. ++ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #include +diff --git a/drivers/net/wireless/ath/ath10k/usb.h b/drivers/net/wireless/ath/ath10k/usb.h +index 48e066ba816249..7e4cfbb673c9a8 100644 +--- a/drivers/net/wireless/ath/ath10k/usb.h ++++ b/drivers/net/wireless/ath/ath10k/usb.h +@@ -3,6 +3,7 @@ + * Copyright (c) 2004-2011 Atheros Communications Inc. + * Copyright (c) 2011-2012 Qualcomm Atheros, Inc. + * Copyright (c) 2016-2017 Erik Stromdahl ++ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #ifndef _USB_H_ +diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h +index dbb48d70f2e93e..83a8f07a687f73 100644 +--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h ++++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h +@@ -3,6 +3,7 @@ + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + #ifndef _WMI_TLV_H + #define _WMI_TLV_H +diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c +index 1c21dbde77b84e..818aea99f85eb3 100644 +--- a/drivers/net/wireless/ath/ath10k/wmi.c ++++ b/drivers/net/wireless/ath/ath10k/wmi.c +@@ -3,6 +3,7 @@ + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #include +diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h +index b112e88260931c..9146df98fceeee 100644 +--- a/drivers/net/wireless/ath/ath10k/wmi.h ++++ b/drivers/net/wireless/ath/ath10k/wmi.h +@@ -3,6 +3,7 @@ + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #ifndef _WMI_H_ +diff --git a/drivers/net/wireless/ath/ath10k/wow.c b/drivers/net/wireless/ath/ath10k/wow.c +index 20b9aa8ddf7d52..aa7b2e703f3d4b 100644 +--- a/drivers/net/wireless/ath/ath10k/wow.c ++++ b/drivers/net/wireless/ath/ath10k/wow.c +@@ -2,6 +2,7 @@ + /* + * Copyright (c) 2015-2017 Qualcomm Atheros, Inc. + * Copyright (c) 2018, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #include "mac.h" +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index f90191a290c26a..713899735ccc5e 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -4945,7 +4945,7 @@ static void ath12k_mac_op_tx(struct ieee80211_hw *hw, + if (ret) { + ath12k_warn(ar->ab, "failed to queue management frame %d\n", + ret); +- ieee80211_free_txskb(ar->hw, skb); ++ ieee80211_free_txskb(hw, skb); + } + return; + } +@@ -4953,7 +4953,7 @@ static void ath12k_mac_op_tx(struct ieee80211_hw *hw, + ret = ath12k_dp_tx(ar, arvif, skb); + if (ret) { + ath12k_warn(ar->ab, "failed to transmit frame %d\n", ret); +- ieee80211_free_txskb(ar->hw, skb); ++ ieee80211_free_txskb(hw, skb); + } + } + +@@ -5496,7 +5496,7 @@ static int ath12k_mac_op_add_interface(struct ieee80211_hw *hw, + goto err_peer_del; + + param_id = WMI_VDEV_PARAM_RTS_THRESHOLD; +- param_value = ar->hw->wiphy->rts_threshold; ++ param_value = hw->wiphy->rts_threshold; + ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, + param_id, param_value); + if (ret) { +@@ -6676,9 +6676,9 @@ ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, + arvif->vdev_id, ret); + return ret; + } +- ieee80211_iterate_stations_atomic(ar->hw, +- ath12k_mac_disable_peer_fixed_rate, +- arvif); ++ ieee80211_iterate_stations_mtx(hw, ++ ath12k_mac_disable_peer_fixed_rate, ++ arvif); + } else if (ath12k_mac_bitrate_mask_get_single_nss(ar, band, mask, + &single_nss)) { + rate = WMI_FIXED_RATE_NONE; +@@ -6722,16 +6722,16 @@ ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, + return -EINVAL; + } + +- ieee80211_iterate_stations_atomic(ar->hw, +- ath12k_mac_disable_peer_fixed_rate, +- arvif); ++ ieee80211_iterate_stations_mtx(hw, ++ ath12k_mac_disable_peer_fixed_rate, ++ arvif); + + mutex_lock(&ar->conf_mutex); + + arvif->bitrate_mask = *mask; +- ieee80211_iterate_stations_atomic(ar->hw, +- ath12k_mac_set_bitrate_mask_iter, +- arvif); ++ ieee80211_iterate_stations_mtx(hw, ++ ath12k_mac_set_bitrate_mask_iter, ++ arvif); + + mutex_unlock(&ar->conf_mutex); + } +@@ -6767,7 +6767,7 @@ ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw, + ath12k_warn(ar->ab, "pdev %d successfully recovered\n", + ar->pdev->pdev_id); + ar->state = ATH12K_STATE_ON; +- ieee80211_wake_queues(ar->hw); ++ ieee80211_wake_queues(hw); + + if (ab->is_reset) { + recovery_count = atomic_inc_return(&ab->recovery_count); +diff --git a/drivers/net/wireless/ath/ath12k/reg.c b/drivers/net/wireless/ath/ath12k/reg.c +index 32bdefeccc2453..837a3e1ec3a49c 100644 +--- a/drivers/net/wireless/ath/ath12k/reg.c ++++ b/drivers/net/wireless/ath/ath12k/reg.c +@@ -28,11 +28,11 @@ static const struct ieee80211_regdomain ath12k_world_regd = { + } + }; + +-static bool ath12k_regdom_changes(struct ath12k *ar, char *alpha2) ++static bool ath12k_regdom_changes(struct ieee80211_hw *hw, char *alpha2) + { + const struct ieee80211_regdomain *regd; + +- regd = rcu_dereference_rtnl(ar->hw->wiphy->regd); ++ regd = rcu_dereference_rtnl(hw->wiphy->regd); + /* This can happen during wiphy registration where the previous + * user request is received before we update the regd received + * from firmware. +@@ -71,7 +71,7 @@ ath12k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) + return; + } + +- if (!ath12k_regdom_changes(ar, request->alpha2)) { ++ if (!ath12k_regdom_changes(hw, request->alpha2)) { + ath12k_dbg(ar->ab, ATH12K_DBG_REG, "Country is already set\n"); + return; + } +diff --git a/drivers/net/wireless/realtek/rtw88/sdio.c b/drivers/net/wireless/realtek/rtw88/sdio.c +index 0cae5746f540fa..5bd1ee81210d1d 100644 +--- a/drivers/net/wireless/realtek/rtw88/sdio.c ++++ b/drivers/net/wireless/realtek/rtw88/sdio.c +@@ -1295,12 +1295,12 @@ static void rtw_sdio_deinit_tx(struct rtw_dev *rtwdev) + struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv; + int i; + +- for (i = 0; i < RTK_MAX_TX_QUEUE_NUM; i++) +- skb_queue_purge(&rtwsdio->tx_queue[i]); +- + flush_workqueue(rtwsdio->txwq); + destroy_workqueue(rtwsdio->txwq); + kfree(rtwsdio->tx_handler_data); ++ ++ for (i = 0; i < RTK_MAX_TX_QUEUE_NUM; i++) ++ ieee80211_purge_tx_queue(rtwdev->hw, &rtwsdio->tx_queue[i]); + } + + int rtw_sdio_probe(struct sdio_func *sdio_func, +diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c +index 04a64afcbf8a2d..8f1d653282b7ec 100644 +--- a/drivers/net/wireless/realtek/rtw88/usb.c ++++ b/drivers/net/wireless/realtek/rtw88/usb.c +@@ -416,10 +416,11 @@ static void rtw_usb_tx_handler(struct work_struct *work) + + static void rtw_usb_tx_queue_purge(struct rtw_usb *rtwusb) + { ++ struct rtw_dev *rtwdev = rtwusb->rtwdev; + int i; + + for (i = 0; i < ARRAY_SIZE(rtwusb->tx_queue); i++) +- skb_queue_purge(&rtwusb->tx_queue[i]); ++ ieee80211_purge_tx_queue(rtwdev->hw, &rtwusb->tx_queue[i]); + } + + static void rtw_usb_write_port_complete(struct urb *urb) +@@ -801,9 +802,9 @@ static void rtw_usb_deinit_tx(struct rtw_dev *rtwdev) + { + struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); + +- rtw_usb_tx_queue_purge(rtwusb); + flush_workqueue(rtwusb->txwq); + destroy_workqueue(rtwusb->txwq); ++ rtw_usb_tx_queue_purge(rtwusb); + } + + static int rtw_usb_intf_init(struct rtw_dev *rtwdev, +diff --git a/drivers/net/wwan/iosm/iosm_ipc_mmio.c b/drivers/net/wwan/iosm/iosm_ipc_mmio.c +index 63eb08c43c0517..6764c13530b9bd 100644 +--- a/drivers/net/wwan/iosm/iosm_ipc_mmio.c ++++ b/drivers/net/wwan/iosm/iosm_ipc_mmio.c +@@ -104,7 +104,7 @@ struct iosm_mmio *ipc_mmio_init(void __iomem *mmio, struct device *dev) + break; + + msleep(20); +- } while (retries-- > 0); ++ } while (--retries > 0); + + if (!retries) { + dev_err(ipc_mmio->dev, "invalid exec stage %X", stage); +diff --git a/drivers/net/wwan/t7xx/t7xx_state_monitor.c b/drivers/net/wwan/t7xx/t7xx_state_monitor.c +index 80edb8e75a6ad7..64868df3640d13 100644 +--- a/drivers/net/wwan/t7xx/t7xx_state_monitor.c ++++ b/drivers/net/wwan/t7xx/t7xx_state_monitor.c +@@ -97,14 +97,21 @@ void t7xx_fsm_broadcast_state(struct t7xx_fsm_ctl *ctl, enum md_state state) + fsm_state_notify(ctl->md, state); + } + ++static void fsm_release_command(struct kref *ref) ++{ ++ struct t7xx_fsm_command *cmd = container_of(ref, typeof(*cmd), refcnt); ++ ++ kfree(cmd); ++} ++ + static void fsm_finish_command(struct t7xx_fsm_ctl *ctl, struct t7xx_fsm_command *cmd, int result) + { + if (cmd->flag & FSM_CMD_FLAG_WAIT_FOR_COMPLETION) { +- *cmd->ret = result; +- complete_all(cmd->done); ++ cmd->result = result; ++ complete_all(&cmd->done); + } + +- kfree(cmd); ++ kref_put(&cmd->refcnt, fsm_release_command); + } + + static void fsm_del_kf_event(struct t7xx_fsm_event *event) +@@ -396,7 +403,6 @@ static int fsm_main_thread(void *data) + + int t7xx_fsm_append_cmd(struct t7xx_fsm_ctl *ctl, enum t7xx_fsm_cmd_state cmd_id, unsigned int flag) + { +- DECLARE_COMPLETION_ONSTACK(done); + struct t7xx_fsm_command *cmd; + unsigned long flags; + int ret; +@@ -408,11 +414,13 @@ int t7xx_fsm_append_cmd(struct t7xx_fsm_ctl *ctl, enum t7xx_fsm_cmd_state cmd_id + INIT_LIST_HEAD(&cmd->entry); + cmd->cmd_id = cmd_id; + cmd->flag = flag; ++ kref_init(&cmd->refcnt); + if (flag & FSM_CMD_FLAG_WAIT_FOR_COMPLETION) { +- cmd->done = &done; +- cmd->ret = &ret; ++ init_completion(&cmd->done); ++ kref_get(&cmd->refcnt); + } + ++ kref_get(&cmd->refcnt); + spin_lock_irqsave(&ctl->command_lock, flags); + list_add_tail(&cmd->entry, &ctl->command_queue); + spin_unlock_irqrestore(&ctl->command_lock, flags); +@@ -422,11 +430,11 @@ int t7xx_fsm_append_cmd(struct t7xx_fsm_ctl *ctl, enum t7xx_fsm_cmd_state cmd_id + if (flag & FSM_CMD_FLAG_WAIT_FOR_COMPLETION) { + unsigned long wait_ret; + +- wait_ret = wait_for_completion_timeout(&done, ++ wait_ret = wait_for_completion_timeout(&cmd->done, + msecs_to_jiffies(FSM_CMD_TIMEOUT_MS)); +- if (!wait_ret) +- return -ETIMEDOUT; + ++ ret = wait_ret ? cmd->result : -ETIMEDOUT; ++ kref_put(&cmd->refcnt, fsm_release_command); + return ret; + } + +diff --git a/drivers/net/wwan/t7xx/t7xx_state_monitor.h b/drivers/net/wwan/t7xx/t7xx_state_monitor.h +index b6e76f3903c892..74f96fd2605e8e 100644 +--- a/drivers/net/wwan/t7xx/t7xx_state_monitor.h ++++ b/drivers/net/wwan/t7xx/t7xx_state_monitor.h +@@ -109,8 +109,9 @@ struct t7xx_fsm_command { + struct list_head entry; + enum t7xx_fsm_cmd_state cmd_id; + unsigned int flag; +- struct completion *done; +- int *ret; ++ struct completion done; ++ int result; ++ struct kref refcnt; + }; + + struct t7xx_fsm_notifier { +diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c +index 5b6a6bd4e6e800..4aad16390d4790 100644 +--- a/drivers/nvme/host/core.c ++++ b/drivers/nvme/host/core.c +@@ -1178,13 +1178,13 @@ static void nvme_queue_keep_alive_work(struct nvme_ctrl *ctrl) + nvme_keep_alive_work_period(ctrl)); + } + +-static void nvme_keep_alive_finish(struct request *rq, +- blk_status_t status, struct nvme_ctrl *ctrl) ++static enum rq_end_io_ret nvme_keep_alive_end_io(struct request *rq, ++ blk_status_t status) + { +- unsigned long flags; +- bool startka = false; ++ struct nvme_ctrl *ctrl = rq->end_io_data; + unsigned long rtt = jiffies - (rq->deadline - rq->timeout); + unsigned long delay = nvme_keep_alive_work_period(ctrl); ++ enum nvme_ctrl_state state = nvme_ctrl_state(ctrl); + + /* + * Subtract off the keepalive RTT so nvme_keep_alive_work runs +@@ -1198,22 +1198,20 @@ static void nvme_keep_alive_finish(struct request *rq, + delay = 0; + } + ++ blk_mq_free_request(rq); ++ + if (status) { + dev_err(ctrl->device, + "failed nvme_keep_alive_end_io error=%d\n", + status); +- return; ++ return RQ_END_IO_NONE; + } + + ctrl->ka_last_check_time = jiffies; + ctrl->comp_seen = false; +- spin_lock_irqsave(&ctrl->lock, flags); +- if (ctrl->state == NVME_CTRL_LIVE || +- ctrl->state == NVME_CTRL_CONNECTING) +- startka = true; +- spin_unlock_irqrestore(&ctrl->lock, flags); +- if (startka) ++ if (state == NVME_CTRL_LIVE || state == NVME_CTRL_CONNECTING) + queue_delayed_work(nvme_wq, &ctrl->ka_work, delay); ++ return RQ_END_IO_NONE; + } + + static void nvme_keep_alive_work(struct work_struct *work) +@@ -1222,7 +1220,6 @@ static void nvme_keep_alive_work(struct work_struct *work) + struct nvme_ctrl, ka_work); + bool comp_seen = ctrl->comp_seen; + struct request *rq; +- blk_status_t status; + + ctrl->ka_last_check_time = jiffies; + +@@ -1245,9 +1242,9 @@ static void nvme_keep_alive_work(struct work_struct *work) + nvme_init_request(rq, &ctrl->ka_cmd); + + rq->timeout = ctrl->kato * HZ; +- status = blk_execute_rq(rq, false); +- nvme_keep_alive_finish(rq, status, ctrl); +- blk_mq_free_request(rq); ++ rq->end_io = nvme_keep_alive_end_io; ++ rq->end_io_data = ctrl; ++ blk_execute_rq_nowait(rq, false); + } + + static void nvme_start_keep_alive(struct nvme_ctrl *ctrl) +diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h +index bddc068d58c7ea..e867ac859a878e 100644 +--- a/drivers/nvme/host/nvme.h ++++ b/drivers/nvme/host/nvme.h +@@ -172,6 +172,11 @@ enum nvme_quirks { + * MSI (but not MSI-X) interrupts are broken and never fire. + */ + NVME_QUIRK_BROKEN_MSI = (1 << 21), ++ ++ /* ++ * Align dma pool segment size to 512 bytes ++ */ ++ NVME_QUIRK_DMAPOOL_ALIGN_512 = (1 << 22), + }; + + /* +diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c +index d525fa1229d791..52c8fd3d5c4796 100644 +--- a/drivers/nvme/host/pci.c ++++ b/drivers/nvme/host/pci.c +@@ -2653,15 +2653,20 @@ static int nvme_disable_prepare_reset(struct nvme_dev *dev, bool shutdown) + + static int nvme_setup_prp_pools(struct nvme_dev *dev) + { ++ size_t small_align = 256; ++ + dev->prp_page_pool = dma_pool_create("prp list page", dev->dev, + NVME_CTRL_PAGE_SIZE, + NVME_CTRL_PAGE_SIZE, 0); + if (!dev->prp_page_pool) + return -ENOMEM; + ++ if (dev->ctrl.quirks & NVME_QUIRK_DMAPOOL_ALIGN_512) ++ small_align = 512; ++ + /* Optimisation for I/Os between 4k and 128k */ + dev->prp_small_pool = dma_pool_create("prp list 256", dev->dev, +- 256, 256, 0); ++ 256, small_align, 0); + if (!dev->prp_small_pool) { + dma_pool_destroy(dev->prp_page_pool); + return -ENOMEM; +@@ -3403,7 +3408,7 @@ static const struct pci_device_id nvme_id_table[] = { + { PCI_VDEVICE(REDHAT, 0x0010), /* Qemu emulated controller */ + .driver_data = NVME_QUIRK_BOGUS_NID, }, + { PCI_DEVICE(0x1217, 0x8760), /* O2 Micro 64GB Steam Deck */ +- .driver_data = NVME_QUIRK_QDEPTH_ONE }, ++ .driver_data = NVME_QUIRK_DMAPOOL_ALIGN_512, }, + { PCI_DEVICE(0x126f, 0x2262), /* Silicon Motion generic */ + .driver_data = NVME_QUIRK_NO_DEEPEST_PS | + NVME_QUIRK_BOGUS_NID, }, +diff --git a/drivers/of/address.c b/drivers/of/address.c +index dfd05cb2b2fcfa..34d880a1be0a5e 100644 +--- a/drivers/of/address.c ++++ b/drivers/of/address.c +@@ -46,7 +46,7 @@ struct of_bus { + u64 (*map)(__be32 *addr, const __be32 *range, + int na, int ns, int pna); + int (*translate)(__be32 *addr, u64 offset, int na); +- bool has_flags; ++ int flag_cells; + unsigned int (*get_flags)(const __be32 *addr); + }; + +@@ -217,10 +217,6 @@ static u64 of_bus_pci_map(__be32 *addr, const __be32 *range, int na, int ns, + return da - cp; + } + +-static int of_bus_pci_translate(__be32 *addr, u64 offset, int na) +-{ +- return of_bus_default_translate(addr + 1, offset, na - 1); +-} + #endif /* CONFIG_PCI */ + + /* +@@ -344,11 +340,6 @@ static u64 of_bus_isa_map(__be32 *addr, const __be32 *range, int na, int ns, + return da - cp; + } + +-static int of_bus_isa_translate(__be32 *addr, u64 offset, int na) +-{ +- return of_bus_default_translate(addr + 1, offset, na - 1); +-} +- + static unsigned int of_bus_isa_get_flags(const __be32 *addr) + { + unsigned int flags = 0; +@@ -379,8 +370,8 @@ static struct of_bus of_busses[] = { + .match = of_bus_pci_match, + .count_cells = of_bus_pci_count_cells, + .map = of_bus_pci_map, +- .translate = of_bus_pci_translate, +- .has_flags = true, ++ .translate = of_bus_default_flags_translate, ++ .flag_cells = 1, + .get_flags = of_bus_pci_get_flags, + }, + #endif /* CONFIG_PCI */ +@@ -391,8 +382,8 @@ static struct of_bus of_busses[] = { + .match = of_bus_isa_match, + .count_cells = of_bus_isa_count_cells, + .map = of_bus_isa_map, +- .translate = of_bus_isa_translate, +- .has_flags = true, ++ .translate = of_bus_default_flags_translate, ++ .flag_cells = 1, + .get_flags = of_bus_isa_get_flags, + }, + /* Default with flags cell */ +@@ -403,7 +394,7 @@ static struct of_bus of_busses[] = { + .count_cells = of_bus_default_count_cells, + .map = of_bus_default_flags_map, + .translate = of_bus_default_flags_translate, +- .has_flags = true, ++ .flag_cells = 1, + .get_flags = of_bus_default_flags_get_flags, + }, + /* Default */ +@@ -485,7 +476,8 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus, + } + if (ranges == NULL || rlen == 0) { + offset = of_read_number(addr, na); +- memset(addr, 0, pna * 4); ++ /* set address to zero, pass flags through */ ++ memset(addr + pbus->flag_cells, 0, (pna - pbus->flag_cells) * 4); + pr_debug("empty ranges; 1:1 translation\n"); + goto finish; + } +@@ -836,7 +828,7 @@ struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser, + int na = parser->na; + int ns = parser->ns; + int np = parser->pna + na + ns; +- int busflag_na = 0; ++ int busflag_na = parser->bus->flag_cells; + + if (!range) + return NULL; +@@ -846,10 +838,6 @@ struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser, + + range->flags = parser->bus->get_flags(parser->range); + +- /* A extra cell for resource flags */ +- if (parser->bus->has_flags) +- busflag_na = 1; +- + range->bus_addr = of_read_number(parser->range + busflag_na, na - busflag_na); + + if (parser->dma) +diff --git a/drivers/pinctrl/pinctrl-mcp23s08.c b/drivers/pinctrl/pinctrl-mcp23s08.c +index 4551575e4e7d7d..fd97b6ee2a8d11 100644 +--- a/drivers/pinctrl/pinctrl-mcp23s08.c ++++ b/drivers/pinctrl/pinctrl-mcp23s08.c +@@ -86,6 +86,7 @@ const struct regmap_config mcp23x08_regmap = { + .num_reg_defaults = ARRAY_SIZE(mcp23x08_defaults), + .cache_type = REGCACHE_FLAT, + .max_register = MCP_OLAT, ++ .disable_locking = true, /* mcp->lock protects the regmap */ + }; + EXPORT_SYMBOL_GPL(mcp23x08_regmap); + +@@ -132,6 +133,7 @@ const struct regmap_config mcp23x17_regmap = { + .num_reg_defaults = ARRAY_SIZE(mcp23x17_defaults), + .cache_type = REGCACHE_FLAT, + .val_format_endian = REGMAP_ENDIAN_LITTLE, ++ .disable_locking = true, /* mcp->lock protects the regmap */ + }; + EXPORT_SYMBOL_GPL(mcp23x17_regmap); + +@@ -228,7 +230,9 @@ static int mcp_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin, + + switch (param) { + case PIN_CONFIG_BIAS_PULL_UP: ++ mutex_lock(&mcp->lock); + ret = mcp_read(mcp, MCP_GPPU, &data); ++ mutex_unlock(&mcp->lock); + if (ret < 0) + return ret; + status = (data & BIT(pin)) ? 1 : 0; +@@ -257,7 +261,9 @@ static int mcp_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, + + switch (param) { + case PIN_CONFIG_BIAS_PULL_UP: ++ mutex_lock(&mcp->lock); + ret = mcp_set_bit(mcp, MCP_GPPU, pin, arg); ++ mutex_unlock(&mcp->lock); + break; + default: + dev_dbg(mcp->dev, "Invalid config param %04x\n", param); +diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c +index a2ffe4157df10c..b8d77adc9ea145 100644 +--- a/drivers/platform/x86/mlx-platform.c ++++ b/drivers/platform/x86/mlx-platform.c +@@ -6237,6 +6237,7 @@ mlxplat_pci_fpga_device_init(unsigned int device, const char *res_name, struct p + fail_pci_request_regions: + pci_disable_device(pci_dev); + fail_pci_enable_device: ++ pci_dev_put(pci_dev); + return err; + } + +@@ -6247,6 +6248,7 @@ mlxplat_pci_fpga_device_exit(struct pci_dev *pci_bridge, + iounmap(pci_bridge_addr); + pci_release_regions(pci_bridge); + pci_disable_device(pci_bridge); ++ pci_dev_put(pci_bridge); + } + + static int +diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c +index 6235721f2c1aec..fd6bf9e77afcb8 100644 +--- a/drivers/remoteproc/qcom_q6v5_pas.c ++++ b/drivers/remoteproc/qcom_q6v5_pas.c +@@ -786,6 +786,23 @@ static const struct adsp_data adsp_resource_init = { + .ssctl_id = 0x14, + }; + ++static const struct adsp_data sa8775p_adsp_resource = { ++ .crash_reason_smem = 423, ++ .firmware_name = "adsp.mbn", ++ .pas_id = 1, ++ .minidump_id = 5, ++ .auto_boot = true, ++ .proxy_pd_names = (char*[]){ ++ "lcx", ++ "lmx", ++ NULL ++ }, ++ .load_state = "adsp", ++ .ssr_name = "lpass", ++ .sysmon_name = "adsp", ++ .ssctl_id = 0x14, ++}; ++ + static const struct adsp_data sdm845_adsp_resource_init = { + .crash_reason_smem = 423, + .firmware_name = "adsp.mdt", +@@ -885,6 +902,42 @@ static const struct adsp_data cdsp_resource_init = { + .ssctl_id = 0x17, + }; + ++static const struct adsp_data sa8775p_cdsp0_resource = { ++ .crash_reason_smem = 601, ++ .firmware_name = "cdsp0.mbn", ++ .pas_id = 18, ++ .minidump_id = 7, ++ .auto_boot = true, ++ .proxy_pd_names = (char*[]){ ++ "cx", ++ "mxc", ++ "nsp", ++ NULL ++ }, ++ .load_state = "cdsp", ++ .ssr_name = "cdsp", ++ .sysmon_name = "cdsp", ++ .ssctl_id = 0x17, ++}; ++ ++static const struct adsp_data sa8775p_cdsp1_resource = { ++ .crash_reason_smem = 633, ++ .firmware_name = "cdsp1.mbn", ++ .pas_id = 30, ++ .minidump_id = 20, ++ .auto_boot = true, ++ .proxy_pd_names = (char*[]){ ++ "cx", ++ "mxc", ++ "nsp", ++ NULL ++ }, ++ .load_state = "nsp", ++ .ssr_name = "cdsp1", ++ .sysmon_name = "cdsp1", ++ .ssctl_id = 0x20, ++}; ++ + static const struct adsp_data sdm845_cdsp_resource_init = { + .crash_reason_smem = 601, + .firmware_name = "cdsp.mdt", +@@ -987,6 +1040,40 @@ static const struct adsp_data sm8350_cdsp_resource = { + .ssctl_id = 0x17, + }; + ++static const struct adsp_data sa8775p_gpdsp0_resource = { ++ .crash_reason_smem = 640, ++ .firmware_name = "gpdsp0.mbn", ++ .pas_id = 39, ++ .minidump_id = 21, ++ .auto_boot = true, ++ .proxy_pd_names = (char*[]){ ++ "cx", ++ "mxc", ++ NULL ++ }, ++ .load_state = "gpdsp0", ++ .ssr_name = "gpdsp0", ++ .sysmon_name = "gpdsp0", ++ .ssctl_id = 0x21, ++}; ++ ++static const struct adsp_data sa8775p_gpdsp1_resource = { ++ .crash_reason_smem = 641, ++ .firmware_name = "gpdsp1.mbn", ++ .pas_id = 40, ++ .minidump_id = 22, ++ .auto_boot = true, ++ .proxy_pd_names = (char*[]){ ++ "cx", ++ "mxc", ++ NULL ++ }, ++ .load_state = "gpdsp1", ++ .ssr_name = "gpdsp1", ++ .sysmon_name = "gpdsp1", ++ .ssctl_id = 0x22, ++}; ++ + static const struct adsp_data mpss_resource_init = { + .crash_reason_smem = 421, + .firmware_name = "modem.mdt", +@@ -1163,6 +1250,13 @@ static const struct of_device_id adsp_of_match[] = { + { .compatible = "qcom,qcs404-adsp-pas", .data = &adsp_resource_init }, + { .compatible = "qcom,qcs404-cdsp-pas", .data = &cdsp_resource_init }, + { .compatible = "qcom,qcs404-wcss-pas", .data = &wcss_resource_init }, ++ { .compatible = "qcom,sa8775p-adsp-pas", .data = &sa8775p_adsp_resource}, ++ { .compatible = "qcom,sa8775p-cdsp0-pas", .data = &sa8775p_cdsp0_resource}, ++ { .compatible = "qcom,sa8775p-cdsp1-pas", .data = &sa8775p_cdsp1_resource}, ++ { .compatible = "qcom,sa8775p-gpdsp0-pas", .data = &sa8775p_gpdsp0_resource}, ++ { .compatible = "qcom,sa8775p-gpdsp1-pas", .data = &sa8775p_gpdsp1_resource}, ++ { .compatible = "qcom,sar2130p-adsp-pas", .data = &sm8350_adsp_resource}, ++ { .compatible = "qcom,sc7180-adsp-pas", .data = &sm8250_adsp_resource}, + { .compatible = "qcom,sc7180-mpss-pas", .data = &mpss_resource_init}, + { .compatible = "qcom,sc7280-mpss-pas", .data = &mpss_resource_init}, + { .compatible = "qcom,sc8180x-adsp-pas", .data = &sm8150_adsp_resource}, +diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h +index 9e73e9cbbcfc6c..1e4550156b735d 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas.h ++++ b/drivers/scsi/hisi_sas/hisi_sas.h +@@ -343,7 +343,7 @@ struct hisi_sas_hw { + u8 reg_index, u8 reg_count, u8 *write_data); + void (*wait_cmds_complete_timeout)(struct hisi_hba *hisi_hba, + int delay_ms, int timeout_ms); +- void (*debugfs_snapshot_regs)(struct hisi_hba *hisi_hba); ++ int (*debugfs_snapshot_regs)(struct hisi_hba *hisi_hba); + int complete_hdr_size; + const struct scsi_host_template *sht; + }; +@@ -451,7 +451,6 @@ struct hisi_hba { + const struct hisi_sas_hw *hw; /* Low level hw interface */ + unsigned long sata_dev_bitmap[BITS_TO_LONGS(HISI_SAS_MAX_DEVICES)]; + struct work_struct rst_work; +- struct work_struct debugfs_work; + u32 phy_state; + u32 intr_coal_ticks; /* Time of interrupt coalesce in us */ + u32 intr_coal_count; /* Interrupt count to coalesce */ +diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c +index db9ae206974c21..f78c5f8a49ffac 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_main.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c +@@ -1579,7 +1579,7 @@ static int hisi_sas_controller_prereset(struct hisi_hba *hisi_hba) + return -EPERM; + } + +- if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct[0].itct) ++ if (hisi_sas_debugfs_enable) + hisi_hba->hw->debugfs_snapshot_regs(hisi_hba); + + return 0; +@@ -1967,8 +1967,19 @@ static bool hisi_sas_internal_abort_timeout(struct sas_task *task, + struct hisi_hba *hisi_hba = dev_to_hisi_hba(device); + struct hisi_sas_internal_abort_data *timeout = data; + +- if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct[0].itct) +- queue_work(hisi_hba->wq, &hisi_hba->debugfs_work); ++ if (hisi_sas_debugfs_enable) { ++ /* ++ * If timeout occurs in device gone scenario, to avoid ++ * circular dependency like: ++ * hisi_sas_dev_gone() -> down() -> ... -> ++ * hisi_sas_internal_abort_timeout() -> down(). ++ */ ++ if (!timeout->rst_ha_timeout) ++ down(&hisi_hba->sem); ++ hisi_hba->hw->debugfs_snapshot_regs(hisi_hba); ++ if (!timeout->rst_ha_timeout) ++ up(&hisi_hba->sem); ++ } + + if (task->task_state_flags & SAS_TASK_STATE_DONE) { + pr_err("Internal abort: timeout %016llx\n", +diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +index 4054659d48f74c..ff5f86867dbf06 100644 +--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c ++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +@@ -558,8 +558,7 @@ static int experimental_iopoll_q_cnt; + module_param(experimental_iopoll_q_cnt, int, 0444); + MODULE_PARM_DESC(experimental_iopoll_q_cnt, "number of queues to be used as poll mode, def=0"); + +-static void debugfs_work_handler_v3_hw(struct work_struct *work); +-static void debugfs_snapshot_regs_v3_hw(struct hisi_hba *hisi_hba); ++static int debugfs_snapshot_regs_v3_hw(struct hisi_hba *hisi_hba); + + static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off) + { +@@ -3397,7 +3396,6 @@ hisi_sas_shost_alloc_pci(struct pci_dev *pdev) + hisi_hba = shost_priv(shost); + + INIT_WORK(&hisi_hba->rst_work, hisi_sas_rst_work_handler); +- INIT_WORK(&hisi_hba->debugfs_work, debugfs_work_handler_v3_hw); + hisi_hba->hw = &hisi_sas_v3_hw; + hisi_hba->pci_dev = pdev; + hisi_hba->dev = dev; +@@ -3562,6 +3560,11 @@ debugfs_to_reg_name_v3_hw(int off, int base_off, + return NULL; + } + ++static bool debugfs_dump_is_generated_v3_hw(void *p) ++{ ++ return p ? true : false; ++} ++ + static void debugfs_print_reg_v3_hw(u32 *regs_val, struct seq_file *s, + const struct hisi_sas_debugfs_reg *reg) + { +@@ -3587,6 +3590,9 @@ static int debugfs_global_v3_hw_show(struct seq_file *s, void *p) + { + struct hisi_sas_debugfs_regs *global = s->private; + ++ if (!debugfs_dump_is_generated_v3_hw(global->data)) ++ return -EPERM; ++ + debugfs_print_reg_v3_hw(global->data, s, + &debugfs_global_reg); + +@@ -3598,6 +3604,9 @@ static int debugfs_axi_v3_hw_show(struct seq_file *s, void *p) + { + struct hisi_sas_debugfs_regs *axi = s->private; + ++ if (!debugfs_dump_is_generated_v3_hw(axi->data)) ++ return -EPERM; ++ + debugfs_print_reg_v3_hw(axi->data, s, + &debugfs_axi_reg); + +@@ -3609,6 +3618,9 @@ static int debugfs_ras_v3_hw_show(struct seq_file *s, void *p) + { + struct hisi_sas_debugfs_regs *ras = s->private; + ++ if (!debugfs_dump_is_generated_v3_hw(ras->data)) ++ return -EPERM; ++ + debugfs_print_reg_v3_hw(ras->data, s, + &debugfs_ras_reg); + +@@ -3621,6 +3633,9 @@ static int debugfs_port_v3_hw_show(struct seq_file *s, void *p) + struct hisi_sas_debugfs_port *port = s->private; + const struct hisi_sas_debugfs_reg *reg_port = &debugfs_port_reg; + ++ if (!debugfs_dump_is_generated_v3_hw(port->data)) ++ return -EPERM; ++ + debugfs_print_reg_v3_hw(port->data, s, reg_port); + + return 0; +@@ -3676,6 +3691,9 @@ static int debugfs_cq_v3_hw_show(struct seq_file *s, void *p) + struct hisi_sas_debugfs_cq *debugfs_cq = s->private; + int slot; + ++ if (!debugfs_dump_is_generated_v3_hw(debugfs_cq->complete_hdr)) ++ return -EPERM; ++ + for (slot = 0; slot < HISI_SAS_QUEUE_SLOTS; slot++) + debugfs_cq_show_slot_v3_hw(s, slot, debugfs_cq); + +@@ -3697,8 +3715,12 @@ static void debugfs_dq_show_slot_v3_hw(struct seq_file *s, int slot, + + static int debugfs_dq_v3_hw_show(struct seq_file *s, void *p) + { ++ struct hisi_sas_debugfs_dq *debugfs_dq = s->private; + int slot; + ++ if (!debugfs_dump_is_generated_v3_hw(debugfs_dq->hdr)) ++ return -EPERM; ++ + for (slot = 0; slot < HISI_SAS_QUEUE_SLOTS; slot++) + debugfs_dq_show_slot_v3_hw(s, slot, s->private); + +@@ -3712,6 +3734,9 @@ static int debugfs_iost_v3_hw_show(struct seq_file *s, void *p) + struct hisi_sas_iost *iost = debugfs_iost->iost; + int i, max_command_entries = HISI_SAS_MAX_COMMANDS; + ++ if (!debugfs_dump_is_generated_v3_hw(iost)) ++ return -EPERM; ++ + for (i = 0; i < max_command_entries; i++, iost++) { + __le64 *data = &iost->qw0; + +@@ -3731,6 +3756,9 @@ static int debugfs_iost_cache_v3_hw_show(struct seq_file *s, void *p) + int i, tab_idx; + __le64 *iost; + ++ if (!debugfs_dump_is_generated_v3_hw(iost_cache)) ++ return -EPERM; ++ + for (i = 0; i < HISI_SAS_IOST_ITCT_CACHE_NUM; i++, iost_cache++) { + /* + * Data struct of IOST cache: +@@ -3754,6 +3782,9 @@ static int debugfs_itct_v3_hw_show(struct seq_file *s, void *p) + struct hisi_sas_debugfs_itct *debugfs_itct = s->private; + struct hisi_sas_itct *itct = debugfs_itct->itct; + ++ if (!debugfs_dump_is_generated_v3_hw(itct)) ++ return -EPERM; ++ + for (i = 0; i < HISI_SAS_MAX_ITCT_ENTRIES; i++, itct++) { + __le64 *data = &itct->qw0; + +@@ -3773,6 +3804,9 @@ static int debugfs_itct_cache_v3_hw_show(struct seq_file *s, void *p) + int i, tab_idx; + __le64 *itct; + ++ if (!debugfs_dump_is_generated_v3_hw(itct_cache)) ++ return -EPERM; ++ + for (i = 0; i < HISI_SAS_IOST_ITCT_CACHE_NUM; i++, itct_cache++) { + /* + * Data struct of ITCT cache: +@@ -3790,10 +3824,9 @@ static int debugfs_itct_cache_v3_hw_show(struct seq_file *s, void *p) + } + DEFINE_SHOW_ATTRIBUTE(debugfs_itct_cache_v3_hw); + +-static void debugfs_create_files_v3_hw(struct hisi_hba *hisi_hba) ++static void debugfs_create_files_v3_hw(struct hisi_hba *hisi_hba, int index) + { + u64 *debugfs_timestamp; +- int dump_index = hisi_hba->debugfs_dump_index; + struct dentry *dump_dentry; + struct dentry *dentry; + char name[256]; +@@ -3801,17 +3834,17 @@ static void debugfs_create_files_v3_hw(struct hisi_hba *hisi_hba) + int c; + int d; + +- snprintf(name, 256, "%d", dump_index); ++ snprintf(name, 256, "%d", index); + + dump_dentry = debugfs_create_dir(name, hisi_hba->debugfs_dump_dentry); + +- debugfs_timestamp = &hisi_hba->debugfs_timestamp[dump_index]; ++ debugfs_timestamp = &hisi_hba->debugfs_timestamp[index]; + + debugfs_create_u64("timestamp", 0400, dump_dentry, + debugfs_timestamp); + + debugfs_create_file("global", 0400, dump_dentry, +- &hisi_hba->debugfs_regs[dump_index][DEBUGFS_GLOBAL], ++ &hisi_hba->debugfs_regs[index][DEBUGFS_GLOBAL], + &debugfs_global_v3_hw_fops); + + /* Create port dir and files */ +@@ -3820,7 +3853,7 @@ static void debugfs_create_files_v3_hw(struct hisi_hba *hisi_hba) + snprintf(name, 256, "%d", p); + + debugfs_create_file(name, 0400, dentry, +- &hisi_hba->debugfs_port_reg[dump_index][p], ++ &hisi_hba->debugfs_port_reg[index][p], + &debugfs_port_v3_hw_fops); + } + +@@ -3830,7 +3863,7 @@ static void debugfs_create_files_v3_hw(struct hisi_hba *hisi_hba) + snprintf(name, 256, "%d", c); + + debugfs_create_file(name, 0400, dentry, +- &hisi_hba->debugfs_cq[dump_index][c], ++ &hisi_hba->debugfs_cq[index][c], + &debugfs_cq_v3_hw_fops); + } + +@@ -3840,66 +3873,35 @@ static void debugfs_create_files_v3_hw(struct hisi_hba *hisi_hba) + snprintf(name, 256, "%d", d); + + debugfs_create_file(name, 0400, dentry, +- &hisi_hba->debugfs_dq[dump_index][d], ++ &hisi_hba->debugfs_dq[index][d], + &debugfs_dq_v3_hw_fops); + } + + debugfs_create_file("iost", 0400, dump_dentry, +- &hisi_hba->debugfs_iost[dump_index], ++ &hisi_hba->debugfs_iost[index], + &debugfs_iost_v3_hw_fops); + + debugfs_create_file("iost_cache", 0400, dump_dentry, +- &hisi_hba->debugfs_iost_cache[dump_index], ++ &hisi_hba->debugfs_iost_cache[index], + &debugfs_iost_cache_v3_hw_fops); + + debugfs_create_file("itct", 0400, dump_dentry, +- &hisi_hba->debugfs_itct[dump_index], ++ &hisi_hba->debugfs_itct[index], + &debugfs_itct_v3_hw_fops); + + debugfs_create_file("itct_cache", 0400, dump_dentry, +- &hisi_hba->debugfs_itct_cache[dump_index], ++ &hisi_hba->debugfs_itct_cache[index], + &debugfs_itct_cache_v3_hw_fops); + + debugfs_create_file("axi", 0400, dump_dentry, +- &hisi_hba->debugfs_regs[dump_index][DEBUGFS_AXI], ++ &hisi_hba->debugfs_regs[index][DEBUGFS_AXI], + &debugfs_axi_v3_hw_fops); + + debugfs_create_file("ras", 0400, dump_dentry, +- &hisi_hba->debugfs_regs[dump_index][DEBUGFS_RAS], ++ &hisi_hba->debugfs_regs[index][DEBUGFS_RAS], + &debugfs_ras_v3_hw_fops); + } + +-static void debugfs_snapshot_regs_v3_hw(struct hisi_hba *hisi_hba) +-{ +- int debugfs_dump_index = hisi_hba->debugfs_dump_index; +- struct device *dev = hisi_hba->dev; +- u64 timestamp = local_clock(); +- +- if (debugfs_dump_index >= hisi_sas_debugfs_dump_count) { +- dev_warn(dev, "dump count exceeded!\n"); +- return; +- } +- +- do_div(timestamp, NSEC_PER_MSEC); +- hisi_hba->debugfs_timestamp[debugfs_dump_index] = timestamp; +- +- debugfs_snapshot_prepare_v3_hw(hisi_hba); +- +- debugfs_snapshot_global_reg_v3_hw(hisi_hba); +- debugfs_snapshot_port_reg_v3_hw(hisi_hba); +- debugfs_snapshot_axi_reg_v3_hw(hisi_hba); +- debugfs_snapshot_ras_reg_v3_hw(hisi_hba); +- debugfs_snapshot_cq_reg_v3_hw(hisi_hba); +- debugfs_snapshot_dq_reg_v3_hw(hisi_hba); +- debugfs_snapshot_itct_reg_v3_hw(hisi_hba); +- debugfs_snapshot_iost_reg_v3_hw(hisi_hba); +- +- debugfs_create_files_v3_hw(hisi_hba); +- +- debugfs_snapshot_restore_v3_hw(hisi_hba); +- hisi_hba->debugfs_dump_index++; +-} +- + static ssize_t debugfs_trigger_dump_v3_hw_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +@@ -3907,9 +3909,6 @@ static ssize_t debugfs_trigger_dump_v3_hw_write(struct file *file, + struct hisi_hba *hisi_hba = file->f_inode->i_private; + char buf[8]; + +- if (hisi_hba->debugfs_dump_index >= hisi_sas_debugfs_dump_count) +- return -EFAULT; +- + if (count > 8) + return -EFAULT; + +@@ -3919,7 +3918,12 @@ static ssize_t debugfs_trigger_dump_v3_hw_write(struct file *file, + if (buf[0] != '1') + return -EFAULT; + +- queue_work(hisi_hba->wq, &hisi_hba->debugfs_work); ++ down(&hisi_hba->sem); ++ if (debugfs_snapshot_regs_v3_hw(hisi_hba)) { ++ up(&hisi_hba->sem); ++ return -EFAULT; ++ } ++ up(&hisi_hba->sem); + + return count; + } +@@ -4670,36 +4674,40 @@ static void debugfs_fifo_init_v3_hw(struct hisi_hba *hisi_hba) + } + } + +-static void debugfs_work_handler_v3_hw(struct work_struct *work) +-{ +- struct hisi_hba *hisi_hba = +- container_of(work, struct hisi_hba, debugfs_work); +- +- debugfs_snapshot_regs_v3_hw(hisi_hba); +-} +- + static void debugfs_release_v3_hw(struct hisi_hba *hisi_hba, int dump_index) + { + struct device *dev = hisi_hba->dev; + int i; + + devm_kfree(dev, hisi_hba->debugfs_iost_cache[dump_index].cache); ++ hisi_hba->debugfs_iost_cache[dump_index].cache = NULL; + devm_kfree(dev, hisi_hba->debugfs_itct_cache[dump_index].cache); ++ hisi_hba->debugfs_itct_cache[dump_index].cache = NULL; + devm_kfree(dev, hisi_hba->debugfs_iost[dump_index].iost); ++ hisi_hba->debugfs_iost[dump_index].iost = NULL; + devm_kfree(dev, hisi_hba->debugfs_itct[dump_index].itct); ++ hisi_hba->debugfs_itct[dump_index].itct = NULL; + +- for (i = 0; i < hisi_hba->queue_count; i++) ++ for (i = 0; i < hisi_hba->queue_count; i++) { + devm_kfree(dev, hisi_hba->debugfs_dq[dump_index][i].hdr); ++ hisi_hba->debugfs_dq[dump_index][i].hdr = NULL; ++ } + +- for (i = 0; i < hisi_hba->queue_count; i++) ++ for (i = 0; i < hisi_hba->queue_count; i++) { + devm_kfree(dev, + hisi_hba->debugfs_cq[dump_index][i].complete_hdr); ++ hisi_hba->debugfs_cq[dump_index][i].complete_hdr = NULL; ++ } + +- for (i = 0; i < DEBUGFS_REGS_NUM; i++) ++ for (i = 0; i < DEBUGFS_REGS_NUM; i++) { + devm_kfree(dev, hisi_hba->debugfs_regs[dump_index][i].data); ++ hisi_hba->debugfs_regs[dump_index][i].data = NULL; ++ } + +- for (i = 0; i < hisi_hba->n_phy; i++) ++ for (i = 0; i < hisi_hba->n_phy; i++) { + devm_kfree(dev, hisi_hba->debugfs_port_reg[dump_index][i].data); ++ hisi_hba->debugfs_port_reg[dump_index][i].data = NULL; ++ } + } + + static const struct hisi_sas_debugfs_reg *debugfs_reg_array_v3_hw[DEBUGFS_REGS_NUM] = { +@@ -4712,7 +4720,7 @@ static int debugfs_alloc_v3_hw(struct hisi_hba *hisi_hba, int dump_index) + { + const struct hisi_sas_hw *hw = hisi_hba->hw; + struct device *dev = hisi_hba->dev; +- int p, c, d, r, i; ++ int p, c, d, r; + size_t sz; + + for (r = 0; r < DEBUGFS_REGS_NUM; r++) { +@@ -4792,11 +4800,46 @@ static int debugfs_alloc_v3_hw(struct hisi_hba *hisi_hba, int dump_index) + + return 0; + fail: +- for (i = 0; i < hisi_sas_debugfs_dump_count; i++) +- debugfs_release_v3_hw(hisi_hba, i); ++ debugfs_release_v3_hw(hisi_hba, dump_index); + return -ENOMEM; + } + ++static int debugfs_snapshot_regs_v3_hw(struct hisi_hba *hisi_hba) ++{ ++ int debugfs_dump_index = hisi_hba->debugfs_dump_index; ++ struct device *dev = hisi_hba->dev; ++ u64 timestamp = local_clock(); ++ ++ if (debugfs_dump_index >= hisi_sas_debugfs_dump_count) { ++ dev_warn(dev, "dump count exceeded!\n"); ++ return -EINVAL; ++ } ++ ++ if (debugfs_alloc_v3_hw(hisi_hba, debugfs_dump_index)) { ++ dev_warn(dev, "failed to alloc memory\n"); ++ return -ENOMEM; ++ } ++ ++ do_div(timestamp, NSEC_PER_MSEC); ++ hisi_hba->debugfs_timestamp[debugfs_dump_index] = timestamp; ++ ++ debugfs_snapshot_prepare_v3_hw(hisi_hba); ++ ++ debugfs_snapshot_global_reg_v3_hw(hisi_hba); ++ debugfs_snapshot_port_reg_v3_hw(hisi_hba); ++ debugfs_snapshot_axi_reg_v3_hw(hisi_hba); ++ debugfs_snapshot_ras_reg_v3_hw(hisi_hba); ++ debugfs_snapshot_cq_reg_v3_hw(hisi_hba); ++ debugfs_snapshot_dq_reg_v3_hw(hisi_hba); ++ debugfs_snapshot_itct_reg_v3_hw(hisi_hba); ++ debugfs_snapshot_iost_reg_v3_hw(hisi_hba); ++ ++ debugfs_snapshot_restore_v3_hw(hisi_hba); ++ hisi_hba->debugfs_dump_index++; ++ ++ return 0; ++} ++ + static void debugfs_phy_down_cnt_init_v3_hw(struct hisi_hba *hisi_hba) + { + struct dentry *dir = debugfs_create_dir("phy_down_cnt", +@@ -4874,6 +4917,17 @@ static void debugfs_bist_init_v3_hw(struct hisi_hba *hisi_hba) + hisi_hba->debugfs_bist_linkrate = SAS_LINK_RATE_1_5_GBPS; + } + ++static void debugfs_dump_init_v3_hw(struct hisi_hba *hisi_hba) ++{ ++ int i; ++ ++ hisi_hba->debugfs_dump_dentry = ++ debugfs_create_dir("dump", hisi_hba->debugfs_dir); ++ ++ for (i = 0; i < hisi_sas_debugfs_dump_count; i++) ++ debugfs_create_files_v3_hw(hisi_hba, i); ++} ++ + static void debugfs_exit_v3_hw(struct hisi_hba *hisi_hba) + { + debugfs_remove_recursive(hisi_hba->debugfs_dir); +@@ -4883,7 +4937,6 @@ static void debugfs_exit_v3_hw(struct hisi_hba *hisi_hba) + static void debugfs_init_v3_hw(struct hisi_hba *hisi_hba) + { + struct device *dev = hisi_hba->dev; +- int i; + + hisi_hba->debugfs_dir = debugfs_create_dir(dev_name(dev), + hisi_sas_debugfs_dir); +@@ -4895,19 +4948,10 @@ static void debugfs_init_v3_hw(struct hisi_hba *hisi_hba) + /* create bist structures */ + debugfs_bist_init_v3_hw(hisi_hba); + +- hisi_hba->debugfs_dump_dentry = +- debugfs_create_dir("dump", hisi_hba->debugfs_dir); ++ debugfs_dump_init_v3_hw(hisi_hba); + + debugfs_phy_down_cnt_init_v3_hw(hisi_hba); + debugfs_fifo_init_v3_hw(hisi_hba); +- +- for (i = 0; i < hisi_sas_debugfs_dump_count; i++) { +- if (debugfs_alloc_v3_hw(hisi_hba, i)) { +- debugfs_exit_v3_hw(hisi_hba); +- dev_dbg(dev, "failed to init debugfs!\n"); +- break; +- } +- } + } + + static int +diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c +index 7f32619234696f..7880675a68dba6 100644 +--- a/drivers/scsi/mpi3mr/mpi3mr_os.c ++++ b/drivers/scsi/mpi3mr/mpi3mr_os.c +@@ -8,11 +8,12 @@ + */ + + #include "mpi3mr.h" ++#include + + /* global driver scop variables */ + LIST_HEAD(mrioc_list); + DEFINE_SPINLOCK(mrioc_list_lock); +-static int mrioc_ids; ++static DEFINE_IDA(mrioc_ida); + static int warn_non_secure_ctlr; + atomic64_t event_counter; + +@@ -5065,7 +5066,10 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id) + } + + mrioc = shost_priv(shost); +- mrioc->id = mrioc_ids++; ++ retval = ida_alloc_range(&mrioc_ida, 0, U8_MAX, GFP_KERNEL); ++ if (retval < 0) ++ goto id_alloc_failed; ++ mrioc->id = (u8)retval; + sprintf(mrioc->driver_name, "%s", MPI3MR_DRIVER_NAME); + sprintf(mrioc->name, "%s%d", mrioc->driver_name, mrioc->id); + INIT_LIST_HEAD(&mrioc->list); +@@ -5215,9 +5219,11 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id) + resource_alloc_failed: + destroy_workqueue(mrioc->fwevt_worker_thread); + fwevtthread_failed: ++ ida_free(&mrioc_ida, mrioc->id); + spin_lock(&mrioc_list_lock); + list_del(&mrioc->list); + spin_unlock(&mrioc_list_lock); ++id_alloc_failed: + scsi_host_put(shost); + shost_failed: + return retval; +@@ -5303,6 +5309,7 @@ static void mpi3mr_remove(struct pci_dev *pdev) + mrioc->sas_hba.num_phys = 0; + } + ++ ida_free(&mrioc_ida, mrioc->id); + spin_lock(&mrioc_list_lock); + list_del(&mrioc->list); + spin_unlock(&mrioc_list_lock); +@@ -5518,6 +5525,7 @@ static void __exit mpi3mr_exit(void) + &driver_attr_event_counter); + pci_unregister_driver(&mpi3mr_pci_driver); + sas_release_transport(mpi3mr_transport_template); ++ ida_destroy(&mrioc_ida); + } + + module_init(mpi3mr_init); +diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c +index 1ec6f9c82aef06..79f2bf5df19a6c 100644 +--- a/drivers/thunderbolt/nhi.c ++++ b/drivers/thunderbolt/nhi.c +@@ -1524,6 +1524,18 @@ static struct pci_device_id nhi_ids[] = { + .driver_data = (kernel_ulong_t)&icl_nhi_ops }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MTL_P_NHI1), + .driver_data = (kernel_ulong_t)&icl_nhi_ops }, ++ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_LNL_NHI0), ++ .driver_data = (kernel_ulong_t)&icl_nhi_ops }, ++ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_LNL_NHI1), ++ .driver_data = (kernel_ulong_t)&icl_nhi_ops }, ++ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_PTL_M_NHI0), ++ .driver_data = (kernel_ulong_t)&icl_nhi_ops }, ++ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_PTL_M_NHI1), ++ .driver_data = (kernel_ulong_t)&icl_nhi_ops }, ++ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_PTL_P_NHI0), ++ .driver_data = (kernel_ulong_t)&icl_nhi_ops }, ++ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_PTL_P_NHI1), ++ .driver_data = (kernel_ulong_t)&icl_nhi_ops }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HOST_80G_NHI) }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HOST_40G_NHI) }, + +diff --git a/drivers/thunderbolt/nhi.h b/drivers/thunderbolt/nhi.h +index 0f029ce758825e..16744f25a9a069 100644 +--- a/drivers/thunderbolt/nhi.h ++++ b/drivers/thunderbolt/nhi.h +@@ -90,6 +90,12 @@ extern const struct tb_nhi_ops icl_nhi_ops; + #define PCI_DEVICE_ID_INTEL_TGL_H_NHI1 0x9a21 + #define PCI_DEVICE_ID_INTEL_RPL_NHI0 0xa73e + #define PCI_DEVICE_ID_INTEL_RPL_NHI1 0xa76d ++#define PCI_DEVICE_ID_INTEL_LNL_NHI0 0xa833 ++#define PCI_DEVICE_ID_INTEL_LNL_NHI1 0xa834 ++#define PCI_DEVICE_ID_INTEL_PTL_M_NHI0 0xe333 ++#define PCI_DEVICE_ID_INTEL_PTL_M_NHI1 0xe334 ++#define PCI_DEVICE_ID_INTEL_PTL_P_NHI0 0xe433 ++#define PCI_DEVICE_ID_INTEL_PTL_P_NHI1 0xe434 + + #define PCI_CLASS_SERIAL_USB_USB4 0x0c0340 + +diff --git a/drivers/thunderbolt/retimer.c b/drivers/thunderbolt/retimer.c +index 47becb363adacb..2ee8c5ebca7c3c 100644 +--- a/drivers/thunderbolt/retimer.c ++++ b/drivers/thunderbolt/retimer.c +@@ -98,6 +98,7 @@ static int tb_retimer_nvm_add(struct tb_retimer *rt) + + err_nvm: + dev_dbg(&rt->dev, "NVM upgrade disabled\n"); ++ rt->no_nvm_upgrade = true; + if (!IS_ERR(nvm)) + tb_nvm_free(nvm); + +@@ -177,8 +178,6 @@ static ssize_t nvm_authenticate_show(struct device *dev, + + if (!rt->nvm) + ret = -EAGAIN; +- else if (rt->no_nvm_upgrade) +- ret = -EOPNOTSUPP; + else + ret = sysfs_emit(buf, "%#x\n", rt->auth_status); + +@@ -331,6 +330,19 @@ static ssize_t vendor_show(struct device *dev, struct device_attribute *attr, + } + static DEVICE_ATTR_RO(vendor); + ++static umode_t retimer_is_visible(struct kobject *kobj, struct attribute *attr, ++ int n) ++{ ++ struct device *dev = kobj_to_dev(kobj); ++ struct tb_retimer *rt = tb_to_retimer(dev); ++ ++ if (attr == &dev_attr_nvm_authenticate.attr || ++ attr == &dev_attr_nvm_version.attr) ++ return rt->no_nvm_upgrade ? 0 : attr->mode; ++ ++ return attr->mode; ++} ++ + static struct attribute *retimer_attrs[] = { + &dev_attr_device.attr, + &dev_attr_nvm_authenticate.attr, +@@ -340,6 +352,7 @@ static struct attribute *retimer_attrs[] = { + }; + + static const struct attribute_group retimer_group = { ++ .is_visible = retimer_is_visible, + .attrs = retimer_attrs, + }; + +diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h +index 2a38e1eb65466c..97437de52ef681 100644 +--- a/drivers/usb/chipidea/ci.h ++++ b/drivers/usb/chipidea/ci.h +@@ -25,6 +25,7 @@ + #define TD_PAGE_COUNT 5 + #define CI_HDRC_PAGE_SIZE 4096ul /* page size for TD's */ + #define ENDPT_MAX 32 ++#define CI_MAX_REQ_SIZE (4 * CI_HDRC_PAGE_SIZE) + #define CI_MAX_BUF_SIZE (TD_PAGE_COUNT * CI_HDRC_PAGE_SIZE) + + /****************************************************************************** +@@ -260,6 +261,7 @@ struct ci_hdrc { + bool b_sess_valid_event; + bool imx28_write_fix; + bool has_portsc_pec_bug; ++ bool has_short_pkt_limit; + bool supports_runtime_pm; + bool in_lpm; + bool wakeup_int; +diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c +index e28bb2f2612dc6..477af457c1a1f0 100644 +--- a/drivers/usb/chipidea/ci_hdrc_imx.c ++++ b/drivers/usb/chipidea/ci_hdrc_imx.c +@@ -334,6 +334,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) + struct ci_hdrc_platform_data pdata = { + .name = dev_name(&pdev->dev), + .capoffset = DEF_CAPOFFSET, ++ .flags = CI_HDRC_HAS_SHORT_PKT_LIMIT, + .notify_event = ci_hdrc_imx_notify_event, + }; + int ret; +diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c +index ca71df4f32e4cc..c161a4ee529064 100644 +--- a/drivers/usb/chipidea/core.c ++++ b/drivers/usb/chipidea/core.c +@@ -1076,6 +1076,8 @@ static int ci_hdrc_probe(struct platform_device *pdev) + CI_HDRC_SUPPORTS_RUNTIME_PM); + ci->has_portsc_pec_bug = !!(ci->platdata->flags & + CI_HDRC_HAS_PORTSC_PEC_MISSED); ++ ci->has_short_pkt_limit = !!(ci->platdata->flags & ++ CI_HDRC_HAS_SHORT_PKT_LIMIT); + platform_set_drvdata(pdev, ci); + + ret = hw_device_init(ci, base); +diff --git a/drivers/usb/chipidea/otg.c b/drivers/usb/chipidea/otg.c +index f5490f2a5b6bca..647e98f4e35110 100644 +--- a/drivers/usb/chipidea/otg.c ++++ b/drivers/usb/chipidea/otg.c +@@ -130,8 +130,11 @@ enum ci_role ci_otg_role(struct ci_hdrc *ci) + + void ci_handle_vbus_change(struct ci_hdrc *ci) + { +- if (!ci->is_otg) ++ if (!ci->is_otg) { ++ if (ci->platdata->flags & CI_HDRC_FORCE_VBUS_ACTIVE_ALWAYS) ++ usb_gadget_vbus_connect(&ci->gadget); + return; ++ } + + if (hw_read_otgsc(ci, OTGSC_BSV) && !ci->vbus_active) + usb_gadget_vbus_connect(&ci->gadget); +diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c +index 9f7d003e467b54..f2ae5f4c58283a 100644 +--- a/drivers/usb/chipidea/udc.c ++++ b/drivers/usb/chipidea/udc.c +@@ -959,6 +959,12 @@ static int _ep_queue(struct usb_ep *ep, struct usb_request *req, + return -EMSGSIZE; + } + ++ if (ci->has_short_pkt_limit && ++ hwreq->req.length > CI_MAX_REQ_SIZE) { ++ dev_err(hwep->ci->dev, "request length too big (max 16KB)\n"); ++ return -EMSGSIZE; ++ } ++ + /* first nuke then test link, e.g. previous status has not sent */ + if (!list_empty(&hwreq->queue)) { + dev_err(hwep->ci->dev, "request already in queue\n"); +diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h +index b118f4aab18984..d00bf714a7ccfb 100644 +--- a/drivers/usb/dwc3/core.h ++++ b/drivers/usb/dwc3/core.h +@@ -899,6 +899,7 @@ struct dwc3_hwparams { + #define DWC3_MODE(n) ((n) & 0x7) + + /* HWPARAMS1 */ ++#define DWC3_SPRAM_TYPE(n) (((n) >> 23) & 1) + #define DWC3_NUM_INT(n) (((n) & (0x3f << 15)) >> 15) + + /* HWPARAMS3 */ +@@ -909,6 +910,9 @@ struct dwc3_hwparams { + #define DWC3_NUM_IN_EPS(p) (((p)->hwparams3 & \ + (DWC3_NUM_IN_EPS_MASK)) >> 18) + ++/* HWPARAMS6 */ ++#define DWC3_RAM0_DEPTH(n) (((n) & (0xffff0000)) >> 16) ++ + /* HWPARAMS7 */ + #define DWC3_RAM1_DEPTH(n) ((n) & 0xffff) + +diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c +index b560996bd4218a..656460c0c1dd7e 100644 +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -687,6 +687,44 @@ static int dwc3_gadget_calc_tx_fifo_size(struct dwc3 *dwc, int mult) + return fifo_size; + } + ++/** ++ * dwc3_gadget_calc_ram_depth - calculates the ram depth for txfifo ++ * @dwc: pointer to the DWC3 context ++ */ ++static int dwc3_gadget_calc_ram_depth(struct dwc3 *dwc) ++{ ++ int ram_depth; ++ int fifo_0_start; ++ bool is_single_port_ram; ++ ++ /* Check supporting RAM type by HW */ ++ is_single_port_ram = DWC3_SPRAM_TYPE(dwc->hwparams.hwparams1); ++ ++ /* ++ * If a single port RAM is utilized, then allocate TxFIFOs from ++ * RAM0. otherwise, allocate them from RAM1. ++ */ ++ ram_depth = is_single_port_ram ? DWC3_RAM0_DEPTH(dwc->hwparams.hwparams6) : ++ DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7); ++ ++ /* ++ * In a single port RAM configuration, the available RAM is shared ++ * between the RX and TX FIFOs. This means that the txfifo can begin ++ * at a non-zero address. ++ */ ++ if (is_single_port_ram) { ++ u32 reg; ++ ++ /* Check if TXFIFOs start at non-zero addr */ ++ reg = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(0)); ++ fifo_0_start = DWC3_GTXFIFOSIZ_TXFSTADDR(reg); ++ ++ ram_depth -= (fifo_0_start >> 16); ++ } ++ ++ return ram_depth; ++} ++ + /** + * dwc3_gadget_clear_tx_fifos - Clears txfifo allocation + * @dwc: pointer to the DWC3 context +@@ -753,7 +791,7 @@ static int dwc3_gadget_resize_tx_fifos(struct dwc3_ep *dep) + { + struct dwc3 *dwc = dep->dwc; + int fifo_0_start; +- int ram1_depth; ++ int ram_depth; + int fifo_size; + int min_depth; + int num_in_ep; +@@ -773,7 +811,7 @@ static int dwc3_gadget_resize_tx_fifos(struct dwc3_ep *dep) + if (dep->flags & DWC3_EP_TXFIFO_RESIZED) + return 0; + +- ram1_depth = DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7); ++ ram_depth = dwc3_gadget_calc_ram_depth(dwc); + + if ((dep->endpoint.maxburst > 1 && + usb_endpoint_xfer_bulk(dep->endpoint.desc)) || +@@ -794,7 +832,7 @@ static int dwc3_gadget_resize_tx_fifos(struct dwc3_ep *dep) + + /* Reserve at least one FIFO for the number of IN EPs */ + min_depth = num_in_ep * (fifo + 1); +- remaining = ram1_depth - min_depth - dwc->last_fifo_depth; ++ remaining = ram_depth - min_depth - dwc->last_fifo_depth; + remaining = max_t(int, 0, remaining); + /* + * We've already reserved 1 FIFO per EP, so check what we can fit in +@@ -820,9 +858,9 @@ static int dwc3_gadget_resize_tx_fifos(struct dwc3_ep *dep) + dwc->last_fifo_depth += DWC31_GTXFIFOSIZ_TXFDEP(fifo_size); + + /* Check fifo size allocation doesn't exceed available RAM size. */ +- if (dwc->last_fifo_depth >= ram1_depth) { ++ if (dwc->last_fifo_depth >= ram_depth) { + dev_err(dwc->dev, "Fifosize(%d) > RAM size(%d) %s depth:%d\n", +- dwc->last_fifo_depth, ram1_depth, ++ dwc->last_fifo_depth, ram_depth, + dep->endpoint.name, fifo_size); + if (DWC3_IP_IS(DWC3)) + fifo_size = DWC3_GTXFIFOSIZ_TXFDEP(fifo_size); +@@ -3078,7 +3116,7 @@ static int dwc3_gadget_check_config(struct usb_gadget *g) + struct dwc3 *dwc = gadget_to_dwc(g); + struct usb_ep *ep; + int fifo_size = 0; +- int ram1_depth; ++ int ram_depth; + int ep_num = 0; + + if (!dwc->do_fifo_resize) +@@ -3101,8 +3139,8 @@ static int dwc3_gadget_check_config(struct usb_gadget *g) + fifo_size += dwc->max_cfg_eps; + + /* Check if we can fit a single fifo per endpoint */ +- ram1_depth = DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7); +- if (fifo_size > ram1_depth) ++ ram_depth = dwc3_gadget_calc_ram_depth(dwc); ++ if (fifo_size > ram_depth) + return -ENOMEM; + + return 0; +diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c +index 50f58801140045..0d628af5c3ba50 100644 +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -52,6 +52,7 @@ + * endpoint rings; it generates events on the event ring for these. + */ + ++#include + #include + #include + #include +@@ -1091,6 +1092,19 @@ static int xhci_invalidate_cancelled_tds(struct xhci_virt_ep *ep) + return 0; + } + ++/* ++ * Erase queued TDs from transfer ring(s) and give back those the xHC didn't ++ * stop on. If necessary, queue commands to move the xHC off cancelled TDs it ++ * stopped on. Those will be given back later when the commands complete. ++ * ++ * Call under xhci->lock on a stopped endpoint. ++ */ ++void xhci_process_cancelled_tds(struct xhci_virt_ep *ep) ++{ ++ xhci_invalidate_cancelled_tds(ep); ++ xhci_giveback_invalidated_tds(ep); ++} ++ + /* + * Returns the TD the endpoint ring halted on. + * Only call for non-running rings without streams. +@@ -1180,9 +1194,35 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id, + break; + ep->ep_state &= ~EP_STOP_CMD_PENDING; + return; ++ case EP_STATE_STOPPED: ++ /* ++ * Per xHCI 4.6.9, Stop Endpoint command on a Stopped ++ * EP is a Context State Error, and EP stays Stopped. ++ * ++ * But maybe it failed on Halted, and somebody ran Reset ++ * Endpoint later. EP state is now Stopped and EP_HALTED ++ * still set because Reset EP handler will run after us. ++ */ ++ if (ep->ep_state & EP_HALTED) ++ break; ++ /* ++ * On some HCs EP state remains Stopped for some tens of ++ * us to a few ms or more after a doorbell ring, and any ++ * new Stop Endpoint fails without aborting the restart. ++ * This handler may run quickly enough to still see this ++ * Stopped state, but it will soon change to Running. ++ * ++ * Assume this bug on unexpected Stop Endpoint failures. ++ * Keep retrying until the EP starts and stops again, on ++ * chips where this is known to help. Wait for 100ms. ++ */ ++ if (time_is_before_jiffies(ep->stop_time + msecs_to_jiffies(100))) ++ break; ++ fallthrough; + case EP_STATE_RUNNING: + /* Race, HW handled stop ep cmd before ep was running */ +- xhci_dbg(xhci, "Stop ep completion ctx error, ep is running\n"); ++ xhci_dbg(xhci, "Stop ep completion ctx error, ctx_state %d\n", ++ GET_EP_CTX_STATE(ep_ctx)); + + command = xhci_alloc_command(xhci, false, GFP_ATOMIC); + if (!command) { +diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c +index 3bd70e6ad64baf..70e6c240a5409f 100644 +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -8,6 +8,7 @@ + * Some code borrowed from the Linux EHCI driver. + */ + ++#include + #include + #include + #include +@@ -1737,15 +1738,27 @@ static int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) + } + } + +- /* Queue a stop endpoint command, but only if this is +- * the first cancellation to be handled. +- */ +- if (!(ep->ep_state & EP_STOP_CMD_PENDING)) { ++ /* These completion handlers will sort out cancelled TDs for us */ ++ if (ep->ep_state & (EP_STOP_CMD_PENDING | EP_HALTED | SET_DEQ_PENDING)) { ++ xhci_dbg(xhci, "Not queuing Stop Endpoint on slot %d ep %d in state 0x%x\n", ++ urb->dev->slot_id, ep_index, ep->ep_state); ++ goto done; ++ } ++ ++ /* In this case no commands are pending but the endpoint is stopped */ ++ if (ep->ep_state & EP_CLEARING_TT) { ++ /* and cancelled TDs can be given back right away */ ++ xhci_dbg(xhci, "Invalidating TDs instantly on slot %d ep %d in state 0x%x\n", ++ urb->dev->slot_id, ep_index, ep->ep_state); ++ xhci_process_cancelled_tds(ep); ++ } else { ++ /* Otherwise, queue a new Stop Endpoint command */ + command = xhci_alloc_command(xhci, false, GFP_ATOMIC); + if (!command) { + ret = -ENOMEM; + goto done; + } ++ ep->stop_time = jiffies; + ep->ep_state |= EP_STOP_CMD_PENDING; + xhci_queue_stop_endpoint(xhci, command, urb->dev->slot_id, + ep_index, 0); +diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h +index 4bbd12db7239ab..fddb3a90dae3df 100644 +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -717,6 +717,7 @@ struct xhci_virt_ep { + /* Bandwidth checking storage */ + struct xhci_bw_info bw_info; + struct list_head bw_endpoint_list; ++ unsigned long stop_time; + /* Isoch Frame ID checking storage */ + int next_frame_id; + /* Use new Isoch TRB layout needed for extended TBC support */ +@@ -1951,6 +1952,7 @@ void xhci_ring_doorbell_for_active_rings(struct xhci_hcd *xhci, + void xhci_cleanup_command_queue(struct xhci_hcd *xhci); + void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring); + unsigned int count_trbs(u64 addr, u64 len); ++void xhci_process_cancelled_tds(struct xhci_virt_ep *ep); + + /* xHCI roothub code */ + void xhci_set_link_state(struct xhci_hcd *xhci, struct xhci_port *port, +diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c +index f6fb5575d4f0ac..d6a3fd00c3a5c4 100644 +--- a/drivers/usb/typec/ucsi/ucsi.c ++++ b/drivers/usb/typec/ucsi/ucsi.c +@@ -903,6 +903,9 @@ static void ucsi_handle_connector_change(struct work_struct *work) + + trace_ucsi_connector_change(con->num, &con->status); + ++ if (ucsi->ops->connector_status) ++ ucsi->ops->connector_status(con); ++ + role = !!(con->status.flags & UCSI_CONSTAT_PWR_DIR); + + if (con->status.change & UCSI_CONSTAT_POWER_DIR_CHANGE) { +@@ -1258,6 +1261,9 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con) + cap->driver_data = con; + cap->ops = &ucsi_ops; + ++ if (ucsi->ops->update_connector) ++ ucsi->ops->update_connector(con); ++ + ret = ucsi_register_port_psy(con); + if (ret) + goto out; +@@ -1322,6 +1328,9 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con) + } + ret = 0; /* ucsi_send_command() returns length on success */ + ++ if (ucsi->ops->connector_status) ++ ucsi->ops->connector_status(con); ++ + switch (UCSI_CONSTAT_PARTNER_TYPE(con->status.flags)) { + case UCSI_CONSTAT_PARTNER_TYPE_UFP: + case UCSI_CONSTAT_PARTNER_TYPE_CABLE_AND_UFP: +diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h +index 42c60eba5fb6ee..921ef0e115cffc 100644 +--- a/drivers/usb/typec/ucsi/ucsi.h ++++ b/drivers/usb/typec/ucsi/ucsi.h +@@ -15,6 +15,7 @@ + + struct ucsi; + struct ucsi_altmode; ++struct ucsi_connector; + struct dentry; + + /* UCSI offsets (Bytes) */ +@@ -52,6 +53,8 @@ struct dentry; + * @sync_write: Blocking write operation + * @async_write: Non-blocking write operation + * @update_altmodes: Squashes duplicate DP altmodes ++ * @update_connector: Update connector capabilities before registering ++ * @connector_status: Updates connector status, called holding connector lock + * + * Read and write routines for UCSI interface. @sync_write must wait for the + * Command Completion Event from the PPM before returning, and @async_write must +@@ -66,6 +69,8 @@ struct ucsi_operations { + const void *val, size_t val_len); + bool (*update_altmodes)(struct ucsi *ucsi, struct ucsi_altmode *orig, + struct ucsi_altmode *updated); ++ void (*update_connector)(struct ucsi_connector *con); ++ void (*connector_status)(struct ucsi_connector *con); + }; + + struct ucsi *ucsi_create(struct device *dev, const struct ucsi_operations *ops); +diff --git a/drivers/usb/typec/ucsi/ucsi_glink.c b/drivers/usb/typec/ucsi/ucsi_glink.c +index 94f2df02f06eeb..82a1081d44f1f0 100644 +--- a/drivers/usb/typec/ucsi/ucsi_glink.c ++++ b/drivers/usb/typec/ucsi/ucsi_glink.c +@@ -186,10 +186,40 @@ static int pmic_glink_ucsi_sync_write(struct ucsi *__ucsi, unsigned int offset, + return ret; + } + ++static void pmic_glink_ucsi_update_connector(struct ucsi_connector *con) ++{ ++ struct pmic_glink_ucsi *ucsi = ucsi_get_drvdata(con->ucsi); ++ ++ if (con->num > PMIC_GLINK_MAX_PORTS || ++ !ucsi->port_orientation[con->num - 1]) ++ return; ++ ++ con->typec_cap.orientation_aware = true; ++} ++ ++static void pmic_glink_ucsi_connector_status(struct ucsi_connector *con) ++{ ++ struct pmic_glink_ucsi *ucsi = ucsi_get_drvdata(con->ucsi); ++ int orientation; ++ ++ if (con->num > PMIC_GLINK_MAX_PORTS || ++ !ucsi->port_orientation[con->num - 1]) ++ return; ++ ++ orientation = gpiod_get_value(ucsi->port_orientation[con->num - 1]); ++ if (orientation >= 0) { ++ typec_switch_set(ucsi->port_switch[con->num - 1], ++ orientation ? TYPEC_ORIENTATION_REVERSE ++ : TYPEC_ORIENTATION_NORMAL); ++ } ++} ++ + static const struct ucsi_operations pmic_glink_ucsi_ops = { + .read = pmic_glink_ucsi_read, + .sync_write = pmic_glink_ucsi_sync_write, +- .async_write = pmic_glink_ucsi_async_write ++ .async_write = pmic_glink_ucsi_async_write, ++ .update_connector = pmic_glink_ucsi_update_connector, ++ .connector_status = pmic_glink_ucsi_connector_status, + }; + + static void pmic_glink_ucsi_read_ack(struct pmic_glink_ucsi *ucsi, const void *data, int len) +@@ -228,20 +258,8 @@ static void pmic_glink_ucsi_notify(struct work_struct *work) + } + + con_num = UCSI_CCI_CONNECTOR(cci); +- if (con_num) { +- if (con_num <= PMIC_GLINK_MAX_PORTS && +- ucsi->port_orientation[con_num - 1]) { +- int orientation = gpiod_get_value(ucsi->port_orientation[con_num - 1]); +- +- if (orientation >= 0) { +- typec_switch_set(ucsi->port_switch[con_num - 1], +- orientation ? TYPEC_ORIENTATION_REVERSE +- : TYPEC_ORIENTATION_NORMAL); +- } +- } +- ++ if (con_num) + ucsi_connector_change(ucsi->ucsi, con_num); +- } + + if (ucsi->sync_pending && + (cci & (UCSI_CCI_ACK_COMPLETE | UCSI_CCI_COMMAND_COMPLETE))) { +@@ -252,20 +270,6 @@ static void pmic_glink_ucsi_notify(struct work_struct *work) + static void pmic_glink_ucsi_register(struct work_struct *work) + { + struct pmic_glink_ucsi *ucsi = container_of(work, struct pmic_glink_ucsi, register_work); +- int orientation; +- int i; +- +- for (i = 0; i < PMIC_GLINK_MAX_PORTS; i++) { +- if (!ucsi->port_orientation[i]) +- continue; +- orientation = gpiod_get_value(ucsi->port_orientation[i]); +- +- if (orientation >= 0) { +- typec_switch_set(ucsi->port_switch[i], +- orientation ? TYPEC_ORIENTATION_REVERSE +- : TYPEC_ORIENTATION_NORMAL); +- } +- } + + ucsi_register(ucsi->ucsi); + } +diff --git a/drivers/watchdog/rzg2l_wdt.c b/drivers/watchdog/rzg2l_wdt.c +index 7bce093316c4d7..525a72d8d746e3 100644 +--- a/drivers/watchdog/rzg2l_wdt.c ++++ b/drivers/watchdog/rzg2l_wdt.c +@@ -8,11 +8,11 @@ + #include + #include + #include +-#include + #include + #include + #include + #include ++#include + #include + #include + #include +@@ -54,35 +54,11 @@ struct rzg2l_wdt_priv { + struct reset_control *rstc; + unsigned long osc_clk_rate; + unsigned long delay; +- unsigned long minimum_assertion_period; + struct clk *pclk; + struct clk *osc_clk; + enum rz_wdt_type devtype; + }; + +-static int rzg2l_wdt_reset(struct rzg2l_wdt_priv *priv) +-{ +- int err, status; +- +- if (priv->devtype == WDT_RZV2M) { +- /* WDT needs TYPE-B reset control */ +- err = reset_control_assert(priv->rstc); +- if (err) +- return err; +- ndelay(priv->minimum_assertion_period); +- err = reset_control_deassert(priv->rstc); +- if (err) +- return err; +- err = read_poll_timeout(reset_control_status, status, +- status != 1, 0, 1000, false, +- priv->rstc); +- } else { +- err = reset_control_reset(priv->rstc); +- } +- +- return err; +-} +- + static void rzg2l_wdt_wait_delay(struct rzg2l_wdt_priv *priv) + { + /* delay timer when change the setting register */ +@@ -129,6 +105,12 @@ static int rzg2l_wdt_start(struct watchdog_device *wdev) + if (ret) + return ret; + ++ ret = reset_control_deassert(priv->rstc); ++ if (ret) { ++ pm_runtime_put(wdev->parent); ++ return ret; ++ } ++ + /* Initialize time out */ + rzg2l_wdt_init_timeout(wdev); + +@@ -146,7 +128,9 @@ static int rzg2l_wdt_stop(struct watchdog_device *wdev) + struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev); + int ret; + +- rzg2l_wdt_reset(priv); ++ ret = reset_control_assert(priv->rstc); ++ if (ret) ++ return ret; + + ret = pm_runtime_put(wdev->parent); + if (ret < 0) +@@ -181,11 +165,30 @@ static int rzg2l_wdt_restart(struct watchdog_device *wdev, + unsigned long action, void *data) + { + struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev); ++ int ret; + +- clk_prepare_enable(priv->pclk); +- clk_prepare_enable(priv->osc_clk); ++ /* ++ * In case of RZ/G3S the watchdog device may be part of an IRQ safe power ++ * domain that is currently powered off. In this case we need to power ++ * it on before accessing registers. Along with this the clocks will be ++ * enabled. We don't undo the pm_runtime_resume_and_get() as the device ++ * need to be on for the reboot to happen. ++ * ++ * For the rest of SoCs not registering a watchdog IRQ safe power ++ * domain it is safe to call pm_runtime_resume_and_get() as the ++ * irq_safe_dev_in_sleep_domain() call in genpd_runtime_resume() ++ * returns non zero value and the genpd_lock() is avoided, thus, there ++ * will be no invalid wait context reported by lockdep. ++ */ ++ ret = pm_runtime_resume_and_get(wdev->parent); ++ if (ret) ++ return ret; + + if (priv->devtype == WDT_RZG2L) { ++ ret = reset_control_deassert(priv->rstc); ++ if (ret) ++ return ret; ++ + /* Generate Reset (WDTRSTB) Signal on parity error */ + rzg2l_wdt_write(priv, 0, PECR); + +@@ -193,7 +196,9 @@ static int rzg2l_wdt_restart(struct watchdog_device *wdev, + rzg2l_wdt_write(priv, PEEN_FORCE, PEEN); + } else { + /* RZ/V2M doesn't have parity error registers */ +- rzg2l_wdt_reset(priv); ++ ret = reset_control_reset(priv->rstc); ++ if (ret) ++ return ret; + + wdev->timeout = 0; + +@@ -236,13 +241,11 @@ static const struct watchdog_ops rzg2l_wdt_ops = { + .restart = rzg2l_wdt_restart, + }; + +-static void rzg2l_wdt_reset_assert_pm_disable(void *data) ++static void rzg2l_wdt_pm_disable(void *data) + { + struct watchdog_device *wdev = data; +- struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev); + + pm_runtime_disable(wdev->parent); +- reset_control_assert(priv->rstc); + } + + static int rzg2l_wdt_probe(struct platform_device *pdev) +@@ -285,19 +288,9 @@ static int rzg2l_wdt_probe(struct platform_device *pdev) + return dev_err_probe(&pdev->dev, PTR_ERR(priv->rstc), + "failed to get cpg reset"); + +- ret = reset_control_deassert(priv->rstc); +- if (ret) +- return dev_err_probe(dev, ret, "failed to deassert"); +- + priv->devtype = (uintptr_t)of_device_get_match_data(dev); + +- if (priv->devtype == WDT_RZV2M) { +- priv->minimum_assertion_period = RZV2M_A_NSEC + +- 3 * F2CYCLE_NSEC(pclk_rate) + 5 * +- max(F2CYCLE_NSEC(priv->osc_clk_rate), +- F2CYCLE_NSEC(pclk_rate)); +- } +- ++ pm_runtime_irq_safe(&pdev->dev); + pm_runtime_enable(&pdev->dev); + + priv->wdev.info = &rzg2l_wdt_ident; +@@ -309,9 +302,7 @@ static int rzg2l_wdt_probe(struct platform_device *pdev) + priv->wdev.timeout = WDT_DEFAULT_TIMEOUT; + + watchdog_set_drvdata(&priv->wdev, priv); +- ret = devm_add_action_or_reset(&pdev->dev, +- rzg2l_wdt_reset_assert_pm_disable, +- &priv->wdev); ++ ret = devm_add_action_or_reset(&pdev->dev, rzg2l_wdt_pm_disable, &priv->wdev); + if (ret < 0) + return ret; + +diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c +index 25c902e7556d57..4b21ca49b6665d 100644 +--- a/fs/btrfs/ctree.c ++++ b/fs/btrfs/ctree.c +@@ -526,13 +526,13 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans, + * bytes the allocator should try to find free next to the block it returns. + * This is just a hint and may be ignored by the allocator. + */ +-static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans, +- struct btrfs_root *root, +- struct extent_buffer *buf, +- struct extent_buffer *parent, int parent_slot, +- struct extent_buffer **cow_ret, +- u64 search_start, u64 empty_size, +- enum btrfs_lock_nesting nest) ++int btrfs_force_cow_block(struct btrfs_trans_handle *trans, ++ struct btrfs_root *root, ++ struct extent_buffer *buf, ++ struct extent_buffer *parent, int parent_slot, ++ struct extent_buffer **cow_ret, ++ u64 search_start, u64 empty_size, ++ enum btrfs_lock_nesting nest) + { + struct btrfs_fs_info *fs_info = root->fs_info; + struct btrfs_disk_key disk_key; +@@ -660,6 +660,8 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans, + return ret; + } + } ++ ++ trace_btrfs_cow_block(root, buf, cow); + if (unlock_orig) + btrfs_tree_unlock(buf); + free_extent_buffer_stale(buf); +@@ -699,7 +701,7 @@ static inline int should_cow_block(struct btrfs_trans_handle *trans, + } + + /* +- * cows a single block, see __btrfs_cow_block for the real work. ++ * COWs a single block, see btrfs_force_cow_block() for the real work. + * This version of it has extra checks so that a block isn't COWed more than + * once per transaction, as long as it hasn't been written yet + */ +@@ -711,7 +713,6 @@ noinline int btrfs_cow_block(struct btrfs_trans_handle *trans, + { + struct btrfs_fs_info *fs_info = root->fs_info; + u64 search_start; +- int ret; + + if (unlikely(test_bit(BTRFS_ROOT_DELETING, &root->state))) { + btrfs_abort_transaction(trans, -EUCLEAN); +@@ -752,12 +753,8 @@ noinline int btrfs_cow_block(struct btrfs_trans_handle *trans, + * Also We don't care about the error, as it's handled internally. + */ + btrfs_qgroup_trace_subtree_after_cow(trans, root, buf); +- ret = __btrfs_cow_block(trans, root, buf, parent, +- parent_slot, cow_ret, search_start, 0, nest); +- +- trace_btrfs_cow_block(root, buf, *cow_ret); +- +- return ret; ++ return btrfs_force_cow_block(trans, root, buf, parent, parent_slot, ++ cow_ret, search_start, 0, nest); + } + ALLOW_ERROR_INJECTION(btrfs_cow_block, ERRNO); + +@@ -904,11 +901,11 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, + search_start = last_block; + + btrfs_tree_lock(cur); +- err = __btrfs_cow_block(trans, root, cur, parent, i, +- &cur, search_start, +- min(16 * blocksize, +- (end_slot - i) * blocksize), +- BTRFS_NESTING_COW); ++ err = btrfs_force_cow_block(trans, root, cur, parent, i, ++ &cur, search_start, ++ min(16 * blocksize, ++ (end_slot - i) * blocksize), ++ BTRFS_NESTING_COW); + if (err) { + btrfs_tree_unlock(cur); + free_extent_buffer(cur); +diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h +index f7bb4c34b984b3..7df3ed2945b049 100644 +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -538,6 +538,13 @@ int btrfs_cow_block(struct btrfs_trans_handle *trans, + struct extent_buffer *parent, int parent_slot, + struct extent_buffer **cow_ret, + enum btrfs_lock_nesting nest); ++int btrfs_force_cow_block(struct btrfs_trans_handle *trans, ++ struct btrfs_root *root, ++ struct extent_buffer *buf, ++ struct extent_buffer *parent, int parent_slot, ++ struct extent_buffer **cow_ret, ++ u64 search_start, u64 empty_size, ++ enum btrfs_lock_nesting nest); + int btrfs_copy_root(struct btrfs_trans_handle *trans, + struct btrfs_root *root, + struct extent_buffer *buf, +diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c +index 8ec411eb9c9b0c..967c6b5dd0a434 100644 +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -4323,6 +4323,15 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info) + * already the cleaner, but below we run all pending delayed iputs. + */ + btrfs_flush_workqueue(fs_info->fixup_workers); ++ /* ++ * Similar case here, we have to wait for delalloc workers before we ++ * proceed below and stop the cleaner kthread, otherwise we trigger a ++ * use-after-tree on the cleaner kthread task_struct when a delalloc ++ * worker running submit_compressed_extents() adds a delayed iput, which ++ * does a wake up on the cleaner kthread, which was already freed below ++ * when we call kthread_stop(). ++ */ ++ btrfs_flush_workqueue(fs_info->delalloc_workers); + + /* + * After we parked the cleaner kthread, ordered extents may have +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index d6767f728c079d..eb9319d856f2d8 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -9972,7 +9972,7 @@ static void btrfs_encoded_read_endio(struct btrfs_bio *bbio) + */ + WRITE_ONCE(priv->status, bbio->bio.bi_status); + } +- if (!atomic_dec_return(&priv->pending)) ++ if (atomic_dec_and_test(&priv->pending)) + wake_up(&priv->wait); + bio_put(&bbio->bio); + } +diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c +index 11289ce8a8cc81..dfa1b3c82b53ac 100644 +--- a/fs/ceph/mds_client.c ++++ b/fs/ceph/mds_client.c +@@ -2713,12 +2713,11 @@ char *ceph_mdsc_build_path(struct ceph_mds_client *mdsc, struct dentry *dentry, + + if (pos < 0) { + /* +- * A rename didn't occur, but somehow we didn't end up where +- * we thought we would. Throw a warning and try again. ++ * The path is longer than PATH_MAX and this function ++ * cannot ever succeed. Creating paths that long is ++ * possible with Ceph, but Linux cannot use them. + */ +- pr_warn("build_path did not end path lookup where expected (pos = %d)\n", +- pos); +- goto retry; ++ return ERR_PTR(-ENAMETOOLONG); + } + + *pbase = base; +diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h +index 3db01b933c3e8b..60455c84a93742 100644 +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -891,10 +891,13 @@ do { \ + (raw_inode)->xtime = cpu_to_le32(clamp_t(int32_t, (ts).tv_sec, S32_MIN, S32_MAX)); \ + } while (0) + +-#define EXT4_INODE_SET_XTIME(xtime, inode, raw_inode) \ +- EXT4_INODE_SET_XTIME_VAL(xtime, inode, raw_inode, (inode)->xtime) ++#define EXT4_INODE_SET_ATIME(inode, raw_inode) \ ++ EXT4_INODE_SET_XTIME_VAL(i_atime, inode, raw_inode, inode_get_atime(inode)) + +-#define EXT4_INODE_SET_CTIME(inode, raw_inode) \ ++#define EXT4_INODE_SET_MTIME(inode, raw_inode) \ ++ EXT4_INODE_SET_XTIME_VAL(i_mtime, inode, raw_inode, inode_get_mtime(inode)) ++ ++#define EXT4_INODE_SET_CTIME(inode, raw_inode) \ + EXT4_INODE_SET_XTIME_VAL(i_ctime, inode, raw_inode, inode_get_ctime(inode)) + + #define EXT4_EINODE_SET_XTIME(xtime, einode, raw_inode) \ +@@ -910,9 +913,16 @@ do { \ + .tv_sec = (signed)le32_to_cpu((raw_inode)->xtime) \ + }) + +-#define EXT4_INODE_GET_XTIME(xtime, inode, raw_inode) \ ++#define EXT4_INODE_GET_ATIME(inode, raw_inode) \ ++do { \ ++ inode_set_atime_to_ts(inode, \ ++ EXT4_INODE_GET_XTIME_VAL(i_atime, inode, raw_inode)); \ ++} while (0) ++ ++#define EXT4_INODE_GET_MTIME(inode, raw_inode) \ + do { \ +- (inode)->xtime = EXT4_INODE_GET_XTIME_VAL(xtime, inode, raw_inode); \ ++ inode_set_mtime_to_ts(inode, \ ++ EXT4_INODE_GET_XTIME_VAL(i_mtime, inode, raw_inode)); \ + } while (0) + + #define EXT4_INODE_GET_CTIME(inode, raw_inode) \ +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index 5ea75af6ca2239..32218ac7f50fe2 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -4475,7 +4475,7 @@ static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset, + int depth = 0; + struct ext4_map_blocks map; + unsigned int credits; +- loff_t epos; ++ loff_t epos, old_size = i_size_read(inode); + + BUG_ON(!ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)); + map.m_lblk = offset; +@@ -4532,7 +4532,13 @@ static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset, + if (epos > new_size) + epos = new_size; + if (ext4_update_inode_size(inode, epos) & 0x1) +- inode->i_mtime = inode_get_ctime(inode); ++ inode_set_mtime_to_ts(inode, ++ inode_get_ctime(inode)); ++ if (epos > old_size) { ++ pagecache_isize_extended(inode, old_size, epos); ++ ext4_zero_partial_blocks(handle, inode, ++ old_size, epos - old_size); ++ } + } + ret2 = ext4_mark_inode_dirty(handle, inode); + ext4_update_inode_fsync_trans(handle, inode, 1); +@@ -4670,7 +4676,7 @@ static long ext4_zero_range(struct file *file, loff_t offset, + + /* Now release the pages and zero block aligned part of pages */ + truncate_pagecache_range(inode, start, end - 1); +- inode->i_mtime = inode_set_ctime_current(inode); ++ inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode)); + + ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size, + flags); +@@ -4695,7 +4701,7 @@ static long ext4_zero_range(struct file *file, loff_t offset, + goto out_mutex; + } + +- inode->i_mtime = inode_set_ctime_current(inode); ++ inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode)); + if (new_size) + ext4_update_inode_size(inode, new_size); + ret = ext4_mark_inode_dirty(handle, inode); +@@ -5431,7 +5437,7 @@ static int ext4_collapse_range(struct file *file, loff_t offset, loff_t len) + up_write(&EXT4_I(inode)->i_data_sem); + if (IS_SYNC(inode)) + ext4_handle_sync(handle); +- inode->i_mtime = inode_set_ctime_current(inode); ++ inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode)); + ret = ext4_mark_inode_dirty(handle, inode); + ext4_update_inode_fsync_trans(handle, inode, 1); + +@@ -5541,7 +5547,7 @@ static int ext4_insert_range(struct file *file, loff_t offset, loff_t len) + /* Expand file to avoid data loss if there is error while shifting */ + inode->i_size += len; + EXT4_I(inode)->i_disksize += len; +- inode->i_mtime = inode_set_ctime_current(inode); ++ inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode)); + ret = ext4_mark_inode_dirty(handle, inode); + if (ret) + goto out_stop; +diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c +index d4d0ad689d3c1c..52f2959d29e6e0 100644 +--- a/fs/ext4/ialloc.c ++++ b/fs/ext4/ialloc.c +@@ -1255,8 +1255,8 @@ struct inode *__ext4_new_inode(struct mnt_idmap *idmap, + inode->i_ino = ino + group * EXT4_INODES_PER_GROUP(sb); + /* This is the optimal IO size (for stat), not the fs block size */ + inode->i_blocks = 0; +- inode->i_mtime = inode->i_atime = inode_set_ctime_current(inode); +- ei->i_crtime = inode->i_mtime; ++ simple_inode_init_ts(inode); ++ ei->i_crtime = inode_get_mtime(inode); + + memset(ei->i_data, 0, sizeof(ei->i_data)); + ei->i_dir_start_lookup = 0; +diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c +index cb65052ee3dec6..3f363276ddd360 100644 +--- a/fs/ext4/inline.c ++++ b/fs/ext4/inline.c +@@ -1037,7 +1037,7 @@ static int ext4_add_dirent_to_inline(handle_t *handle, + * happen is that the times are slightly out of date + * and/or different from the directory change time. + */ +- dir->i_mtime = inode_set_ctime_current(dir); ++ inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir)); + ext4_update_dx_flag(dir); + inode_inc_iversion(dir); + return 1; +@@ -2010,7 +2010,7 @@ int ext4_inline_data_truncate(struct inode *inode, int *has_inline) + ext4_orphan_del(handle, inode); + + if (err == 0) { +- inode->i_mtime = inode_set_ctime_current(inode); ++ inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode)); + err = ext4_mark_inode_dirty(handle, inode); + if (IS_SYNC(inode)) + ext4_handle_sync(handle); +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index 18ec9106c5b09f..19d7bcf16ebb88 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -1328,8 +1328,10 @@ static int ext4_write_end(struct file *file, + folio_unlock(folio); + folio_put(folio); + +- if (old_size < pos && !verity) ++ if (old_size < pos && !verity) { + pagecache_isize_extended(inode, old_size, pos); ++ ext4_zero_partial_blocks(handle, inode, old_size, pos - old_size); ++ } + /* + * Don't mark the inode dirty under folio lock. First, it unnecessarily + * makes the holding time of folio lock longer. Second, it forces lock +@@ -1445,8 +1447,10 @@ static int ext4_journalled_write_end(struct file *file, + folio_unlock(folio); + folio_put(folio); + +- if (old_size < pos && !verity) ++ if (old_size < pos && !verity) { + pagecache_isize_extended(inode, old_size, pos); ++ ext4_zero_partial_blocks(handle, inode, old_size, pos - old_size); ++ } + + if (size_changed) { + ret2 = ext4_mark_inode_dirty(handle, inode); +@@ -2971,7 +2975,8 @@ static int ext4_da_do_write_end(struct address_space *mapping, + struct inode *inode = mapping->host; + loff_t old_size = inode->i_size; + bool disksize_changed = false; +- loff_t new_i_size; ++ loff_t new_i_size, zero_len = 0; ++ handle_t *handle; + + if (unlikely(!folio_buffers(folio))) { + folio_unlock(folio); +@@ -3015,18 +3020,21 @@ static int ext4_da_do_write_end(struct address_space *mapping, + folio_unlock(folio); + folio_put(folio); + +- if (old_size < pos) ++ if (pos > old_size) { + pagecache_isize_extended(inode, old_size, pos); ++ zero_len = pos - old_size; ++ } + +- if (disksize_changed) { +- handle_t *handle; ++ if (!disksize_changed && !zero_len) ++ return copied; + +- handle = ext4_journal_start(inode, EXT4_HT_INODE, 2); +- if (IS_ERR(handle)) +- return PTR_ERR(handle); +- ext4_mark_inode_dirty(handle, inode); +- ext4_journal_stop(handle); +- } ++ handle = ext4_journal_start(inode, EXT4_HT_INODE, 2); ++ if (IS_ERR(handle)) ++ return PTR_ERR(handle); ++ if (zero_len) ++ ext4_zero_partial_blocks(handle, inode, old_size, zero_len); ++ ext4_mark_inode_dirty(handle, inode); ++ ext4_journal_stop(handle); + + return copied; + } +@@ -4055,7 +4063,7 @@ int ext4_punch_hole(struct file *file, loff_t offset, loff_t length) + if (IS_SYNC(inode)) + ext4_handle_sync(handle); + +- inode->i_mtime = inode_set_ctime_current(inode); ++ inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode)); + ret2 = ext4_mark_inode_dirty(handle, inode); + if (unlikely(ret2)) + ret = ret2; +@@ -4215,7 +4223,7 @@ int ext4_truncate(struct inode *inode) + if (inode->i_nlink) + ext4_orphan_del(handle, inode); + +- inode->i_mtime = inode_set_ctime_current(inode); ++ inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode)); + err2 = ext4_mark_inode_dirty(handle, inode); + if (unlikely(err2 && !err)) + err = err2; +@@ -4319,8 +4327,8 @@ static int ext4_fill_raw_inode(struct inode *inode, struct ext4_inode *raw_inode + raw_inode->i_links_count = cpu_to_le16(inode->i_nlink); + + EXT4_INODE_SET_CTIME(inode, raw_inode); +- EXT4_INODE_SET_XTIME(i_mtime, inode, raw_inode); +- EXT4_INODE_SET_XTIME(i_atime, inode, raw_inode); ++ EXT4_INODE_SET_MTIME(inode, raw_inode); ++ EXT4_INODE_SET_ATIME(inode, raw_inode); + EXT4_EINODE_SET_XTIME(i_crtime, ei, raw_inode); + + raw_inode->i_dtime = cpu_to_le32(ei->i_dtime); +@@ -4928,8 +4936,8 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino, + } + + EXT4_INODE_GET_CTIME(inode, raw_inode); +- EXT4_INODE_GET_XTIME(i_mtime, inode, raw_inode); +- EXT4_INODE_GET_XTIME(i_atime, inode, raw_inode); ++ EXT4_INODE_GET_ATIME(inode, raw_inode); ++ EXT4_INODE_GET_MTIME(inode, raw_inode); + EXT4_EINODE_GET_XTIME(i_crtime, ei, raw_inode); + + if (likely(!test_opt2(inode->i_sb, HURD_COMPAT))) { +@@ -5054,8 +5062,8 @@ static void __ext4_update_other_inode_time(struct super_block *sb, + + spin_lock(&ei->i_raw_lock); + EXT4_INODE_SET_CTIME(inode, raw_inode); +- EXT4_INODE_SET_XTIME(i_mtime, inode, raw_inode); +- EXT4_INODE_SET_XTIME(i_atime, inode, raw_inode); ++ EXT4_INODE_SET_MTIME(inode, raw_inode); ++ EXT4_INODE_SET_ATIME(inode, raw_inode); + ext4_inode_csum_set(inode, raw_inode, ei); + spin_unlock(&ei->i_raw_lock); + trace_ext4_other_inode_update_time(inode, orig_ino); +@@ -5437,6 +5445,14 @@ int ext4_setattr(struct mnt_idmap *idmap, struct dentry *dentry, + } + + if (attr->ia_size != inode->i_size) { ++ /* attach jbd2 jinode for EOF folio tail zeroing */ ++ if (attr->ia_size & (inode->i_sb->s_blocksize - 1) || ++ oldsize & (inode->i_sb->s_blocksize - 1)) { ++ error = ext4_inode_attach_jinode(inode); ++ if (error) ++ goto err_out; ++ } ++ + handle = ext4_journal_start(inode, EXT4_HT_INODE, 3); + if (IS_ERR(handle)) { + error = PTR_ERR(handle); +@@ -5447,11 +5463,17 @@ int ext4_setattr(struct mnt_idmap *idmap, struct dentry *dentry, + orphan = 1; + } + /* +- * Update c/mtime on truncate up, ext4_truncate() will +- * update c/mtime in shrink case below ++ * Update c/mtime and tail zero the EOF folio on ++ * truncate up. ext4_truncate() handles the shrink case ++ * below. + */ +- if (!shrink) +- inode->i_mtime = inode_set_ctime_current(inode); ++ if (!shrink) { ++ inode_set_mtime_to_ts(inode, ++ inode_set_ctime_current(inode)); ++ if (oldsize & (inode->i_sb->s_blocksize - 1)) ++ ext4_block_truncate_page(handle, ++ inode->i_mapping, oldsize); ++ } + + if (shrink) + ext4_fc_track_range(handle, inode, +diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c +index 0bfe2ce589e224..4f931f80cb3489 100644 +--- a/fs/ext4/ioctl.c ++++ b/fs/ext4/ioctl.c +@@ -312,13 +312,22 @@ static void swap_inode_data(struct inode *inode1, struct inode *inode2) + struct ext4_inode_info *ei1; + struct ext4_inode_info *ei2; + unsigned long tmp; ++ struct timespec64 ts1, ts2; + + ei1 = EXT4_I(inode1); + ei2 = EXT4_I(inode2); + + swap(inode1->i_version, inode2->i_version); +- swap(inode1->i_atime, inode2->i_atime); +- swap(inode1->i_mtime, inode2->i_mtime); ++ ++ ts1 = inode_get_atime(inode1); ++ ts2 = inode_get_atime(inode2); ++ inode_set_atime_to_ts(inode1, ts2); ++ inode_set_atime_to_ts(inode2, ts1); ++ ++ ts1 = inode_get_mtime(inode1); ++ ts2 = inode_get_mtime(inode2); ++ inode_set_mtime_to_ts(inode1, ts2); ++ inode_set_mtime_to_ts(inode2, ts1); + + memswap(ei1->i_data, ei2->i_data, sizeof(ei1->i_data)); + tmp = ei1->i_flags & EXT4_FL_SHOULD_SWAP; +diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c +index 4de1f61bba76b3..96a048d3f51bf5 100644 +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -2210,7 +2210,7 @@ static int add_dirent_to_buf(handle_t *handle, struct ext4_filename *fname, + * happen is that the times are slightly out of date + * and/or different from the directory change time. + */ +- dir->i_mtime = inode_set_ctime_current(dir); ++ inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir)); + ext4_update_dx_flag(dir); + inode_inc_iversion(dir); + err2 = ext4_mark_inode_dirty(handle, dir); +@@ -3248,7 +3248,7 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry) + * recovery. */ + inode->i_size = 0; + ext4_orphan_add(handle, inode); +- dir->i_mtime = inode_set_ctime_current(dir); ++ inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir)); + inode_set_ctime_current(inode); + retval = ext4_mark_inode_dirty(handle, inode); + if (retval) +@@ -3323,7 +3323,7 @@ int __ext4_unlink(struct inode *dir, const struct qstr *d_name, + retval = ext4_delete_entry(handle, dir, de, bh); + if (retval) + goto out_handle; +- dir->i_mtime = inode_set_ctime_current(dir); ++ inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir)); + ext4_update_dx_flag(dir); + retval = ext4_mark_inode_dirty(handle, dir); + if (retval) +@@ -3691,7 +3691,7 @@ static int ext4_setent(handle_t *handle, struct ext4_renament *ent, + if (ext4_has_feature_filetype(ent->dir->i_sb)) + ent->de->file_type = file_type; + inode_inc_iversion(ent->dir); +- ent->dir->i_mtime = inode_set_ctime_current(ent->dir); ++ inode_set_mtime_to_ts(ent->dir, inode_set_ctime_current(ent->dir)); + retval = ext4_mark_inode_dirty(handle, ent->dir); + BUFFER_TRACE(ent->bh, "call ext4_handle_dirty_metadata"); + if (!ent->inlined) { +@@ -4006,7 +4006,7 @@ static int ext4_rename(struct mnt_idmap *idmap, struct inode *old_dir, + ext4_dec_count(new.inode); + inode_set_ctime_current(new.inode); + } +- old.dir->i_mtime = inode_set_ctime_current(old.dir); ++ inode_set_mtime_to_ts(old.dir, inode_set_ctime_current(old.dir)); + ext4_update_dx_flag(old.dir); + if (old.dir_bh) { + retval = ext4_rename_dir_finish(handle, &old, new.dir->i_ino); +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index 2346ef071b2421..71ced0ada9a2e5 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -7180,7 +7180,7 @@ static int ext4_quota_off(struct super_block *sb, int type) + } + EXT4_I(inode)->i_flags &= ~(EXT4_NOATIME_FL | EXT4_IMMUTABLE_FL); + inode_set_flags(inode, 0, S_NOATIME | S_IMMUTABLE); +- inode->i_mtime = inode_set_ctime_current(inode); ++ inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode)); + err = ext4_mark_inode_dirty(handle, inode); + ext4_journal_stop(handle); + out_unlock: +diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c +index f40785bc4e5549..df5ab1a75fc482 100644 +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -356,7 +356,7 @@ ext4_xattr_inode_hash(struct ext4_sb_info *sbi, const void *buffer, size_t size) + + static u64 ext4_xattr_inode_get_ref(struct inode *ea_inode) + { +- return ((u64) inode_get_ctime(ea_inode).tv_sec << 32) | ++ return ((u64) inode_get_ctime_sec(ea_inode) << 32) | + (u32) inode_peek_iversion_raw(ea_inode); + } + +@@ -368,12 +368,12 @@ static void ext4_xattr_inode_set_ref(struct inode *ea_inode, u64 ref_count) + + static u32 ext4_xattr_inode_get_hash(struct inode *ea_inode) + { +- return (u32)ea_inode->i_atime.tv_sec; ++ return (u32) inode_get_atime_sec(ea_inode); + } + + static void ext4_xattr_inode_set_hash(struct inode *ea_inode, u32 hash) + { +- ea_inode->i_atime.tv_sec = hash; ++ inode_set_atime(ea_inode, hash, 0); + } + + /* +@@ -418,7 +418,7 @@ static int ext4_xattr_inode_read(struct inode *ea_inode, void *buf, size_t size) + return ret; + } + +-#define EXT4_XATTR_INODE_GET_PARENT(inode) ((__u32)(inode)->i_mtime.tv_sec) ++#define EXT4_XATTR_INODE_GET_PARENT(inode) ((__u32)(inode_get_mtime_sec(inode))) + + static int ext4_xattr_inode_iget(struct inode *parent, unsigned long ea_ino, + u32 ea_inode_hash, struct inode **ea_inode) +diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c +index 196755a34833d2..ae129044c52f42 100644 +--- a/fs/f2fs/file.c ++++ b/fs/f2fs/file.c +@@ -1037,6 +1037,13 @@ int f2fs_setattr(struct mnt_idmap *idmap, struct dentry *dentry, + return err; + } + ++ /* ++ * wait for inflight dio, blocks should be removed after ++ * IO completion. ++ */ ++ if (attr->ia_size < old_size) ++ inode_dio_wait(inode); ++ + f2fs_down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]); + filemap_invalidate_lock(inode->i_mapping); + +@@ -1873,6 +1880,12 @@ static long f2fs_fallocate(struct file *file, int mode, + if (ret) + goto out; + ++ /* ++ * wait for inflight dio, blocks should be removed after IO ++ * completion. ++ */ ++ inode_dio_wait(inode); ++ + if (mode & FALLOC_FL_PUNCH_HOLE) { + if (offset >= inode->i_size) + goto out; +diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c +index fc6cea60044edf..e25989dd2c6bba 100644 +--- a/fs/ntfs3/attrib.c ++++ b/fs/ntfs3/attrib.c +@@ -977,15 +977,17 @@ int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn, + goto out; + + /* Check for compressed frame. */ +- err = attr_is_frame_compressed(ni, attr, vcn >> NTFS_LZNT_CUNIT, &hint); ++ err = attr_is_frame_compressed(ni, attr_b, vcn >> NTFS_LZNT_CUNIT, ++ &hint, run); + if (err) + goto out; + + if (hint) { + /* if frame is compressed - don't touch it. */ + *lcn = COMPRESSED_LCN; +- *len = hint; +- err = -EOPNOTSUPP; ++ /* length to the end of frame. */ ++ *len = NTFS_LZNT_CLUSTERS - (vcn & (NTFS_LZNT_CLUSTERS - 1)); ++ err = 0; + goto out; + } + +@@ -1028,16 +1030,16 @@ int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn, + + /* Check if 'vcn' and 'vcn0' in different attribute segments. */ + if (vcn < svcn || evcn1 <= vcn) { +- /* Load attribute for truncated vcn. */ +- attr = ni_find_attr(ni, attr_b, &le, ATTR_DATA, NULL, 0, +- &vcn, &mi); +- if (!attr) { ++ struct ATTRIB *attr2; ++ /* Load runs for truncated vcn. */ ++ attr2 = ni_find_attr(ni, attr_b, &le_b, ATTR_DATA, NULL, ++ 0, &vcn, &mi); ++ if (!attr2) { + err = -EINVAL; + goto out; + } +- svcn = le64_to_cpu(attr->nres.svcn); +- evcn1 = le64_to_cpu(attr->nres.evcn) + 1; +- err = attr_load_runs(attr, ni, run, NULL); ++ evcn1 = le64_to_cpu(attr2->nres.evcn) + 1; ++ err = attr_load_runs(attr2, ni, run, NULL); + if (err) + goto out; + } +@@ -1530,15 +1532,18 @@ int attr_wof_frame_info(struct ntfs_inode *ni, struct ATTRIB *attr, + + /* + * attr_is_frame_compressed - Used to detect compressed frame. ++ * ++ * attr - base (primary) attribute segment. ++ * run - run to use, usually == &ni->file.run. ++ * Only base segments contains valid 'attr->nres.c_unit' + */ + int attr_is_frame_compressed(struct ntfs_inode *ni, struct ATTRIB *attr, +- CLST frame, CLST *clst_data) ++ CLST frame, CLST *clst_data, struct runs_tree *run) + { + int err; + u32 clst_frame; + CLST clen, lcn, vcn, alen, slen, vcn_next; + size_t idx; +- struct runs_tree *run; + + *clst_data = 0; + +@@ -1550,7 +1555,6 @@ int attr_is_frame_compressed(struct ntfs_inode *ni, struct ATTRIB *attr, + + clst_frame = 1u << attr->nres.c_unit; + vcn = frame * clst_frame; +- run = &ni->file.run; + + if (!run_lookup_entry(run, vcn, &lcn, &clen, &idx)) { + err = attr_load_runs_vcn(ni, attr->type, attr_name(attr), +@@ -1686,7 +1690,7 @@ int attr_allocate_frame(struct ntfs_inode *ni, CLST frame, size_t compr_size, + if (err) + goto out; + +- err = attr_is_frame_compressed(ni, attr_b, frame, &clst_data); ++ err = attr_is_frame_compressed(ni, attr_b, frame, &clst_data, run); + if (err) + goto out; + +diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c +index 12e03feb3074a0..3c876c468c2c47 100644 +--- a/fs/ntfs3/frecord.c ++++ b/fs/ntfs3/frecord.c +@@ -1900,46 +1900,6 @@ enum REPARSE_SIGN ni_parse_reparse(struct ntfs_inode *ni, struct ATTRIB *attr, + return REPARSE_LINK; + } + +-/* +- * fiemap_fill_next_extent_k - a copy of fiemap_fill_next_extent +- * but it uses 'fe_k' instead of fieinfo->fi_extents_start +- */ +-static int fiemap_fill_next_extent_k(struct fiemap_extent_info *fieinfo, +- struct fiemap_extent *fe_k, u64 logical, +- u64 phys, u64 len, u32 flags) +-{ +- struct fiemap_extent extent; +- +- /* only count the extents */ +- if (fieinfo->fi_extents_max == 0) { +- fieinfo->fi_extents_mapped++; +- return (flags & FIEMAP_EXTENT_LAST) ? 1 : 0; +- } +- +- if (fieinfo->fi_extents_mapped >= fieinfo->fi_extents_max) +- return 1; +- +- if (flags & FIEMAP_EXTENT_DELALLOC) +- flags |= FIEMAP_EXTENT_UNKNOWN; +- if (flags & FIEMAP_EXTENT_DATA_ENCRYPTED) +- flags |= FIEMAP_EXTENT_ENCODED; +- if (flags & (FIEMAP_EXTENT_DATA_TAIL | FIEMAP_EXTENT_DATA_INLINE)) +- flags |= FIEMAP_EXTENT_NOT_ALIGNED; +- +- memset(&extent, 0, sizeof(extent)); +- extent.fe_logical = logical; +- extent.fe_physical = phys; +- extent.fe_length = len; +- extent.fe_flags = flags; +- +- memcpy(fe_k + fieinfo->fi_extents_mapped, &extent, sizeof(extent)); +- +- fieinfo->fi_extents_mapped++; +- if (fieinfo->fi_extents_mapped == fieinfo->fi_extents_max) +- return 1; +- return (flags & FIEMAP_EXTENT_LAST) ? 1 : 0; +-} +- + /* + * ni_fiemap - Helper for file_fiemap(). + * +@@ -1950,11 +1910,9 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo, + __u64 vbo, __u64 len) + { + int err = 0; +- struct fiemap_extent *fe_k = NULL; + struct ntfs_sb_info *sbi = ni->mi.sbi; + u8 cluster_bits = sbi->cluster_bits; +- struct runs_tree *run; +- struct rw_semaphore *run_lock; ++ struct runs_tree run; + struct ATTRIB *attr; + CLST vcn = vbo >> cluster_bits; + CLST lcn, clen; +@@ -1965,13 +1923,11 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo, + u32 flags; + bool ok; + ++ run_init(&run); + if (S_ISDIR(ni->vfs_inode.i_mode)) { +- run = &ni->dir.alloc_run; + attr = ni_find_attr(ni, NULL, NULL, ATTR_ALLOC, I30_NAME, + ARRAY_SIZE(I30_NAME), NULL, NULL); +- run_lock = &ni->dir.run_lock; + } else { +- run = &ni->file.run; + attr = ni_find_attr(ni, NULL, NULL, ATTR_DATA, NULL, 0, NULL, + NULL); + if (!attr) { +@@ -1986,7 +1942,6 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo, + "fiemap is not supported for compressed file (cp -r)"); + goto out; + } +- run_lock = &ni->file.run_lock; + } + + if (!attr || !attr->non_res) { +@@ -1998,51 +1953,33 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo, + goto out; + } + +- /* +- * To avoid lock problems replace pointer to user memory by pointer to kernel memory. +- */ +- fe_k = kmalloc_array(fieinfo->fi_extents_max, +- sizeof(struct fiemap_extent), +- GFP_NOFS | __GFP_ZERO); +- if (!fe_k) { +- err = -ENOMEM; +- goto out; +- } +- + end = vbo + len; + alloc_size = le64_to_cpu(attr->nres.alloc_size); + if (end > alloc_size) + end = alloc_size; + +- down_read(run_lock); + + while (vbo < end) { + if (idx == -1) { +- ok = run_lookup_entry(run, vcn, &lcn, &clen, &idx); ++ ok = run_lookup_entry(&run, vcn, &lcn, &clen, &idx); + } else { + CLST vcn_next = vcn; + +- ok = run_get_entry(run, ++idx, &vcn, &lcn, &clen) && ++ ok = run_get_entry(&run, ++idx, &vcn, &lcn, &clen) && + vcn == vcn_next; + if (!ok) + vcn = vcn_next; + } + + if (!ok) { +- up_read(run_lock); +- down_write(run_lock); +- + err = attr_load_runs_vcn(ni, attr->type, + attr_name(attr), +- attr->name_len, run, vcn); +- +- up_write(run_lock); +- down_read(run_lock); ++ attr->name_len, &run, vcn); + + if (err) + break; + +- ok = run_lookup_entry(run, vcn, &lcn, &clen, &idx); ++ ok = run_lookup_entry(&run, vcn, &lcn, &clen, &idx); + + if (!ok) { + err = -EINVAL; +@@ -2067,8 +2004,9 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo, + } else if (is_attr_compressed(attr)) { + CLST clst_data; + +- err = attr_is_frame_compressed( +- ni, attr, vcn >> attr->nres.c_unit, &clst_data); ++ err = attr_is_frame_compressed(ni, attr, ++ vcn >> attr->nres.c_unit, ++ &clst_data, &run); + if (err) + break; + if (clst_data < NTFS_LZNT_CLUSTERS) +@@ -2097,8 +2035,8 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo, + if (vbo + dlen >= end) + flags |= FIEMAP_EXTENT_LAST; + +- err = fiemap_fill_next_extent_k(fieinfo, fe_k, vbo, lbo, +- dlen, flags); ++ err = fiemap_fill_next_extent(fieinfo, vbo, lbo, dlen, ++ flags); + + if (err < 0) + break; +@@ -2119,8 +2057,7 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo, + if (vbo + bytes >= end) + flags |= FIEMAP_EXTENT_LAST; + +- err = fiemap_fill_next_extent_k(fieinfo, fe_k, vbo, lbo, bytes, +- flags); ++ err = fiemap_fill_next_extent(fieinfo, vbo, lbo, bytes, flags); + if (err < 0) + break; + if (err == 1) { +@@ -2131,19 +2068,8 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo, + vbo += bytes; + } + +- up_read(run_lock); +- +- /* +- * Copy to user memory out of lock +- */ +- if (copy_to_user(fieinfo->fi_extents_start, fe_k, +- fieinfo->fi_extents_max * +- sizeof(struct fiemap_extent))) { +- err = -EFAULT; +- } +- + out: +- kfree(fe_k); ++ run_close(&run); + return err; + } + +@@ -2674,7 +2600,8 @@ int ni_read_frame(struct ntfs_inode *ni, u64 frame_vbo, struct page **pages, + down_write(&ni->file.run_lock); + run_truncate_around(run, le64_to_cpu(attr->nres.svcn)); + frame = frame_vbo >> (cluster_bits + NTFS_LZNT_CUNIT); +- err = attr_is_frame_compressed(ni, attr, frame, &clst_data); ++ err = attr_is_frame_compressed(ni, attr, frame, &clst_data, ++ run); + up_write(&ni->file.run_lock); + if (err) + goto out1; +diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c +index 52b80fd1591478..af7c0cbba74e3d 100644 +--- a/fs/ntfs3/inode.c ++++ b/fs/ntfs3/inode.c +@@ -604,7 +604,8 @@ static noinline int ntfs_get_block_vbo(struct inode *inode, u64 vbo, + + bytes = ((u64)len << cluster_bits) - off; + +- if (lcn == SPARSE_LCN) { ++ if (lcn >= sbi->used.bitmap.nbits) { ++ /* This case includes resident/compressed/sparse. */ + if (!create) { + if (bh->b_size > bytes) + bh->b_size = bytes; +diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h +index cfe9d3bf07f910..c98e6868bfbadb 100644 +--- a/fs/ntfs3/ntfs_fs.h ++++ b/fs/ntfs3/ntfs_fs.h +@@ -446,7 +446,8 @@ int attr_wof_frame_info(struct ntfs_inode *ni, struct ATTRIB *attr, + struct runs_tree *run, u64 frame, u64 frames, + u8 frame_bits, u32 *ondisk_size, u64 *vbo_data); + int attr_is_frame_compressed(struct ntfs_inode *ni, struct ATTRIB *attr, +- CLST frame, CLST *clst_data); ++ CLST frame, CLST *clst_data, ++ struct runs_tree *run); + int attr_allocate_frame(struct ntfs_inode *ni, CLST frame, size_t compr_size, + u64 new_valid); + int attr_collapse_range(struct ntfs_inode *ni, u64 vbo, u64 bytes); +diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c +index dc9f76ab7e13c3..0dffd6a44d39dc 100644 +--- a/fs/ocfs2/quota_global.c ++++ b/fs/ocfs2/quota_global.c +@@ -881,7 +881,7 @@ static int ocfs2_get_next_id(struct super_block *sb, struct kqid *qid) + int status = 0; + + trace_ocfs2_get_next_id(from_kqid(&init_user_ns, *qid), type); +- if (!sb_has_quota_loaded(sb, type)) { ++ if (!sb_has_quota_active(sb, type)) { + status = -ESRCH; + goto out; + } +diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c +index 257f13cdd14c1f..4b4fa58cd32ff0 100644 +--- a/fs/ocfs2/quota_local.c ++++ b/fs/ocfs2/quota_local.c +@@ -864,6 +864,7 @@ static int ocfs2_local_free_info(struct super_block *sb, int type) + brelse(oinfo->dqi_libh); + brelse(oinfo->dqi_lqi_bh); + kfree(oinfo); ++ info->dqi_priv = NULL; + return status; + } + +diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c +index 59571737e16771..b8640f36ebf8ab 100644 +--- a/fs/proc/task_mmu.c ++++ b/fs/proc/task_mmu.c +@@ -1516,7 +1516,7 @@ static int pagemap_pmd_range(pmd_t *pmdp, unsigned long addr, unsigned long end, + flags |= PM_FILE; + + for (; addr != end; addr += PAGE_SIZE, idx++) { +- unsigned long cur_flags = flags; ++ u64 cur_flags = flags; + pagemap_entry_t pme; + + if (page && (flags & PM_PRESENT) && +diff --git a/fs/smb/client/cifsacl.c b/fs/smb/client/cifsacl.c +index f5b6df82e8570a..bff8d0dd74fe7d 100644 +--- a/fs/smb/client/cifsacl.c ++++ b/fs/smb/client/cifsacl.c +@@ -27,18 +27,18 @@ + #include "cifs_unicode.h" + + /* security id for everyone/world system group */ +-static const struct cifs_sid sid_everyone = { ++static const struct smb_sid sid_everyone = { + 1, 1, {0, 0, 0, 0, 0, 1}, {0} }; + /* security id for Authenticated Users system group */ +-static const struct cifs_sid sid_authusers = { ++static const struct smb_sid sid_authusers = { + 1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(11)} }; + + /* S-1-22-1 Unmapped Unix users */ +-static const struct cifs_sid sid_unix_users = {1, 1, {0, 0, 0, 0, 0, 22}, ++static const struct smb_sid sid_unix_users = {1, 1, {0, 0, 0, 0, 0, 22}, + {cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; + + /* S-1-22-2 Unmapped Unix groups */ +-static const struct cifs_sid sid_unix_groups = { 1, 1, {0, 0, 0, 0, 0, 22}, ++static const struct smb_sid sid_unix_groups = { 1, 1, {0, 0, 0, 0, 0, 22}, + {cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; + + /* +@@ -48,17 +48,17 @@ static const struct cifs_sid sid_unix_groups = { 1, 1, {0, 0, 0, 0, 0, 22}, + /* S-1-5-88 MS NFS and Apple style UID/GID/mode */ + + /* S-1-5-88-1 Unix uid */ +-static const struct cifs_sid sid_unix_NFS_users = { 1, 2, {0, 0, 0, 0, 0, 5}, ++static const struct smb_sid sid_unix_NFS_users = { 1, 2, {0, 0, 0, 0, 0, 5}, + {cpu_to_le32(88), + cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; + + /* S-1-5-88-2 Unix gid */ +-static const struct cifs_sid sid_unix_NFS_groups = { 1, 2, {0, 0, 0, 0, 0, 5}, ++static const struct smb_sid sid_unix_NFS_groups = { 1, 2, {0, 0, 0, 0, 0, 5}, + {cpu_to_le32(88), + cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; + + /* S-1-5-88-3 Unix mode */ +-static const struct cifs_sid sid_unix_NFS_mode = { 1, 2, {0, 0, 0, 0, 0, 5}, ++static const struct smb_sid sid_unix_NFS_mode = { 1, 2, {0, 0, 0, 0, 0, 5}, + {cpu_to_le32(88), + cpu_to_le32(3), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; + +@@ -106,7 +106,7 @@ static struct key_type cifs_idmap_key_type = { + }; + + static char * +-sid_to_key_str(struct cifs_sid *sidptr, unsigned int type) ++sid_to_key_str(struct smb_sid *sidptr, unsigned int type) + { + int i, len; + unsigned int saval; +@@ -158,7 +158,7 @@ sid_to_key_str(struct cifs_sid *sidptr, unsigned int type) + * the same returns zero, if they do not match returns non-zero. + */ + static int +-compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid) ++compare_sids(const struct smb_sid *ctsid, const struct smb_sid *cwsid) + { + int i; + int num_subauth, num_sat, num_saw; +@@ -204,11 +204,11 @@ compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid) + } + + static bool +-is_well_known_sid(const struct cifs_sid *psid, uint32_t *puid, bool is_group) ++is_well_known_sid(const struct smb_sid *psid, uint32_t *puid, bool is_group) + { + int i; + int num_subauth; +- const struct cifs_sid *pwell_known_sid; ++ const struct smb_sid *pwell_known_sid; + + if (!psid || (puid == NULL)) + return false; +@@ -260,7 +260,7 @@ is_well_known_sid(const struct cifs_sid *psid, uint32_t *puid, bool is_group) + } + + static __u16 +-cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src) ++cifs_copy_sid(struct smb_sid *dst, const struct smb_sid *src) + { + int i; + __u16 size = 1 + 1 + 6; +@@ -277,11 +277,11 @@ cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src) + } + + static int +-id_to_sid(unsigned int cid, uint sidtype, struct cifs_sid *ssid) ++id_to_sid(unsigned int cid, uint sidtype, struct smb_sid *ssid) + { + int rc; + struct key *sidkey; +- struct cifs_sid *ksid; ++ struct smb_sid *ksid; + unsigned int ksid_size; + char desc[3 + 10 + 1]; /* 3 byte prefix + 10 bytes for value + NULL */ + const struct cred *saved_cred; +@@ -312,8 +312,8 @@ id_to_sid(unsigned int cid, uint sidtype, struct cifs_sid *ssid) + * it could be. + */ + ksid = sidkey->datalen <= sizeof(sidkey->payload) ? +- (struct cifs_sid *)&sidkey->payload : +- (struct cifs_sid *)sidkey->payload.data[0]; ++ (struct smb_sid *)&sidkey->payload : ++ (struct smb_sid *)sidkey->payload.data[0]; + + ksid_size = CIFS_SID_BASE_SIZE + (ksid->num_subauth * sizeof(__le32)); + if (ksid_size > sidkey->datalen) { +@@ -336,7 +336,7 @@ id_to_sid(unsigned int cid, uint sidtype, struct cifs_sid *ssid) + } + + int +-sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid, ++sid_to_id(struct cifs_sb_info *cifs_sb, struct smb_sid *psid, + struct cifs_fattr *fattr, uint sidtype) + { + int rc = 0; +@@ -515,43 +515,43 @@ exit_cifs_idmap(void) + } + + /* copy ntsd, owner sid, and group sid from a security descriptor to another */ +-static __u32 copy_sec_desc(const struct cifs_ntsd *pntsd, +- struct cifs_ntsd *pnntsd, ++static __u32 copy_sec_desc(const struct smb_ntsd *pntsd, ++ struct smb_ntsd *pnntsd, + __u32 sidsoffset, +- struct cifs_sid *pownersid, +- struct cifs_sid *pgrpsid) ++ struct smb_sid *pownersid, ++ struct smb_sid *pgrpsid) + { +- struct cifs_sid *owner_sid_ptr, *group_sid_ptr; +- struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr; ++ struct smb_sid *owner_sid_ptr, *group_sid_ptr; ++ struct smb_sid *nowner_sid_ptr, *ngroup_sid_ptr; + + /* copy security descriptor control portion */ + pnntsd->revision = pntsd->revision; + pnntsd->type = pntsd->type; +- pnntsd->dacloffset = cpu_to_le32(sizeof(struct cifs_ntsd)); ++ pnntsd->dacloffset = cpu_to_le32(sizeof(struct smb_ntsd)); + pnntsd->sacloffset = 0; + pnntsd->osidoffset = cpu_to_le32(sidsoffset); +- pnntsd->gsidoffset = cpu_to_le32(sidsoffset + sizeof(struct cifs_sid)); ++ pnntsd->gsidoffset = cpu_to_le32(sidsoffset + sizeof(struct smb_sid)); + + /* copy owner sid */ + if (pownersid) + owner_sid_ptr = pownersid; + else +- owner_sid_ptr = (struct cifs_sid *)((char *)pntsd + ++ owner_sid_ptr = (struct smb_sid *)((char *)pntsd + + le32_to_cpu(pntsd->osidoffset)); +- nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset); ++ nowner_sid_ptr = (struct smb_sid *)((char *)pnntsd + sidsoffset); + cifs_copy_sid(nowner_sid_ptr, owner_sid_ptr); + + /* copy group sid */ + if (pgrpsid) + group_sid_ptr = pgrpsid; + else +- group_sid_ptr = (struct cifs_sid *)((char *)pntsd + ++ group_sid_ptr = (struct smb_sid *)((char *)pntsd + + le32_to_cpu(pntsd->gsidoffset)); +- ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset + +- sizeof(struct cifs_sid)); ++ ngroup_sid_ptr = (struct smb_sid *)((char *)pnntsd + sidsoffset + ++ sizeof(struct smb_sid)); + cifs_copy_sid(ngroup_sid_ptr, group_sid_ptr); + +- return sidsoffset + (2 * sizeof(struct cifs_sid)); ++ return sidsoffset + (2 * sizeof(struct smb_sid)); + } + + +@@ -666,7 +666,7 @@ static void mode_to_access_flags(umode_t mode, umode_t bits_to_use, + return; + } + +-static __u16 cifs_copy_ace(struct cifs_ace *dst, struct cifs_ace *src, struct cifs_sid *psid) ++static __u16 cifs_copy_ace(struct smb_ace *dst, struct smb_ace *src, struct smb_sid *psid) + { + __u16 size = 1 + 1 + 2 + 4; + +@@ -685,8 +685,8 @@ static __u16 cifs_copy_ace(struct cifs_ace *dst, struct cifs_ace *src, struct ci + return size; + } + +-static __u16 fill_ace_for_sid(struct cifs_ace *pntace, +- const struct cifs_sid *psid, __u64 nmode, ++static __u16 fill_ace_for_sid(struct smb_ace *pntace, ++ const struct smb_sid *psid, __u64 nmode, + umode_t bits, __u8 access_type, + bool allow_delete_child) + { +@@ -723,7 +723,7 @@ static __u16 fill_ace_for_sid(struct cifs_ace *pntace, + + + #ifdef CONFIG_CIFS_DEBUG2 +-static void dump_ace(struct cifs_ace *pace, char *end_of_acl) ++static void dump_ace(struct smb_ace *pace, char *end_of_acl) + { + int num_subauth; + +@@ -758,15 +758,15 @@ static void dump_ace(struct cifs_ace *pace, char *end_of_acl) + } + #endif + +-static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, +- struct cifs_sid *pownersid, struct cifs_sid *pgrpsid, ++static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl, ++ struct smb_sid *pownersid, struct smb_sid *pgrpsid, + struct cifs_fattr *fattr, bool mode_from_special_sid) + { + int i; + int num_aces = 0; + int acl_size; + char *acl_base; +- struct cifs_ace **ppace; ++ struct smb_ace **ppace; + + /* BB need to add parm so we can store the SID BB */ + +@@ -793,21 +793,21 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, + fattr->cf_mode &= ~(0777); + + acl_base = (char *)pdacl; +- acl_size = sizeof(struct cifs_acl); ++ acl_size = sizeof(struct smb_acl); + + num_aces = le32_to_cpu(pdacl->num_aces); + if (num_aces > 0) { + umode_t denied_mode = 0; + +- if (num_aces > ULONG_MAX / sizeof(struct cifs_ace *)) ++ if (num_aces > ULONG_MAX / sizeof(struct smb_ace *)) + return; +- ppace = kmalloc_array(num_aces, sizeof(struct cifs_ace *), ++ ppace = kmalloc_array(num_aces, sizeof(struct smb_ace *), + GFP_KERNEL); + if (!ppace) + return; + + for (i = 0; i < num_aces; ++i) { +- ppace[i] = (struct cifs_ace *) (acl_base + acl_size); ++ ppace[i] = (struct smb_ace *) (acl_base + acl_size); + #ifdef CONFIG_CIFS_DEBUG2 + dump_ace(ppace[i], end_of_acl); + #endif +@@ -849,7 +849,7 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, + + /* memcpy((void *)(&(cifscred->aces[i])), + (void *)ppace[i], +- sizeof(struct cifs_ace)); */ ++ sizeof(struct smb_ace)); */ + + acl_base = (char *)ppace[i]; + acl_size = le16_to_cpu(ppace[i]->size); +@@ -861,7 +861,7 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, + return; + } + +-unsigned int setup_authusers_ACE(struct cifs_ace *pntace) ++unsigned int setup_authusers_ACE(struct smb_ace *pntace) + { + int i; + unsigned int ace_size = 20; +@@ -885,12 +885,17 @@ unsigned int setup_authusers_ACE(struct cifs_ace *pntace) + * Fill in the special SID based on the mode. See + * https://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx + */ +-unsigned int setup_special_mode_ACE(struct cifs_ace *pntace, __u64 nmode) ++unsigned int setup_special_mode_ACE(struct smb_ace *pntace, ++ bool posix, ++ __u64 nmode) + { + int i; + unsigned int ace_size = 28; + +- pntace->type = ACCESS_DENIED_ACE_TYPE; ++ if (posix) ++ pntace->type = ACCESS_ALLOWED_ACE_TYPE; ++ else ++ pntace->type = ACCESS_DENIED_ACE_TYPE; + pntace->flags = 0x0; + pntace->access_req = 0; + pntace->sid.num_subauth = 3; +@@ -907,7 +912,7 @@ unsigned int setup_special_mode_ACE(struct cifs_ace *pntace, __u64 nmode) + return ace_size; + } + +-unsigned int setup_special_user_owner_ACE(struct cifs_ace *pntace) ++unsigned int setup_special_user_owner_ACE(struct smb_ace *pntace) + { + int i; + unsigned int ace_size = 28; +@@ -930,10 +935,11 @@ unsigned int setup_special_user_owner_ACE(struct cifs_ace *pntace) + } + + static void populate_new_aces(char *nacl_base, +- struct cifs_sid *pownersid, +- struct cifs_sid *pgrpsid, ++ struct smb_sid *pownersid, ++ struct smb_sid *pgrpsid, + __u64 *pnmode, u32 *pnum_aces, u16 *pnsize, +- bool modefromsid) ++ bool modefromsid, ++ bool posix) + { + __u64 nmode; + u32 num_aces = 0; +@@ -944,19 +950,21 @@ static void populate_new_aces(char *nacl_base, + __u64 deny_user_mode = 0; + __u64 deny_group_mode = 0; + bool sticky_set = false; +- struct cifs_ace *pnntace = NULL; ++ struct smb_ace *pnntace = NULL; + + nmode = *pnmode; + num_aces = *pnum_aces; + nsize = *pnsize; + +- if (modefromsid) { +- pnntace = (struct cifs_ace *) (nacl_base + nsize); +- nsize += setup_special_mode_ACE(pnntace, nmode); +- num_aces++; +- pnntace = (struct cifs_ace *) (nacl_base + nsize); +- nsize += setup_authusers_ACE(pnntace); ++ if (modefromsid || posix) { ++ pnntace = (struct smb_ace *) (nacl_base + nsize); ++ nsize += setup_special_mode_ACE(pnntace, posix, nmode); + num_aces++; ++ if (modefromsid) { ++ pnntace = (struct smb_ace *) (nacl_base + nsize); ++ nsize += setup_authusers_ACE(pnntace); ++ num_aces++; ++ } + goto set_size; + } + +@@ -967,7 +975,7 @@ static void populate_new_aces(char *nacl_base, + * updated in the inode. + */ + +- if (!memcmp(pownersid, pgrpsid, sizeof(struct cifs_sid))) { ++ if (!memcmp(pownersid, pgrpsid, sizeof(struct smb_sid))) { + /* + * Case when owner and group SIDs are the same. + * Set the more restrictive of the two modes. +@@ -992,7 +1000,7 @@ static void populate_new_aces(char *nacl_base, + sticky_set = true; + + if (deny_user_mode) { +- pnntace = (struct cifs_ace *) (nacl_base + nsize); ++ pnntace = (struct smb_ace *) (nacl_base + nsize); + nsize += fill_ace_for_sid(pnntace, pownersid, deny_user_mode, + 0700, ACCESS_DENIED, false); + num_aces++; +@@ -1000,31 +1008,31 @@ static void populate_new_aces(char *nacl_base, + + /* Group DENY ACE does not conflict with owner ALLOW ACE. Keep in preferred order*/ + if (deny_group_mode && !(deny_group_mode & (user_mode >> 3))) { +- pnntace = (struct cifs_ace *) (nacl_base + nsize); ++ pnntace = (struct smb_ace *) (nacl_base + nsize); + nsize += fill_ace_for_sid(pnntace, pgrpsid, deny_group_mode, + 0070, ACCESS_DENIED, false); + num_aces++; + } + +- pnntace = (struct cifs_ace *) (nacl_base + nsize); ++ pnntace = (struct smb_ace *) (nacl_base + nsize); + nsize += fill_ace_for_sid(pnntace, pownersid, user_mode, + 0700, ACCESS_ALLOWED, true); + num_aces++; + + /* Group DENY ACE conflicts with owner ALLOW ACE. So keep it after. */ + if (deny_group_mode && (deny_group_mode & (user_mode >> 3))) { +- pnntace = (struct cifs_ace *) (nacl_base + nsize); ++ pnntace = (struct smb_ace *) (nacl_base + nsize); + nsize += fill_ace_for_sid(pnntace, pgrpsid, deny_group_mode, + 0070, ACCESS_DENIED, false); + num_aces++; + } + +- pnntace = (struct cifs_ace *) (nacl_base + nsize); ++ pnntace = (struct smb_ace *) (nacl_base + nsize); + nsize += fill_ace_for_sid(pnntace, pgrpsid, group_mode, + 0070, ACCESS_ALLOWED, !sticky_set); + num_aces++; + +- pnntace = (struct cifs_ace *) (nacl_base + nsize); ++ pnntace = (struct smb_ace *) (nacl_base + nsize); + nsize += fill_ace_for_sid(pnntace, &sid_everyone, other_mode, + 0007, ACCESS_ALLOWED, !sticky_set); + num_aces++; +@@ -1034,31 +1042,31 @@ static void populate_new_aces(char *nacl_base, + *pnsize = nsize; + } + +-static __u16 replace_sids_and_copy_aces(struct cifs_acl *pdacl, struct cifs_acl *pndacl, +- struct cifs_sid *pownersid, struct cifs_sid *pgrpsid, +- struct cifs_sid *pnownersid, struct cifs_sid *pngrpsid) ++static __u16 replace_sids_and_copy_aces(struct smb_acl *pdacl, struct smb_acl *pndacl, ++ struct smb_sid *pownersid, struct smb_sid *pgrpsid, ++ struct smb_sid *pnownersid, struct smb_sid *pngrpsid) + { + int i; + u16 size = 0; +- struct cifs_ace *pntace = NULL; ++ struct smb_ace *pntace = NULL; + char *acl_base = NULL; + u32 src_num_aces = 0; + u16 nsize = 0; +- struct cifs_ace *pnntace = NULL; ++ struct smb_ace *pnntace = NULL; + char *nacl_base = NULL; + u16 ace_size = 0; + + acl_base = (char *)pdacl; +- size = sizeof(struct cifs_acl); ++ size = sizeof(struct smb_acl); + src_num_aces = le32_to_cpu(pdacl->num_aces); + + nacl_base = (char *)pndacl; +- nsize = sizeof(struct cifs_acl); ++ nsize = sizeof(struct smb_acl); + + /* Go through all the ACEs */ + for (i = 0; i < src_num_aces; ++i) { +- pntace = (struct cifs_ace *) (acl_base + size); +- pnntace = (struct cifs_ace *) (nacl_base + nsize); ++ pntace = (struct smb_ace *) (acl_base + size); ++ pnntace = (struct smb_ace *) (nacl_base + nsize); + + if (pnownersid && compare_sids(&pntace->sid, pownersid) == 0) + ace_size = cifs_copy_ace(pnntace, pntace, pnownersid); +@@ -1074,48 +1082,48 @@ static __u16 replace_sids_and_copy_aces(struct cifs_acl *pdacl, struct cifs_acl + return nsize; + } + +-static int set_chmod_dacl(struct cifs_acl *pdacl, struct cifs_acl *pndacl, +- struct cifs_sid *pownersid, struct cifs_sid *pgrpsid, +- __u64 *pnmode, bool mode_from_sid) ++static int set_chmod_dacl(struct smb_acl *pdacl, struct smb_acl *pndacl, ++ struct smb_sid *pownersid, struct smb_sid *pgrpsid, ++ __u64 *pnmode, bool mode_from_sid, bool posix) + { + int i; + u16 size = 0; +- struct cifs_ace *pntace = NULL; ++ struct smb_ace *pntace = NULL; + char *acl_base = NULL; + u32 src_num_aces = 0; + u16 nsize = 0; +- struct cifs_ace *pnntace = NULL; ++ struct smb_ace *pnntace = NULL; + char *nacl_base = NULL; + u32 num_aces = 0; + bool new_aces_set = false; + + /* Assuming that pndacl and pnmode are never NULL */ + nacl_base = (char *)pndacl; +- nsize = sizeof(struct cifs_acl); ++ nsize = sizeof(struct smb_acl); + + /* If pdacl is NULL, we don't have a src. Simply populate new ACL. */ +- if (!pdacl) { ++ if (!pdacl || posix) { + populate_new_aces(nacl_base, + pownersid, pgrpsid, + pnmode, &num_aces, &nsize, +- mode_from_sid); ++ mode_from_sid, posix); + goto finalize_dacl; + } + + acl_base = (char *)pdacl; +- size = sizeof(struct cifs_acl); ++ size = sizeof(struct smb_acl); + src_num_aces = le32_to_cpu(pdacl->num_aces); + + /* Retain old ACEs which we can retain */ + for (i = 0; i < src_num_aces; ++i) { +- pntace = (struct cifs_ace *) (acl_base + size); ++ pntace = (struct smb_ace *) (acl_base + size); + + if (!new_aces_set && (pntace->flags & INHERITED_ACE)) { + /* Place the new ACEs in between existing explicit and inherited */ + populate_new_aces(nacl_base, + pownersid, pgrpsid, + pnmode, &num_aces, &nsize, +- mode_from_sid); ++ mode_from_sid, posix); + + new_aces_set = true; + } +@@ -1130,7 +1138,7 @@ static int set_chmod_dacl(struct cifs_acl *pdacl, struct cifs_acl *pndacl, + } + + /* update the pointer to the next ACE to populate*/ +- pnntace = (struct cifs_ace *) (nacl_base + nsize); ++ pnntace = (struct smb_ace *) (nacl_base + nsize); + + nsize += cifs_copy_ace(pnntace, pntace, NULL); + num_aces++; +@@ -1144,7 +1152,7 @@ static int set_chmod_dacl(struct cifs_acl *pdacl, struct cifs_acl *pndacl, + populate_new_aces(nacl_base, + pownersid, pgrpsid, + pnmode, &num_aces, &nsize, +- mode_from_sid); ++ mode_from_sid, posix); + + new_aces_set = true; + } +@@ -1156,7 +1164,7 @@ static int set_chmod_dacl(struct cifs_acl *pdacl, struct cifs_acl *pndacl, + return 0; + } + +-static int parse_sid(struct cifs_sid *psid, char *end_of_acl) ++static int parse_sid(struct smb_sid *psid, char *end_of_acl) + { + /* BB need to add parm so we can store the SID BB */ + +@@ -1191,24 +1199,24 @@ static int parse_sid(struct cifs_sid *psid, char *end_of_acl) + + /* Convert CIFS ACL to POSIX form */ + static int parse_sec_desc(struct cifs_sb_info *cifs_sb, +- struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr, ++ struct smb_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr, + bool get_mode_from_special_sid) + { + int rc = 0; +- struct cifs_sid *owner_sid_ptr, *group_sid_ptr; +- struct cifs_acl *dacl_ptr; /* no need for SACL ptr */ ++ struct smb_sid *owner_sid_ptr, *group_sid_ptr; ++ struct smb_acl *dacl_ptr; /* no need for SACL ptr */ + char *end_of_acl = ((char *)pntsd) + acl_len; + __u32 dacloffset; + + if (pntsd == NULL) + return -EIO; + +- owner_sid_ptr = (struct cifs_sid *)((char *)pntsd + ++ owner_sid_ptr = (struct smb_sid *)((char *)pntsd + + le32_to_cpu(pntsd->osidoffset)); +- group_sid_ptr = (struct cifs_sid *)((char *)pntsd + ++ group_sid_ptr = (struct smb_sid *)((char *)pntsd + + le32_to_cpu(pntsd->gsidoffset)); + dacloffset = le32_to_cpu(pntsd->dacloffset); +- dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset); ++ dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset); + cifs_dbg(NOISY, "revision %d type 0x%x ooffset 0x%x goffset 0x%x sacloffset 0x%x dacloffset 0x%x\n", + pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset), + le32_to_cpu(pntsd->gsidoffset), +@@ -1249,38 +1257,38 @@ static int parse_sec_desc(struct cifs_sb_info *cifs_sb, + } + + /* Convert permission bits from mode to equivalent CIFS ACL */ +-static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, ++static int build_sec_desc(struct smb_ntsd *pntsd, struct smb_ntsd *pnntsd, + __u32 secdesclen, __u32 *pnsecdesclen, __u64 *pnmode, kuid_t uid, kgid_t gid, +- bool mode_from_sid, bool id_from_sid, int *aclflag) ++ bool mode_from_sid, bool id_from_sid, bool posix, int *aclflag) + { + int rc = 0; + __u32 dacloffset; + __u32 ndacloffset; + __u32 sidsoffset; +- struct cifs_sid *owner_sid_ptr, *group_sid_ptr; +- struct cifs_sid *nowner_sid_ptr = NULL, *ngroup_sid_ptr = NULL; +- struct cifs_acl *dacl_ptr = NULL; /* no need for SACL ptr */ +- struct cifs_acl *ndacl_ptr = NULL; /* no need for SACL ptr */ ++ struct smb_sid *owner_sid_ptr, *group_sid_ptr; ++ struct smb_sid *nowner_sid_ptr = NULL, *ngroup_sid_ptr = NULL; ++ struct smb_acl *dacl_ptr = NULL; /* no need for SACL ptr */ ++ struct smb_acl *ndacl_ptr = NULL; /* no need for SACL ptr */ + char *end_of_acl = ((char *)pntsd) + secdesclen; + u16 size = 0; + + dacloffset = le32_to_cpu(pntsd->dacloffset); + if (dacloffset) { +- dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset); ++ dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset); + if (end_of_acl < (char *)dacl_ptr + le16_to_cpu(dacl_ptr->size)) { + cifs_dbg(VFS, "Server returned illegal ACL size\n"); + return -EINVAL; + } + } + +- owner_sid_ptr = (struct cifs_sid *)((char *)pntsd + ++ owner_sid_ptr = (struct smb_sid *)((char *)pntsd + + le32_to_cpu(pntsd->osidoffset)); +- group_sid_ptr = (struct cifs_sid *)((char *)pntsd + ++ group_sid_ptr = (struct smb_sid *)((char *)pntsd + + le32_to_cpu(pntsd->gsidoffset)); + + if (pnmode && *pnmode != NO_CHANGE_64) { /* chmod */ +- ndacloffset = sizeof(struct cifs_ntsd); +- ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset); ++ ndacloffset = sizeof(struct smb_ntsd); ++ ndacl_ptr = (struct smb_acl *)((char *)pnntsd + ndacloffset); + ndacl_ptr->revision = + dacloffset ? dacl_ptr->revision : cpu_to_le16(ACL_REVISION); + +@@ -1288,7 +1296,7 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, + ndacl_ptr->num_aces = cpu_to_le32(0); + + rc = set_chmod_dacl(dacl_ptr, ndacl_ptr, owner_sid_ptr, group_sid_ptr, +- pnmode, mode_from_sid); ++ pnmode, mode_from_sid, posix); + + sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size); + /* copy the non-dacl portion of secdesc */ +@@ -1297,15 +1305,15 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, + + *aclflag |= CIFS_ACL_DACL; + } else { +- ndacloffset = sizeof(struct cifs_ntsd); +- ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset); ++ ndacloffset = sizeof(struct smb_ntsd); ++ ndacl_ptr = (struct smb_acl *)((char *)pnntsd + ndacloffset); + ndacl_ptr->revision = + dacloffset ? dacl_ptr->revision : cpu_to_le16(ACL_REVISION); + ndacl_ptr->num_aces = dacl_ptr ? dacl_ptr->num_aces : 0; + + if (uid_valid(uid)) { /* chown */ + uid_t id; +- nowner_sid_ptr = kzalloc(sizeof(struct cifs_sid), ++ nowner_sid_ptr = kzalloc(sizeof(struct smb_sid), + GFP_KERNEL); + if (!nowner_sid_ptr) { + rc = -ENOMEM; +@@ -1334,7 +1342,7 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, + } + if (gid_valid(gid)) { /* chgrp */ + gid_t id; +- ngroup_sid_ptr = kzalloc(sizeof(struct cifs_sid), ++ ngroup_sid_ptr = kzalloc(sizeof(struct smb_sid), + GFP_KERNEL); + if (!ngroup_sid_ptr) { + rc = -ENOMEM; +@@ -1385,11 +1393,11 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, + } + + #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY +-struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, ++struct smb_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, + const struct cifs_fid *cifsfid, u32 *pacllen, + u32 __maybe_unused unused) + { +- struct cifs_ntsd *pntsd = NULL; ++ struct smb_ntsd *pntsd = NULL; + unsigned int xid; + int rc; + struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); +@@ -1410,10 +1418,10 @@ struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, + return pntsd; + } + +-static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, ++static struct smb_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, + const char *path, u32 *pacllen) + { +- struct cifs_ntsd *pntsd = NULL; ++ struct smb_ntsd *pntsd = NULL; + int oplock = 0; + unsigned int xid; + int rc; +@@ -1454,11 +1462,11 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, + } + + /* Retrieve an ACL from the server */ +-struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb, ++struct smb_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb, + struct inode *inode, const char *path, + u32 *pacllen, u32 info) + { +- struct cifs_ntsd *pntsd = NULL; ++ struct smb_ntsd *pntsd = NULL; + struct cifsFileInfo *open_file = NULL; + + if (inode) +@@ -1472,7 +1480,7 @@ struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb, + } + + /* Set an ACL on the server */ +-int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, ++int set_cifs_acl(struct smb_ntsd *pnntsd, __u32 acllen, + struct inode *inode, const char *path, int aclflag) + { + int oplock = 0; +@@ -1528,7 +1536,7 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, + struct inode *inode, bool mode_from_special_sid, + const char *path, const struct cifs_fid *pfid) + { +- struct cifs_ntsd *pntsd = NULL; ++ struct smb_ntsd *pntsd = NULL; + u32 acllen = 0; + int rc = 0; + struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); +@@ -1580,13 +1588,14 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 *pnmode, + __u32 secdesclen = 0; + __u32 nsecdesclen = 0; + __u32 dacloffset = 0; +- struct cifs_acl *dacl_ptr = NULL; +- struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */ +- struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */ ++ struct smb_acl *dacl_ptr = NULL; ++ struct smb_ntsd *pntsd = NULL; /* acl obtained from server */ ++ struct smb_ntsd *pnntsd = NULL; /* modified acl to be sent to server */ + struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); + struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); + struct smb_version_operations *ops; + bool mode_from_sid, id_from_sid; ++ bool posix = tlink_tcon(tlink)->posix_extensions; + const u32 info = 0; + + if (IS_ERR(tlink)) +@@ -1622,21 +1631,22 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 *pnmode, + id_from_sid = false; + + /* Potentially, five new ACEs can be added to the ACL for U,G,O mapping */ +- nsecdesclen = secdesclen; + if (pnmode && *pnmode != NO_CHANGE_64) { /* chmod */ +- if (mode_from_sid) +- nsecdesclen += 2 * sizeof(struct cifs_ace); ++ if (posix) ++ nsecdesclen = 1 * sizeof(struct smb_ace); ++ else if (mode_from_sid) ++ nsecdesclen = secdesclen + (2 * sizeof(struct smb_ace)); + else /* cifsacl */ +- nsecdesclen += 5 * sizeof(struct cifs_ace); ++ nsecdesclen = secdesclen + (5 * sizeof(struct smb_ace)); + } else { /* chown */ + /* When ownership changes, changes new owner sid length could be different */ +- nsecdesclen = sizeof(struct cifs_ntsd) + (sizeof(struct cifs_sid) * 2); ++ nsecdesclen = sizeof(struct smb_ntsd) + (sizeof(struct smb_sid) * 2); + dacloffset = le32_to_cpu(pntsd->dacloffset); + if (dacloffset) { +- dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset); ++ dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset); + if (mode_from_sid) + nsecdesclen += +- le32_to_cpu(dacl_ptr->num_aces) * sizeof(struct cifs_ace); ++ le32_to_cpu(dacl_ptr->num_aces) * sizeof(struct smb_ace); + else /* cifsacl */ + nsecdesclen += le16_to_cpu(dacl_ptr->size); + } +@@ -1657,7 +1667,7 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 *pnmode, + } + + rc = build_sec_desc(pntsd, pnntsd, secdesclen, &nsecdesclen, pnmode, uid, gid, +- mode_from_sid, id_from_sid, &aclflag); ++ mode_from_sid, id_from_sid, posix, &aclflag); + + cifs_dbg(NOISY, "build_sec_desc rc: %d\n", rc); + +diff --git a/fs/smb/client/cifsacl.h b/fs/smb/client/cifsacl.h +index ccbfc754bd3c7f..cbaed8038e3654 100644 +--- a/fs/smb/client/cifsacl.h ++++ b/fs/smb/client/cifsacl.h +@@ -33,9 +33,9 @@ + * Security Descriptor length containing DACL with 3 ACEs (one each for + * owner, group and world). + */ +-#define DEFAULT_SEC_DESC_LEN (sizeof(struct cifs_ntsd) + \ +- sizeof(struct cifs_acl) + \ +- (sizeof(struct cifs_ace) * 4)) ++#define DEFAULT_SEC_DESC_LEN (sizeof(struct smb_ntsd) + \ ++ sizeof(struct smb_acl) + \ ++ (sizeof(struct smb_ace) * 4)) + + /* + * Maximum size of a string representation of a SID: +@@ -55,7 +55,7 @@ + #define SID_STRING_BASE_SIZE (2 + 3 + 15 + 1) + #define SID_STRING_SUBAUTH_SIZE (11) /* size of a single subauth string */ + +-struct cifs_ntsd { ++struct smb_ntsd { + __le16 revision; /* revision level */ + __le16 type; + __le32 osidoffset; +@@ -64,17 +64,17 @@ struct cifs_ntsd { + __le32 dacloffset; + } __attribute__((packed)); + +-struct cifs_sid { ++struct smb_sid { + __u8 revision; /* revision level */ + __u8 num_subauth; + __u8 authority[NUM_AUTHS]; + __le32 sub_auth[SID_MAX_SUB_AUTHORITIES]; /* sub_auth[num_subauth] */ + } __attribute__((packed)); + +-/* size of a struct cifs_sid, sans sub_auth array */ ++/* size of a struct smb_sid, sans sub_auth array */ + #define CIFS_SID_BASE_SIZE (1 + 1 + NUM_AUTHS) + +-struct cifs_acl { ++struct smb_acl { + __le16 revision; /* revision level */ + __le16 size; + __le32 num_aces; +@@ -111,12 +111,12 @@ struct cifs_acl { + #define SUCCESSFUL_ACCESS_ACE_FLAG 0x40 + #define FAILED_ACCESS_ACE_FLAG 0x80 + +-struct cifs_ace { ++struct smb_ace { + __u8 type; /* see above and MS-DTYP 2.4.4.1 */ + __u8 flags; + __le16 size; + __le32 access_req; +- struct cifs_sid sid; /* ie UUID of user or group who gets these perms */ ++ struct smb_sid sid; /* ie UUID of user or group who gets these perms */ + } __attribute__((packed)); + + /* +@@ -194,6 +194,6 @@ struct owner_group_sids { + * Minimum security descriptor can be one without any SACL and DACL and can + * consist of revision, type, and two sids of minimum size for owner and group + */ +-#define MIN_SEC_DESC_LEN (sizeof(struct cifs_ntsd) + (2 * MIN_SID_LEN)) ++#define MIN_SEC_DESC_LEN (sizeof(struct smb_ntsd) + (2 * MIN_SID_LEN)) + + #endif /* _CIFSACL_H */ +diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c +index 6ed0f2548232f9..bbb0ef18d7b8c8 100644 +--- a/fs/smb/client/cifsfs.c ++++ b/fs/smb/client/cifsfs.c +@@ -2015,6 +2015,7 @@ exit_cifs(void) + destroy_workqueue(decrypt_wq); + destroy_workqueue(fileinfo_put_wq); + destroy_workqueue(serverclose_wq); ++ destroy_workqueue(cfid_put_wq); + destroy_workqueue(cifsiod_wq); + cifs_proc_clean(); + } +diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h +index 6b57b167a49d80..43b42eca6780cf 100644 +--- a/fs/smb/client/cifsglob.h ++++ b/fs/smb/client/cifsglob.h +@@ -202,10 +202,10 @@ struct cifs_cred { + int gid; + int mode; + int cecount; +- struct cifs_sid osid; +- struct cifs_sid gsid; ++ struct smb_sid osid; ++ struct smb_sid gsid; + struct cifs_ntace *ntaces; +- struct cifs_ace *aces; ++ struct smb_ace *aces; + }; + + struct cifs_open_info_data { +@@ -231,8 +231,8 @@ struct cifs_open_info_data { + unsigned int eas_len; + } wsl; + char *symlink_target; +- struct cifs_sid posix_owner; +- struct cifs_sid posix_group; ++ struct smb_sid posix_owner; ++ struct smb_sid posix_group; + union { + struct smb2_file_all_info fi; + struct smb311_posix_qinfo posix_fi; +@@ -539,12 +539,12 @@ struct smb_version_operations { + int (*set_EA)(const unsigned int, struct cifs_tcon *, const char *, + const char *, const void *, const __u16, + const struct nls_table *, struct cifs_sb_info *); +- struct cifs_ntsd * (*get_acl)(struct cifs_sb_info *, struct inode *, +- const char *, u32 *, u32); +- struct cifs_ntsd * (*get_acl_by_fid)(struct cifs_sb_info *, +- const struct cifs_fid *, u32 *, u32); +- int (*set_acl)(struct cifs_ntsd *, __u32, struct inode *, const char *, +- int); ++ struct smb_ntsd * (*get_acl)(struct cifs_sb_info *cifssb, struct inode *ino, ++ const char *patch, u32 *plen, u32 info); ++ struct smb_ntsd * (*get_acl_by_fid)(struct cifs_sb_info *cifssmb, ++ const struct cifs_fid *pfid, u32 *plen, u32 info); ++ int (*set_acl)(struct smb_ntsd *pntsd, __u32 len, struct inode *ino, const char *path, ++ int flag); + /* writepages retry size */ + unsigned int (*wp_retry_size)(struct inode *); + /* get mtu credits */ +diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h +index 83692bf60007a0..a151ffffc6f38e 100644 +--- a/fs/smb/client/cifsproto.h ++++ b/fs/smb/client/cifsproto.h +@@ -223,7 +223,7 @@ extern int cifs_set_file_info(struct inode *inode, struct iattr *attrs, + extern int cifs_rename_pending_delete(const char *full_path, + struct dentry *dentry, + const unsigned int xid); +-extern int sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid, ++extern int sid_to_id(struct cifs_sb_info *cifs_sb, struct smb_sid *psid, + struct cifs_fattr *fattr, uint sidtype); + extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, + struct cifs_fattr *fattr, struct inode *inode, +@@ -231,19 +231,21 @@ extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, + const char *path, const struct cifs_fid *pfid); + extern int id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 *pnmode, + kuid_t uid, kgid_t gid); +-extern struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *, struct inode *, +- const char *, u32 *, u32); +-extern struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *, +- const struct cifs_fid *, u32 *, u32); ++extern struct smb_ntsd *get_cifs_acl(struct cifs_sb_info *cifssmb, struct inode *ino, ++ const char *path, u32 *plen, u32 info); ++extern struct smb_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifssb, ++ const struct cifs_fid *pfid, u32 *plen, u32 info); + extern struct posix_acl *cifs_get_acl(struct mnt_idmap *idmap, + struct dentry *dentry, int type); + extern int cifs_set_acl(struct mnt_idmap *idmap, + struct dentry *dentry, struct posix_acl *acl, int type); +-extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *, +- const char *, int); +-extern unsigned int setup_authusers_ACE(struct cifs_ace *pace); +-extern unsigned int setup_special_mode_ACE(struct cifs_ace *pace, __u64 nmode); +-extern unsigned int setup_special_user_owner_ACE(struct cifs_ace *pace); ++extern int set_cifs_acl(struct smb_ntsd *pntsd, __u32 len, struct inode *ino, ++ const char *path, int flag); ++extern unsigned int setup_authusers_ACE(struct smb_ace *pace); ++extern unsigned int setup_special_mode_ACE(struct smb_ace *pace, ++ bool posix, ++ __u64 nmode); ++extern unsigned int setup_special_user_owner_ACE(struct smb_ace *pace); + + extern void dequeue_mid(struct mid_q_entry *mid, bool malformed); + extern int cifs_read_from_socket(struct TCP_Server_Info *server, char *buf, +@@ -568,9 +570,9 @@ extern int CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon, + const struct nls_table *nls_codepage, + struct cifs_sb_info *cifs_sb); + extern int CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, +- __u16 fid, struct cifs_ntsd **acl_inf, __u32 *buflen); ++ __u16 fid, struct smb_ntsd **acl_inf, __u32 *buflen); + extern int CIFSSMBSetCIFSACL(const unsigned int, struct cifs_tcon *, __u16, +- struct cifs_ntsd *, __u32, int); ++ struct smb_ntsd *pntsd, __u32 len, int aclflag); + extern int cifs_do_get_acl(const unsigned int xid, struct cifs_tcon *tcon, + const unsigned char *searchName, + struct posix_acl **acl, const int acl_type, +diff --git a/fs/smb/client/cifssmb.c b/fs/smb/client/cifssmb.c +index a34db419e46f7f..2f8745736dbb02 100644 +--- a/fs/smb/client/cifssmb.c ++++ b/fs/smb/client/cifssmb.c +@@ -3385,7 +3385,7 @@ validate_ntransact(char *buf, char **ppparm, char **ppdata, + /* Get Security Descriptor (by handle) from remote server for a file or dir */ + int + CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid, +- struct cifs_ntsd **acl_inf, __u32 *pbuflen) ++ struct smb_ntsd **acl_inf, __u32 *pbuflen) + { + int rc = 0; + int buf_type = 0; +@@ -3455,7 +3455,7 @@ CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid, + + /* check if buffer is big enough for the acl + header followed by the smallest SID */ +- if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) || ++ if ((*pbuflen < sizeof(struct smb_ntsd) + 8) || + (*pbuflen >= 64 * 1024)) { + cifs_dbg(VFS, "bad acl length %d\n", *pbuflen); + rc = -EINVAL; +@@ -3475,7 +3475,7 @@ CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid, + + int + CIFSSMBSetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid, +- struct cifs_ntsd *pntsd, __u32 acllen, int aclflag) ++ struct smb_ntsd *pntsd, __u32 acllen, int aclflag) + { + __u16 byte_count, param_count, data_count, param_offset, data_offset; + int rc = 0; +diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c +index ce7e0aed8f7d2b..b3e59a7c71205f 100644 +--- a/fs/smb/client/inode.c ++++ b/fs/smb/client/inode.c +@@ -3087,6 +3087,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) + int rc = -EACCES; + __u32 dosattr = 0; + __u64 mode = NO_CHANGE_64; ++ bool posix = cifs_sb_master_tcon(cifs_sb)->posix_extensions; + + xid = get_xid(); + +@@ -3177,7 +3178,8 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) + mode = attrs->ia_mode; + rc = 0; + if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) || +- (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)) { ++ (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) || ++ posix) { + rc = id_mode_to_cifs_acl(inode, full_path, &mode, + INVALID_UID, INVALID_GID); + if (rc) { +diff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c +index 2a292736c89a2a..e695df1dbb23b2 100644 +--- a/fs/smb/client/smb2inode.c ++++ b/fs/smb/client/smb2inode.c +@@ -315,7 +315,7 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, + SMB2_O_INFO_FILE, 0, + sizeof(struct smb311_posix_qinfo *) + + (PATH_MAX * 2) + +- (sizeof(struct cifs_sid) * 2), 0, NULL); ++ (sizeof(struct smb_sid) * 2), 0, NULL); + } else { + rc = SMB2_query_info_init(tcon, server, + &rqst[num_rqst], +@@ -325,7 +325,7 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, + SMB2_O_INFO_FILE, 0, + sizeof(struct smb311_posix_qinfo *) + + (PATH_MAX * 2) + +- (sizeof(struct cifs_sid) * 2), 0, NULL); ++ (sizeof(struct smb_sid) * 2), 0, NULL); + } + if (!rc && (!cfile || num_rqst > 1)) { + smb2_set_next_command(tcon, &rqst[num_rqst]); +diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c +index 6645f147d57c29..fc6d00344c50ea 100644 +--- a/fs/smb/client/smb2ops.c ++++ b/fs/smb/client/smb2ops.c +@@ -3001,11 +3001,11 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses, + return rc; + } + +-static struct cifs_ntsd * ++static struct smb_ntsd * + get_smb2_acl_by_fid(struct cifs_sb_info *cifs_sb, + const struct cifs_fid *cifsfid, u32 *pacllen, u32 info) + { +- struct cifs_ntsd *pntsd = NULL; ++ struct smb_ntsd *pntsd = NULL; + unsigned int xid; + int rc = -EOPNOTSUPP; + struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); +@@ -3030,11 +3030,11 @@ get_smb2_acl_by_fid(struct cifs_sb_info *cifs_sb, + + } + +-static struct cifs_ntsd * ++static struct smb_ntsd * + get_smb2_acl_by_path(struct cifs_sb_info *cifs_sb, + const char *path, u32 *pacllen, u32 info) + { +- struct cifs_ntsd *pntsd = NULL; ++ struct smb_ntsd *pntsd = NULL; + u8 oplock = SMB2_OPLOCK_LEVEL_NONE; + unsigned int xid; + int rc; +@@ -3097,7 +3097,7 @@ get_smb2_acl_by_path(struct cifs_sb_info *cifs_sb, + } + + static int +-set_smb2_acl(struct cifs_ntsd *pnntsd, __u32 acllen, ++set_smb2_acl(struct smb_ntsd *pnntsd, __u32 acllen, + struct inode *inode, const char *path, int aclflag) + { + u8 oplock = SMB2_OPLOCK_LEVEL_NONE; +@@ -3155,12 +3155,12 @@ set_smb2_acl(struct cifs_ntsd *pnntsd, __u32 acllen, + } + + /* Retrieve an ACL from the server */ +-static struct cifs_ntsd * ++static struct smb_ntsd * + get_smb2_acl(struct cifs_sb_info *cifs_sb, + struct inode *inode, const char *path, + u32 *pacllen, u32 info) + { +- struct cifs_ntsd *pntsd = NULL; ++ struct smb_ntsd *pntsd = NULL; + struct cifsFileInfo *open_file = NULL; + + if (inode && !(info & SACL_SECINFO)) +diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c +index 38b26468eb0c53..c012fbc2638ed5 100644 +--- a/fs/smb/client/smb2pdu.c ++++ b/fs/smb/client/smb2pdu.c +@@ -2623,7 +2623,7 @@ create_sd_buf(umode_t mode, bool set_owner, unsigned int *len) + unsigned int group_offset = 0; + struct smb3_acl acl = {}; + +- *len = round_up(sizeof(struct crt_sd_ctxt) + (sizeof(struct cifs_ace) * 4), 8); ++ *len = round_up(sizeof(struct crt_sd_ctxt) + (sizeof(struct smb_ace) * 4), 8); + + if (set_owner) { + /* sizeof(struct owner_group_sids) is already multiple of 8 so no need to round */ +@@ -2672,21 +2672,21 @@ create_sd_buf(umode_t mode, bool set_owner, unsigned int *len) + ptr += sizeof(struct smb3_acl); + + /* create one ACE to hold the mode embedded in reserved special SID */ +- acelen = setup_special_mode_ACE((struct cifs_ace *)ptr, (__u64)mode); ++ acelen = setup_special_mode_ACE((struct smb_ace *)ptr, false, (__u64)mode); + ptr += acelen; + acl_size = acelen + sizeof(struct smb3_acl); + ace_count = 1; + + if (set_owner) { + /* we do not need to reallocate buffer to add the two more ACEs. plenty of space */ +- acelen = setup_special_user_owner_ACE((struct cifs_ace *)ptr); ++ acelen = setup_special_user_owner_ACE((struct smb_ace *)ptr); + ptr += acelen; + acl_size += acelen; + ace_count += 1; + } + + /* and one more ACE to allow access for authenticated users */ +- acelen = setup_authusers_ACE((struct cifs_ace *)ptr); ++ acelen = setup_authusers_ACE((struct smb_ace *)ptr); + ptr += acelen; + acl_size += acelen; + ace_count += 1; +@@ -3915,7 +3915,7 @@ SMB311_posix_query_info(const unsigned int xid, struct cifs_tcon *tcon, + u64 persistent_fid, u64 volatile_fid, struct smb311_posix_qinfo *data, u32 *plen) + { + size_t output_len = sizeof(struct smb311_posix_qinfo *) + +- (sizeof(struct cifs_sid) * 2) + (PATH_MAX * 2); ++ (sizeof(struct smb_sid) * 2) + (PATH_MAX * 2); + *plen = 0; + + return query_info(xid, tcon, persistent_fid, volatile_fid, +@@ -5626,7 +5626,7 @@ SMB2_set_eof(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, + int + SMB2_set_acl(const unsigned int xid, struct cifs_tcon *tcon, + u64 persistent_fid, u64 volatile_fid, +- struct cifs_ntsd *pnntsd, int pacllen, int aclflag) ++ struct smb_ntsd *pnntsd, int pacllen, int aclflag) + { + return send_set_info(xid, tcon, persistent_fid, volatile_fid, + current->tgid, 0, SMB2_O_INFO_SECURITY, aclflag, +diff --git a/fs/smb/client/smb2pdu.h b/fs/smb/client/smb2pdu.h +index 5c458ab3b05a44..076d9e83e1a044 100644 +--- a/fs/smb/client/smb2pdu.h ++++ b/fs/smb/client/smb2pdu.h +@@ -364,8 +364,8 @@ struct create_posix_rsp { + u32 nlink; + u32 reparse_tag; + u32 mode; +- struct cifs_sid owner; /* var-sized on the wire */ +- struct cifs_sid group; /* var-sized on the wire */ ++ struct smb_sid owner; /* var-sized on the wire */ ++ struct smb_sid group; /* var-sized on the wire */ + } __packed; + + #define SMB2_QUERY_DIRECTORY_IOV_SIZE 2 +@@ -408,8 +408,8 @@ struct smb2_posix_info { + struct smb2_posix_info_parsed { + const struct smb2_posix_info *base; + size_t size; +- struct cifs_sid owner; +- struct cifs_sid group; ++ struct smb_sid owner; ++ struct smb_sid group; + int name_len; + const u8 *name; + }; +diff --git a/fs/smb/client/smb2proto.h b/fs/smb/client/smb2proto.h +index 613667b46c5802..750e4e397b1393 100644 +--- a/fs/smb/client/smb2proto.h ++++ b/fs/smb/client/smb2proto.h +@@ -37,8 +37,6 @@ extern struct mid_q_entry *smb2_setup_request(struct cifs_ses *ses, + struct smb_rqst *rqst); + extern struct mid_q_entry *smb2_setup_async_request( + struct TCP_Server_Info *server, struct smb_rqst *rqst); +-extern struct cifs_ses *smb2_find_smb_ses(struct TCP_Server_Info *server, +- __u64 ses_id); + extern struct cifs_tcon *smb2_find_smb_tcon(struct TCP_Server_Info *server, + __u64 ses_id, __u32 tid); + extern int smb2_calc_signature(struct smb_rqst *rqst, +@@ -247,7 +245,7 @@ extern int SMB2_set_info_init(struct cifs_tcon *tcon, + extern void SMB2_set_info_free(struct smb_rqst *rqst); + extern int SMB2_set_acl(const unsigned int xid, struct cifs_tcon *tcon, + u64 persistent_fid, u64 volatile_fid, +- struct cifs_ntsd *pnntsd, int pacllen, int aclflag); ++ struct smb_ntsd *pnntsd, int pacllen, int aclflag); + extern int SMB2_set_ea(const unsigned int xid, struct cifs_tcon *tcon, + u64 persistent_fid, u64 volatile_fid, + struct smb2_file_full_ea_info *buf, int len); +diff --git a/fs/smb/client/smb2transport.c b/fs/smb/client/smb2transport.c +index 4ca04e62a993cf..4a43802375b3a3 100644 +--- a/fs/smb/client/smb2transport.c ++++ b/fs/smb/client/smb2transport.c +@@ -74,7 +74,7 @@ smb311_crypto_shash_allocate(struct TCP_Server_Info *server) + + + static +-int smb2_get_sign_key(__u64 ses_id, struct TCP_Server_Info *server, u8 *key) ++int smb3_get_sign_key(__u64 ses_id, struct TCP_Server_Info *server, u8 *key) + { + struct cifs_chan *chan; + struct TCP_Server_Info *pserver; +@@ -168,16 +168,41 @@ smb2_find_smb_ses_unlocked(struct TCP_Server_Info *server, __u64 ses_id) + return NULL; + } + +-struct cifs_ses * +-smb2_find_smb_ses(struct TCP_Server_Info *server, __u64 ses_id) ++static int smb2_get_sign_key(struct TCP_Server_Info *server, ++ __u64 ses_id, u8 *key) + { + struct cifs_ses *ses; ++ int rc = -ENOENT; ++ ++ if (SERVER_IS_CHAN(server)) ++ server = server->primary_server; + + spin_lock(&cifs_tcp_ses_lock); +- ses = smb2_find_smb_ses_unlocked(server, ses_id); +- spin_unlock(&cifs_tcp_ses_lock); ++ list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { ++ if (ses->Suid != ses_id) ++ continue; + +- return ses; ++ rc = 0; ++ spin_lock(&ses->ses_lock); ++ switch (ses->ses_status) { ++ case SES_EXITING: /* SMB2_LOGOFF */ ++ case SES_GOOD: ++ if (likely(ses->auth_key.response)) { ++ memcpy(key, ses->auth_key.response, ++ SMB2_NTLMV2_SESSKEY_SIZE); ++ } else { ++ rc = -EIO; ++ } ++ break; ++ default: ++ rc = -EAGAIN; ++ break; ++ } ++ spin_unlock(&ses->ses_lock); ++ break; ++ } ++ spin_unlock(&cifs_tcp_ses_lock); ++ return rc; + } + + static struct cifs_tcon * +@@ -236,14 +261,16 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server, + unsigned char *sigptr = smb2_signature; + struct kvec *iov = rqst->rq_iov; + struct smb2_hdr *shdr = (struct smb2_hdr *)iov[0].iov_base; +- struct cifs_ses *ses; + struct shash_desc *shash = NULL; + struct smb_rqst drqst; ++ __u64 sid = le64_to_cpu(shdr->SessionId); ++ u8 key[SMB2_NTLMV2_SESSKEY_SIZE]; + +- ses = smb2_find_smb_ses(server, le64_to_cpu(shdr->SessionId)); +- if (unlikely(!ses)) { +- cifs_server_dbg(VFS, "%s: Could not find session\n", __func__); +- return -ENOENT; ++ rc = smb2_get_sign_key(server, sid, key); ++ if (unlikely(rc)) { ++ cifs_server_dbg(FYI, "%s: [sesid=0x%llx] couldn't find signing key: %d\n", ++ __func__, sid, rc); ++ return rc; + } + + memset(smb2_signature, 0x0, SMB2_HMACSHA256_SIZE); +@@ -260,8 +287,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server, + shash = server->secmech.hmacsha256; + } + +- rc = crypto_shash_setkey(shash->tfm, ses->auth_key.response, +- SMB2_NTLMV2_SESSKEY_SIZE); ++ rc = crypto_shash_setkey(shash->tfm, key, sizeof(key)); + if (rc) { + cifs_server_dbg(VFS, + "%s: Could not update with response\n", +@@ -303,8 +329,6 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server, + out: + if (allocate_crypto) + cifs_free_hash(&shash); +- if (ses) +- cifs_put_smb_ses(ses); + return rc; + } + +@@ -570,7 +594,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server, + struct smb_rqst drqst; + u8 key[SMB3_SIGN_KEY_SIZE]; + +- rc = smb2_get_sign_key(le64_to_cpu(shdr->SessionId), server, key); ++ rc = smb3_get_sign_key(le64_to_cpu(shdr->SessionId), server, key); + if (unlikely(rc)) { + cifs_server_dbg(FYI, "%s: Could not get signing key\n", __func__); + return rc; +diff --git a/fs/smb/client/xattr.c b/fs/smb/client/xattr.c +index c2bf829310bee2..e8696ad4da994e 100644 +--- a/fs/smb/client/xattr.c ++++ b/fs/smb/client/xattr.c +@@ -162,7 +162,7 @@ static int cifs_xattr_set(const struct xattr_handler *handler, + case XATTR_CIFS_ACL: + case XATTR_CIFS_NTSD: + case XATTR_CIFS_NTSD_FULL: { +- struct cifs_ntsd *pacl; ++ struct smb_ntsd *pacl; + + if (!value) + goto out; +@@ -315,7 +315,7 @@ static int cifs_xattr_get(const struct xattr_handler *handler, + * fetch owner and DACL otherwise + */ + u32 acllen, extra_info; +- struct cifs_ntsd *pacl; ++ struct smb_ntsd *pacl; + + if (pTcon->ses->server->ops->get_acl == NULL) + goto out; /* rc already EOPNOTSUPP */ +diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c +index cd530b9a00caa3..2884ebdc0eda02 100644 +--- a/fs/smb/server/smb2pdu.c ++++ b/fs/smb/server/smb2pdu.c +@@ -4225,6 +4225,7 @@ static bool __query_dir(struct dir_context *ctx, const char *name, int namlen, + /* dot and dotdot entries are already reserved */ + if (!strcmp(".", name) || !strcmp("..", name)) + return true; ++ d_info->num_scan++; + if (ksmbd_share_veto_filename(priv->work->tcon->share_conf, name)) + return true; + if (!match_pattern(name, namlen, priv->search_pattern)) +@@ -4385,8 +4386,17 @@ int smb2_query_dir(struct ksmbd_work *work) + query_dir_private.info_level = req->FileInformationClass; + dir_fp->readdir_data.private = &query_dir_private; + set_ctx_actor(&dir_fp->readdir_data.ctx, __query_dir); +- ++again: ++ d_info.num_scan = 0; + rc = iterate_dir(dir_fp->filp, &dir_fp->readdir_data.ctx); ++ /* ++ * num_entry can be 0 if the directory iteration stops before reaching ++ * the end of the directory and no file is matched with the search ++ * pattern. ++ */ ++ if (rc >= 0 && !d_info.num_entry && d_info.num_scan && ++ d_info.out_buf_len > 0) ++ goto again; + /* + * req->OutputBufferLength is too small to contain even one entry. + * In this case, it immediately returns OutputBufferLength 0 to client. +@@ -6007,15 +6017,13 @@ static int set_file_basic_info(struct ksmbd_file *fp, + attrs.ia_valid |= (ATTR_ATIME | ATTR_ATIME_SET); + } + +- attrs.ia_valid |= ATTR_CTIME; + if (file_info->ChangeTime) +- attrs.ia_ctime = ksmbd_NTtimeToUnix(file_info->ChangeTime); +- else +- attrs.ia_ctime = inode_get_ctime(inode); ++ inode_set_ctime_to_ts(inode, ++ ksmbd_NTtimeToUnix(file_info->ChangeTime)); + + if (file_info->LastWriteTime) { + attrs.ia_mtime = ksmbd_NTtimeToUnix(file_info->LastWriteTime); +- attrs.ia_valid |= (ATTR_MTIME | ATTR_MTIME_SET); ++ attrs.ia_valid |= (ATTR_MTIME | ATTR_MTIME_SET | ATTR_CTIME); + } + + if (file_info->Attributes) { +@@ -6057,8 +6065,6 @@ static int set_file_basic_info(struct ksmbd_file *fp, + return -EACCES; + + inode_lock(inode); +- inode_set_ctime_to_ts(inode, attrs.ia_ctime); +- attrs.ia_valid &= ~ATTR_CTIME; + rc = notify_change(idmap, dentry, &attrs, NULL); + inode_unlock(inode); + } +diff --git a/fs/smb/server/vfs.h b/fs/smb/server/vfs.h +index cb76f4b5bafe8c..06903024a2d88b 100644 +--- a/fs/smb/server/vfs.h ++++ b/fs/smb/server/vfs.h +@@ -43,6 +43,7 @@ struct ksmbd_dir_info { + char *rptr; + int name_len; + int out_buf_len; ++ int num_scan; + int num_entry; + int data_count; + int last_entry_offset; +diff --git a/fs/udf/namei.c b/fs/udf/namei.c +index b3f57ad2b869ff..8ac73f41d6ebe6 100644 +--- a/fs/udf/namei.c ++++ b/fs/udf/namei.c +@@ -770,7 +770,7 @@ static int udf_rename(struct mnt_idmap *idmap, struct inode *old_dir, + struct inode *old_inode = d_inode(old_dentry); + struct inode *new_inode = d_inode(new_dentry); + struct udf_fileident_iter oiter, niter, diriter; +- bool has_diriter = false; ++ bool has_diriter = false, is_dir = false; + int retval; + struct kernel_lb_addr tloc; + +@@ -792,7 +792,20 @@ static int udf_rename(struct mnt_idmap *idmap, struct inode *old_dir, + retval = -ENOTEMPTY; + if (!empty_dir(new_inode)) + goto out_oiter; ++ retval = -EFSCORRUPTED; ++ if (new_inode->i_nlink != 2) ++ goto out_oiter; + } ++ retval = -EFSCORRUPTED; ++ if (old_dir->i_nlink < 3) ++ goto out_oiter; ++ is_dir = true; ++ } else if (new_inode) { ++ retval = -EFSCORRUPTED; ++ if (new_inode->i_nlink < 1) ++ goto out_oiter; ++ } ++ if (is_dir && old_dir != new_dir) { + retval = udf_fiiter_find_entry(old_inode, &dotdot_name, + &diriter); + if (retval == -ENOENT) { +@@ -880,7 +893,9 @@ static int udf_rename(struct mnt_idmap *idmap, struct inode *old_dir, + cpu_to_lelb(UDF_I(new_dir)->i_location); + udf_fiiter_write_fi(&diriter, NULL); + udf_fiiter_release(&diriter); ++ } + ++ if (is_dir) { + inode_dec_link_count(old_dir); + if (new_inode) + inode_dec_link_count(new_inode); +diff --git a/include/acpi/pcc.h b/include/acpi/pcc.h +index 73e806fe7ce707..699c1a37b8e784 100644 +--- a/include/acpi/pcc.h ++++ b/include/acpi/pcc.h +@@ -12,17 +12,33 @@ + struct pcc_mbox_chan { + struct mbox_chan *mchan; + u64 shmem_base_addr; ++ void __iomem *shmem; + u64 shmem_size; + u32 latency; + u32 max_access_rate; + u16 min_turnaround_time; + }; + ++/* Generic Communications Channel Shared Memory Region */ ++#define PCC_SIGNATURE 0x50434300 ++/* Generic Communications Channel Command Field */ ++#define PCC_CMD_GENERATE_DB_INTR BIT(15) ++/* Generic Communications Channel Status Field */ ++#define PCC_STATUS_CMD_COMPLETE BIT(0) ++#define PCC_STATUS_SCI_DOORBELL BIT(1) ++#define PCC_STATUS_ERROR BIT(2) ++#define PCC_STATUS_PLATFORM_NOTIFY BIT(3) ++/* Initiator Responder Communications Channel Flags */ ++#define PCC_CMD_COMPLETION_NOTIFY BIT(0) ++ + #define MAX_PCC_SUBSPACES 256 ++#define PCC_ACK_FLAG_MASK 0x1 ++ + #ifdef CONFIG_PCC + extern struct pcc_mbox_chan * + pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id); + extern void pcc_mbox_free_channel(struct pcc_mbox_chan *chan); ++extern int pcc_mbox_ioremap(struct mbox_chan *chan); + #else + static inline struct pcc_mbox_chan * + pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id) +@@ -30,6 +46,10 @@ pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id) + return ERR_PTR(-ENODEV); + } + static inline void pcc_mbox_free_channel(struct pcc_mbox_chan *chan) { } ++static inline int pcc_mbox_ioremap(struct mbox_chan *chan) ++{ ++ return 0; ++}; + #endif + + #endif /* _PCC_H */ +diff --git a/include/clocksource/hyperv_timer.h b/include/clocksource/hyperv_timer.h +index 6cdc873ac907f5..aa5233b1eba970 100644 +--- a/include/clocksource/hyperv_timer.h ++++ b/include/clocksource/hyperv_timer.h +@@ -38,6 +38,8 @@ extern void hv_remap_tsc_clocksource(void); + extern unsigned long hv_get_tsc_pfn(void); + extern struct ms_hyperv_tsc_page *hv_get_tsc_page(void); + ++extern void hv_adj_sched_clock_offset(u64 offset); ++ + static __always_inline bool + hv_read_tsc_page_tsc(const struct ms_hyperv_tsc_page *tsc_pg, + u64 *cur_tsc, u64 *time) +diff --git a/include/crypto/internal/ecc.h b/include/crypto/internal/ecc.h +index 4f6c1a68882fa1..c0b8be63cbde7c 100644 +--- a/include/crypto/internal/ecc.h ++++ b/include/crypto/internal/ecc.h +@@ -56,6 +56,16 @@ static inline void ecc_swap_digits(const void *in, u64 *out, unsigned int ndigit + out[i] = get_unaligned_be64(&src[ndigits - 1 - i]); + } + ++/** ++ * ecc_digits_from_bytes() - Create ndigits-sized digits array from byte array ++ * @in: Input byte array ++ * @nbytes Size of input byte array ++ * @out Output digits array ++ * @ndigits: Number of digits to create from byte array ++ */ ++void ecc_digits_from_bytes(const u8 *in, unsigned int nbytes, ++ u64 *out, unsigned int ndigits); ++ + /** + * ecc_is_key_valid() - Validate a given ECDH private key + * +diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h +index cb8e97665eaa59..92919d52f7e1b2 100644 +--- a/include/linux/bpf_verifier.h ++++ b/include/linux/bpf_verifier.h +@@ -319,34 +319,12 @@ struct bpf_func_state { + struct bpf_stack_state *stack; + }; + +-#define MAX_CALL_FRAMES 8 +- +-/* instruction history flags, used in bpf_jmp_history_entry.flags field */ +-enum { +- /* instruction references stack slot through PTR_TO_STACK register; +- * we also store stack's frame number in lower 3 bits (MAX_CALL_FRAMES is 8) +- * and accessed stack slot's index in next 6 bits (MAX_BPF_STACK is 512, +- * 8 bytes per slot, so slot index (spi) is [0, 63]) +- */ +- INSN_F_FRAMENO_MASK = 0x7, /* 3 bits */ +- +- INSN_F_SPI_MASK = 0x3f, /* 6 bits */ +- INSN_F_SPI_SHIFT = 3, /* shifted 3 bits to the left */ +- +- INSN_F_STACK_ACCESS = BIT(9), /* we need 10 bits total */ +-}; +- +-static_assert(INSN_F_FRAMENO_MASK + 1 >= MAX_CALL_FRAMES); +-static_assert(INSN_F_SPI_MASK + 1 >= MAX_BPF_STACK / 8); +- +-struct bpf_jmp_history_entry { ++struct bpf_idx_pair { ++ u32 prev_idx; + u32 idx; +- /* insn idx can't be bigger than 1 million */ +- u32 prev_idx : 22; +- /* special flags, e.g., whether insn is doing register stack spill/load */ +- u32 flags : 10; + }; + ++#define MAX_CALL_FRAMES 8 + /* Maximum number of register states that can exist at once */ + #define BPF_ID_MAP_SIZE ((MAX_BPF_REG + MAX_BPF_STACK / BPF_REG_SIZE) * MAX_CALL_FRAMES) + struct bpf_verifier_state { +@@ -429,7 +407,7 @@ struct bpf_verifier_state { + * For most states jmp_history_cnt is [0-3]. + * For loops can go up to ~40. + */ +- struct bpf_jmp_history_entry *jmp_history; ++ struct bpf_idx_pair *jmp_history; + u32 jmp_history_cnt; + u32 dfs_depth; + u32 callback_unroll_depth; +@@ -662,7 +640,6 @@ struct bpf_verifier_env { + int cur_stack; + } cfg; + struct backtrack_state bt; +- struct bpf_jmp_history_entry *cur_hist_ent; + u32 pass_cnt; /* number of times do_check() was called */ + u32 subprog_cnt; + /* number of instructions analyzed by the verifier */ +diff --git a/include/linux/cleanup.h b/include/linux/cleanup.h +index 53f1a7a932b08c..64b8600eb8c0e4 100644 +--- a/include/linux/cleanup.h ++++ b/include/linux/cleanup.h +@@ -92,26 +92,85 @@ static inline class_##_name##_t class_##_name##ext##_constructor(_init_args) \ + * trivial wrapper around DEFINE_CLASS() above specifically + * for locks. + * ++ * DEFINE_GUARD_COND(name, ext, condlock) ++ * wrapper around EXTEND_CLASS above to add conditional lock ++ * variants to a base class, eg. mutex_trylock() or ++ * mutex_lock_interruptible(). ++ * + * guard(name): +- * an anonymous instance of the (guard) class ++ * an anonymous instance of the (guard) class, not recommended for ++ * conditional locks. + * + * scoped_guard (name, args...) { }: + * similar to CLASS(name, scope)(args), except the variable (with the + * explicit name 'scope') is declard in a for-loop such that its scope is + * bound to the next (compound) statement. + * ++ * for conditional locks the loop body is skipped when the lock is not ++ * acquired. ++ * ++ * scoped_cond_guard (name, fail, args...) { }: ++ * similar to scoped_guard(), except it does fail when the lock ++ * acquire fails. ++ * ++ * Only for conditional locks. + */ + ++#define __DEFINE_CLASS_IS_CONDITIONAL(_name, _is_cond) \ ++static __maybe_unused const bool class_##_name##_is_conditional = _is_cond ++ + #define DEFINE_GUARD(_name, _type, _lock, _unlock) \ +- DEFINE_CLASS(_name, _type, _unlock, ({ _lock; _T; }), _type _T) ++ __DEFINE_CLASS_IS_CONDITIONAL(_name, false); \ ++ DEFINE_CLASS(_name, _type, if (_T) { _unlock; }, ({ _lock; _T; }), _type _T); \ ++ static inline void * class_##_name##_lock_ptr(class_##_name##_t *_T) \ ++ { return (void *)(__force unsigned long)*_T; } ++ ++#define DEFINE_GUARD_COND(_name, _ext, _condlock) \ ++ __DEFINE_CLASS_IS_CONDITIONAL(_name##_ext, true); \ ++ EXTEND_CLASS(_name, _ext, \ ++ ({ void *_t = _T; if (_T && !(_condlock)) _t = NULL; _t; }), \ ++ class_##_name##_t _T) \ ++ static inline void * class_##_name##_ext##_lock_ptr(class_##_name##_t *_T) \ ++ { return class_##_name##_lock_ptr(_T); } + + #define guard(_name) \ + CLASS(_name, __UNIQUE_ID(guard)) + +-#define scoped_guard(_name, args...) \ +- for (CLASS(_name, scope)(args), \ +- *done = NULL; !done; done = (void *)1) ++#define __guard_ptr(_name) class_##_name##_lock_ptr ++#define __is_cond_ptr(_name) class_##_name##_is_conditional + ++/* ++ * Helper macro for scoped_guard(). ++ * ++ * Note that the "!__is_cond_ptr(_name)" part of the condition ensures that ++ * compiler would be sure that for the unconditional locks the body of the ++ * loop (caller-provided code glued to the else clause) could not be skipped. ++ * It is needed because the other part - "__guard_ptr(_name)(&scope)" - is too ++ * hard to deduce (even if could be proven true for unconditional locks). ++ */ ++#define __scoped_guard(_name, _label, args...) \ ++ for (CLASS(_name, scope)(args); \ ++ __guard_ptr(_name)(&scope) || !__is_cond_ptr(_name); \ ++ ({ goto _label; })) \ ++ if (0) { \ ++_label: \ ++ break; \ ++ } else ++ ++#define scoped_guard(_name, args...) \ ++ __scoped_guard(_name, __UNIQUE_ID(label), args) ++ ++#define __scoped_cond_guard(_name, _fail, _label, args...) \ ++ for (CLASS(_name, scope)(args); true; ({ goto _label; })) \ ++ if (!__guard_ptr(_name)(&scope)) { \ ++ BUILD_BUG_ON(!__is_cond_ptr(_name)); \ ++ _fail; \ ++_label: \ ++ break; \ ++ } else ++ ++#define scoped_cond_guard(_name, _fail, args...) \ ++ __scoped_cond_guard(_name, _fail, __UNIQUE_ID(label), args) + /* + * Additional helper macros for generating lock guards with types, either for + * locks that don't have a native type (eg. RCU, preempt) or those that need a +@@ -119,6 +178,7 @@ static inline class_##_name##_t class_##_name##ext##_constructor(_init_args) \ + * + * DEFINE_LOCK_GUARD_0(name, lock, unlock, ...) + * DEFINE_LOCK_GUARD_1(name, type, lock, unlock, ...) ++ * DEFINE_LOCK_GUARD_1_COND(name, ext, condlock) + * + * will result in the following type: + * +@@ -140,6 +200,11 @@ typedef struct { \ + static inline void class_##_name##_destructor(class_##_name##_t *_T) \ + { \ + if (_T->lock) { _unlock; } \ ++} \ ++ \ ++static inline void *class_##_name##_lock_ptr(class_##_name##_t *_T) \ ++{ \ ++ return (void *)(__force unsigned long)_T->lock; \ + } + + +@@ -161,11 +226,24 @@ static inline class_##_name##_t class_##_name##_constructor(void) \ + } + + #define DEFINE_LOCK_GUARD_1(_name, _type, _lock, _unlock, ...) \ ++__DEFINE_CLASS_IS_CONDITIONAL(_name, false); \ + __DEFINE_UNLOCK_GUARD(_name, _type, _unlock, __VA_ARGS__) \ + __DEFINE_LOCK_GUARD_1(_name, _type, _lock) + + #define DEFINE_LOCK_GUARD_0(_name, _lock, _unlock, ...) \ ++__DEFINE_CLASS_IS_CONDITIONAL(_name, false); \ + __DEFINE_UNLOCK_GUARD(_name, void, _unlock, __VA_ARGS__) \ + __DEFINE_LOCK_GUARD_0(_name, _lock) + ++#define DEFINE_LOCK_GUARD_1_COND(_name, _ext, _condlock) \ ++ __DEFINE_CLASS_IS_CONDITIONAL(_name##_ext, true); \ ++ EXTEND_CLASS(_name, _ext, \ ++ ({ class_##_name##_t _t = { .lock = l }, *_T = &_t;\ ++ if (_T->lock && !(_condlock)) _T->lock = NULL; \ ++ _t; }), \ ++ typeof_member(class_##_name##_t, lock) l) \ ++ static inline void * class_##_name##_ext##_lock_ptr(class_##_name##_t *_T) \ ++ { return class_##_name##_lock_ptr(_T); } ++ ++ + #endif /* __LINUX_GUARDS_H */ +diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h +index 3028af87716e29..430749a0f362aa 100644 +--- a/include/linux/if_vlan.h ++++ b/include/linux/if_vlan.h +@@ -585,13 +585,16 @@ static inline int vlan_get_tag(const struct sk_buff *skb, u16 *vlan_tci) + * vlan_get_protocol - get protocol EtherType. + * @skb: skbuff to query + * @type: first vlan protocol ++ * @mac_offset: MAC offset + * @depth: buffer to store length of eth and vlan tags in bytes + * + * Returns the EtherType of the packet, regardless of whether it is + * vlan encapsulated (normal or hardware accelerated) or not. + */ +-static inline __be16 __vlan_get_protocol(const struct sk_buff *skb, __be16 type, +- int *depth) ++static inline __be16 __vlan_get_protocol_offset(const struct sk_buff *skb, ++ __be16 type, ++ int mac_offset, ++ int *depth) + { + unsigned int vlan_depth = skb->mac_len, parse_depth = VLAN_MAX_DEPTH; + +@@ -610,7 +613,8 @@ static inline __be16 __vlan_get_protocol(const struct sk_buff *skb, __be16 type, + do { + struct vlan_hdr vhdr, *vh; + +- vh = skb_header_pointer(skb, vlan_depth, sizeof(vhdr), &vhdr); ++ vh = skb_header_pointer(skb, mac_offset + vlan_depth, ++ sizeof(vhdr), &vhdr); + if (unlikely(!vh || !--parse_depth)) + return 0; + +@@ -625,6 +629,12 @@ static inline __be16 __vlan_get_protocol(const struct sk_buff *skb, __be16 type, + return type; + } + ++static inline __be16 __vlan_get_protocol(const struct sk_buff *skb, __be16 type, ++ int *depth) ++{ ++ return __vlan_get_protocol_offset(skb, type, 0, depth); ++} ++ + /** + * vlan_get_protocol - get protocol EtherType. + * @skb: skbuff to query +diff --git a/include/linux/memblock.h b/include/linux/memblock.h +index ed57c23f80ac2b..ed64240041e857 100644 +--- a/include/linux/memblock.h ++++ b/include/linux/memblock.h +@@ -122,6 +122,7 @@ unsigned long memblock_addrs_overlap(phys_addr_t base1, phys_addr_t size1, + phys_addr_t base2, phys_addr_t size2); + bool memblock_overlaps_region(struct memblock_type *type, + phys_addr_t base, phys_addr_t size); ++bool memblock_validate_numa_coverage(unsigned long threshold_bytes); + int memblock_mark_hotplug(phys_addr_t base, phys_addr_t size); + int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size); + int memblock_mark_mirror(phys_addr_t base, phys_addr_t size); +diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h +index ffb98bc43b2db2..38a8ff9c685cb8 100644 +--- a/include/linux/mlx5/driver.h ++++ b/include/linux/mlx5/driver.h +@@ -1225,6 +1225,12 @@ static inline bool mlx5_core_is_vf(const struct mlx5_core_dev *dev) + return dev->coredev_type == MLX5_COREDEV_VF; + } + ++static inline bool mlx5_core_same_coredev_type(const struct mlx5_core_dev *dev1, ++ const struct mlx5_core_dev *dev2) ++{ ++ return dev1->coredev_type == dev2->coredev_type; ++} ++ + static inline bool mlx5_core_is_ecpf(const struct mlx5_core_dev *dev) + { + return dev->caps.embedded_cpu; +diff --git a/include/linux/mutex.h b/include/linux/mutex.h +index 5b5630e58407a5..e1c323c7d75ba9 100644 +--- a/include/linux/mutex.h ++++ b/include/linux/mutex.h +@@ -248,6 +248,7 @@ extern void mutex_unlock(struct mutex *lock); + extern int atomic_dec_and_mutex_lock(atomic_t *cnt, struct mutex *lock); + + DEFINE_GUARD(mutex, struct mutex *, mutex_lock(_T), mutex_unlock(_T)) +-DEFINE_FREE(mutex, struct mutex *, if (_T) mutex_unlock(_T)) ++DEFINE_GUARD_COND(mutex, _try, mutex_trylock(_T)) ++DEFINE_GUARD_COND(mutex, _intr, mutex_lock_interruptible(_T) == 0) + + #endif /* __LINUX_MUTEX_H */ +diff --git a/include/linux/rwsem.h b/include/linux/rwsem.h +index 1dd530ce8b45b9..9c29689ff505e0 100644 +--- a/include/linux/rwsem.h ++++ b/include/linux/rwsem.h +@@ -203,11 +203,11 @@ extern void up_read(struct rw_semaphore *sem); + extern void up_write(struct rw_semaphore *sem); + + DEFINE_GUARD(rwsem_read, struct rw_semaphore *, down_read(_T), up_read(_T)) +-DEFINE_GUARD(rwsem_write, struct rw_semaphore *, down_write(_T), up_write(_T)) +- +-DEFINE_FREE(up_read, struct rw_semaphore *, if (_T) up_read(_T)) +-DEFINE_FREE(up_write, struct rw_semaphore *, if (_T) up_write(_T)) ++DEFINE_GUARD_COND(rwsem_read, _try, down_read_trylock(_T)) ++DEFINE_GUARD_COND(rwsem_read, _intr, down_read_interruptible(_T) == 0) + ++DEFINE_GUARD(rwsem_write, struct rw_semaphore *, down_write(_T), up_write(_T)) ++DEFINE_GUARD_COND(rwsem_write, _try, down_write_trylock(_T)) + + /* + * downgrade write lock to read lock +diff --git a/include/linux/seq_buf.h b/include/linux/seq_buf.h +index 515d7fcb9634b5..468d8c5eef4a08 100644 +--- a/include/linux/seq_buf.h ++++ b/include/linux/seq_buf.h +@@ -14,19 +14,24 @@ + * @buffer: pointer to the buffer + * @size: size of the buffer + * @len: the amount of data inside the buffer +- * @readpos: The next position to read in the buffer. + */ + struct seq_buf { + char *buffer; + size_t size; + size_t len; +- loff_t readpos; + }; + ++#define DECLARE_SEQ_BUF(NAME, SIZE) \ ++ struct seq_buf NAME = { \ ++ .buffer = (char[SIZE]) { 0 }, \ ++ .size = SIZE, \ ++ } ++ + static inline void seq_buf_clear(struct seq_buf *s) + { + s->len = 0; +- s->readpos = 0; ++ if (s->size) ++ s->buffer[0] = '\0'; + } + + static inline void +@@ -72,8 +77,8 @@ static inline unsigned int seq_buf_used(struct seq_buf *s) + } + + /** +- * seq_buf_terminate - Make sure buffer is nul terminated +- * @s: the seq_buf descriptor to terminate. ++ * seq_buf_str - get %NUL-terminated C string from seq_buf ++ * @s: the seq_buf handle + * + * This makes sure that the buffer in @s is nul terminated and + * safe to read as a string. +@@ -84,16 +89,20 @@ static inline unsigned int seq_buf_used(struct seq_buf *s) + * + * After this function is called, s->buffer is safe to use + * in string operations. ++ * ++ * Returns @s->buf after making sure it is terminated. + */ +-static inline void seq_buf_terminate(struct seq_buf *s) ++static inline const char *seq_buf_str(struct seq_buf *s) + { + if (WARN_ON(s->size == 0)) +- return; ++ return ""; + + if (seq_buf_buffer_left(s)) + s->buffer[s->len] = 0; + else + s->buffer[s->size - 1] = 0; ++ ++ return s->buffer; + } + + /** +@@ -143,7 +152,7 @@ extern __printf(2, 0) + int seq_buf_vprintf(struct seq_buf *s, const char *fmt, va_list args); + extern int seq_buf_print_seq(struct seq_file *m, struct seq_buf *s); + extern int seq_buf_to_user(struct seq_buf *s, char __user *ubuf, +- int cnt); ++ size_t start, int cnt); + extern int seq_buf_puts(struct seq_buf *s, const char *str); + extern int seq_buf_putc(struct seq_buf *s, unsigned char c); + extern int seq_buf_putmem(struct seq_buf *s, const void *mem, unsigned int len); +diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h +index 31d3d747a9db78..ceb56b39c70f77 100644 +--- a/include/linux/spinlock.h ++++ b/include/linux/spinlock.h +@@ -507,6 +507,8 @@ DEFINE_LOCK_GUARD_1(raw_spinlock, raw_spinlock_t, + raw_spin_lock(_T->lock), + raw_spin_unlock(_T->lock)) + ++DEFINE_LOCK_GUARD_1_COND(raw_spinlock, _try, raw_spin_trylock(_T->lock)) ++ + DEFINE_LOCK_GUARD_1(raw_spinlock_nested, raw_spinlock_t, + raw_spin_lock_nested(_T->lock, SINGLE_DEPTH_NESTING), + raw_spin_unlock(_T->lock)) +@@ -515,23 +517,36 @@ DEFINE_LOCK_GUARD_1(raw_spinlock_irq, raw_spinlock_t, + raw_spin_lock_irq(_T->lock), + raw_spin_unlock_irq(_T->lock)) + ++DEFINE_LOCK_GUARD_1_COND(raw_spinlock_irq, _try, raw_spin_trylock_irq(_T->lock)) ++ + DEFINE_LOCK_GUARD_1(raw_spinlock_irqsave, raw_spinlock_t, + raw_spin_lock_irqsave(_T->lock, _T->flags), + raw_spin_unlock_irqrestore(_T->lock, _T->flags), + unsigned long flags) + ++DEFINE_LOCK_GUARD_1_COND(raw_spinlock_irqsave, _try, ++ raw_spin_trylock_irqsave(_T->lock, _T->flags)) ++ + DEFINE_LOCK_GUARD_1(spinlock, spinlock_t, + spin_lock(_T->lock), + spin_unlock(_T->lock)) + ++DEFINE_LOCK_GUARD_1_COND(spinlock, _try, spin_trylock(_T->lock)) ++ + DEFINE_LOCK_GUARD_1(spinlock_irq, spinlock_t, + spin_lock_irq(_T->lock), + spin_unlock_irq(_T->lock)) + ++DEFINE_LOCK_GUARD_1_COND(spinlock_irq, _try, ++ spin_trylock_irq(_T->lock)) ++ + DEFINE_LOCK_GUARD_1(spinlock_irqsave, spinlock_t, + spin_lock_irqsave(_T->lock, _T->flags), + spin_unlock_irqrestore(_T->lock, _T->flags), + unsigned long flags) + ++DEFINE_LOCK_GUARD_1_COND(spinlock_irqsave, _try, ++ spin_trylock_irqsave(_T->lock, _T->flags)) ++ + #undef __LINUX_INSIDE_SPINLOCK_H + #endif /* __LINUX_SPINLOCK_H */ +diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h +index 9df2524fff33ae..aa1bc417266208 100644 +--- a/include/linux/trace_events.h ++++ b/include/linux/trace_events.h +@@ -279,7 +279,8 @@ struct trace_event_fields { + const char *name; + const int size; + const int align; +- const int is_signed; ++ const unsigned int is_signed:1; ++ unsigned int needs_test:1; + const int filter_type; + const int len; + }; +@@ -331,6 +332,7 @@ enum { + TRACE_EVENT_FL_EPROBE_BIT, + TRACE_EVENT_FL_FPROBE_BIT, + TRACE_EVENT_FL_CUSTOM_BIT, ++ TRACE_EVENT_FL_TEST_STR_BIT, + }; + + /* +@@ -348,6 +350,7 @@ enum { + * CUSTOM - Event is a custom event (to be attached to an exsiting tracepoint) + * This is set when the custom event has not been attached + * to a tracepoint yet, then it is cleared when it is. ++ * TEST_STR - The event has a "%s" that points to a string outside the event + */ + enum { + TRACE_EVENT_FL_FILTERED = (1 << TRACE_EVENT_FL_FILTERED_BIT), +@@ -361,6 +364,7 @@ enum { + TRACE_EVENT_FL_EPROBE = (1 << TRACE_EVENT_FL_EPROBE_BIT), + TRACE_EVENT_FL_FPROBE = (1 << TRACE_EVENT_FL_FPROBE_BIT), + TRACE_EVENT_FL_CUSTOM = (1 << TRACE_EVENT_FL_CUSTOM_BIT), ++ TRACE_EVENT_FL_TEST_STR = (1 << TRACE_EVENT_FL_TEST_STR_BIT), + }; + + #define TRACE_EVENT_FL_UKPROBE (TRACE_EVENT_FL_KPROBE | TRACE_EVENT_FL_UPROBE) +diff --git a/include/linux/trace_seq.h b/include/linux/trace_seq.h +index 6be92bf559fe7c..3691e0e76a1a20 100644 +--- a/include/linux/trace_seq.h ++++ b/include/linux/trace_seq.h +@@ -14,6 +14,7 @@ + struct trace_seq { + char buffer[PAGE_SIZE]; + struct seq_buf seq; ++ size_t readpos; + int full; + }; + +@@ -22,6 +23,7 @@ trace_seq_init(struct trace_seq *s) + { + seq_buf_init(&s->seq, s->buffer, PAGE_SIZE); + s->full = 0; ++ s->readpos = 0; + } + + /** +diff --git a/include/linux/usb/chipidea.h b/include/linux/usb/chipidea.h +index 0b4f2d5faa080d..ebdfef124b2bc0 100644 +--- a/include/linux/usb/chipidea.h ++++ b/include/linux/usb/chipidea.h +@@ -64,6 +64,8 @@ struct ci_hdrc_platform_data { + #define CI_HDRC_PMQOS BIT(15) + #define CI_HDRC_PHY_VBUS_CONTROL BIT(16) + #define CI_HDRC_HAS_PORTSC_PEC_MISSED BIT(17) ++#define CI_HDRC_FORCE_VBUS_ACTIVE_ALWAYS BIT(18) ++#define CI_HDRC_HAS_SHORT_PKT_LIMIT BIT(19) + enum usb_dr_mode dr_mode; + #define CI_HDRC_CONTROLLER_RESET_EVENT 0 + #define CI_HDRC_CONTROLLER_STOPPED_EVENT 1 +diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h +index e9214ccfde2d72..4fcee6b734b74c 100644 +--- a/include/net/bluetooth/hci_core.h ++++ b/include/net/bluetooth/hci_core.h +@@ -800,7 +800,6 @@ struct hci_conn_params { + extern struct list_head hci_dev_list; + extern struct list_head hci_cb_list; + extern rwlock_t hci_dev_list_lock; +-extern struct mutex hci_cb_list_lock; + + #define hci_dev_set_flag(hdev, nr) set_bit((nr), (hdev)->dev_flags) + #define hci_dev_clear_flag(hdev, nr) clear_bit((nr), (hdev)->dev_flags) +@@ -1949,24 +1948,47 @@ struct hci_cb { + + char *name; + ++ bool (*match) (struct hci_conn *conn); + void (*connect_cfm) (struct hci_conn *conn, __u8 status); + void (*disconn_cfm) (struct hci_conn *conn, __u8 status); + void (*security_cfm) (struct hci_conn *conn, __u8 status, +- __u8 encrypt); ++ __u8 encrypt); + void (*key_change_cfm) (struct hci_conn *conn, __u8 status); + void (*role_switch_cfm) (struct hci_conn *conn, __u8 status, __u8 role); + }; + ++static inline void hci_cb_lookup(struct hci_conn *conn, struct list_head *list) ++{ ++ struct hci_cb *cb, *cpy; ++ ++ rcu_read_lock(); ++ list_for_each_entry_rcu(cb, &hci_cb_list, list) { ++ if (cb->match && cb->match(conn)) { ++ cpy = kmalloc(sizeof(*cpy), GFP_ATOMIC); ++ if (!cpy) ++ break; ++ ++ *cpy = *cb; ++ INIT_LIST_HEAD(&cpy->list); ++ list_add_rcu(&cpy->list, list); ++ } ++ } ++ rcu_read_unlock(); ++} ++ + static inline void hci_connect_cfm(struct hci_conn *conn, __u8 status) + { +- struct hci_cb *cb; ++ struct list_head list; ++ struct hci_cb *cb, *tmp; ++ ++ INIT_LIST_HEAD(&list); ++ hci_cb_lookup(conn, &list); + +- mutex_lock(&hci_cb_list_lock); +- list_for_each_entry(cb, &hci_cb_list, list) { ++ list_for_each_entry_safe(cb, tmp, &list, list) { + if (cb->connect_cfm) + cb->connect_cfm(conn, status); ++ kfree(cb); + } +- mutex_unlock(&hci_cb_list_lock); + + if (conn->connect_cfm_cb) + conn->connect_cfm_cb(conn, status); +@@ -1974,43 +1996,55 @@ static inline void hci_connect_cfm(struct hci_conn *conn, __u8 status) + + static inline void hci_disconn_cfm(struct hci_conn *conn, __u8 reason) + { +- struct hci_cb *cb; ++ struct list_head list; ++ struct hci_cb *cb, *tmp; ++ ++ INIT_LIST_HEAD(&list); ++ hci_cb_lookup(conn, &list); + +- mutex_lock(&hci_cb_list_lock); +- list_for_each_entry(cb, &hci_cb_list, list) { ++ list_for_each_entry_safe(cb, tmp, &list, list) { + if (cb->disconn_cfm) + cb->disconn_cfm(conn, reason); ++ kfree(cb); + } +- mutex_unlock(&hci_cb_list_lock); + + if (conn->disconn_cfm_cb) + conn->disconn_cfm_cb(conn, reason); + } + +-static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status) ++static inline void hci_security_cfm(struct hci_conn *conn, __u8 status, ++ __u8 encrypt) + { +- struct hci_cb *cb; +- __u8 encrypt; +- +- if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) +- return; ++ struct list_head list; ++ struct hci_cb *cb, *tmp; + +- encrypt = test_bit(HCI_CONN_ENCRYPT, &conn->flags) ? 0x01 : 0x00; ++ INIT_LIST_HEAD(&list); ++ hci_cb_lookup(conn, &list); + +- mutex_lock(&hci_cb_list_lock); +- list_for_each_entry(cb, &hci_cb_list, list) { ++ list_for_each_entry_safe(cb, tmp, &list, list) { + if (cb->security_cfm) + cb->security_cfm(conn, status, encrypt); ++ kfree(cb); + } +- mutex_unlock(&hci_cb_list_lock); + + if (conn->security_cfm_cb) + conn->security_cfm_cb(conn, status); + } + ++static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status) ++{ ++ __u8 encrypt; ++ ++ if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) ++ return; ++ ++ encrypt = test_bit(HCI_CONN_ENCRYPT, &conn->flags) ? 0x01 : 0x00; ++ ++ hci_security_cfm(conn, status, encrypt); ++} ++ + static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status) + { +- struct hci_cb *cb; + __u8 encrypt; + + if (conn->state == BT_CONFIG) { +@@ -2037,40 +2071,38 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status) + conn->sec_level = conn->pending_sec_level; + } + +- mutex_lock(&hci_cb_list_lock); +- list_for_each_entry(cb, &hci_cb_list, list) { +- if (cb->security_cfm) +- cb->security_cfm(conn, status, encrypt); +- } +- mutex_unlock(&hci_cb_list_lock); +- +- if (conn->security_cfm_cb) +- conn->security_cfm_cb(conn, status); ++ hci_security_cfm(conn, status, encrypt); + } + + static inline void hci_key_change_cfm(struct hci_conn *conn, __u8 status) + { +- struct hci_cb *cb; ++ struct list_head list; ++ struct hci_cb *cb, *tmp; ++ ++ INIT_LIST_HEAD(&list); ++ hci_cb_lookup(conn, &list); + +- mutex_lock(&hci_cb_list_lock); +- list_for_each_entry(cb, &hci_cb_list, list) { ++ list_for_each_entry_safe(cb, tmp, &list, list) { + if (cb->key_change_cfm) + cb->key_change_cfm(conn, status); ++ kfree(cb); + } +- mutex_unlock(&hci_cb_list_lock); + } + + static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status, + __u8 role) + { +- struct hci_cb *cb; ++ struct list_head list; ++ struct hci_cb *cb, *tmp; ++ ++ INIT_LIST_HEAD(&list); ++ hci_cb_lookup(conn, &list); + +- mutex_lock(&hci_cb_list_lock); +- list_for_each_entry(cb, &hci_cb_list, list) { ++ list_for_each_entry_safe(cb, tmp, &list, list) { + if (cb->role_switch_cfm) + cb->role_switch_cfm(conn, status, role); ++ kfree(cb); + } +- mutex_unlock(&hci_cb_list_lock); + } + + static inline bool hci_bdaddr_is_rpa(bdaddr_t *bdaddr, u8 addr_type) +diff --git a/include/net/mac80211.h b/include/net/mac80211.h +index 47ade676565dbc..835a58ce9ca57c 100644 +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -3039,6 +3039,19 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw, + */ + void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb); + ++/** ++ * ieee80211_purge_tx_queue - purge TX skb queue ++ * @hw: the hardware ++ * @skbs: the skbs ++ * ++ * Free a set of transmit skbs. Use this function when device is going to stop ++ * but some transmit skbs without TX status are still queued. ++ * This function does not take the list lock and the caller must hold the ++ * relevant locks to use it. ++ */ ++void ieee80211_purge_tx_queue(struct ieee80211_hw *hw, ++ struct sk_buff_head *skbs); ++ + /** + * DOC: Hardware crypto acceleration + * +@@ -6067,6 +6080,24 @@ void ieee80211_iterate_stations_atomic(struct ieee80211_hw *hw, + void (*iterator)(void *data, + struct ieee80211_sta *sta), + void *data); ++ ++/** ++ * ieee80211_iterate_stations_mtx - iterate stations ++ * ++ * This function iterates over all stations associated with a given ++ * hardware that are currently uploaded to the driver and calls the callback ++ * function for them. This version can only be used while holding the wiphy ++ * mutex. ++ * ++ * @hw: the hardware struct of which the interfaces should be iterated over ++ * @iterator: the iterator function to call ++ * @data: first argument of the iterator function ++ */ ++void ieee80211_iterate_stations_mtx(struct ieee80211_hw *hw, ++ void (*iterator)(void *data, ++ struct ieee80211_sta *sta), ++ void *data); ++ + /** + * ieee80211_queue_work - add work onto the mac80211 workqueue + * +diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h +index b5f9ee5810a347..8321915dddb284 100644 +--- a/include/net/netfilter/nf_tables.h ++++ b/include/net/netfilter/nf_tables.h +@@ -721,15 +721,18 @@ struct nft_set_ext_tmpl { + /** + * struct nft_set_ext - set extensions + * +- * @genmask: generation mask ++ * @genmask: generation mask, but also flags (see NFT_SET_ELEM_DEAD_BIT) + * @offset: offsets of individual extension types + * @data: beginning of extension data ++ * ++ * This structure must be aligned to word size, otherwise atomic bitops ++ * on genmask field can cause alignment failure on some archs. + */ + struct nft_set_ext { + u8 genmask; + u8 offset[NFT_SET_EXT_NUM]; + char data[]; +-}; ++} __aligned(BITS_PER_LONG / 8); + + static inline void nft_set_ext_prepare(struct nft_set_ext_tmpl *tmpl) + { +diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c +index 58ee17f429a33a..02f327f05fd619 100644 +--- a/kernel/bpf/core.c ++++ b/kernel/bpf/core.c +@@ -529,6 +529,8 @@ struct bpf_prog *bpf_patch_insn_single(struct bpf_prog *prog, u32 off, + + int bpf_remove_insns(struct bpf_prog *prog, u32 off, u32 cnt) + { ++ int err; ++ + /* Branch offsets can't overflow when program is shrinking, no need + * to call bpf_adj_branches(..., true) here + */ +@@ -536,7 +538,9 @@ int bpf_remove_insns(struct bpf_prog *prog, u32 off, u32 cnt) + sizeof(struct bpf_insn) * (prog->len - off - cnt)); + prog->len -= cnt; + +- return WARN_ON_ONCE(bpf_adj_branches(prog, off, off + cnt, off, false)); ++ err = bpf_adj_branches(prog, off, off + cnt, off, false); ++ WARN_ON_ONCE(err); ++ return err; + } + + static void bpf_prog_kallsyms_del_subprogs(struct bpf_prog *fp) +diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c +index a3c3c66ca04759..d6a4102312fadd 100644 +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -1762,8 +1762,8 @@ static int copy_verifier_state(struct bpf_verifier_state *dst_state, + int i, err; + + dst_state->jmp_history = copy_array(dst_state->jmp_history, src->jmp_history, +- src->jmp_history_cnt, sizeof(*dst_state->jmp_history), +- GFP_USER); ++ src->jmp_history_cnt, sizeof(struct bpf_idx_pair), ++ GFP_USER); + if (!dst_state->jmp_history) + return -ENOMEM; + dst_state->jmp_history_cnt = src->jmp_history_cnt; +@@ -3397,21 +3397,6 @@ static int check_reg_arg(struct bpf_verifier_env *env, u32 regno, + return __check_reg_arg(env, state->regs, regno, t); + } + +-static int insn_stack_access_flags(int frameno, int spi) +-{ +- return INSN_F_STACK_ACCESS | (spi << INSN_F_SPI_SHIFT) | frameno; +-} +- +-static int insn_stack_access_spi(int insn_flags) +-{ +- return (insn_flags >> INSN_F_SPI_SHIFT) & INSN_F_SPI_MASK; +-} +- +-static int insn_stack_access_frameno(int insn_flags) +-{ +- return insn_flags & INSN_F_FRAMENO_MASK; +-} +- + static void mark_jmp_point(struct bpf_verifier_env *env, int idx) + { + env->insn_aux_data[idx].jmp_point = true; +@@ -3423,51 +3408,28 @@ static bool is_jmp_point(struct bpf_verifier_env *env, int insn_idx) + } + + /* for any branch, call, exit record the history of jmps in the given state */ +-static int push_jmp_history(struct bpf_verifier_env *env, struct bpf_verifier_state *cur, +- int insn_flags) ++static int push_jmp_history(struct bpf_verifier_env *env, ++ struct bpf_verifier_state *cur) + { + u32 cnt = cur->jmp_history_cnt; +- struct bpf_jmp_history_entry *p; ++ struct bpf_idx_pair *p; + size_t alloc_size; + +- /* combine instruction flags if we already recorded this instruction */ +- if (env->cur_hist_ent) { +- /* atomic instructions push insn_flags twice, for READ and +- * WRITE sides, but they should agree on stack slot +- */ +- WARN_ONCE((env->cur_hist_ent->flags & insn_flags) && +- (env->cur_hist_ent->flags & insn_flags) != insn_flags, +- "verifier insn history bug: insn_idx %d cur flags %x new flags %x\n", +- env->insn_idx, env->cur_hist_ent->flags, insn_flags); +- env->cur_hist_ent->flags |= insn_flags; ++ if (!is_jmp_point(env, env->insn_idx)) + return 0; +- } + + cnt++; + alloc_size = kmalloc_size_roundup(size_mul(cnt, sizeof(*p))); + p = krealloc(cur->jmp_history, alloc_size, GFP_USER); + if (!p) + return -ENOMEM; ++ p[cnt - 1].idx = env->insn_idx; ++ p[cnt - 1].prev_idx = env->prev_insn_idx; + cur->jmp_history = p; +- +- p = &cur->jmp_history[cnt - 1]; +- p->idx = env->insn_idx; +- p->prev_idx = env->prev_insn_idx; +- p->flags = insn_flags; + cur->jmp_history_cnt = cnt; +- env->cur_hist_ent = p; +- + return 0; + } + +-static struct bpf_jmp_history_entry *get_jmp_hist_entry(struct bpf_verifier_state *st, +- u32 hist_end, int insn_idx) +-{ +- if (hist_end > 0 && st->jmp_history[hist_end - 1].idx == insn_idx) +- return &st->jmp_history[hist_end - 1]; +- return NULL; +-} +- + /* Backtrack one insn at a time. If idx is not at the top of recorded + * history then previous instruction came from straight line execution. + * Return -ENOENT if we exhausted all instructions within given state. +@@ -3629,14 +3591,9 @@ static inline bool bt_is_reg_set(struct backtrack_state *bt, u32 reg) + return bt->reg_masks[bt->frame] & (1 << reg); + } + +-static inline bool bt_is_frame_slot_set(struct backtrack_state *bt, u32 frame, u32 slot) +-{ +- return bt->stack_masks[frame] & (1ull << slot); +-} +- + static inline bool bt_is_slot_set(struct backtrack_state *bt, u32 slot) + { +- return bt_is_frame_slot_set(bt, bt->frame, slot); ++ return bt->stack_masks[bt->frame] & (1ull << slot); + } + + /* format registers bitmask, e.g., "r0,r2,r4" for 0x15 mask */ +@@ -3690,7 +3647,7 @@ static bool calls_callback(struct bpf_verifier_env *env, int insn_idx); + * - *was* processed previously during backtracking. + */ + static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx, +- struct bpf_jmp_history_entry *hist, struct backtrack_state *bt) ++ struct backtrack_state *bt) + { + const struct bpf_insn_cbs cbs = { + .cb_call = disasm_kfunc_name, +@@ -3703,7 +3660,7 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx, + u8 mode = BPF_MODE(insn->code); + u32 dreg = insn->dst_reg; + u32 sreg = insn->src_reg; +- u32 spi, i, fr; ++ u32 spi, i; + + if (insn->code == 0) + return 0; +@@ -3766,15 +3723,20 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx, + * by 'precise' mark in corresponding register of this state. + * No further tracking necessary. + */ +- if (!hist || !(hist->flags & INSN_F_STACK_ACCESS)) ++ if (insn->src_reg != BPF_REG_FP) + return 0; ++ + /* dreg = *(u64 *)[fp - off] was a fill from the stack. + * that [fp - off] slot contains scalar that needs to be + * tracked with precision + */ +- spi = insn_stack_access_spi(hist->flags); +- fr = insn_stack_access_frameno(hist->flags); +- bt_set_frame_slot(bt, fr, spi); ++ spi = (-insn->off - 1) / BPF_REG_SIZE; ++ if (spi >= 64) { ++ verbose(env, "BUG spi %d\n", spi); ++ WARN_ONCE(1, "verifier backtracking bug"); ++ return -EFAULT; ++ } ++ bt_set_slot(bt, spi); + } else if (class == BPF_STX || class == BPF_ST) { + if (bt_is_reg_set(bt, dreg)) + /* stx & st shouldn't be using _scalar_ dst_reg +@@ -3783,13 +3745,17 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx, + */ + return -ENOTSUPP; + /* scalars can only be spilled into stack */ +- if (!hist || !(hist->flags & INSN_F_STACK_ACCESS)) ++ if (insn->dst_reg != BPF_REG_FP) + return 0; +- spi = insn_stack_access_spi(hist->flags); +- fr = insn_stack_access_frameno(hist->flags); +- if (!bt_is_frame_slot_set(bt, fr, spi)) ++ spi = (-insn->off - 1) / BPF_REG_SIZE; ++ if (spi >= 64) { ++ verbose(env, "BUG spi %d\n", spi); ++ WARN_ONCE(1, "verifier backtracking bug"); ++ return -EFAULT; ++ } ++ if (!bt_is_slot_set(bt, spi)) + return 0; +- bt_clear_frame_slot(bt, fr, spi); ++ bt_clear_slot(bt, spi); + if (class == BPF_STX) + bt_set_reg(bt, sreg); + } else if (class == BPF_JMP || class == BPF_JMP32) { +@@ -3833,14 +3799,10 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx, + WARN_ONCE(1, "verifier backtracking bug"); + return -EFAULT; + } +- /* we are now tracking register spills correctly, +- * so any instance of leftover slots is a bug +- */ +- if (bt_stack_mask(bt) != 0) { +- verbose(env, "BUG stack slots %llx\n", bt_stack_mask(bt)); +- WARN_ONCE(1, "verifier backtracking bug (subprog leftover stack slots)"); +- return -EFAULT; +- } ++ /* we don't track register spills perfectly, ++ * so fallback to force-precise instead of failing */ ++ if (bt_stack_mask(bt) != 0) ++ return -ENOTSUPP; + /* propagate r1-r5 to the caller */ + for (i = BPF_REG_1; i <= BPF_REG_5; i++) { + if (bt_is_reg_set(bt, i)) { +@@ -3865,11 +3827,8 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx, + WARN_ONCE(1, "verifier backtracking bug"); + return -EFAULT; + } +- if (bt_stack_mask(bt) != 0) { +- verbose(env, "BUG stack slots %llx\n", bt_stack_mask(bt)); +- WARN_ONCE(1, "verifier backtracking bug (callback leftover stack slots)"); +- return -EFAULT; +- } ++ if (bt_stack_mask(bt) != 0) ++ return -ENOTSUPP; + /* clear r1-r5 in callback subprog's mask */ + for (i = BPF_REG_1; i <= BPF_REG_5; i++) + bt_clear_reg(bt, i); +@@ -4306,7 +4265,6 @@ static int __mark_chain_precision(struct bpf_verifier_env *env, int regno) + for (;;) { + DECLARE_BITMAP(mask, 64); + u32 history = st->jmp_history_cnt; +- struct bpf_jmp_history_entry *hist; + + if (env->log.level & BPF_LOG_LEVEL2) { + verbose(env, "mark_precise: frame%d: last_idx %d first_idx %d subseq_idx %d \n", +@@ -4370,8 +4328,7 @@ static int __mark_chain_precision(struct bpf_verifier_env *env, int regno) + err = 0; + skip_first = false; + } else { +- hist = get_jmp_hist_entry(st, history, i); +- err = backtrack_insn(env, i, subseq_idx, hist, bt); ++ err = backtrack_insn(env, i, subseq_idx, bt); + } + if (err == -ENOTSUPP) { + mark_all_scalars_precise(env, env->cur_state); +@@ -4424,10 +4381,22 @@ static int __mark_chain_precision(struct bpf_verifier_env *env, int regno) + bitmap_from_u64(mask, bt_frame_stack_mask(bt, fr)); + for_each_set_bit(i, mask, 64) { + if (i >= func->allocated_stack / BPF_REG_SIZE) { +- verbose(env, "BUG backtracking (stack slot %d, total slots %d)\n", +- i, func->allocated_stack / BPF_REG_SIZE); +- WARN_ONCE(1, "verifier backtracking bug (stack slot out of bounds)"); +- return -EFAULT; ++ /* the sequence of instructions: ++ * 2: (bf) r3 = r10 ++ * 3: (7b) *(u64 *)(r3 -8) = r0 ++ * 4: (79) r4 = *(u64 *)(r10 -8) ++ * doesn't contain jmps. It's backtracked ++ * as a single block. ++ * During backtracking insn 3 is not recognized as ++ * stack access, so at the end of backtracking ++ * stack slot fp-8 is still marked in stack_mask. ++ * However the parent state may not have accessed ++ * fp-8 and it's "unallocated" stack space. ++ * In such case fallback to conservative. ++ */ ++ mark_all_scalars_precise(env, env->cur_state); ++ bt_reset(bt); ++ return 0; + } + + if (!is_spilled_scalar_reg(&func->stack[i])) { +@@ -4592,7 +4561,7 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env, + int i, slot = -off - 1, spi = slot / BPF_REG_SIZE, err; + struct bpf_insn *insn = &env->prog->insnsi[insn_idx]; + struct bpf_reg_state *reg = NULL; +- int insn_flags = insn_stack_access_flags(state->frameno, spi); ++ u32 dst_reg = insn->dst_reg; + + /* caller checked that off % size == 0 and -MAX_BPF_STACK <= off < 0, + * so it's aligned access and [off, off + size) are within stack limits +@@ -4631,6 +4600,17 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env, + mark_stack_slot_scratched(env, spi); + if (reg && !(off % BPF_REG_SIZE) && register_is_bounded(reg) && + !register_is_null(reg) && env->bpf_capable) { ++ if (dst_reg != BPF_REG_FP) { ++ /* The backtracking logic can only recognize explicit ++ * stack slot address like [fp - 8]. Other spill of ++ * scalar via different register has to be conservative. ++ * Backtrack from here and mark all registers as precise ++ * that contributed into 'reg' being a constant. ++ */ ++ err = mark_chain_precision(env, value_regno); ++ if (err) ++ return err; ++ } + save_register_state(state, spi, reg, size); + /* Break the relation on a narrowing spill. */ + if (fls64(reg->umax_value) > BITS_PER_BYTE * size) +@@ -4642,7 +4622,6 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env, + __mark_reg_known(&fake_reg, insn->imm); + fake_reg.type = SCALAR_VALUE; + save_register_state(state, spi, &fake_reg, size); +- insn_flags = 0; /* not a register spill */ + } else if (reg && is_spillable_regtype(reg->type)) { + /* register containing pointer is being spilled into stack */ + if (size != BPF_REG_SIZE) { +@@ -4688,12 +4667,9 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env, + + /* Mark slots affected by this stack write. */ + for (i = 0; i < size; i++) +- state->stack[spi].slot_type[(slot - i) % BPF_REG_SIZE] = type; +- insn_flags = 0; /* not a register spill */ ++ state->stack[spi].slot_type[(slot - i) % BPF_REG_SIZE] = ++ type; + } +- +- if (insn_flags) +- return push_jmp_history(env, env->cur_state, insn_flags); + return 0; + } + +@@ -4882,7 +4858,6 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env, + int i, slot = -off - 1, spi = slot / BPF_REG_SIZE; + struct bpf_reg_state *reg; + u8 *stype, type; +- int insn_flags = insn_stack_access_flags(reg_state->frameno, spi); + + stype = reg_state->stack[spi].slot_type; + reg = ®_state->stack[spi].spilled_ptr; +@@ -4928,10 +4903,12 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env, + return -EACCES; + } + mark_reg_unknown(env, state->regs, dst_regno); +- insn_flags = 0; /* not restoring original register state */ + } + state->regs[dst_regno].live |= REG_LIVE_WRITTEN; +- } else if (dst_regno >= 0) { ++ return 0; ++ } ++ ++ if (dst_regno >= 0) { + /* restore register state from stack */ + copy_register_state(&state->regs[dst_regno], reg); + /* mark reg as written since spilled pointer state likely +@@ -4967,10 +4944,7 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env, + mark_reg_read(env, reg, reg->parent, REG_LIVE_READ64); + if (dst_regno >= 0) + mark_reg_stack_read(env, reg_state, off, off + size, dst_regno); +- insn_flags = 0; /* we are not restoring spilled register */ + } +- if (insn_flags) +- return push_jmp_history(env, env->cur_state, insn_flags); + return 0; + } + +@@ -7054,6 +7028,7 @@ static int check_atomic(struct bpf_verifier_env *env, int insn_idx, struct bpf_i + BPF_SIZE(insn->code), BPF_WRITE, -1, true, false); + if (err) + return err; ++ + return 0; + } + +@@ -16802,8 +16777,7 @@ static int is_state_visited(struct bpf_verifier_env *env, int insn_idx) + * the precision needs to be propagated back in + * the current state. + */ +- if (is_jmp_point(env, env->insn_idx)) +- err = err ? : push_jmp_history(env, cur, 0); ++ err = err ? : push_jmp_history(env, cur); + err = err ? : propagate_precision(env, &sl->state); + if (err) + return err; +@@ -17027,9 +17001,6 @@ static int do_check(struct bpf_verifier_env *env) + u8 class; + int err; + +- /* reset current history entry on each new instruction */ +- env->cur_hist_ent = NULL; +- + env->prev_insn_idx = prev_insn_idx; + if (env->insn_idx >= insn_cnt) { + verbose(env, "invalid insn idx %d insn_cnt %d\n", +@@ -17069,7 +17040,7 @@ static int do_check(struct bpf_verifier_env *env) + } + + if (is_jmp_point(env, env->insn_idx)) { +- err = push_jmp_history(env, state, 0); ++ err = push_jmp_history(env, state); + if (err) + return err; + } +diff --git a/kernel/kcov.c b/kernel/kcov.c +index 72d9aa6fb50c3e..097c8afa675578 100644 +--- a/kernel/kcov.c ++++ b/kernel/kcov.c +@@ -165,7 +165,7 @@ static void kcov_remote_area_put(struct kcov_remote_area *area, + * Unlike in_serving_softirq(), this function returns false when called during + * a hardirq or an NMI that happened in the softirq context. + */ +-static inline bool in_softirq_really(void) ++static __always_inline bool in_softirq_really(void) + { + return in_serving_softirq() && !in_hardirq() && !in_nmi(); + } +diff --git a/kernel/sched/core.c b/kernel/sched/core.c +index 228f7c07da7284..86606fb9e6bc6c 100644 +--- a/kernel/sched/core.c ++++ b/kernel/sched/core.c +@@ -4488,7 +4488,8 @@ int wake_up_state(struct task_struct *p, unsigned int state) + * Perform scheduler related setup for a newly forked process p. + * p is forked by current. + * +- * __sched_fork() is basic setup used by init_idle() too: ++ * __sched_fork() is basic setup which is also used by sched_init() to ++ * initialize the boot CPU's idle task. + */ + static void __sched_fork(unsigned long clone_flags, struct task_struct *p) + { +@@ -9257,8 +9258,6 @@ void __init init_idle(struct task_struct *idle, int cpu) + struct rq *rq = cpu_rq(cpu); + unsigned long flags; + +- __sched_fork(0, idle); +- + raw_spin_lock_irqsave(&idle->pi_lock, flags); + raw_spin_rq_lock(rq); + +@@ -9273,10 +9272,8 @@ void __init init_idle(struct task_struct *idle, int cpu) + + #ifdef CONFIG_SMP + /* +- * It's possible that init_idle() gets called multiple times on a task, +- * in that case do_set_cpus_allowed() will not do the right thing. +- * +- * And since this is boot we can forgo the serialization. ++ * No validation and serialization required at boot time and for ++ * setting up the idle tasks of not yet online CPUs. + */ + set_cpus_allowed_common(idle, &ac); + #endif +@@ -10105,6 +10102,7 @@ void __init sched_init(void) + * but because we are the idle thread, we just pick up running again + * when this runqueue becomes "idle". + */ ++ __sched_fork(0, current); + init_idle(current, smp_processor_id()); + + calc_load_update = jiffies + LOAD_FREQ; +diff --git a/kernel/softirq.c b/kernel/softirq.c +index bd9716d7bb6383..f24d80cf20bd35 100644 +--- a/kernel/softirq.c ++++ b/kernel/softirq.c +@@ -279,17 +279,24 @@ static inline void invoke_softirq(void) + wakeup_softirqd(); + } + ++#define SCHED_SOFTIRQ_MASK BIT(SCHED_SOFTIRQ) ++ + /* + * flush_smp_call_function_queue() can raise a soft interrupt in a function +- * call. On RT kernels this is undesired and the only known functionality +- * in the block layer which does this is disabled on RT. If soft interrupts +- * get raised which haven't been raised before the flush, warn so it can be ++ * call. On RT kernels this is undesired and the only known functionalities ++ * are in the block layer which is disabled on RT, and in the scheduler for ++ * idle load balancing. If soft interrupts get raised which haven't been ++ * raised before the flush, warn if it is not a SCHED_SOFTIRQ so it can be + * investigated. + */ + void do_softirq_post_smp_call_flush(unsigned int was_pending) + { +- if (WARN_ON_ONCE(was_pending != local_softirq_pending())) ++ unsigned int is_pending = local_softirq_pending(); ++ ++ if (unlikely(was_pending != is_pending)) { ++ WARN_ON_ONCE(was_pending != (is_pending & ~SCHED_SOFTIRQ_MASK)); + invoke_softirq(); ++ } + } + + #else /* CONFIG_PREEMPT_RT */ +diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c +index 220903117c5139..9d9af60b238e27 100644 +--- a/kernel/trace/trace.c ++++ b/kernel/trace/trace.c +@@ -1731,15 +1731,15 @@ static ssize_t trace_seq_to_buffer(struct trace_seq *s, void *buf, size_t cnt) + { + int len; + +- if (trace_seq_used(s) <= s->seq.readpos) ++ if (trace_seq_used(s) <= s->readpos) + return -EBUSY; + +- len = trace_seq_used(s) - s->seq.readpos; ++ len = trace_seq_used(s) - s->readpos; + if (cnt > len) + cnt = len; +- memcpy(buf, s->buffer + s->seq.readpos, cnt); ++ memcpy(buf, s->buffer + s->readpos, cnt); + +- s->seq.readpos += cnt; ++ s->readpos += cnt; + return cnt; + } + +@@ -3760,17 +3760,12 @@ char *trace_iter_expand_format(struct trace_iterator *iter) + } + + /* Returns true if the string is safe to dereference from an event */ +-static bool trace_safe_str(struct trace_iterator *iter, const char *str, +- bool star, int len) ++static bool trace_safe_str(struct trace_iterator *iter, const char *str) + { + unsigned long addr = (unsigned long)str; + struct trace_event *trace_event; + struct trace_event_call *event; + +- /* Ignore strings with no length */ +- if (star && !len) +- return true; +- + /* OK if part of the event data */ + if ((addr >= (unsigned long)iter->ent) && + (addr < (unsigned long)iter->ent + iter->ent_size)) +@@ -3810,142 +3805,69 @@ static bool trace_safe_str(struct trace_iterator *iter, const char *str, + return false; + } + +-static const char *show_buffer(struct trace_seq *s) +-{ +- struct seq_buf *seq = &s->seq; +- +- seq_buf_terminate(seq); +- +- return seq->buffer; +-} +- +-static DEFINE_STATIC_KEY_FALSE(trace_no_verify); +- +-static int test_can_verify_check(const char *fmt, ...) +-{ +- char buf[16]; +- va_list ap; +- int ret; +- +- /* +- * The verifier is dependent on vsnprintf() modifies the va_list +- * passed to it, where it is sent as a reference. Some architectures +- * (like x86_32) passes it by value, which means that vsnprintf() +- * does not modify the va_list passed to it, and the verifier +- * would then need to be able to understand all the values that +- * vsnprintf can use. If it is passed by value, then the verifier +- * is disabled. +- */ +- va_start(ap, fmt); +- vsnprintf(buf, 16, "%d", ap); +- ret = va_arg(ap, int); +- va_end(ap); +- +- return ret; +-} +- +-static void test_can_verify(void) +-{ +- if (!test_can_verify_check("%d %d", 0, 1)) { +- pr_info("trace event string verifier disabled\n"); +- static_branch_inc(&trace_no_verify); +- } +-} +- + /** +- * trace_check_vprintf - Check dereferenced strings while writing to the seq buffer ++ * ignore_event - Check dereferenced fields while writing to the seq buffer + * @iter: The iterator that holds the seq buffer and the event being printed +- * @fmt: The format used to print the event +- * @ap: The va_list holding the data to print from @fmt. + * +- * This writes the data into the @iter->seq buffer using the data from +- * @fmt and @ap. If the format has a %s, then the source of the string +- * is examined to make sure it is safe to print, otherwise it will +- * warn and print "[UNSAFE MEMORY]" in place of the dereferenced string +- * pointer. ++ * At boot up, test_event_printk() will flag any event that dereferences ++ * a string with "%s" that does exist in the ring buffer. It may still ++ * be valid, as the string may point to a static string in the kernel ++ * rodata that never gets freed. But if the string pointer is pointing ++ * to something that was allocated, there's a chance that it can be freed ++ * by the time the user reads the trace. This would cause a bad memory ++ * access by the kernel and possibly crash the system. ++ * ++ * This function will check if the event has any fields flagged as needing ++ * to be checked at runtime and perform those checks. ++ * ++ * If it is found that a field is unsafe, it will write into the @iter->seq ++ * a message stating what was found to be unsafe. ++ * ++ * @return: true if the event is unsafe and should be ignored, ++ * false otherwise. + */ +-void trace_check_vprintf(struct trace_iterator *iter, const char *fmt, +- va_list ap) ++bool ignore_event(struct trace_iterator *iter) + { +- const char *p = fmt; +- const char *str; +- int i, j; ++ struct ftrace_event_field *field; ++ struct trace_event *trace_event; ++ struct trace_event_call *event; ++ struct list_head *head; ++ struct trace_seq *seq; ++ const void *ptr; + +- if (WARN_ON_ONCE(!fmt)) +- return; ++ trace_event = ftrace_find_event(iter->ent->type); + +- if (static_branch_unlikely(&trace_no_verify)) +- goto print; ++ seq = &iter->seq; + +- /* Don't bother checking when doing a ftrace_dump() */ +- if (iter->fmt == static_fmt_buf) +- goto print; ++ if (!trace_event) { ++ trace_seq_printf(seq, "EVENT ID %d NOT FOUND?\n", iter->ent->type); ++ return true; ++ } + +- while (*p) { +- bool star = false; +- int len = 0; +- +- j = 0; +- +- /* We only care about %s and variants */ +- for (i = 0; p[i]; i++) { +- if (i + 1 >= iter->fmt_size) { +- /* +- * If we can't expand the copy buffer, +- * just print it. +- */ +- if (!trace_iter_expand_format(iter)) +- goto print; +- } ++ event = container_of(trace_event, struct trace_event_call, event); ++ if (!(event->flags & TRACE_EVENT_FL_TEST_STR)) ++ return false; + +- if (p[i] == '\\' && p[i+1]) { +- i++; +- continue; +- } +- if (p[i] == '%') { +- /* Need to test cases like %08.*s */ +- for (j = 1; p[i+j]; j++) { +- if (isdigit(p[i+j]) || +- p[i+j] == '.') +- continue; +- if (p[i+j] == '*') { +- star = true; +- continue; +- } +- break; +- } +- if (p[i+j] == 's') +- break; +- star = false; +- } +- j = 0; +- } +- /* If no %s found then just print normally */ +- if (!p[i]) +- break; ++ head = trace_get_fields(event); ++ if (!head) { ++ trace_seq_printf(seq, "FIELDS FOR EVENT '%s' NOT FOUND?\n", ++ trace_event_name(event)); ++ return true; ++ } + +- /* Copy up to the %s, and print that */ +- strncpy(iter->fmt, p, i); +- iter->fmt[i] = '\0'; +- trace_seq_vprintf(&iter->seq, iter->fmt, ap); ++ /* Offsets are from the iter->ent that points to the raw event */ ++ ptr = iter->ent; + +- /* +- * If iter->seq is full, the above call no longer guarantees +- * that ap is in sync with fmt processing, and further calls +- * to va_arg() can return wrong positional arguments. +- * +- * Ensure that ap is no longer used in this case. +- */ +- if (iter->seq.full) { +- p = ""; +- break; +- } ++ list_for_each_entry(field, head, link) { ++ const char *str; ++ bool good; ++ ++ if (!field->needs_test) ++ continue; + +- if (star) +- len = va_arg(ap, int); ++ str = *(const char **)(ptr + field->offset); + +- /* The ap now points to the string data of the %s */ +- str = va_arg(ap, const char *); ++ good = trace_safe_str(iter, str); + + /* + * If you hit this warning, it is likely that the +@@ -3956,45 +3878,14 @@ void trace_check_vprintf(struct trace_iterator *iter, const char *fmt, + * instead. See samples/trace_events/trace-events-sample.h + * for reference. + */ +- if (WARN_ONCE(!trace_safe_str(iter, str, star, len), +- "fmt: '%s' current_buffer: '%s'", +- fmt, show_buffer(&iter->seq))) { +- int ret; +- +- /* Try to safely read the string */ +- if (star) { +- if (len + 1 > iter->fmt_size) +- len = iter->fmt_size - 1; +- if (len < 0) +- len = 0; +- ret = copy_from_kernel_nofault(iter->fmt, str, len); +- iter->fmt[len] = 0; +- star = false; +- } else { +- ret = strncpy_from_kernel_nofault(iter->fmt, str, +- iter->fmt_size); +- } +- if (ret < 0) +- trace_seq_printf(&iter->seq, "(0x%px)", str); +- else +- trace_seq_printf(&iter->seq, "(0x%px:%s)", +- str, iter->fmt); +- str = "[UNSAFE-MEMORY]"; +- strcpy(iter->fmt, "%s"); +- } else { +- strncpy(iter->fmt, p + i, j + 1); +- iter->fmt[j+1] = '\0'; ++ if (WARN_ONCE(!good, "event '%s' has unsafe pointer field '%s'", ++ trace_event_name(event), field->name)) { ++ trace_seq_printf(seq, "EVENT %s: HAS UNSAFE POINTER FIELD '%s'\n", ++ trace_event_name(event), field->name); ++ return true; + } +- if (star) +- trace_seq_printf(&iter->seq, iter->fmt, len, str); +- else +- trace_seq_printf(&iter->seq, iter->fmt, str); +- +- p += i + j + 1; + } +- print: +- if (*p) +- trace_seq_vprintf(&iter->seq, p, ap); ++ return false; + } + + const char *trace_event_format(struct trace_iterator *iter, const char *fmt) +@@ -7011,7 +6902,7 @@ tracing_read_pipe(struct file *filp, char __user *ubuf, + + /* Now copy what we have to the user */ + sret = trace_seq_to_user(&iter->seq, ubuf, cnt); +- if (iter->seq.seq.readpos >= trace_seq_used(&iter->seq)) ++ if (iter->seq.readpos >= trace_seq_used(&iter->seq)) + trace_seq_init(&iter->seq); + + /* +@@ -10539,8 +10430,6 @@ __init static int tracer_alloc_buffers(void) + + register_snapshot_cmd(); + +- test_can_verify(); +- + return 0; + + out_free_pipe_cpumask: +diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h +index 3db42bae73f8e0..e45756f1ac2b12 100644 +--- a/kernel/trace/trace.h ++++ b/kernel/trace/trace.h +@@ -644,9 +644,8 @@ void trace_buffer_unlock_commit_nostack(struct trace_buffer *buffer, + + bool trace_is_tracepoint_string(const char *str); + const char *trace_event_format(struct trace_iterator *iter, const char *fmt); +-void trace_check_vprintf(struct trace_iterator *iter, const char *fmt, +- va_list ap) __printf(2, 0); + char *trace_iter_expand_format(struct trace_iterator *iter); ++bool ignore_event(struct trace_iterator *iter); + + int trace_empty(struct trace_iterator *iter); + +@@ -1323,7 +1322,8 @@ struct ftrace_event_field { + int filter_type; + int offset; + int size; +- int is_signed; ++ unsigned int is_signed:1; ++ unsigned int needs_test:1; + int len; + }; + +diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c +index 64cd856308e77c..9d22745cdea5aa 100644 +--- a/kernel/trace/trace_events.c ++++ b/kernel/trace/trace_events.c +@@ -82,7 +82,7 @@ static int system_refcount_dec(struct event_subsystem *system) + } + + static struct ftrace_event_field * +-__find_event_field(struct list_head *head, char *name) ++__find_event_field(struct list_head *head, const char *name) + { + struct ftrace_event_field *field; + +@@ -114,7 +114,8 @@ trace_find_event_field(struct trace_event_call *call, char *name) + + static int __trace_define_field(struct list_head *head, const char *type, + const char *name, int offset, int size, +- int is_signed, int filter_type, int len) ++ int is_signed, int filter_type, int len, ++ int need_test) + { + struct ftrace_event_field *field; + +@@ -133,6 +134,7 @@ static int __trace_define_field(struct list_head *head, const char *type, + field->offset = offset; + field->size = size; + field->is_signed = is_signed; ++ field->needs_test = need_test; + field->len = len; + + list_add(&field->link, head); +@@ -151,13 +153,13 @@ int trace_define_field(struct trace_event_call *call, const char *type, + + head = trace_get_fields(call); + return __trace_define_field(head, type, name, offset, size, +- is_signed, filter_type, 0); ++ is_signed, filter_type, 0, 0); + } + EXPORT_SYMBOL_GPL(trace_define_field); + + static int trace_define_field_ext(struct trace_event_call *call, const char *type, + const char *name, int offset, int size, int is_signed, +- int filter_type, int len) ++ int filter_type, int len, int need_test) + { + struct list_head *head; + +@@ -166,13 +168,13 @@ static int trace_define_field_ext(struct trace_event_call *call, const char *typ + + head = trace_get_fields(call); + return __trace_define_field(head, type, name, offset, size, +- is_signed, filter_type, len); ++ is_signed, filter_type, len, need_test); + } + + #define __generic_field(type, item, filter_type) \ + ret = __trace_define_field(&ftrace_generic_fields, #type, \ + #item, 0, 0, is_signed_type(type), \ +- filter_type, 0); \ ++ filter_type, 0, 0); \ + if (ret) \ + return ret; + +@@ -181,7 +183,8 @@ static int trace_define_field_ext(struct trace_event_call *call, const char *typ + "common_" #item, \ + offsetof(typeof(ent), item), \ + sizeof(ent.item), \ +- is_signed_type(type), FILTER_OTHER, 0); \ ++ is_signed_type(type), FILTER_OTHER, \ ++ 0, 0); \ + if (ret) \ + return ret; + +@@ -332,6 +335,7 @@ static bool process_pointer(const char *fmt, int len, struct trace_event_call *c + /* Return true if the string is safe */ + static bool process_string(const char *fmt, int len, struct trace_event_call *call) + { ++ struct trace_event_fields *field; + const char *r, *e, *s; + + e = fmt + len; +@@ -360,6 +364,18 @@ static bool process_string(const char *fmt, int len, struct trace_event_call *ca + s = r + 1; + } while (s < e); + ++ /* ++ * Check for arrays. If the argument has: foo[REC->val] ++ * then it is very likely that foo is an array of strings ++ * that are safe to use. ++ */ ++ r = strstr(s, "["); ++ if (r && r < e) { ++ r = strstr(r, "REC->"); ++ if (r && r < e) ++ return true; ++ } ++ + /* + * If there's any strings in the argument consider this arg OK as it + * could be: REC->field ? "foo" : "bar" and we don't want to get into +@@ -372,8 +388,16 @@ static bool process_string(const char *fmt, int len, struct trace_event_call *ca + if (process_pointer(fmt, len, call)) + return true; + +- /* Make sure the field is found, and consider it OK for now if it is */ +- return find_event_field(fmt, call) != NULL; ++ /* Make sure the field is found */ ++ field = find_event_field(fmt, call); ++ if (!field) ++ return false; ++ ++ /* Test this field's string before printing the event */ ++ call->flags |= TRACE_EVENT_FL_TEST_STR; ++ field->needs_test = 1; ++ ++ return true; + } + + /* +@@ -2552,7 +2576,7 @@ event_define_fields(struct trace_event_call *call) + ret = trace_define_field_ext(call, field->type, field->name, + offset, field->size, + field->is_signed, field->filter_type, +- field->len); ++ field->len, field->needs_test); + if (WARN_ON_ONCE(ret)) { + pr_err("error code is %d\n", ret); + break; +diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c +index db575094c49825..2b948d35fb59ea 100644 +--- a/kernel/trace/trace_output.c ++++ b/kernel/trace/trace_output.c +@@ -317,10 +317,14 @@ EXPORT_SYMBOL(trace_raw_output_prep); + + void trace_event_printf(struct trace_iterator *iter, const char *fmt, ...) + { ++ struct trace_seq *s = &iter->seq; + va_list ap; + ++ if (ignore_event(iter)) ++ return; ++ + va_start(ap, fmt); +- trace_check_vprintf(iter, trace_event_format(iter, fmt), ap); ++ trace_seq_vprintf(s, trace_event_format(iter, fmt), ap); + va_end(ap); + } + EXPORT_SYMBOL(trace_event_printf); +diff --git a/kernel/trace/trace_seq.c b/kernel/trace/trace_seq.c +index bac06ee3b98b81..7be97229ddf860 100644 +--- a/kernel/trace/trace_seq.c ++++ b/kernel/trace/trace_seq.c +@@ -370,8 +370,12 @@ EXPORT_SYMBOL_GPL(trace_seq_path); + */ + int trace_seq_to_user(struct trace_seq *s, char __user *ubuf, int cnt) + { ++ int ret; + __trace_seq_init(s); +- return seq_buf_to_user(&s->seq, ubuf, cnt); ++ ret = seq_buf_to_user(&s->seq, ubuf, s->readpos, cnt); ++ if (ret > 0) ++ s->readpos += ret; ++ return ret; + } + EXPORT_SYMBOL_GPL(trace_seq_to_user); + +diff --git a/lib/seq_buf.c b/lib/seq_buf.c +index 45c450f423fa87..23518f77ea9c53 100644 +--- a/lib/seq_buf.c ++++ b/lib/seq_buf.c +@@ -109,9 +109,7 @@ void seq_buf_do_printk(struct seq_buf *s, const char *lvl) + if (s->size == 0 || s->len == 0) + return; + +- seq_buf_terminate(s); +- +- start = s->buffer; ++ start = seq_buf_str(s); + while ((lf = strchr(start, '\n'))) { + int len = lf - start + 1; + +@@ -324,23 +322,24 @@ int seq_buf_path(struct seq_buf *s, const struct path *path, const char *esc) + * seq_buf_to_user - copy the sequence buffer to user space + * @s: seq_buf descriptor + * @ubuf: The userspace memory location to copy to ++ * @start: The first byte in the buffer to copy + * @cnt: The amount to copy + * + * Copies the sequence buffer into the userspace memory pointed to +- * by @ubuf. It starts from the last read position (@s->readpos) +- * and writes up to @cnt characters or till it reaches the end of +- * the content in the buffer (@s->len), which ever comes first. ++ * by @ubuf. It starts from @start and writes up to @cnt characters ++ * or until it reaches the end of the content in the buffer (@s->len), ++ * whichever comes first. + * + * On success, it returns a positive number of the number of bytes + * it copied. + * + * On failure it returns -EBUSY if all of the content in the + * sequence has been already read, which includes nothing in the +- * sequence (@s->len == @s->readpos). ++ * sequence (@s->len == @start). + * + * Returns -EFAULT if the copy to userspace fails. + */ +-int seq_buf_to_user(struct seq_buf *s, char __user *ubuf, int cnt) ++int seq_buf_to_user(struct seq_buf *s, char __user *ubuf, size_t start, int cnt) + { + int len; + int ret; +@@ -350,20 +349,17 @@ int seq_buf_to_user(struct seq_buf *s, char __user *ubuf, int cnt) + + len = seq_buf_used(s); + +- if (len <= s->readpos) ++ if (len <= start) + return -EBUSY; + +- len -= s->readpos; ++ len -= start; + if (cnt > len) + cnt = len; +- ret = copy_to_user(ubuf, s->buffer + s->readpos, cnt); ++ ret = copy_to_user(ubuf, s->buffer + start, cnt); + if (ret == cnt) + return -EFAULT; + +- cnt -= ret; +- +- s->readpos += cnt; +- return cnt; ++ return cnt - ret; + } + + /** +diff --git a/mm/kmemleak.c b/mm/kmemleak.c +index 54c2c90d3abc9d..5811a11cc53a6d 100644 +--- a/mm/kmemleak.c ++++ b/mm/kmemleak.c +@@ -368,7 +368,7 @@ static void print_unreferenced(struct seq_file *seq, + + for (i = 0; i < nr_entries; i++) { + void *ptr = (void *)entries[i]; +- warn_or_seq_printf(seq, " [<%pK>] %pS\n", ptr, ptr); ++ warn_or_seq_printf(seq, " %pS\n", ptr); + } + } + +diff --git a/mm/memblock.c b/mm/memblock.c +index d630f5c2bdb90e..87a2b4340ce4ea 100644 +--- a/mm/memblock.c ++++ b/mm/memblock.c +@@ -735,6 +735,40 @@ int __init_memblock memblock_add(phys_addr_t base, phys_addr_t size) + return memblock_add_range(&memblock.memory, base, size, MAX_NUMNODES, 0); + } + ++/** ++ * memblock_validate_numa_coverage - check if amount of memory with ++ * no node ID assigned is less than a threshold ++ * @threshold_bytes: maximal memory size that can have unassigned node ++ * ID (in bytes). ++ * ++ * A buggy firmware may report memory that does not belong to any node. ++ * Check if amount of such memory is below @threshold_bytes. ++ * ++ * Return: true on success, false on failure. ++ */ ++bool __init_memblock memblock_validate_numa_coverage(unsigned long threshold_bytes) ++{ ++ unsigned long nr_pages = 0; ++ unsigned long start_pfn, end_pfn, mem_size_mb; ++ int nid, i; ++ ++ /* calculate lose page */ ++ for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, &nid) { ++ if (nid == NUMA_NO_NODE) ++ nr_pages += end_pfn - start_pfn; ++ } ++ ++ if ((nr_pages << PAGE_SHIFT) > threshold_bytes) { ++ mem_size_mb = memblock_phys_mem_size() >> 20; ++ pr_err("NUMA: no nodes coverage for %luMB of %luMB RAM\n", ++ (nr_pages << PAGE_SHIFT) >> 20, mem_size_mb); ++ return false; ++ } ++ ++ return true; ++} ++ ++ + /** + * memblock_isolate_range - isolate given range into disjoint memblocks + * @type: memblock type to isolate range for +diff --git a/mm/readahead.c b/mm/readahead.c +index e9b11d928b0c48..f1595c032ce7e3 100644 +--- a/mm/readahead.c ++++ b/mm/readahead.c +@@ -580,7 +580,11 @@ static void ondemand_readahead(struct readahead_control *ractl, + 1UL << order); + if (index == expected || index == (ra->start + ra->size)) { + ra->start += ra->size; +- ra->size = get_next_ra_size(ra, max_pages); ++ /* ++ * In the case of MADV_HUGEPAGE, the actual size might exceed ++ * the readahead window. ++ */ ++ ra->size = max(ra->size, get_next_ra_size(ra, max_pages)); + ra->async_size = ra->size; + goto readit; + } +diff --git a/mm/vmscan.c b/mm/vmscan.c +index 3c91b86d59e935..49456b72575529 100644 +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -641,7 +641,14 @@ unsigned long zone_reclaimable_pages(struct zone *zone) + if (can_reclaim_anon_pages(NULL, zone_to_nid(zone), NULL)) + nr += zone_page_state_snapshot(zone, NR_ZONE_INACTIVE_ANON) + + zone_page_state_snapshot(zone, NR_ZONE_ACTIVE_ANON); +- ++ /* ++ * If there are no reclaimable file-backed or anonymous pages, ++ * ensure zones with sufficient free pages are not skipped. ++ * This prevents zones like DMA32 from being ignored in reclaim ++ * scenarios where they can still help alleviate memory pressure. ++ */ ++ if (nr == 0) ++ nr = zone_page_state_snapshot(zone, NR_FREE_PAGES); + return nr; + } + +diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c +index 6178ae8feafc0f..549ee9e87d6366 100644 +--- a/net/bluetooth/hci_conn.c ++++ b/net/bluetooth/hci_conn.c +@@ -2178,13 +2178,9 @@ struct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst, + conn->iso_qos.bcast.big); + if (parent && parent != conn) { + link = hci_conn_link(parent, conn); +- if (!link) { +- hci_conn_drop(conn); +- return ERR_PTR(-ENOLINK); +- } +- +- /* Link takes the refcount */ + hci_conn_drop(conn); ++ if (!link) ++ return ERR_PTR(-ENOLINK); + } + + return conn; +@@ -2274,15 +2270,12 @@ struct hci_conn *hci_connect_cis(struct hci_dev *hdev, bdaddr_t *dst, + } + + link = hci_conn_link(le, cis); ++ hci_conn_drop(cis); + if (!link) { + hci_conn_drop(le); +- hci_conn_drop(cis); + return ERR_PTR(-ENOLINK); + } + +- /* Link takes the refcount */ +- hci_conn_drop(cis); +- + cis->state = BT_CONNECT; + + hci_le_create_cis_pending(hdev); +diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c +index 30519d47e8a695..f29fd326440115 100644 +--- a/net/bluetooth/hci_core.c ++++ b/net/bluetooth/hci_core.c +@@ -58,7 +58,6 @@ DEFINE_RWLOCK(hci_dev_list_lock); + + /* HCI callback list */ + LIST_HEAD(hci_cb_list); +-DEFINE_MUTEX(hci_cb_list_lock); + + /* HCI ID Numbering */ + static DEFINE_IDA(hci_index_ida); +@@ -2957,9 +2956,7 @@ int hci_register_cb(struct hci_cb *cb) + { + BT_DBG("%p name %s", cb, cb->name); + +- mutex_lock(&hci_cb_list_lock); +- list_add_tail(&cb->list, &hci_cb_list); +- mutex_unlock(&hci_cb_list_lock); ++ list_add_tail_rcu(&cb->list, &hci_cb_list); + + return 0; + } +@@ -2969,9 +2966,8 @@ int hci_unregister_cb(struct hci_cb *cb) + { + BT_DBG("%p name %s", cb, cb->name); + +- mutex_lock(&hci_cb_list_lock); +- list_del(&cb->list); +- mutex_unlock(&hci_cb_list_lock); ++ list_del_rcu(&cb->list); ++ synchronize_rcu(); + + return 0; + } +diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c +index b94d202bf3745c..f165cafa3aa98b 100644 +--- a/net/bluetooth/iso.c ++++ b/net/bluetooth/iso.c +@@ -1929,6 +1929,11 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags) + return lm; + } + ++static bool iso_match(struct hci_conn *hcon) ++{ ++ return hcon->type == ISO_LINK || hcon->type == LE_LINK; ++} ++ + static void iso_connect_cfm(struct hci_conn *hcon, __u8 status) + { + if (hcon->type != ISO_LINK) { +@@ -2110,6 +2115,7 @@ void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) + + static struct hci_cb iso_cb = { + .name = "ISO", ++ .match = iso_match, + .connect_cfm = iso_connect_cfm, + .disconn_cfm = iso_disconn_cfm, + }; +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 93651c421767a0..acb148759bd049 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -7223,6 +7223,11 @@ static struct l2cap_chan *l2cap_global_fixed_chan(struct l2cap_chan *c, + return NULL; + } + ++static bool l2cap_match(struct hci_conn *hcon) ++{ ++ return hcon->type == ACL_LINK || hcon->type == LE_LINK; ++} ++ + static void l2cap_connect_cfm(struct hci_conn *hcon, u8 status) + { + struct hci_dev *hdev = hcon->hdev; +@@ -7230,9 +7235,6 @@ static void l2cap_connect_cfm(struct hci_conn *hcon, u8 status) + struct l2cap_chan *pchan; + u8 dst_type; + +- if (hcon->type != ACL_LINK && hcon->type != LE_LINK) +- return; +- + BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status); + + if (status) { +@@ -7297,9 +7299,6 @@ int l2cap_disconn_ind(struct hci_conn *hcon) + + static void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) + { +- if (hcon->type != ACL_LINK && hcon->type != LE_LINK) +- return; +- + BT_DBG("hcon %p reason %d", hcon, reason); + + l2cap_conn_del(hcon, bt_to_errno(reason)); +@@ -7578,6 +7577,7 @@ void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) + + static struct hci_cb l2cap_cb = { + .name = "L2CAP", ++ .match = l2cap_match, + .connect_cfm = l2cap_connect_cfm, + .disconn_cfm = l2cap_disconn_cfm, + .security_cfm = l2cap_security_cfm, +diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c +index 1d34d849703329..9d46afb24caf07 100644 +--- a/net/bluetooth/rfcomm/core.c ++++ b/net/bluetooth/rfcomm/core.c +@@ -2134,6 +2134,11 @@ static int rfcomm_run(void *unused) + return 0; + } + ++static bool rfcomm_match(struct hci_conn *hcon) ++{ ++ return hcon->type == ACL_LINK; ++} ++ + static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt) + { + struct rfcomm_session *s; +@@ -2180,6 +2185,7 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt) + + static struct hci_cb rfcomm_cb = { + .name = "RFCOMM", ++ .match = rfcomm_match, + .security_cfm = rfcomm_security_cfm + }; + +diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c +index 64d4d57c7033a3..c4c36ff25fb202 100644 +--- a/net/bluetooth/sco.c ++++ b/net/bluetooth/sco.c +@@ -1353,11 +1353,13 @@ int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags) + return lm; + } + +-static void sco_connect_cfm(struct hci_conn *hcon, __u8 status) ++static bool sco_match(struct hci_conn *hcon) + { +- if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK) +- return; ++ return hcon->type == SCO_LINK || hcon->type == ESCO_LINK; ++} + ++static void sco_connect_cfm(struct hci_conn *hcon, __u8 status) ++{ + BT_DBG("hcon %p bdaddr %pMR status %u", hcon, &hcon->dst, status); + + if (!status) { +@@ -1372,9 +1374,6 @@ static void sco_connect_cfm(struct hci_conn *hcon, __u8 status) + + static void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason) + { +- if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK) +- return; +- + BT_DBG("hcon %p reason %d", hcon, reason); + + sco_conn_del(hcon, bt_to_errno(reason)); +@@ -1400,6 +1399,7 @@ void sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb) + + static struct hci_cb sco_cb = { + .name = "SCO", ++ .match = sco_match, + .connect_cfm = sco_connect_cfm, + .disconn_cfm = sco_disconn_cfm, + }; +diff --git a/net/core/dev.c b/net/core/dev.c +index 4beb9acf2c1839..69da7b009f8b98 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -3628,8 +3628,10 @@ int skb_csum_hwoffload_help(struct sk_buff *skb, + + if (features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)) { + if (vlan_get_protocol(skb) == htons(ETH_P_IPV6) && +- skb_network_header_len(skb) != sizeof(struct ipv6hdr)) ++ skb_network_header_len(skb) != sizeof(struct ipv6hdr) && ++ !ipv6_has_hopopt_jumbo(skb)) + goto sw_checksum; ++ + switch (skb->csum_offset) { + case offsetof(struct tcphdr, check): + case offsetof(struct udphdr, check): +diff --git a/net/core/sock.c b/net/core/sock.c +index bc2a4e38dcea8e..84ba3f67bca97b 100644 +--- a/net/core/sock.c ++++ b/net/core/sock.c +@@ -1133,7 +1133,10 @@ int sk_setsockopt(struct sock *sk, int level, int optname, + sk->sk_reuse = (valbool ? SK_CAN_REUSE : SK_NO_REUSE); + break; + case SO_REUSEPORT: +- sk->sk_reuseport = valbool; ++ if (valbool && !sk_is_inet(sk)) ++ ret = -EOPNOTSUPP; ++ else ++ sk->sk_reuseport = valbool; + break; + case SO_TYPE: + case SO_PROTOCOL: +diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c +index 72b2d68ef4da5f..dd1803bf9c5c63 100644 +--- a/net/ipv4/ip_tunnel.c ++++ b/net/ipv4/ip_tunnel.c +@@ -43,6 +43,7 @@ + #include + #include + #include ++#include + + #if IS_ENABLED(CONFIG_IPV6) + #include +@@ -102,10 +103,9 @@ struct ip_tunnel *ip_tunnel_lookup(struct ip_tunnel_net *itn, + if (!ip_tunnel_key_match(&t->parms, flags, key)) + continue; + +- if (t->parms.link == link) ++ if (READ_ONCE(t->parms.link) == link) + return t; +- else +- cand = t; ++ cand = t; + } + + hlist_for_each_entry_rcu(t, head, hash_node) { +@@ -117,9 +117,9 @@ struct ip_tunnel *ip_tunnel_lookup(struct ip_tunnel_net *itn, + if (!ip_tunnel_key_match(&t->parms, flags, key)) + continue; + +- if (t->parms.link == link) ++ if (READ_ONCE(t->parms.link) == link) + return t; +- else if (!cand) ++ if (!cand) + cand = t; + } + +@@ -137,9 +137,9 @@ struct ip_tunnel *ip_tunnel_lookup(struct ip_tunnel_net *itn, + if (!ip_tunnel_key_match(&t->parms, flags, key)) + continue; + +- if (t->parms.link == link) ++ if (READ_ONCE(t->parms.link) == link) + return t; +- else if (!cand) ++ if (!cand) + cand = t; + } + +@@ -150,9 +150,9 @@ struct ip_tunnel *ip_tunnel_lookup(struct ip_tunnel_net *itn, + !(t->dev->flags & IFF_UP)) + continue; + +- if (t->parms.link == link) ++ if (READ_ONCE(t->parms.link) == link) + return t; +- else if (!cand) ++ if (!cand) + cand = t; + } + +@@ -221,7 +221,7 @@ static struct ip_tunnel *ip_tunnel_find(struct ip_tunnel_net *itn, + hlist_for_each_entry_rcu(t, head, hash_node) { + if (local == t->parms.iph.saddr && + remote == t->parms.iph.daddr && +- link == t->parms.link && ++ link == READ_ONCE(t->parms.link) && + type == t->dev->type && + ip_tunnel_key_match(&t->parms, flags, key)) + break; +@@ -294,7 +294,7 @@ static int ip_tunnel_bind_dev(struct net_device *dev) + + ip_tunnel_init_flow(&fl4, iph->protocol, iph->daddr, + iph->saddr, tunnel->parms.o_key, +- RT_TOS(iph->tos), dev_net(dev), ++ iph->tos & INET_DSCP_MASK, tunnel->net, + tunnel->parms.link, tunnel->fwmark, 0, 0); + rt = ip_route_output_key(tunnel->net, &fl4); + +@@ -610,9 +610,9 @@ void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, + tos = ipv6_get_dsfield((const struct ipv6hdr *)inner_iph); + } + ip_tunnel_init_flow(&fl4, proto, key->u.ipv4.dst, key->u.ipv4.src, +- tunnel_id_to_key32(key->tun_id), RT_TOS(tos), +- dev_net(dev), 0, skb->mark, skb_get_hash(skb), +- key->flow_flags); ++ tunnel_id_to_key32(key->tun_id), ++ tos & INET_DSCP_MASK, tunnel->net, 0, skb->mark, ++ skb_get_hash(skb), key->flow_flags); + + if (!tunnel_hlen) + tunnel_hlen = ip_encap_hlen(&tun_info->encap); +@@ -773,8 +773,8 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, + } + + ip_tunnel_init_flow(&fl4, protocol, dst, tnl_params->saddr, +- tunnel->parms.o_key, RT_TOS(tos), +- dev_net(dev), tunnel->parms.link, ++ tunnel->parms.o_key, tos & INET_DSCP_MASK, ++ tunnel->net, READ_ONCE(tunnel->parms.link), + tunnel->fwmark, skb_get_hash(skb), 0); + + if (ip_tunnel_encap(skb, &tunnel->encap, &protocol, &fl4) < 0) +@@ -894,7 +894,7 @@ static void ip_tunnel_update(struct ip_tunnel_net *itn, + if (t->parms.link != p->link || t->fwmark != fwmark) { + int mtu; + +- t->parms.link = p->link; ++ WRITE_ONCE(t->parms.link, p->link); + t->fwmark = fwmark; + mtu = ip_tunnel_bind_dev(dev); + if (set_mtu) +@@ -1084,9 +1084,9 @@ EXPORT_SYMBOL(ip_tunnel_get_link_net); + + int ip_tunnel_get_iflink(const struct net_device *dev) + { +- struct ip_tunnel *tunnel = netdev_priv(dev); ++ const struct ip_tunnel *tunnel = netdev_priv(dev); + +- return tunnel->parms.link; ++ return READ_ONCE(tunnel->parms.link); + } + EXPORT_SYMBOL(ip_tunnel_get_iflink); + +diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +index fb053942dba2a1..f6a213bae5cccb 100644 +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -7192,6 +7192,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops, + if (unlikely(!inet_csk_reqsk_queue_hash_add(sk, req, + req->timeout))) { + reqsk_free(req); ++ dst_release(dst); + return 0; + } + +diff --git a/net/ipv6/ila/ila_xlat.c b/net/ipv6/ila/ila_xlat.c +index 534a4498e280d7..fff09f5a796a75 100644 +--- a/net/ipv6/ila/ila_xlat.c ++++ b/net/ipv6/ila/ila_xlat.c +@@ -200,6 +200,8 @@ static const struct nf_hook_ops ila_nf_hook_ops[] = { + }, + }; + ++static DEFINE_MUTEX(ila_mutex); ++ + static int ila_add_mapping(struct net *net, struct ila_xlat_params *xp) + { + struct ila_net *ilan = net_generic(net, ila_net_id); +@@ -207,16 +209,20 @@ static int ila_add_mapping(struct net *net, struct ila_xlat_params *xp) + spinlock_t *lock = ila_get_lock(ilan, xp->ip.locator_match); + int err = 0, order; + +- if (!ilan->xlat.hooks_registered) { ++ if (!READ_ONCE(ilan->xlat.hooks_registered)) { + /* We defer registering net hooks in the namespace until the + * first mapping is added. + */ +- err = nf_register_net_hooks(net, ila_nf_hook_ops, +- ARRAY_SIZE(ila_nf_hook_ops)); ++ mutex_lock(&ila_mutex); ++ if (!ilan->xlat.hooks_registered) { ++ err = nf_register_net_hooks(net, ila_nf_hook_ops, ++ ARRAY_SIZE(ila_nf_hook_ops)); ++ if (!err) ++ WRITE_ONCE(ilan->xlat.hooks_registered, true); ++ } ++ mutex_unlock(&ila_mutex); + if (err) + return err; +- +- ilan->xlat.hooks_registered = true; + } + + ila = kzalloc(sizeof(*ila), GFP_KERNEL); +diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c +index 51bccfb00a9cd9..61b0159b2fbee6 100644 +--- a/net/llc/llc_input.c ++++ b/net/llc/llc_input.c +@@ -124,8 +124,8 @@ static inline int llc_fixup_skb(struct sk_buff *skb) + if (unlikely(!pskb_may_pull(skb, llc_len))) + return 0; + +- skb->transport_header += llc_len; + skb_pull(skb, llc_len); ++ skb_reset_transport_header(skb); + if (skb->protocol == htons(ETH_P_802_2)) { + __be16 pdulen; + s32 data_size; +diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h +index daea061d0fc136..04c876d78d3bf0 100644 +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -2057,8 +2057,6 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb, + u32 info_flags, + u32 ctrl_flags, + u64 *cookie); +-void ieee80211_purge_tx_queue(struct ieee80211_hw *hw, +- struct sk_buff_head *skbs); + struct sk_buff * + ieee80211_build_data_template(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb, u32 info_flags); +diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c +index 25223184d6e5b0..a5e7edd2f2d137 100644 +--- a/net/mac80211/mesh.c ++++ b/net/mac80211/mesh.c +@@ -1173,14 +1173,14 @@ void ieee80211_mbss_info_change_notify(struct ieee80211_sub_if_data *sdata, + u64 changed) + { + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; +- unsigned long bits = changed; ++ unsigned long bits[] = { BITMAP_FROM_U64(changed) }; + u32 bit; + +- if (!bits) ++ if (!changed) + return; + + /* if we race with running work, worst case this work becomes a noop */ +- for_each_set_bit(bit, &bits, sizeof(changed) * BITS_PER_BYTE) ++ for_each_set_bit(bit, bits, sizeof(changed) * BITS_PER_BYTE) + set_bit(bit, ifmsh->mbss_changed); + set_bit(MESH_WORK_MBSS_CHANGED, &ifmsh->wrkq_flags); + wiphy_work_queue(sdata->local->hw.wiphy, &sdata->work); +diff --git a/net/mac80211/status.c b/net/mac80211/status.c +index 44d83da60aee44..9676ed15efecc8 100644 +--- a/net/mac80211/status.c ++++ b/net/mac80211/status.c +@@ -1270,3 +1270,4 @@ void ieee80211_purge_tx_queue(struct ieee80211_hw *hw, + while ((skb = __skb_dequeue(skbs))) + ieee80211_free_txskb(hw, skb); + } ++EXPORT_SYMBOL(ieee80211_purge_tx_queue); +diff --git a/net/mac80211/util.c b/net/mac80211/util.c +index d682c32821a110..154b41af4157d0 100644 +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -827,7 +827,8 @@ static void __iterate_stations(struct ieee80211_local *local, + { + struct sta_info *sta; + +- list_for_each_entry_rcu(sta, &local->sta_list, list) { ++ list_for_each_entry_rcu(sta, &local->sta_list, list, ++ lockdep_is_held(&local->hw.wiphy->mtx)) { + if (!sta->uploaded) + continue; + +@@ -848,6 +849,19 @@ void ieee80211_iterate_stations_atomic(struct ieee80211_hw *hw, + } + EXPORT_SYMBOL_GPL(ieee80211_iterate_stations_atomic); + ++void ieee80211_iterate_stations_mtx(struct ieee80211_hw *hw, ++ void (*iterator)(void *data, ++ struct ieee80211_sta *sta), ++ void *data) ++{ ++ struct ieee80211_local *local = hw_to_local(hw); ++ ++ lockdep_assert_wiphy(local->hw.wiphy); ++ ++ __iterate_stations(local, iterator, data); ++} ++EXPORT_SYMBOL_GPL(ieee80211_iterate_stations_mtx); ++ + struct ieee80211_vif *wdev_to_ieee80211_vif(struct wireless_dev *wdev) + { + struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); +@@ -2572,6 +2586,9 @@ int ieee80211_reconfig(struct ieee80211_local *local) + WARN(1, "Hardware became unavailable upon resume. This could be a software issue prior to suspend or a hardware issue.\n"); + else + WARN(1, "Hardware became unavailable during restart.\n"); ++ ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP, ++ IEEE80211_QUEUE_STOP_REASON_SUSPEND, ++ false); + ieee80211_handle_reconfig_failure(local); + return res; + } +diff --git a/net/mctp/route.c b/net/mctp/route.c +index c6a815df9d358c..d3c1f54386efc1 100644 +--- a/net/mctp/route.c ++++ b/net/mctp/route.c +@@ -334,8 +334,13 @@ static int mctp_route_input(struct mctp_route *route, struct sk_buff *skb) + msk = NULL; + rc = -EINVAL; + +- /* we may be receiving a locally-routed packet; drop source sk +- * accounting ++ /* We may be receiving a locally-routed packet; drop source sk ++ * accounting. ++ * ++ * From here, we will either queue the skb - either to a frag_queue, or ++ * to a receiving socket. When that succeeds, we clear the skb pointer; ++ * a non-NULL skb on exit will be otherwise unowned, and hence ++ * kfree_skb()-ed. + */ + skb_orphan(skb); + +@@ -389,7 +394,9 @@ static int mctp_route_input(struct mctp_route *route, struct sk_buff *skb) + * pending key. + */ + if (flags & MCTP_HDR_FLAG_EOM) { +- sock_queue_rcv_skb(&msk->sk, skb); ++ rc = sock_queue_rcv_skb(&msk->sk, skb); ++ if (!rc) ++ skb = NULL; + if (key) { + /* we've hit a pending reassembly; not much we + * can do but drop it +@@ -398,7 +405,6 @@ static int mctp_route_input(struct mctp_route *route, struct sk_buff *skb) + MCTP_TRACE_KEY_REPLIED); + key = NULL; + } +- rc = 0; + goto out_unlock; + } + +@@ -425,8 +431,10 @@ static int mctp_route_input(struct mctp_route *route, struct sk_buff *skb) + * this function. + */ + rc = mctp_key_add(key, msk); +- if (!rc) ++ if (!rc) { + trace_mctp_key_acquire(key); ++ skb = NULL; ++ } + + /* we don't need to release key->lock on exit, so + * clean up here and suppress the unlock via +@@ -444,6 +452,8 @@ static int mctp_route_input(struct mctp_route *route, struct sk_buff *skb) + key = NULL; + } else { + rc = mctp_frag_queue(key, skb); ++ if (!rc) ++ skb = NULL; + } + } + +@@ -458,12 +468,19 @@ static int mctp_route_input(struct mctp_route *route, struct sk_buff *skb) + else + rc = mctp_frag_queue(key, skb); + ++ if (rc) ++ goto out_unlock; ++ ++ /* we've queued; the queue owns the skb now */ ++ skb = NULL; ++ + /* end of message? deliver to socket, and we're done with + * the reassembly/response key + */ +- if (!rc && flags & MCTP_HDR_FLAG_EOM) { +- sock_queue_rcv_skb(key->sk, key->reasm_head); +- key->reasm_head = NULL; ++ if (flags & MCTP_HDR_FLAG_EOM) { ++ rc = sock_queue_rcv_skb(key->sk, key->reasm_head); ++ if (!rc) ++ key->reasm_head = NULL; + __mctp_key_done_in(key, net, f, MCTP_TRACE_KEY_REPLIED); + key = NULL; + } +@@ -482,8 +499,7 @@ static int mctp_route_input(struct mctp_route *route, struct sk_buff *skb) + if (any_key) + mctp_key_unref(any_key); + out: +- if (rc) +- kfree_skb(skb); ++ kfree_skb(skb); + return rc; + } + +diff --git a/net/mptcp/options.c b/net/mptcp/options.c +index 2ad9006a157aef..2e1539027e6d33 100644 +--- a/net/mptcp/options.c ++++ b/net/mptcp/options.c +@@ -667,8 +667,15 @@ static bool mptcp_established_options_add_addr(struct sock *sk, struct sk_buff * + &echo, &drop_other_suboptions)) + return false; + ++ /* ++ * Later on, mptcp_write_options() will enforce mutually exclusion with ++ * DSS, bail out if such option is set and we can't drop it. ++ */ + if (drop_other_suboptions) + remaining += opt_size; ++ else if (opts->suboptions & OPTION_MPTCP_DSS) ++ return false; ++ + len = mptcp_add_addr_len(opts->addr.family, echo, !!opts->addr.port); + if (remaining < len) + return false; +diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c +index 01f6ce970918c5..07f3a9703312e5 100644 +--- a/net/mptcp/protocol.c ++++ b/net/mptcp/protocol.c +@@ -528,13 +528,13 @@ static void mptcp_send_ack(struct mptcp_sock *msk) + mptcp_subflow_send_ack(mptcp_subflow_tcp_sock(subflow)); + } + +-static void mptcp_subflow_cleanup_rbuf(struct sock *ssk) ++static void mptcp_subflow_cleanup_rbuf(struct sock *ssk, int copied) + { + bool slow; + + slow = lock_sock_fast(ssk); + if (tcp_can_send_ack(ssk)) +- tcp_cleanup_rbuf(ssk, 1); ++ tcp_cleanup_rbuf(ssk, copied); + unlock_sock_fast(ssk, slow); + } + +@@ -551,7 +551,7 @@ static bool mptcp_subflow_could_cleanup(const struct sock *ssk, bool rx_empty) + (ICSK_ACK_PUSHED2 | ICSK_ACK_PUSHED))); + } + +-static void mptcp_cleanup_rbuf(struct mptcp_sock *msk) ++static void mptcp_cleanup_rbuf(struct mptcp_sock *msk, int copied) + { + int old_space = READ_ONCE(msk->old_wspace); + struct mptcp_subflow_context *subflow; +@@ -559,14 +559,14 @@ static void mptcp_cleanup_rbuf(struct mptcp_sock *msk) + int space = __mptcp_space(sk); + bool cleanup, rx_empty; + +- cleanup = (space > 0) && (space >= (old_space << 1)); +- rx_empty = !__mptcp_rmem(sk); ++ cleanup = (space > 0) && (space >= (old_space << 1)) && copied; ++ rx_empty = !__mptcp_rmem(sk) && copied; + + mptcp_for_each_subflow(msk, subflow) { + struct sock *ssk = mptcp_subflow_tcp_sock(subflow); + + if (cleanup || mptcp_subflow_could_cleanup(ssk, rx_empty)) +- mptcp_subflow_cleanup_rbuf(ssk); ++ mptcp_subflow_cleanup_rbuf(ssk, copied); + } + } + +@@ -1902,6 +1902,8 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) + goto out; + } + ++static void mptcp_rcv_space_adjust(struct mptcp_sock *msk, int copied); ++ + static int __mptcp_recvmsg_mskq(struct mptcp_sock *msk, + struct msghdr *msg, + size_t len, int flags, +@@ -1955,6 +1957,7 @@ static int __mptcp_recvmsg_mskq(struct mptcp_sock *msk, + break; + } + ++ mptcp_rcv_space_adjust(msk, copied); + return copied; + } + +@@ -2180,9 +2183,6 @@ static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, + + copied += bytes_read; + +- /* be sure to advertise window change */ +- mptcp_cleanup_rbuf(msk); +- + if (skb_queue_empty(&msk->receive_queue) && __mptcp_move_skbs(msk)) + continue; + +@@ -2231,7 +2231,7 @@ static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, + } + + pr_debug("block timeout %ld\n", timeo); +- mptcp_rcv_space_adjust(msk, copied); ++ mptcp_cleanup_rbuf(msk, copied); + err = sk_wait_data(sk, &timeo, NULL); + if (err < 0) { + err = copied ? : err; +@@ -2239,7 +2239,7 @@ static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, + } + } + +- mptcp_rcv_space_adjust(msk, copied); ++ mptcp_cleanup_rbuf(msk, copied); + + out_err: + if (cmsg_flags && copied >= 0) { +diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c +index bd2b17b219ae90..0b270893ee14c5 100644 +--- a/net/netrom/nr_route.c ++++ b/net/netrom/nr_route.c +@@ -754,6 +754,12 @@ int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25) + int ret; + struct sk_buff *skbn; + ++ /* ++ * Reject malformed packets early. Check that it contains at least 2 ++ * addresses and 1 byte more for Time-To-Live ++ */ ++ if (skb->len < 2 * sizeof(ax25_address) + 1) ++ return 0; + + nr_src = (ax25_address *)(skb->data + 0); + nr_dest = (ax25_address *)(skb->data + 7); +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index 56e3ae3b6be93f..4abf7e9ac4f2f7 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -538,10 +538,8 @@ static void *packet_current_frame(struct packet_sock *po, + return packet_lookup_frame(po, rb, rb->head, status); + } + +-static u16 vlan_get_tci(struct sk_buff *skb, struct net_device *dev) ++static u16 vlan_get_tci(const struct sk_buff *skb, struct net_device *dev) + { +- u8 *skb_orig_data = skb->data; +- int skb_orig_len = skb->len; + struct vlan_hdr vhdr, *vh; + unsigned int header_len; + +@@ -562,33 +560,21 @@ static u16 vlan_get_tci(struct sk_buff *skb, struct net_device *dev) + else + return 0; + +- skb_push(skb, skb->data - skb_mac_header(skb)); +- vh = skb_header_pointer(skb, header_len, sizeof(vhdr), &vhdr); +- if (skb_orig_data != skb->data) { +- skb->data = skb_orig_data; +- skb->len = skb_orig_len; +- } ++ vh = skb_header_pointer(skb, skb_mac_offset(skb) + header_len, ++ sizeof(vhdr), &vhdr); + if (unlikely(!vh)) + return 0; + + return ntohs(vh->h_vlan_TCI); + } + +-static __be16 vlan_get_protocol_dgram(struct sk_buff *skb) ++static __be16 vlan_get_protocol_dgram(const struct sk_buff *skb) + { + __be16 proto = skb->protocol; + +- if (unlikely(eth_type_vlan(proto))) { +- u8 *skb_orig_data = skb->data; +- int skb_orig_len = skb->len; +- +- skb_push(skb, skb->data - skb_mac_header(skb)); +- proto = __vlan_get_protocol(skb, proto, NULL); +- if (skb_orig_data != skb->data) { +- skb->data = skb_orig_data; +- skb->len = skb_orig_len; +- } +- } ++ if (unlikely(eth_type_vlan(proto))) ++ proto = __vlan_get_protocol_offset(skb, proto, ++ skb_mac_offset(skb), NULL); + + return proto; + } +diff --git a/net/sctp/associola.c b/net/sctp/associola.c +index c45c192b787873..0b0794f164cf2e 100644 +--- a/net/sctp/associola.c ++++ b/net/sctp/associola.c +@@ -137,7 +137,8 @@ static struct sctp_association *sctp_association_init( + = 5 * asoc->rto_max; + + asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = asoc->sackdelay; +- asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] = sp->autoclose * HZ; ++ asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] = ++ (unsigned long)sp->autoclose * HZ; + + /* Initializes the timers */ + for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i) +diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c +index efbb4836ec668f..ea498eff1f2ae5 100644 +--- a/scripts/mod/file2alias.c ++++ b/scripts/mod/file2alias.c +@@ -742,8 +742,8 @@ static void do_input(char *alias, + + for (i = min / BITS_PER_LONG; i < max / BITS_PER_LONG + 1; i++) + arr[i] = TO_NATIVE(arr[i]); +- for (i = min; i < max; i++) +- if (arr[i / BITS_PER_LONG] & (1L << (i%BITS_PER_LONG))) ++ for (i = min; i <= max; i++) ++ if (arr[i / BITS_PER_LONG] & (1ULL << (i%BITS_PER_LONG))) + sprintf(alias + strlen(alias), "%X,*", i); + } + +diff --git a/scripts/sorttable.h b/scripts/sorttable.h +index 7bd0184380d3b9..a7c5445baf0027 100644 +--- a/scripts/sorttable.h ++++ b/scripts/sorttable.h +@@ -110,7 +110,7 @@ static inline unsigned long orc_ip(const int *ip) + + static int orc_sort_cmp(const void *_a, const void *_b) + { +- struct orc_entry *orc_a; ++ struct orc_entry *orc_a, *orc_b; + const int *a = g_orc_ip_table + *(int *)_a; + const int *b = g_orc_ip_table + *(int *)_b; + unsigned long a_val = orc_ip(a); +@@ -128,6 +128,9 @@ static int orc_sort_cmp(const void *_a, const void *_b) + * whitelisted .o files which didn't get objtool generation. + */ + orc_a = g_orc_table + (a - g_orc_ip_table); ++ orc_b = g_orc_table + (b - g_orc_ip_table); ++ if (orc_a->type == ORC_TYPE_UNDEFINED && orc_b->type == ORC_TYPE_UNDEFINED) ++ return 0; + return orc_a->type == ORC_TYPE_UNDEFINED ? -1 : 1; + } + +diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c +index 379ac7b5c7098c..f5eead8af2e210 100644 +--- a/security/selinux/ss/services.c ++++ b/security/selinux/ss/services.c +@@ -956,7 +956,10 @@ void services_compute_xperms_decision(struct extended_perms_decision *xpermd, + xpermd->driver)) + return; + } else { +- BUG(); ++ pr_warn_once( ++ "SELinux: unknown extended permission (%u) will be ignored\n", ++ node->datum.u.xperms->specified); ++ return; + } + + if (node->key.specified == AVTAB_XPERMS_ALLOWED) { +@@ -993,7 +996,8 @@ void services_compute_xperms_decision(struct extended_perms_decision *xpermd, + node->datum.u.xperms->perms.p[i]; + } + } else { +- BUG(); ++ pr_warn_once("SELinux: unknown specified key (%u)\n", ++ node->key.specified); + } + } + +diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c +index e3394919daa09a..51ee4c00a84310 100644 +--- a/sound/core/seq/oss/seq_oss_synth.c ++++ b/sound/core/seq/oss/seq_oss_synth.c +@@ -66,6 +66,7 @@ static struct seq_oss_synth midi_synth_dev = { + }; + + static DEFINE_SPINLOCK(register_lock); ++static DEFINE_MUTEX(sysex_mutex); + + /* + * prototypes +@@ -497,6 +498,7 @@ snd_seq_oss_synth_sysex(struct seq_oss_devinfo *dp, int dev, unsigned char *buf, + if (!info) + return -ENXIO; + ++ guard(mutex)(&sysex_mutex); + sysex = info->sysex; + if (sysex == NULL) { + sysex = kzalloc(sizeof(*sysex), GFP_KERNEL); +diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c +index e115fe18363495..8b7dfbc8e82075 100644 +--- a/sound/core/seq/seq_clientmgr.c ++++ b/sound/core/seq/seq_clientmgr.c +@@ -1280,10 +1280,16 @@ static int snd_seq_ioctl_set_client_info(struct snd_seq_client *client, + if (client->type != client_info->type) + return -EINVAL; + +- /* check validity of midi_version field */ +- if (client->user_pversion >= SNDRV_PROTOCOL_VERSION(1, 0, 3) && +- client_info->midi_version > SNDRV_SEQ_CLIENT_UMP_MIDI_2_0) +- return -EINVAL; ++ if (client->user_pversion >= SNDRV_PROTOCOL_VERSION(1, 0, 3)) { ++ /* check validity of midi_version field */ ++ if (client_info->midi_version > SNDRV_SEQ_CLIENT_UMP_MIDI_2_0) ++ return -EINVAL; ++ ++ /* check if UMP is supported in kernel */ ++ if (!IS_ENABLED(CONFIG_SND_SEQ_UMP) && ++ client_info->midi_version > 0) ++ return -EINVAL; ++ } + + /* fill the info fields */ + if (client_info->name[0]) +diff --git a/sound/core/ump.c b/sound/core/ump.c +index 83856b2f88b89f..32d27e58416aa3 100644 +--- a/sound/core/ump.c ++++ b/sound/core/ump.c +@@ -37,6 +37,7 @@ static int process_legacy_output(struct snd_ump_endpoint *ump, + u32 *buffer, int count); + static void process_legacy_input(struct snd_ump_endpoint *ump, const u32 *src, + int words); ++static void update_legacy_names(struct snd_ump_endpoint *ump); + #else + static inline int process_legacy_output(struct snd_ump_endpoint *ump, + u32 *buffer, int count) +@@ -47,6 +48,9 @@ static inline void process_legacy_input(struct snd_ump_endpoint *ump, + const u32 *src, int words) + { + } ++static inline void update_legacy_names(struct snd_ump_endpoint *ump) ++{ ++} + #endif + + static const struct snd_rawmidi_global_ops snd_ump_rawmidi_ops = { +@@ -850,6 +854,7 @@ static int ump_handle_fb_info_msg(struct snd_ump_endpoint *ump, + fill_fb_info(ump, &fb->info, buf); + if (ump->parsed) { + snd_ump_update_group_attrs(ump); ++ update_legacy_names(ump); + seq_notify_fb_change(ump, fb); + } + } +@@ -882,6 +887,7 @@ static int ump_handle_fb_name_msg(struct snd_ump_endpoint *ump, + /* notify the FB name update to sequencer, too */ + if (ret > 0 && ump->parsed) { + snd_ump_update_group_attrs(ump); ++ update_legacy_names(ump); + seq_notify_fb_change(ump, fb); + } + return ret; +@@ -1076,13 +1082,13 @@ static int snd_ump_legacy_open(struct snd_rawmidi_substream *substream) + struct snd_ump_endpoint *ump = substream->rmidi->private_data; + int dir = substream->stream; + int group = ump->legacy_mapping[substream->number]; +- int err = 0; ++ int err; + +- mutex_lock(&ump->open_mutex); +- if (ump->legacy_substreams[dir][group]) { +- err = -EBUSY; +- goto unlock; +- } ++ guard(mutex)(&ump->open_mutex); ++ if (ump->legacy_substreams[dir][group]) ++ return -EBUSY; ++ if (!ump->groups[group].active) ++ return -ENODEV; + if (dir == SNDRV_RAWMIDI_STREAM_OUTPUT) { + if (!ump->legacy_out_opens) { + err = snd_rawmidi_kernel_open(&ump->core, 0, +@@ -1090,17 +1096,14 @@ static int snd_ump_legacy_open(struct snd_rawmidi_substream *substream) + SNDRV_RAWMIDI_LFLG_APPEND, + &ump->legacy_out_rfile); + if (err < 0) +- goto unlock; ++ return err; + } + ump->legacy_out_opens++; + snd_ump_convert_reset(&ump->out_cvts[group]); + } +- spin_lock_irq(&ump->legacy_locks[dir]); ++ guard(spinlock_irq)(&ump->legacy_locks[dir]); + ump->legacy_substreams[dir][group] = substream; +- spin_unlock_irq(&ump->legacy_locks[dir]); +- unlock: +- mutex_unlock(&ump->open_mutex); +- return err; ++ return 0; + } + + static int snd_ump_legacy_close(struct snd_rawmidi_substream *substream) +@@ -1109,15 +1112,13 @@ static int snd_ump_legacy_close(struct snd_rawmidi_substream *substream) + int dir = substream->stream; + int group = ump->legacy_mapping[substream->number]; + +- mutex_lock(&ump->open_mutex); +- spin_lock_irq(&ump->legacy_locks[dir]); +- ump->legacy_substreams[dir][group] = NULL; +- spin_unlock_irq(&ump->legacy_locks[dir]); ++ guard(mutex)(&ump->open_mutex); ++ scoped_guard(spinlock_irq, &ump->legacy_locks[dir]) ++ ump->legacy_substreams[dir][group] = NULL; + if (dir == SNDRV_RAWMIDI_STREAM_OUTPUT) { + if (!--ump->legacy_out_opens) + snd_rawmidi_kernel_release(&ump->legacy_out_rfile); + } +- mutex_unlock(&ump->open_mutex); + return 0; + } + +@@ -1169,12 +1170,11 @@ static int process_legacy_output(struct snd_ump_endpoint *ump, + const int dir = SNDRV_RAWMIDI_STREAM_OUTPUT; + unsigned char c; + int group, size = 0; +- unsigned long flags; + + if (!ump->out_cvts || !ump->legacy_out_opens) + return 0; + +- spin_lock_irqsave(&ump->legacy_locks[dir], flags); ++ guard(spinlock_irqsave)(&ump->legacy_locks[dir]); + for (group = 0; group < SNDRV_UMP_MAX_GROUPS; group++) { + substream = ump->legacy_substreams[dir][group]; + if (!substream) +@@ -1190,7 +1190,6 @@ static int process_legacy_output(struct snd_ump_endpoint *ump, + break; + } + } +- spin_unlock_irqrestore(&ump->legacy_locks[dir], flags); + return size; + } + +@@ -1200,18 +1199,16 @@ static void process_legacy_input(struct snd_ump_endpoint *ump, const u32 *src, + struct snd_rawmidi_substream *substream; + unsigned char buf[16]; + unsigned char group; +- unsigned long flags; + const int dir = SNDRV_RAWMIDI_STREAM_INPUT; + int size; + + size = snd_ump_convert_from_ump(src, buf, &group); + if (size <= 0) + return; +- spin_lock_irqsave(&ump->legacy_locks[dir], flags); ++ guard(spinlock_irqsave)(&ump->legacy_locks[dir]); + substream = ump->legacy_substreams[dir][group]; + if (substream) + snd_rawmidi_receive(substream, buf, size); +- spin_unlock_irqrestore(&ump->legacy_locks[dir], flags); + } + + /* Fill ump->legacy_mapping[] for groups to be used for legacy rawmidi */ +@@ -1254,11 +1251,20 @@ static void fill_substream_names(struct snd_ump_endpoint *ump, + name = ump->groups[idx].name; + if (!*name) + name = ump->info.name; +- snprintf(s->name, sizeof(s->name), "Group %d (%.16s)", +- idx + 1, name); ++ scnprintf(s->name, sizeof(s->name), "Group %d (%.16s)%s", ++ idx + 1, name, ++ ump->groups[idx].active ? "" : " [Inactive]"); + } + } + ++static void update_legacy_names(struct snd_ump_endpoint *ump) ++{ ++ struct snd_rawmidi *rmidi = ump->legacy_rmidi; ++ ++ fill_substream_names(ump, rmidi, SNDRV_RAWMIDI_STREAM_INPUT); ++ fill_substream_names(ump, rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT); ++} ++ + int snd_ump_attach_legacy_rawmidi(struct snd_ump_endpoint *ump, + char *id, int device) + { +@@ -1295,10 +1301,7 @@ int snd_ump_attach_legacy_rawmidi(struct snd_ump_endpoint *ump, + rmidi->ops = &snd_ump_legacy_ops; + rmidi->private_data = ump; + ump->legacy_rmidi = rmidi; +- if (input) +- fill_substream_names(ump, rmidi, SNDRV_RAWMIDI_STREAM_INPUT); +- if (output) +- fill_substream_names(ump, rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT); ++ update_legacy_names(ump); + + ump_dbg(ump, "Created a legacy rawmidi #%d (%s)\n", device, id); + return 0; +diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c +index 748a3c40966e97..27e48fdbbf3aa0 100644 +--- a/sound/pci/hda/patch_ca0132.c ++++ b/sound/pci/hda/patch_ca0132.c +@@ -1134,7 +1134,6 @@ struct ca0132_spec { + + struct hda_codec *codec; + struct delayed_work unsol_hp_work; +- int quirk; + + #ifdef ENABLE_TUNING_CONTROLS + long cur_ctl_vals[TUNING_CTLS_COUNT]; +@@ -1166,7 +1165,6 @@ struct ca0132_spec { + * CA0132 quirks table + */ + enum { +- QUIRK_NONE, + QUIRK_ALIENWARE, + QUIRK_ALIENWARE_M17XR4, + QUIRK_SBZ, +@@ -1176,10 +1174,11 @@ enum { + QUIRK_R3D, + QUIRK_AE5, + QUIRK_AE7, ++ QUIRK_NONE = HDA_FIXUP_ID_NOT_SET, + }; + + #ifdef CONFIG_PCI +-#define ca0132_quirk(spec) ((spec)->quirk) ++#define ca0132_quirk(spec) ((spec)->codec->fixup_id) + #define ca0132_use_pci_mmio(spec) ((spec)->use_pci_mmio) + #define ca0132_use_alt_functions(spec) ((spec)->use_alt_functions) + #define ca0132_use_alt_controls(spec) ((spec)->use_alt_controls) +@@ -1293,7 +1292,7 @@ static const struct hda_pintbl ae7_pincfgs[] = { + {} + }; + +-static const struct snd_pci_quirk ca0132_quirks[] = { ++static const struct hda_quirk ca0132_quirks[] = { + SND_PCI_QUIRK(0x1028, 0x057b, "Alienware M17x R4", QUIRK_ALIENWARE_M17XR4), + SND_PCI_QUIRK(0x1028, 0x0685, "Alienware 15 2015", QUIRK_ALIENWARE), + SND_PCI_QUIRK(0x1028, 0x0688, "Alienware 17 2015", QUIRK_ALIENWARE), +@@ -1316,6 +1315,19 @@ static const struct snd_pci_quirk ca0132_quirks[] = { + {} + }; + ++static const struct hda_model_fixup ca0132_quirk_models[] = { ++ { .id = QUIRK_ALIENWARE, .name = "alienware" }, ++ { .id = QUIRK_ALIENWARE_M17XR4, .name = "alienware-m17xr4" }, ++ { .id = QUIRK_SBZ, .name = "sbz" }, ++ { .id = QUIRK_ZXR, .name = "zxr" }, ++ { .id = QUIRK_ZXR_DBPRO, .name = "zxr-dbpro" }, ++ { .id = QUIRK_R3DI, .name = "r3di" }, ++ { .id = QUIRK_R3D, .name = "r3d" }, ++ { .id = QUIRK_AE5, .name = "ae5" }, ++ { .id = QUIRK_AE7, .name = "ae7" }, ++ {} ++}; ++ + /* Output selection quirk info structures. */ + #define MAX_QUIRK_MMIO_GPIO_SET_VALS 3 + #define MAX_QUIRK_SCP_SET_VALS 2 +@@ -9962,17 +9974,15 @@ static int ca0132_prepare_verbs(struct hda_codec *codec) + */ + static void sbz_detect_quirk(struct hda_codec *codec) + { +- struct ca0132_spec *spec = codec->spec; +- + switch (codec->core.subsystem_id) { + case 0x11020033: +- spec->quirk = QUIRK_ZXR; ++ codec->fixup_id = QUIRK_ZXR; + break; + case 0x1102003f: +- spec->quirk = QUIRK_ZXR_DBPRO; ++ codec->fixup_id = QUIRK_ZXR_DBPRO; + break; + default: +- spec->quirk = QUIRK_SBZ; ++ codec->fixup_id = QUIRK_SBZ; + break; + } + } +@@ -9981,7 +9991,6 @@ static int patch_ca0132(struct hda_codec *codec) + { + struct ca0132_spec *spec; + int err; +- const struct snd_pci_quirk *quirk; + + codec_dbg(codec, "patch_ca0132\n"); + +@@ -9992,11 +10001,7 @@ static int patch_ca0132(struct hda_codec *codec) + spec->codec = codec; + + /* Detect codec quirk */ +- quirk = snd_pci_quirk_lookup(codec->bus->pci, ca0132_quirks); +- if (quirk) +- spec->quirk = quirk->value; +- else +- spec->quirk = QUIRK_NONE; ++ snd_hda_pick_fixup(codec, ca0132_quirk_models, ca0132_quirks, NULL); + if (ca0132_quirk(spec) == QUIRK_SBZ) + sbz_detect_quirk(codec); + +@@ -10073,7 +10078,7 @@ static int patch_ca0132(struct hda_codec *codec) + spec->mem_base = pci_iomap(codec->bus->pci, 2, 0xC20); + if (spec->mem_base == NULL) { + codec_warn(codec, "pci_iomap failed! Setting quirk to QUIRK_NONE."); +- spec->quirk = QUIRK_NONE; ++ codec->fixup_id = QUIRK_NONE; + } + } + #endif +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 29d7eb8c6bec3e..fc93af80f0bffe 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -10443,6 +10443,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0xf111, 0x0001, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0xf111, 0x0006, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0xf111, 0x0009, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE), ++ SND_PCI_QUIRK(0xf111, 0x000c, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE), + + #if 0 + /* Below is a quirk table taken from the old code. +@@ -10631,6 +10632,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = { + {.id = ALC255_FIXUP_ACER_HEADPHONE_AND_MIC, .name = "alc255-acer-headphone-and-mic"}, + {.id = ALC285_FIXUP_HP_GPIO_AMP_INIT, .name = "alc285-hp-amp-init"}, + {.id = ALC236_FIXUP_LENOVO_INV_DMIC, .name = "alc236-fixup-lenovo-inv-mic"}, ++ {.id = ALC2XX_FIXUP_HEADSET_MIC, .name = "alc2xx-fixup-headset-mic"}, + {} + }; + #define ALC225_STANDARD_PINS \ +diff --git a/sound/usb/format.c b/sound/usb/format.c +index 3b45d0ee769389..3b3a5ea6fcbfc0 100644 +--- a/sound/usb/format.c ++++ b/sound/usb/format.c +@@ -60,6 +60,8 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip, + pcm_formats |= SNDRV_PCM_FMTBIT_SPECIAL; + /* flag potentially raw DSD capable altsettings */ + fp->dsd_raw = true; ++ /* clear special format bit to avoid "unsupported format" msg below */ ++ format &= ~UAC2_FORMAT_TYPE_I_RAW_DATA; + } + + format <<= 1; +@@ -71,8 +73,11 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip, + sample_width = as->bBitResolution; + sample_bytes = as->bSubslotSize; + +- if (format & UAC3_FORMAT_TYPE_I_RAW_DATA) ++ if (format & UAC3_FORMAT_TYPE_I_RAW_DATA) { + pcm_formats |= SNDRV_PCM_FMTBIT_SPECIAL; ++ /* clear special format bit to avoid "unsupported format" msg below */ ++ format &= ~UAC3_FORMAT_TYPE_I_RAW_DATA; ++ } + + format <<= 1; + break; +diff --git a/sound/usb/mixer_us16x08.c b/sound/usb/mixer_us16x08.c +index 6eb7d93b358d99..20ac32635f1f50 100644 +--- a/sound/usb/mixer_us16x08.c ++++ b/sound/usb/mixer_us16x08.c +@@ -687,7 +687,7 @@ static int snd_us16x08_meter_get(struct snd_kcontrol *kcontrol, + struct usb_mixer_elem_info *elem = kcontrol->private_data; + struct snd_usb_audio *chip = elem->head.mixer->chip; + struct snd_us16x08_meter_store *store = elem->private_data; +- u8 meter_urb[64]; ++ u8 meter_urb[64] = {0}; + + switch (kcontrol->private_value) { + case 0: { +diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c +index 8eed8d9742fda9..ec81b47c41c9ea 100644 +--- a/sound/usb/quirks.c ++++ b/sound/usb/quirks.c +@@ -2225,6 +2225,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { + QUIRK_FLAG_DSD_RAW), + DEVICE_FLG(0x2522, 0x0007, /* LH Labs Geek Out HD Audio 1V5 */ + QUIRK_FLAG_SET_IFACE_FIRST), ++ DEVICE_FLG(0x262a, 0x9302, /* ddHiFi TC44C */ ++ QUIRK_FLAG_DSD_RAW), + DEVICE_FLG(0x2708, 0x0002, /* Audient iD14 */ + QUIRK_FLAG_IGNORE_CTL_ERROR), + DEVICE_FLG(0x2912, 0x30c8, /* Audioengine D1 */ +diff --git a/tools/testing/selftests/bpf/progs/verifier_subprog_precision.c b/tools/testing/selftests/bpf/progs/verifier_subprog_precision.c +index f87365f7599bf7..f61d623b1ce8df 100644 +--- a/tools/testing/selftests/bpf/progs/verifier_subprog_precision.c ++++ b/tools/testing/selftests/bpf/progs/verifier_subprog_precision.c +@@ -541,24 +541,11 @@ static __u64 subprog_spill_reg_precise(void) + + SEC("?raw_tp") + __success __log_level(2) +-__msg("10: (0f) r1 += r7") +-__msg("mark_precise: frame0: last_idx 10 first_idx 7 subseq_idx -1") +-__msg("mark_precise: frame0: regs=r7 stack= before 9: (bf) r1 = r8") +-__msg("mark_precise: frame0: regs=r7 stack= before 8: (27) r7 *= 4") +-__msg("mark_precise: frame0: regs=r7 stack= before 7: (79) r7 = *(u64 *)(r10 -8)") +-__msg("mark_precise: frame0: parent state regs= stack=-8: R0_w=2 R6_w=1 R8_rw=map_value(map=.data.vals,ks=4,vs=16) R10=fp0 fp-8_rw=P1") +-__msg("mark_precise: frame0: last_idx 18 first_idx 0 subseq_idx 7") +-__msg("mark_precise: frame0: regs= stack=-8 before 18: (95) exit") +-__msg("mark_precise: frame1: regs= stack= before 17: (0f) r0 += r2") +-__msg("mark_precise: frame1: regs= stack= before 16: (79) r2 = *(u64 *)(r1 +0)") +-__msg("mark_precise: frame1: regs= stack= before 15: (79) r0 = *(u64 *)(r10 -16)") +-__msg("mark_precise: frame1: regs= stack= before 14: (7b) *(u64 *)(r10 -16) = r2") +-__msg("mark_precise: frame1: regs= stack= before 13: (7b) *(u64 *)(r1 +0) = r2") +-__msg("mark_precise: frame1: regs=r2 stack= before 6: (85) call pc+6") +-__msg("mark_precise: frame0: regs=r2 stack= before 5: (bf) r2 = r6") +-__msg("mark_precise: frame0: regs=r6 stack= before 4: (07) r1 += -8") +-__msg("mark_precise: frame0: regs=r6 stack= before 3: (bf) r1 = r10") +-__msg("mark_precise: frame0: regs=r6 stack= before 2: (b7) r6 = 1") ++/* precision backtracking can't currently handle stack access not through r10, ++ * so we won't be able to mark stack slot fp-8 as precise, and so will ++ * fallback to forcing all as precise ++ */ ++__msg("mark_precise: frame0: falling back to forcing all scalars precise") + __naked int subprog_spill_into_parent_stack_slot_precise(void) + { + asm volatile ( +diff --git a/tools/testing/selftests/bpf/verifier/precise.c b/tools/testing/selftests/bpf/verifier/precise.c +index 8a2ff81d835088..0d84dd1f38b6b0 100644 +--- a/tools/testing/selftests/bpf/verifier/precise.c ++++ b/tools/testing/selftests/bpf/verifier/precise.c +@@ -140,11 +140,10 @@ + .result = REJECT, + }, + { +- "precise: ST zero to stack insn is supported", ++ "precise: ST insn causing spi > allocated_stack", + .insns = { + BPF_MOV64_REG(BPF_REG_3, BPF_REG_10), + BPF_JMP_IMM(BPF_JNE, BPF_REG_3, 123, 0), +- /* not a register spill, so we stop precision propagation for R4 here */ + BPF_ST_MEM(BPF_DW, BPF_REG_3, -8, 0), + BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_10, -8), + BPF_MOV64_IMM(BPF_REG_0, -1), +@@ -158,11 +157,11 @@ + mark_precise: frame0: last_idx 4 first_idx 2\ + mark_precise: frame0: regs=r4 stack= before 4\ + mark_precise: frame0: regs=r4 stack= before 3\ ++ mark_precise: frame0: regs= stack=-8 before 2\ ++ mark_precise: frame0: falling back to forcing all scalars precise\ ++ force_precise: frame0: forcing r0 to be precise\ + mark_precise: frame0: last_idx 5 first_idx 5\ +- mark_precise: frame0: parent state regs=r0 stack=:\ +- mark_precise: frame0: last_idx 4 first_idx 2\ +- mark_precise: frame0: regs=r0 stack= before 4\ +- 5: R0=-1 R4=0", ++ mark_precise: frame0: parent state regs= stack=:", + .result = VERBOSE_ACCEPT, + .retval = -1, + }, +@@ -170,8 +169,6 @@ + "precise: STX insn causing spi > allocated_stack", + .insns = { + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32), +- /* make later reg spill more interesting by having somewhat known scalar */ +- BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xff), + BPF_MOV64_REG(BPF_REG_3, BPF_REG_10), + BPF_JMP_IMM(BPF_JNE, BPF_REG_3, 123, 0), + BPF_STX_MEM(BPF_DW, BPF_REG_3, BPF_REG_0, -8), +@@ -182,21 +179,18 @@ + }, + .prog_type = BPF_PROG_TYPE_XDP, + .flags = BPF_F_TEST_STATE_FREQ, +- .errstr = "mark_precise: frame0: last_idx 7 first_idx 7\ ++ .errstr = "mark_precise: frame0: last_idx 6 first_idx 6\ + mark_precise: frame0: parent state regs=r4 stack=:\ +- mark_precise: frame0: last_idx 6 first_idx 4\ +- mark_precise: frame0: regs=r4 stack= before 6: (b7) r0 = -1\ +- mark_precise: frame0: regs=r4 stack= before 5: (79) r4 = *(u64 *)(r10 -8)\ +- mark_precise: frame0: regs= stack=-8 before 4: (7b) *(u64 *)(r3 -8) = r0\ +- mark_precise: frame0: parent state regs=r0 stack=:\ +- mark_precise: frame0: last_idx 3 first_idx 3\ +- mark_precise: frame0: regs=r0 stack= before 3: (55) if r3 != 0x7b goto pc+0\ +- mark_precise: frame0: regs=r0 stack= before 2: (bf) r3 = r10\ +- mark_precise: frame0: regs=r0 stack= before 1: (57) r0 &= 255\ +- mark_precise: frame0: parent state regs=r0 stack=:\ +- mark_precise: frame0: last_idx 0 first_idx 0\ +- mark_precise: frame0: regs=r0 stack= before 0: (85) call bpf_get_prandom_u32#7\ +- mark_precise: frame0: last_idx 7 first_idx 7\ ++ mark_precise: frame0: last_idx 5 first_idx 3\ ++ mark_precise: frame0: regs=r4 stack= before 5\ ++ mark_precise: frame0: regs=r4 stack= before 4\ ++ mark_precise: frame0: regs= stack=-8 before 3\ ++ mark_precise: frame0: falling back to forcing all scalars precise\ ++ force_precise: frame0: forcing r0 to be precise\ ++ force_precise: frame0: forcing r0 to be precise\ ++ force_precise: frame0: forcing r0 to be precise\ ++ force_precise: frame0: forcing r0 to be precise\ ++ mark_precise: frame0: last_idx 6 first_idx 6\ + mark_precise: frame0: parent state regs= stack=:", + .result = VERBOSE_ACCEPT, + .retval = -1, diff --git a/patch/kernel/archive/odroidxu4-6.6/patch-6.6.70-71.patch b/patch/kernel/archive/odroidxu4-6.6/patch-6.6.70-71.patch new file mode 100644 index 0000000000..9e3ccd9c83 --- /dev/null +++ b/patch/kernel/archive/odroidxu4-6.6/patch-6.6.70-71.patch @@ -0,0 +1,227 @@ +diff --git a/Makefile b/Makefile +index 4c0dd62e02e465..9476e4502bbb0b 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 6 + PATCHLEVEL = 6 +-SUBLEVEL = 70 ++SUBLEVEL = 71 + EXTRAVERSION = + NAME = Pinguïn Aangedreven + +diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile +index 15fc9fc3dcf052..3269a0e23d3ab8 100644 +--- a/arch/x86/kernel/Makefile ++++ b/arch/x86/kernel/Makefile +@@ -99,9 +99,9 @@ obj-$(CONFIG_TRACING) += trace.o + obj-$(CONFIG_RETHOOK) += rethook.o + obj-$(CONFIG_CRASH_CORE) += crash_core_$(BITS).o + obj-$(CONFIG_KEXEC_CORE) += machine_kexec_$(BITS).o +-obj-$(CONFIG_KEXEC_CORE) += relocate_kernel_$(BITS).o ++obj-$(CONFIG_KEXEC_CORE) += relocate_kernel_$(BITS).o crash.o + obj-$(CONFIG_KEXEC_FILE) += kexec-bzimage64.o +-obj-$(CONFIG_CRASH_DUMP) += crash_dump_$(BITS).o crash.o ++obj-$(CONFIG_CRASH_DUMP) += crash_dump_$(BITS).o + obj-y += kprobes/ + obj-$(CONFIG_MODULES) += module.o + obj-$(CONFIG_X86_32) += doublefault_32.o +diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c +index 6328cf56e59be2..5ae77d966cafea 100644 +--- a/arch/x86/kernel/cpu/mshyperv.c ++++ b/arch/x86/kernel/cpu/mshyperv.c +@@ -209,9 +209,7 @@ static void hv_machine_shutdown(void) + if (kexec_in_progress) + hyperv_cleanup(); + } +-#endif /* CONFIG_KEXEC_CORE */ + +-#ifdef CONFIG_CRASH_DUMP + static void hv_machine_crash_shutdown(struct pt_regs *regs) + { + if (hv_crash_handler) +@@ -223,7 +221,7 @@ static void hv_machine_crash_shutdown(struct pt_regs *regs) + /* Disable the hypercall page when there is only 1 active CPU. */ + hyperv_cleanup(); + } +-#endif /* CONFIG_CRASH_DUMP */ ++#endif /* CONFIG_KEXEC_CORE */ + + static u64 hv_ref_counter_at_suspend; + static void (*old_save_sched_clock_state)(void); +@@ -552,13 +550,9 @@ static void __init ms_hyperv_init_platform(void) + no_timer_check = 1; + #endif + +-#if IS_ENABLED(CONFIG_HYPERV) +-#if defined(CONFIG_KEXEC_CORE) ++#if IS_ENABLED(CONFIG_HYPERV) && defined(CONFIG_KEXEC_CORE) + machine_ops.shutdown = hv_machine_shutdown; +-#endif +-#if defined(CONFIG_CRASH_DUMP) + machine_ops.crash_shutdown = hv_machine_crash_shutdown; +-#endif + #endif + if (ms_hyperv.features & HV_ACCESS_TSC_INVARIANT) { + /* +diff --git a/arch/x86/kernel/kexec-bzimage64.c b/arch/x86/kernel/kexec-bzimage64.c +index 0de509c02d18b9..a61c12c0127097 100644 +--- a/arch/x86/kernel/kexec-bzimage64.c ++++ b/arch/x86/kernel/kexec-bzimage64.c +@@ -263,13 +263,11 @@ setup_boot_parameters(struct kimage *image, struct boot_params *params, + memset(¶ms->hd0_info, 0, sizeof(params->hd0_info)); + memset(¶ms->hd1_info, 0, sizeof(params->hd1_info)); + +-#ifdef CONFIG_CRASH_DUMP + if (image->type == KEXEC_TYPE_CRASH) { + ret = crash_setup_memmap_entries(image, params); + if (ret) + return ret; + } else +-#endif + setup_e820_entries(params); + + nr_e820_entries = params->e820_entries; +@@ -430,14 +428,12 @@ static void *bzImage64_load(struct kimage *image, char *kernel, + return ERR_PTR(-EINVAL); + } + +-#ifdef CONFIG_CRASH_DUMP + /* Allocate and load backup region */ + if (image->type == KEXEC_TYPE_CRASH) { + ret = crash_load_segments(image); + if (ret) + return ERR_PTR(ret); + } +-#endif + + /* + * Load purgatory. For 64bit entry point, purgatory code can be +diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c +index 38d88c8b56ec07..b8ab9ee5896c19 100644 +--- a/arch/x86/kernel/kvm.c ++++ b/arch/x86/kernel/kvm.c +@@ -769,7 +769,7 @@ static struct notifier_block kvm_pv_reboot_nb = { + * won't be valid. In cases like kexec, in which you install a new kernel, this + * means a random memory location will be kept being written. + */ +-#ifdef CONFIG_CRASH_DUMP ++#ifdef CONFIG_KEXEC_CORE + static void kvm_crash_shutdown(struct pt_regs *regs) + { + kvm_guest_cpu_offline(true); +@@ -852,7 +852,7 @@ static void __init kvm_guest_init(void) + kvm_guest_cpu_init(); + #endif + +-#ifdef CONFIG_CRASH_DUMP ++#ifdef CONFIG_KEXEC_CORE + machine_ops.crash_shutdown = kvm_crash_shutdown; + #endif + +diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c +index aaeac2deb85dc6..2fa12d1dc67602 100644 +--- a/arch/x86/kernel/machine_kexec_64.c ++++ b/arch/x86/kernel/machine_kexec_64.c +@@ -545,8 +545,6 @@ int arch_kimage_file_post_load_cleanup(struct kimage *image) + } + #endif /* CONFIG_KEXEC_FILE */ + +-#ifdef CONFIG_CRASH_DUMP +- + static int + kexec_mark_range(unsigned long start, unsigned long end, bool protect) + { +@@ -591,7 +589,6 @@ void arch_kexec_unprotect_crashkres(void) + { + kexec_mark_crashkres(false); + } +-#endif + + /* + * During a traditional boot under SME, SME will encrypt the kernel, +diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c +index f3130f762784a1..830425e6d38e2f 100644 +--- a/arch/x86/kernel/reboot.c ++++ b/arch/x86/kernel/reboot.c +@@ -796,7 +796,7 @@ struct machine_ops machine_ops __ro_after_init = { + .emergency_restart = native_machine_emergency_restart, + .restart = native_machine_restart, + .halt = native_machine_halt, +-#ifdef CONFIG_CRASH_DUMP ++#ifdef CONFIG_KEXEC_CORE + .crash_shutdown = native_machine_crash_shutdown, + #endif + }; +@@ -826,7 +826,7 @@ void machine_halt(void) + machine_ops.halt(); + } + +-#ifdef CONFIG_CRASH_DUMP ++#ifdef CONFIG_KEXEC_CORE + void machine_crash_shutdown(struct pt_regs *regs) + { + machine_ops.crash_shutdown(regs); +diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c +index 8bcecabd475bdf..eb129277dcdd64 100644 +--- a/arch/x86/kernel/setup.c ++++ b/arch/x86/kernel/setup.c +@@ -547,7 +547,7 @@ static void __init reserve_crashkernel(void) + bool high = false; + int ret; + +- if (!IS_ENABLED(CONFIG_CRASH_RESERVE)) ++ if (!IS_ENABLED(CONFIG_KEXEC_CORE)) + return; + + total_mem = memblock_phys_mem_size(); +diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c +index 52c3823b721191..96a771f9f930a6 100644 +--- a/arch/x86/kernel/smp.c ++++ b/arch/x86/kernel/smp.c +@@ -282,7 +282,7 @@ struct smp_ops smp_ops = { + .smp_cpus_done = native_smp_cpus_done, + + .stop_other_cpus = native_stop_other_cpus, +-#if defined(CONFIG_CRASH_DUMP) ++#if defined(CONFIG_KEXEC_CORE) + .crash_stop_other_cpus = kdump_nmi_shootdown_cpus, + #endif + .smp_send_reschedule = native_smp_send_reschedule, +diff --git a/arch/x86/xen/enlighten_hvm.c b/arch/x86/xen/enlighten_hvm.c +index ade22feee7aeb1..70be57e8f51caa 100644 +--- a/arch/x86/xen/enlighten_hvm.c ++++ b/arch/x86/xen/enlighten_hvm.c +@@ -141,9 +141,7 @@ static void xen_hvm_shutdown(void) + if (kexec_in_progress) + xen_reboot(SHUTDOWN_soft_reset); + } +-#endif + +-#ifdef CONFIG_CRASH_DUMP + static void xen_hvm_crash_shutdown(struct pt_regs *regs) + { + native_machine_crash_shutdown(regs); +@@ -231,8 +229,6 @@ static void __init xen_hvm_guest_init(void) + + #ifdef CONFIG_KEXEC_CORE + machine_ops.shutdown = xen_hvm_shutdown; +-#endif +-#ifdef CONFIG_CRASH_DUMP + machine_ops.crash_shutdown = xen_hvm_crash_shutdown; + #endif + } +diff --git a/arch/x86/xen/mmu_pv.c b/arch/x86/xen/mmu_pv.c +index bfd57d07f4b5ee..6b201e64d8abc8 100644 +--- a/arch/x86/xen/mmu_pv.c ++++ b/arch/x86/xen/mmu_pv.c +@@ -2517,7 +2517,7 @@ int xen_remap_pfn(struct vm_area_struct *vma, unsigned long addr, + } + EXPORT_SYMBOL_GPL(xen_remap_pfn); + +-#ifdef CONFIG_VMCORE_INFO ++#ifdef CONFIG_KEXEC_CORE + phys_addr_t paddr_vmcoreinfo_note(void) + { + if (xen_pv_domain()) diff --git a/patch/kernel/archive/odroidxu4-6.6/patch-6.6.71-72.patch b/patch/kernel/archive/odroidxu4-6.6/patch-6.6.71-72.patch new file mode 100644 index 0000000000..891def085e --- /dev/null +++ b/patch/kernel/archive/odroidxu4-6.6/patch-6.6.71-72.patch @@ -0,0 +1,4467 @@ +diff --git a/Makefile b/Makefile +index 9476e4502bbb0b..fb4949cac6ffbf 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 6 + PATCHLEVEL = 6 +-SUBLEVEL = 71 ++SUBLEVEL = 72 + EXTRAVERSION = + NAME = Pinguïn Aangedreven + +diff --git a/arch/arm/boot/dts/nxp/imx/imxrt1050.dtsi b/arch/arm/boot/dts/nxp/imx/imxrt1050.dtsi +index dd714d235d5f6a..b0bad0d1ba36f4 100644 +--- a/arch/arm/boot/dts/nxp/imx/imxrt1050.dtsi ++++ b/arch/arm/boot/dts/nxp/imx/imxrt1050.dtsi +@@ -87,7 +87,7 @@ usdhc1: mmc@402c0000 { + reg = <0x402c0000 0x4000>; + interrupts = <110>; + clocks = <&clks IMXRT1050_CLK_IPG_PDOF>, +- <&clks IMXRT1050_CLK_OSC>, ++ <&clks IMXRT1050_CLK_AHB_PODF>, + <&clks IMXRT1050_CLK_USDHC1>; + clock-names = "ipg", "ahb", "per"; + bus-width = <4>; +diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi +index 5d47acbf4a2497..82eb7c49e825e4 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi +@@ -304,6 +304,7 @@ power: power-controller { + + power-domain@RK3328_PD_HEVC { + reg = ; ++ clocks = <&cru SCLK_VENC_CORE>; + #power-domain-cells = <0>; + }; + power-domain@RK3328_PD_VIDEO { +diff --git a/arch/riscv/include/asm/cacheflush.h b/arch/riscv/include/asm/cacheflush.h +index a129dac4521d35..3f65acd0ef7560 100644 +--- a/arch/riscv/include/asm/cacheflush.h ++++ b/arch/riscv/include/asm/cacheflush.h +@@ -13,6 +13,12 @@ static inline void local_flush_icache_all(void) + asm volatile ("fence.i" ::: "memory"); + } + ++static inline void local_flush_icache_range(unsigned long start, ++ unsigned long end) ++{ ++ local_flush_icache_all(); ++} ++ + #define PG_dcache_clean PG_arch_1 + + static inline void flush_dcache_folio(struct folio *folio) +diff --git a/arch/riscv/include/asm/page.h b/arch/riscv/include/asm/page.h +index 94b3d6930fc370..4d1f58848129e8 100644 +--- a/arch/riscv/include/asm/page.h ++++ b/arch/riscv/include/asm/page.h +@@ -122,6 +122,7 @@ struct kernel_mapping { + + extern struct kernel_mapping kernel_map; + extern phys_addr_t phys_ram_base; ++extern unsigned long vmemmap_start_pfn; + + #define is_kernel_mapping(x) \ + ((x) >= kernel_map.virt_addr && (x) < (kernel_map.virt_addr + kernel_map.size)) +diff --git a/arch/riscv/include/asm/patch.h b/arch/riscv/include/asm/patch.h +index e88b52d39eac76..9f5d6e14c40553 100644 +--- a/arch/riscv/include/asm/patch.h ++++ b/arch/riscv/include/asm/patch.h +@@ -6,6 +6,7 @@ + #ifndef _ASM_RISCV_PATCH_H + #define _ASM_RISCV_PATCH_H + ++int patch_insn_write(void *addr, const void *insn, size_t len); + int patch_text_nosync(void *addr, const void *insns, size_t len); + int patch_text_set_nosync(void *addr, u8 c, size_t len); + int patch_text(void *addr, u32 *insns, int ninsns); +diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h +index 37829dab4a0a48..f540b2625714d0 100644 +--- a/arch/riscv/include/asm/pgtable.h ++++ b/arch/riscv/include/asm/pgtable.h +@@ -84,7 +84,7 @@ + * Define vmemmap for pfn_to_page & page_to_pfn calls. Needed if kernel + * is configured with CONFIG_SPARSEMEM_VMEMMAP enabled. + */ +-#define vmemmap ((struct page *)VMEMMAP_START - (phys_ram_base >> PAGE_SHIFT)) ++#define vmemmap ((struct page *)VMEMMAP_START - vmemmap_start_pfn) + + #define PCI_IO_SIZE SZ_16M + #define PCI_IO_END VMEMMAP_START +diff --git a/arch/riscv/kernel/ftrace.c b/arch/riscv/kernel/ftrace.c +index 03a6434a8cdd00..4c58c2f8098401 100644 +--- a/arch/riscv/kernel/ftrace.c ++++ b/arch/riscv/kernel/ftrace.c +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -75,8 +76,7 @@ static int __ftrace_modify_call(unsigned long hook_pos, unsigned long target, + make_call_t0(hook_pos, target, call); + + /* Replace the auipc-jalr pair at once. Return -EPERM on write error. */ +- if (patch_text_nosync +- ((void *)hook_pos, enable ? call : nops, MCOUNT_INSN_SIZE)) ++ if (patch_insn_write((void *)hook_pos, enable ? call : nops, MCOUNT_INSN_SIZE)) + return -EPERM; + + return 0; +@@ -88,7 +88,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) + + make_call_t0(rec->ip, addr, call); + +- if (patch_text_nosync((void *)rec->ip, call, MCOUNT_INSN_SIZE)) ++ if (patch_insn_write((void *)rec->ip, call, MCOUNT_INSN_SIZE)) + return -EPERM; + + return 0; +@@ -99,7 +99,7 @@ int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, + { + unsigned int nops[2] = {NOP4, NOP4}; + +- if (patch_text_nosync((void *)rec->ip, nops, MCOUNT_INSN_SIZE)) ++ if (patch_insn_write((void *)rec->ip, nops, MCOUNT_INSN_SIZE)) + return -EPERM; + + return 0; +@@ -120,6 +120,9 @@ int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec) + out = ftrace_make_nop(mod, rec, MCOUNT_ADDR); + mutex_unlock(&text_mutex); + ++ if (!mod) ++ local_flush_icache_range(rec->ip, rec->ip + MCOUNT_INSN_SIZE); ++ + return out; + } + +@@ -134,6 +137,42 @@ int ftrace_update_ftrace_func(ftrace_func_t func) + + return ret; + } ++ ++struct ftrace_modify_param { ++ int command; ++ atomic_t cpu_count; ++}; ++ ++static int __ftrace_modify_code(void *data) ++{ ++ struct ftrace_modify_param *param = data; ++ ++ if (atomic_inc_return(¶m->cpu_count) == num_online_cpus()) { ++ ftrace_modify_all_code(param->command); ++ /* ++ * Make sure the patching store is effective *before* we ++ * increment the counter which releases all waiting CPUs ++ * by using the release variant of atomic increment. The ++ * release pairs with the call to local_flush_icache_all() ++ * on the waiting CPU. ++ */ ++ atomic_inc_return_release(¶m->cpu_count); ++ } else { ++ while (atomic_read(¶m->cpu_count) <= num_online_cpus()) ++ cpu_relax(); ++ } ++ ++ local_flush_icache_all(); ++ ++ return 0; ++} ++ ++void arch_ftrace_update_code(int command) ++{ ++ struct ftrace_modify_param param = { command, ATOMIC_INIT(0) }; ++ ++ stop_machine(__ftrace_modify_code, ¶m, cpu_online_mask); ++} + #endif + + #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS +diff --git a/arch/riscv/kernel/patch.c b/arch/riscv/kernel/patch.c +index 30e12b310cab73..78387d843aa56b 100644 +--- a/arch/riscv/kernel/patch.c ++++ b/arch/riscv/kernel/patch.c +@@ -196,7 +196,7 @@ int patch_text_set_nosync(void *addr, u8 c, size_t len) + } + NOKPROBE_SYMBOL(patch_text_set_nosync); + +-static int patch_insn_write(void *addr, const void *insn, size_t len) ++int patch_insn_write(void *addr, const void *insn, size_t len) + { + size_t patched = 0; + size_t size; +@@ -240,16 +240,24 @@ static int patch_text_cb(void *data) + if (atomic_inc_return(&patch->cpu_count) == num_online_cpus()) { + for (i = 0; ret == 0 && i < patch->ninsns; i++) { + len = GET_INSN_LENGTH(patch->insns[i]); +- ret = patch_text_nosync(patch->addr + i * len, +- &patch->insns[i], len); ++ ret = patch_insn_write(patch->addr + i * len, &patch->insns[i], len); + } +- atomic_inc(&patch->cpu_count); ++ /* ++ * Make sure the patching store is effective *before* we ++ * increment the counter which releases all waiting CPUs ++ * by using the release variant of atomic increment. The ++ * release pairs with the call to local_flush_icache_all() ++ * on the waiting CPU. ++ */ ++ atomic_inc_return_release(&patch->cpu_count); + } else { + while (atomic_read(&patch->cpu_count) <= num_online_cpus()) + cpu_relax(); + smp_mb(); + } + ++ local_flush_icache_all(); ++ + return ret; + } + NOKPROBE_SYMBOL(patch_text_cb); +diff --git a/arch/riscv/kernel/probes/kprobes.c b/arch/riscv/kernel/probes/kprobes.c +index fecbbcf40ac3fe..4fbc70e823f0fa 100644 +--- a/arch/riscv/kernel/probes/kprobes.c ++++ b/arch/riscv/kernel/probes/kprobes.c +@@ -29,7 +29,7 @@ static void __kprobes arch_prepare_ss_slot(struct kprobe *p) + p->ainsn.api.restore = (unsigned long)p->addr + offset; + + patch_text_nosync(p->ainsn.api.insn, &p->opcode, 1); +- patch_text_nosync(p->ainsn.api.insn + offset, &insn, 1); ++ patch_text_nosync((void *)p->ainsn.api.insn + offset, &insn, 1); + } + + static void __kprobes arch_prepare_simulate(struct kprobe *p) +diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c +index 2158b7a65d74f7..53c7de4878c227 100644 +--- a/arch/riscv/kernel/traps.c ++++ b/arch/riscv/kernel/traps.c +@@ -34,7 +34,7 @@ + + int show_unhandled_signals = 1; + +-static DEFINE_SPINLOCK(die_lock); ++static DEFINE_RAW_SPINLOCK(die_lock); + + static void dump_kernel_instr(const char *loglvl, struct pt_regs *regs) + { +@@ -66,7 +66,7 @@ void die(struct pt_regs *regs, const char *str) + + oops_enter(); + +- spin_lock_irqsave(&die_lock, flags); ++ raw_spin_lock_irqsave(&die_lock, flags); + console_verbose(); + bust_spinlocks(1); + +@@ -85,7 +85,7 @@ void die(struct pt_regs *regs, const char *str) + + bust_spinlocks(0); + add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE); +- spin_unlock_irqrestore(&die_lock, flags); ++ raw_spin_unlock_irqrestore(&die_lock, flags); + oops_exit(); + + if (in_interrupt()) +diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c +index 3245bb525212e3..bdf8ac6c7e309d 100644 +--- a/arch/riscv/mm/init.c ++++ b/arch/riscv/mm/init.c +@@ -32,6 +32,7 @@ + #include + #include + #include ++#include + #include + + #include "../kernel/head.h" +@@ -57,6 +58,13 @@ EXPORT_SYMBOL(pgtable_l5_enabled); + phys_addr_t phys_ram_base __ro_after_init; + EXPORT_SYMBOL(phys_ram_base); + ++#ifdef CONFIG_SPARSEMEM_VMEMMAP ++#define VMEMMAP_ADDR_ALIGN (1ULL << SECTION_SIZE_BITS) ++ ++unsigned long vmemmap_start_pfn __ro_after_init; ++EXPORT_SYMBOL(vmemmap_start_pfn); ++#endif ++ + unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)] + __page_aligned_bss; + EXPORT_SYMBOL(empty_zero_page); +@@ -221,8 +229,12 @@ static void __init setup_bootmem(void) + * Make sure we align the start of the memory on a PMD boundary so that + * at worst, we map the linear mapping with PMD mappings. + */ +- if (!IS_ENABLED(CONFIG_XIP_KERNEL)) ++ if (!IS_ENABLED(CONFIG_XIP_KERNEL)) { + phys_ram_base = memblock_start_of_DRAM() & PMD_MASK; ++#ifdef CONFIG_SPARSEMEM_VMEMMAP ++ vmemmap_start_pfn = round_down(phys_ram_base, VMEMMAP_ADDR_ALIGN) >> PAGE_SHIFT; ++#endif ++ } + + /* + * In 64-bit, any use of __va/__pa before this point is wrong as we +@@ -1080,6 +1092,9 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa) + kernel_map.xiprom_sz = (uintptr_t)(&_exiprom) - (uintptr_t)(&_xiprom); + + phys_ram_base = CONFIG_PHYS_RAM_BASE; ++#ifdef CONFIG_SPARSEMEM_VMEMMAP ++ vmemmap_start_pfn = round_down(phys_ram_base, VMEMMAP_ADDR_ALIGN) >> PAGE_SHIFT; ++#endif + kernel_map.phys_addr = (uintptr_t)CONFIG_PHYS_RAM_BASE; + kernel_map.size = (uintptr_t)(&_end) - (uintptr_t)(&_start); + +diff --git a/arch/x86/kernel/fpu/regset.c b/arch/x86/kernel/fpu/regset.c +index 6bc1eb2a21bd92..887b0b8e21e364 100644 +--- a/arch/x86/kernel/fpu/regset.c ++++ b/arch/x86/kernel/fpu/regset.c +@@ -190,7 +190,8 @@ int ssp_get(struct task_struct *target, const struct user_regset *regset, + struct fpu *fpu = &target->thread.fpu; + struct cet_user_state *cetregs; + +- if (!cpu_feature_enabled(X86_FEATURE_USER_SHSTK)) ++ if (!cpu_feature_enabled(X86_FEATURE_USER_SHSTK) || ++ !ssp_active(target, regset)) + return -ENODEV; + + sync_fpstate(fpu); +diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c +index 2c67bfc3cf3204..8b374c6919e604 100644 +--- a/arch/x86/mm/numa.c ++++ b/arch/x86/mm/numa.c +@@ -492,7 +492,7 @@ static void __init numa_clear_kernel_node_hotplug(void) + for_each_reserved_mem_region(mb_region) { + int nid = memblock_get_region_node(mb_region); + +- if (nid != MAX_NUMNODES) ++ if (nid != NUMA_NO_NODE) + node_set(nid, reserved_nodemask); + } + +@@ -613,9 +613,9 @@ static int __init numa_init(int (*init_func)(void)) + nodes_clear(node_online_map); + memset(&numa_meminfo, 0, sizeof(numa_meminfo)); + WARN_ON(memblock_set_node(0, ULLONG_MAX, &memblock.memory, +- MAX_NUMNODES)); ++ NUMA_NO_NODE)); + WARN_ON(memblock_set_node(0, ULLONG_MAX, &memblock.reserved, +- MAX_NUMNODES)); ++ NUMA_NO_NODE)); + /* In case that parsing SRAT failed. */ + WARN_ON(memblock_clear_hotplug(0, ULLONG_MAX)); + numa_reset_distance(); +diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c +index dd8ca3f7ba60a1..617d6802b8a0c7 100644 +--- a/block/bfq-iosched.c ++++ b/block/bfq-iosched.c +@@ -6843,16 +6843,24 @@ static struct bfq_queue *bfq_waker_bfqq(struct bfq_queue *bfqq) + if (new_bfqq == waker_bfqq) { + /* + * If waker_bfqq is in the merge chain, and current +- * is the only procress. ++ * is the only process, waker_bfqq can be freed. + */ + if (bfqq_process_refs(waker_bfqq) == 1) + return NULL; +- break; ++ ++ return waker_bfqq; + } + + new_bfqq = new_bfqq->new_bfqq; + } + ++ /* ++ * If waker_bfqq is not in the merge chain, and it's procress reference ++ * is 0, waker_bfqq can be freed. ++ */ ++ if (bfqq_process_refs(waker_bfqq) == 0) ++ return NULL; ++ + return waker_bfqq; + } + +diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c +index df598de0cb184f..c82b255f82bc41 100644 +--- a/drivers/acpi/resource.c ++++ b/drivers/acpi/resource.c +@@ -439,6 +439,13 @@ static const struct dmi_system_id asus_laptop[] = { + DMI_MATCH(DMI_BOARD_NAME, "S5602ZA"), + }, + }, ++ { ++ /* Asus Vivobook X1504VAP */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), ++ DMI_MATCH(DMI_BOARD_NAME, "X1504VAP"), ++ }, ++ }, + { + /* Asus Vivobook X1704VAP */ + .matches = { +@@ -633,6 +640,17 @@ static const struct dmi_system_id lg_laptop[] = { + DMI_MATCH(DMI_BOARD_NAME, "GMxHGxx"), + }, + }, ++ { ++ /* ++ * TongFang GM5HG0A in case of the SKIKK Vanaheim relabel the ++ * board-name is changed, so check OEM strings instead. Note ++ * OEM string matches are always exact matches. ++ * https://bugzilla.kernel.org/show_bug.cgi?id=219614 ++ */ ++ .matches = { ++ DMI_EXACT_MATCH(DMI_OEM_STRING, "GM5HG0A"), ++ }, ++ }, + { } + }; + +diff --git a/drivers/base/topology.c b/drivers/base/topology.c +index 89f98be5c5b991..d293cbd253e4f9 100644 +--- a/drivers/base/topology.c ++++ b/drivers/base/topology.c +@@ -27,9 +27,17 @@ static ssize_t name##_read(struct file *file, struct kobject *kobj, \ + loff_t off, size_t count) \ + { \ + struct device *dev = kobj_to_dev(kobj); \ ++ cpumask_var_t mask; \ ++ ssize_t n; \ + \ +- return cpumap_print_bitmask_to_buf(buf, topology_##mask(dev->id), \ +- off, count); \ ++ if (!alloc_cpumask_var(&mask, GFP_KERNEL)) \ ++ return -ENOMEM; \ ++ \ ++ cpumask_copy(mask, topology_##mask(dev->id)); \ ++ n = cpumap_print_bitmask_to_buf(buf, mask, off, count); \ ++ free_cpumask_var(mask); \ ++ \ ++ return n; \ + } \ + \ + static ssize_t name##_list_read(struct file *file, struct kobject *kobj, \ +@@ -37,9 +45,17 @@ static ssize_t name##_list_read(struct file *file, struct kobject *kobj, \ + loff_t off, size_t count) \ + { \ + struct device *dev = kobj_to_dev(kobj); \ ++ cpumask_var_t mask; \ ++ ssize_t n; \ ++ \ ++ if (!alloc_cpumask_var(&mask, GFP_KERNEL)) \ ++ return -ENOMEM; \ ++ \ ++ cpumask_copy(mask, topology_##mask(dev->id)); \ ++ n = cpumap_print_list_to_buf(buf, mask, off, count); \ ++ free_cpumask_var(mask); \ + \ +- return cpumap_print_list_to_buf(buf, topology_##mask(dev->id), \ +- off, count); \ ++ return n; \ + } + + define_id_show_func(physical_package_id, "%d"); +diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c +index 5ee9a8b8dcfdb8..e809bb2dbe5e07 100644 +--- a/drivers/bluetooth/btnxpuart.c ++++ b/drivers/bluetooth/btnxpuart.c +@@ -1280,6 +1280,7 @@ static void btnxpuart_tx_work(struct work_struct *work) + + while ((skb = nxp_dequeue(nxpdev))) { + len = serdev_device_write_buf(serdev, skb->data, skb->len); ++ serdev_device_wait_until_sent(serdev, 0); + hdev->stat.byte_tx += len; + + skb_pull(skb, len); +diff --git a/drivers/cpuidle/cpuidle-riscv-sbi.c b/drivers/cpuidle/cpuidle-riscv-sbi.c +index c0fe92409175a4..71d433bb0ce694 100644 +--- a/drivers/cpuidle/cpuidle-riscv-sbi.c ++++ b/drivers/cpuidle/cpuidle-riscv-sbi.c +@@ -534,12 +534,12 @@ static int sbi_cpuidle_probe(struct platform_device *pdev) + int cpu, ret; + struct cpuidle_driver *drv; + struct cpuidle_device *dev; +- struct device_node *np, *pds_node; ++ struct device_node *pds_node; + + /* Detect OSI support based on CPU DT nodes */ + sbi_cpuidle_use_osi = true; + for_each_possible_cpu(cpu) { +- np = of_cpu_device_node_get(cpu); ++ struct device_node *np __free(device_node) = of_cpu_device_node_get(cpu); + if (np && + of_property_present(np, "power-domains") && + of_property_present(np, "power-domain-names")) { +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_debug.c b/drivers/gpu/drm/amd/amdkfd/kfd_debug.c +index 94aaf2fc556ca1..9c32c64c407fa9 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_debug.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_debug.c +@@ -349,10 +349,27 @@ int kfd_dbg_set_mes_debug_mode(struct kfd_process_device *pdd, bool sq_trap_en) + { + uint32_t spi_dbg_cntl = pdd->spi_dbg_override | pdd->spi_dbg_launch_mode; + uint32_t flags = pdd->process->dbg_flags; ++ struct amdgpu_device *adev = pdd->dev->adev; ++ int r; + + if (!kfd_dbg_is_per_vmid_supported(pdd->dev)) + return 0; + ++ if (!pdd->proc_ctx_cpu_ptr) { ++ r = amdgpu_amdkfd_alloc_gtt_mem(adev, ++ AMDGPU_MES_PROC_CTX_SIZE, ++ &pdd->proc_ctx_bo, ++ &pdd->proc_ctx_gpu_addr, ++ &pdd->proc_ctx_cpu_ptr, ++ false); ++ if (r) { ++ dev_err(adev->dev, ++ "failed to allocate process context bo\n"); ++ return r; ++ } ++ memset(pdd->proc_ctx_cpu_ptr, 0, AMDGPU_MES_PROC_CTX_SIZE); ++ } ++ + return amdgpu_mes_set_shader_debugger(pdd->dev->adev, pdd->proc_ctx_gpu_addr, spi_dbg_cntl, + pdd->watch_points, flags, sq_trap_en); + } +diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h +index 5f2eac868b7472..cc5e01df151356 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc.h ++++ b/drivers/gpu/drm/amd/display/dc/dc.h +@@ -49,7 +49,7 @@ struct dmub_notification; + + #define DC_VER "3.2.247" + +-#define MAX_SURFACES 3 ++#define MAX_SURFACES 4 + #define MAX_PLANES 6 + #define MAX_STREAMS 6 + #define MIN_VIEWPORT_SIZE 12 +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h b/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h +index 072bd053960594..6b2ab4ec2b5ffe 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h ++++ b/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h +@@ -66,11 +66,15 @@ static inline double dml_max5(double a, double b, double c, double d, double e) + + static inline double dml_ceil(double a, double granularity) + { ++ if (granularity == 0) ++ return 0; + return (double) dcn_bw_ceil2(a, granularity); + } + + static inline double dml_floor(double a, double granularity) + { ++ if (granularity == 0) ++ return 0; + return (double) dcn_bw_floor2(a, granularity); + } + +@@ -114,11 +118,15 @@ static inline double dml_ceil_2(double f) + + static inline double dml_ceil_ex(double x, double granularity) + { ++ if (granularity == 0) ++ return 0; + return (double) dcn_bw_ceil2(x, granularity); + } + + static inline double dml_floor_ex(double x, double granularity) + { ++ if (granularity == 0) ++ return 0; + return (double) dcn_bw_floor2(x, granularity); + } + +diff --git a/drivers/gpu/drm/mediatek/Kconfig b/drivers/gpu/drm/mediatek/Kconfig +index 76cab28e010c51..d2652751d1904c 100644 +--- a/drivers/gpu/drm/mediatek/Kconfig ++++ b/drivers/gpu/drm/mediatek/Kconfig +@@ -10,9 +10,6 @@ config DRM_MEDIATEK + select DRM_KMS_HELPER + select DRM_MIPI_DSI + select DRM_PANEL +- select MEMORY +- select MTK_SMI +- select PHY_MTK_MIPI_DSI + select VIDEOMODE_HELPERS + help + Choose this option if you have a Mediatek SoCs. +@@ -23,7 +20,6 @@ config DRM_MEDIATEK + config DRM_MEDIATEK_DP + tristate "DRM DPTX Support for MediaTek SoCs" + depends on DRM_MEDIATEK +- select PHY_MTK_DP + select DRM_DISPLAY_HELPER + select DRM_DISPLAY_DP_HELPER + select DRM_DP_AUX_BUS +@@ -34,6 +30,5 @@ config DRM_MEDIATEK_HDMI + tristate "DRM HDMI Support for Mediatek SoCs" + depends on DRM_MEDIATEK + select SND_SOC_HDMI_CODEC if SND_SOC +- select PHY_MTK_HDMI + help + DRM/KMS HDMI driver for Mediatek SoCs +diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +index 6f15069da8b020..ce0f441e3f136c 100644 +--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c ++++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +@@ -403,6 +403,29 @@ static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt) + } + } + ++static void mtk_ovl_afbc_layer_config(struct mtk_disp_ovl *ovl, ++ unsigned int idx, ++ struct mtk_plane_pending_state *pending, ++ struct cmdq_pkt *cmdq_pkt) ++{ ++ unsigned int pitch_msb = pending->pitch >> 16; ++ unsigned int hdr_pitch = pending->hdr_pitch; ++ unsigned int hdr_addr = pending->hdr_addr; ++ ++ if (pending->modifier != DRM_FORMAT_MOD_LINEAR) { ++ mtk_ddp_write_relaxed(cmdq_pkt, hdr_addr, &ovl->cmdq_reg, ovl->regs, ++ DISP_REG_OVL_HDR_ADDR(ovl, idx)); ++ mtk_ddp_write_relaxed(cmdq_pkt, ++ OVL_PITCH_MSB_2ND_SUBBUF | pitch_msb, ++ &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_PITCH_MSB(idx)); ++ mtk_ddp_write_relaxed(cmdq_pkt, hdr_pitch, &ovl->cmdq_reg, ovl->regs, ++ DISP_REG_OVL_HDR_PITCH(ovl, idx)); ++ } else { ++ mtk_ddp_write_relaxed(cmdq_pkt, pitch_msb, ++ &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_PITCH_MSB(idx)); ++ } ++} ++ + void mtk_ovl_layer_config(struct device *dev, unsigned int idx, + struct mtk_plane_state *state, + struct cmdq_pkt *cmdq_pkt) +@@ -410,24 +433,12 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx, + struct mtk_disp_ovl *ovl = dev_get_drvdata(dev); + struct mtk_plane_pending_state *pending = &state->pending; + unsigned int addr = pending->addr; +- unsigned int hdr_addr = pending->hdr_addr; +- unsigned int pitch = pending->pitch; +- unsigned int hdr_pitch = pending->hdr_pitch; ++ unsigned int pitch_lsb = pending->pitch & GENMASK(15, 0); + unsigned int fmt = pending->format; + unsigned int offset = (pending->y << 16) | pending->x; + unsigned int src_size = (pending->height << 16) | pending->width; + unsigned int ignore_pixel_alpha = 0; + unsigned int con; +- bool is_afbc = pending->modifier != DRM_FORMAT_MOD_LINEAR; +- union overlay_pitch { +- struct split_pitch { +- u16 lsb; +- u16 msb; +- } split_pitch; +- u32 pitch; +- } overlay_pitch; +- +- overlay_pitch.pitch = pitch; + + if (!pending->enable) { + mtk_ovl_layer_off(dev, idx, cmdq_pkt); +@@ -457,11 +468,12 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx, + } + + if (ovl->data->supports_afbc) +- mtk_ovl_set_afbc(ovl, cmdq_pkt, idx, is_afbc); ++ mtk_ovl_set_afbc(ovl, cmdq_pkt, idx, ++ pending->modifier != DRM_FORMAT_MOD_LINEAR); + + mtk_ddp_write_relaxed(cmdq_pkt, con, &ovl->cmdq_reg, ovl->regs, + DISP_REG_OVL_CON(idx)); +- mtk_ddp_write_relaxed(cmdq_pkt, overlay_pitch.split_pitch.lsb | ignore_pixel_alpha, ++ mtk_ddp_write_relaxed(cmdq_pkt, pitch_lsb | ignore_pixel_alpha, + &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_PITCH(idx)); + mtk_ddp_write_relaxed(cmdq_pkt, src_size, &ovl->cmdq_reg, ovl->regs, + DISP_REG_OVL_SRC_SIZE(idx)); +@@ -470,19 +482,8 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx, + mtk_ddp_write_relaxed(cmdq_pkt, addr, &ovl->cmdq_reg, ovl->regs, + DISP_REG_OVL_ADDR(ovl, idx)); + +- if (is_afbc) { +- mtk_ddp_write_relaxed(cmdq_pkt, hdr_addr, &ovl->cmdq_reg, ovl->regs, +- DISP_REG_OVL_HDR_ADDR(ovl, idx)); +- mtk_ddp_write_relaxed(cmdq_pkt, +- OVL_PITCH_MSB_2ND_SUBBUF | overlay_pitch.split_pitch.msb, +- &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_PITCH_MSB(idx)); +- mtk_ddp_write_relaxed(cmdq_pkt, hdr_pitch, &ovl->cmdq_reg, ovl->regs, +- DISP_REG_OVL_HDR_PITCH(ovl, idx)); +- } else { +- mtk_ddp_write_relaxed(cmdq_pkt, +- overlay_pitch.split_pitch.msb, +- &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_PITCH_MSB(idx)); +- } ++ if (ovl->data->supports_afbc) ++ mtk_ovl_afbc_layer_config(ovl, idx, pending, cmdq_pkt); + + mtk_ovl_set_bit_depth(dev, idx, fmt, cmdq_pkt); + mtk_ovl_layer_on(dev, idx, cmdq_pkt); +diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c +index 48a4defbc66cc8..be4de26c77f917 100644 +--- a/drivers/gpu/drm/mediatek/mtk_dp.c ++++ b/drivers/gpu/drm/mediatek/mtk_dp.c +@@ -458,18 +458,16 @@ static int mtk_dp_set_color_format(struct mtk_dp *mtk_dp, + enum dp_pixelformat color_format) + { + u32 val; +- +- /* update MISC0 */ +- mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3034, +- color_format << DP_TEST_COLOR_FORMAT_SHIFT, +- DP_TEST_COLOR_FORMAT_MASK); ++ u32 misc0_color; + + switch (color_format) { + case DP_PIXELFORMAT_YUV422: + val = PIXEL_ENCODE_FORMAT_DP_ENC0_P0_YCBCR422; ++ misc0_color = DP_COLOR_FORMAT_YCbCr422; + break; + case DP_PIXELFORMAT_RGB: + val = PIXEL_ENCODE_FORMAT_DP_ENC0_P0_RGB; ++ misc0_color = DP_COLOR_FORMAT_RGB; + break; + default: + drm_warn(mtk_dp->drm_dev, "Unsupported color format: %d\n", +@@ -477,6 +475,11 @@ static int mtk_dp_set_color_format(struct mtk_dp *mtk_dp, + return -EINVAL; + } + ++ /* update MISC0 */ ++ mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_3034, ++ misc0_color, ++ DP_TEST_COLOR_FORMAT_MASK); ++ + mtk_dp_update_bits(mtk_dp, MTK_DP_ENC0_P0_303C, + val, PIXEL_ENCODE_FORMAT_DP_ENC0_P0_MASK); + return 0; +@@ -2002,7 +2005,6 @@ static enum drm_connector_status mtk_dp_bdg_detect(struct drm_bridge *bridge) + struct mtk_dp *mtk_dp = mtk_dp_from_bridge(bridge); + enum drm_connector_status ret = connector_status_disconnected; + bool enabled = mtk_dp->enabled; +- u8 sink_count = 0; + + if (!mtk_dp->train_info.cable_plugged_in) + return ret; +@@ -2017,8 +2019,8 @@ static enum drm_connector_status mtk_dp_bdg_detect(struct drm_bridge *bridge) + * function, we just need to check the HPD connection to check + * whether we connect to a sink device. + */ +- drm_dp_dpcd_readb(&mtk_dp->aux, DP_SINK_COUNT, &sink_count); +- if (DP_GET_SINK_COUNT(sink_count)) ++ ++ if (drm_dp_read_sink_count(&mtk_dp->aux) > 0) + ret = connector_status_connected; + + if (!enabled) +@@ -2310,12 +2312,19 @@ mtk_dp_bridge_mode_valid(struct drm_bridge *bridge, + { + struct mtk_dp *mtk_dp = mtk_dp_from_bridge(bridge); + u32 bpp = info->color_formats & DRM_COLOR_FORMAT_YCBCR422 ? 16 : 24; +- u32 rate = min_t(u32, drm_dp_max_link_rate(mtk_dp->rx_cap) * +- drm_dp_max_lane_count(mtk_dp->rx_cap), +- drm_dp_bw_code_to_link_rate(mtk_dp->max_linkrate) * +- mtk_dp->max_lanes); ++ u32 lane_count_min = mtk_dp->train_info.lane_count; ++ u32 rate = drm_dp_bw_code_to_link_rate(mtk_dp->train_info.link_rate) * ++ lane_count_min; + +- if (rate < mode->clock * bpp / 8) ++ /* ++ *FEC overhead is approximately 2.4% from DP 1.4a spec 2.2.1.4.2. ++ *The down-spread amplitude shall either be disabled (0.0%) or up ++ *to 0.5% from 1.4a 3.5.2.6. Add up to approximately 3% total overhead. ++ * ++ *Because rate is already divided by 10, ++ *mode->clock does not need to be multiplied by 10 ++ */ ++ if ((rate * 97 / 100) < (mode->clock * bpp / 8)) + return MODE_CLOCK_HIGH; + + return MODE_OK; +@@ -2356,10 +2365,9 @@ static u32 *mtk_dp_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge, + struct drm_display_mode *mode = &crtc_state->adjusted_mode; + struct drm_display_info *display_info = + &conn_state->connector->display_info; +- u32 rate = min_t(u32, drm_dp_max_link_rate(mtk_dp->rx_cap) * +- drm_dp_max_lane_count(mtk_dp->rx_cap), +- drm_dp_bw_code_to_link_rate(mtk_dp->max_linkrate) * +- mtk_dp->max_lanes); ++ u32 lane_count_min = mtk_dp->train_info.lane_count; ++ u32 rate = drm_dp_bw_code_to_link_rate(mtk_dp->train_info.link_rate) * ++ lane_count_min; + + *num_input_fmts = 0; + +@@ -2368,8 +2376,8 @@ static u32 *mtk_dp_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge, + * datarate of YUV422 and sink device supports YUV422, we output YUV422 + * format. Use this condition, we can support more resolution. + */ +- if ((rate < (mode->clock * 24 / 8)) && +- (rate > (mode->clock * 16 / 8)) && ++ if (((rate * 97 / 100) < (mode->clock * 24 / 8)) && ++ ((rate * 97 / 100) > (mode->clock * 16 / 8)) && + (display_info->color_formats & DRM_COLOR_FORMAT_YCBCR422)) { + input_fmts = kcalloc(1, sizeof(*input_fmts), GFP_KERNEL); + if (!input_fmts) +diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c +index 600f4ccc90d378..8b41a07c3641f5 100644 +--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c ++++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c +@@ -633,6 +633,8 @@ static int mtk_drm_bind(struct device *dev) + err_free: + private->drm = NULL; + drm_dev_put(drm); ++ for (i = 0; i < private->data->mmsys_dev_num; i++) ++ private->all_drm_private[i]->drm = NULL; + return ret; + } + +diff --git a/drivers/hwmon/drivetemp.c b/drivers/hwmon/drivetemp.c +index 6bdd21aa005ab8..2a4ec55ddb47ed 100644 +--- a/drivers/hwmon/drivetemp.c ++++ b/drivers/hwmon/drivetemp.c +@@ -165,6 +165,7 @@ static int drivetemp_scsi_command(struct drivetemp_data *st, + { + u8 scsi_cmd[MAX_COMMAND_SIZE]; + enum req_op op; ++ int err; + + memset(scsi_cmd, 0, sizeof(scsi_cmd)); + scsi_cmd[0] = ATA_16; +@@ -192,8 +193,11 @@ static int drivetemp_scsi_command(struct drivetemp_data *st, + scsi_cmd[12] = lba_high; + scsi_cmd[14] = ata_command; + +- return scsi_execute_cmd(st->sdev, scsi_cmd, op, st->smartdata, +- ATA_SECT_SIZE, HZ, 5, NULL); ++ err = scsi_execute_cmd(st->sdev, scsi_cmd, op, st->smartdata, ++ ATA_SECT_SIZE, HZ, 5, NULL); ++ if (err > 0) ++ err = -EIO; ++ return err; + } + + static int drivetemp_ata_command(struct drivetemp_data *st, u8 feature, +diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c +index 34e06e2e51d625..d2060d394c8d27 100644 +--- a/drivers/iio/adc/ad7124.c ++++ b/drivers/iio/adc/ad7124.c +@@ -923,6 +923,9 @@ static int ad7124_setup(struct ad7124_state *st) + * set all channels to this default value. + */ + ad7124_set_channel_odr(st, i, 10); ++ ++ /* Disable all channels to prevent unintended conversions. */ ++ ad_sd_write_reg(&st->sd, AD7124_CHANNEL(i), 2, 0); + } + + return ret; +diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c +index de6650f9c4b1c2..55f0c1afe505e7 100644 +--- a/drivers/iio/adc/at91_adc.c ++++ b/drivers/iio/adc/at91_adc.c +@@ -984,7 +984,7 @@ static int at91_ts_register(struct iio_dev *idev, + return ret; + + err: +- input_free_device(st->ts_input); ++ input_free_device(input); + return ret; + } + +diff --git a/drivers/iio/adc/rockchip_saradc.c b/drivers/iio/adc/rockchip_saradc.c +index 1c0042fbbb5481..929cba215d99ab 100644 +--- a/drivers/iio/adc/rockchip_saradc.c ++++ b/drivers/iio/adc/rockchip_saradc.c +@@ -368,6 +368,8 @@ static irqreturn_t rockchip_saradc_trigger_handler(int irq, void *p) + int ret; + int i, j = 0; + ++ memset(&data, 0, sizeof(data)); ++ + mutex_lock(&info->lock); + + for_each_set_bit(i, i_dev->active_scan_mask, i_dev->masklength) { +diff --git a/drivers/iio/adc/ti-ads124s08.c b/drivers/iio/adc/ti-ads124s08.c +index 4ca62121f0d176..c6004f2b5d3d1c 100644 +--- a/drivers/iio/adc/ti-ads124s08.c ++++ b/drivers/iio/adc/ti-ads124s08.c +@@ -183,9 +183,9 @@ static int ads124s_reset(struct iio_dev *indio_dev) + struct ads124s_private *priv = iio_priv(indio_dev); + + if (priv->reset_gpio) { +- gpiod_set_value(priv->reset_gpio, 0); ++ gpiod_set_value_cansleep(priv->reset_gpio, 0); + udelay(200); +- gpiod_set_value(priv->reset_gpio, 1); ++ gpiod_set_value_cansleep(priv->reset_gpio, 1); + } else { + return ads124s_write_cmd(indio_dev, ADS124S08_CMD_RESET); + } +diff --git a/drivers/iio/adc/ti-ads8688.c b/drivers/iio/adc/ti-ads8688.c +index ef06a897421ac4..66a3b67019b8d9 100644 +--- a/drivers/iio/adc/ti-ads8688.c ++++ b/drivers/iio/adc/ti-ads8688.c +@@ -382,7 +382,7 @@ static irqreturn_t ads8688_trigger_handler(int irq, void *p) + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + /* Ensure naturally aligned timestamp */ +- u16 buffer[ADS8688_MAX_CHANNELS + sizeof(s64)/sizeof(u16)] __aligned(8); ++ u16 buffer[ADS8688_MAX_CHANNELS + sizeof(s64)/sizeof(u16)] __aligned(8) = { }; + int i, j = 0; + + for (i = 0; i < indio_dev->masklength; i++) { +diff --git a/drivers/iio/dummy/iio_simple_dummy_buffer.c b/drivers/iio/dummy/iio_simple_dummy_buffer.c +index 9b2f99449a8292..bc85fe6610c138 100644 +--- a/drivers/iio/dummy/iio_simple_dummy_buffer.c ++++ b/drivers/iio/dummy/iio_simple_dummy_buffer.c +@@ -48,7 +48,7 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p) + int i = 0, j; + u16 *data; + +- data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); ++ data = kzalloc(indio_dev->scan_bytes, GFP_KERNEL); + if (!data) + goto done; + +diff --git a/drivers/iio/gyro/fxas21002c_core.c b/drivers/iio/gyro/fxas21002c_core.c +index c28d17ca6f5ee0..aabc5e2d788d15 100644 +--- a/drivers/iio/gyro/fxas21002c_core.c ++++ b/drivers/iio/gyro/fxas21002c_core.c +@@ -730,14 +730,21 @@ static irqreturn_t fxas21002c_trigger_handler(int irq, void *p) + int ret; + + mutex_lock(&data->lock); ++ ret = fxas21002c_pm_get(data); ++ if (ret < 0) ++ goto out_unlock; ++ + ret = regmap_bulk_read(data->regmap, FXAS21002C_REG_OUT_X_MSB, + data->buffer, CHANNEL_SCAN_MAX * sizeof(s16)); + if (ret < 0) +- goto out_unlock; ++ goto out_pm_put; + + iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + data->timestamp); + ++out_pm_put: ++ fxas21002c_pm_put(data); ++ + out_unlock: + mutex_unlock(&data->lock); + +diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c +index a5e81906e37ecf..d938bc45439729 100644 +--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c ++++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c +@@ -17,6 +17,7 @@ + #include + + #include ++#include + + #include "inv_icm42600.h" + #include "inv_icm42600_buffer.h" +@@ -725,6 +726,8 @@ static int inv_icm42600_suspend(struct device *dev) + static int inv_icm42600_resume(struct device *dev) + { + struct inv_icm42600_state *st = dev_get_drvdata(dev); ++ struct inv_sensors_timestamp *gyro_ts = iio_priv(st->indio_gyro); ++ struct inv_sensors_timestamp *accel_ts = iio_priv(st->indio_accel); + int ret; + + mutex_lock(&st->lock); +@@ -745,9 +748,12 @@ static int inv_icm42600_resume(struct device *dev) + goto out_unlock; + + /* restore FIFO data streaming */ +- if (st->fifo.on) ++ if (st->fifo.on) { ++ inv_sensors_timestamp_reset(gyro_ts); ++ inv_sensors_timestamp_reset(accel_ts); + ret = regmap_write(st->map, INV_ICM42600_REG_FIFO_CONFIG, + INV_ICM42600_FIFO_CONFIG_STREAM); ++ } + + out_unlock: + mutex_unlock(&st->lock); +diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c +index 958167b31241e6..09d2db8f8bae14 100644 +--- a/drivers/iio/imu/kmx61.c ++++ b/drivers/iio/imu/kmx61.c +@@ -1192,7 +1192,7 @@ static irqreturn_t kmx61_trigger_handler(int irq, void *p) + struct kmx61_data *data = kmx61_get_data(indio_dev); + int bit, ret, i = 0; + u8 base; +- s16 buffer[8]; ++ s16 buffer[8] = { }; + + if (indio_dev == data->acc_indio_dev) + base = KMX61_ACC_XOUT_L; +diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c +index 079e30c522bbd0..8255035ff124f3 100644 +--- a/drivers/iio/inkern.c ++++ b/drivers/iio/inkern.c +@@ -514,7 +514,7 @@ struct iio_channel *iio_channel_get_all(struct device *dev) + return chans; + + error_free_chans: +- for (i = 0; i < nummaps; i++) ++ for (i = 0; i < mapind; i++) + iio_device_put(chans[i].indio_dev); + kfree(chans); + error_ret: +diff --git a/drivers/iio/light/vcnl4035.c b/drivers/iio/light/vcnl4035.c +index 56bbefbc0ae643..fe3c4c5db6205d 100644 +--- a/drivers/iio/light/vcnl4035.c ++++ b/drivers/iio/light/vcnl4035.c +@@ -105,7 +105,7 @@ static irqreturn_t vcnl4035_trigger_consumer_handler(int irq, void *p) + struct iio_dev *indio_dev = pf->indio_dev; + struct vcnl4035_data *data = iio_priv(indio_dev); + /* Ensure naturally aligned timestamp */ +- u8 buffer[ALIGN(sizeof(u16), sizeof(s64)) + sizeof(s64)] __aligned(8); ++ u8 buffer[ALIGN(sizeof(u16), sizeof(s64)) + sizeof(s64)] __aligned(8) = { }; + int ret; + + ret = regmap_read(data->regmap, VCNL4035_ALS_DATA, (int *)buffer); +diff --git a/drivers/iio/pressure/zpa2326.c b/drivers/iio/pressure/zpa2326.c +index 421e059d1f190a..ef1d0349f4247d 100644 +--- a/drivers/iio/pressure/zpa2326.c ++++ b/drivers/iio/pressure/zpa2326.c +@@ -586,6 +586,8 @@ static int zpa2326_fill_sample_buffer(struct iio_dev *indio_dev, + } sample; + int err; + ++ memset(&sample, 0, sizeof(sample)); ++ + if (test_bit(0, indio_dev->active_scan_mask)) { + /* Get current pressure from hardware FIFO. */ + err = zpa2326_dequeue_pressure(indio_dev, &sample.pressure); +diff --git a/drivers/md/dm-ebs-target.c b/drivers/md/dm-ebs-target.c +index 435b45201f4d61..66d9622b684dd4 100644 +--- a/drivers/md/dm-ebs-target.c ++++ b/drivers/md/dm-ebs-target.c +@@ -442,7 +442,7 @@ static int ebs_iterate_devices(struct dm_target *ti, + static struct target_type ebs_target = { + .name = "ebs", + .version = {1, 0, 1}, +- .features = DM_TARGET_PASSES_INTEGRITY, ++ .features = 0, + .module = THIS_MODULE, + .ctr = ebs_ctr, + .dtr = ebs_dtr, +diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c +index 032cefe3e351aa..7935363d13b1d0 100644 +--- a/drivers/md/dm-thin.c ++++ b/drivers/md/dm-thin.c +@@ -2334,10 +2334,9 @@ static struct thin_c *get_first_thin(struct pool *pool) + struct thin_c *tc = NULL; + + rcu_read_lock(); +- if (!list_empty(&pool->active_thins)) { +- tc = list_entry_rcu(pool->active_thins.next, struct thin_c, list); ++ tc = list_first_or_null_rcu(&pool->active_thins, struct thin_c, list); ++ if (tc) + thin_get(tc); +- } + rcu_read_unlock(); + + return tc; +diff --git a/drivers/md/dm-verity-fec.c b/drivers/md/dm-verity-fec.c +index b475200d8586a6..6a7a17c489c998 100644 +--- a/drivers/md/dm-verity-fec.c ++++ b/drivers/md/dm-verity-fec.c +@@ -60,14 +60,19 @@ static int fec_decode_rs8(struct dm_verity *v, struct dm_verity_fec_io *fio, + * to the data block. Caller is responsible for releasing buf. + */ + static u8 *fec_read_parity(struct dm_verity *v, u64 rsb, int index, +- unsigned int *offset, struct dm_buffer **buf) ++ unsigned int *offset, unsigned int par_buf_offset, ++ struct dm_buffer **buf) + { + u64 position, block, rem; + u8 *res; + ++ /* We have already part of parity bytes read, skip to the next block */ ++ if (par_buf_offset) ++ index++; ++ + position = (index + rsb) * v->fec->roots; + block = div64_u64_rem(position, v->fec->io_size, &rem); +- *offset = (unsigned int)rem; ++ *offset = par_buf_offset ? 0 : (unsigned int)rem; + + res = dm_bufio_read(v->fec->bufio, block, buf); + if (IS_ERR(res)) { +@@ -127,10 +132,11 @@ static int fec_decode_bufs(struct dm_verity *v, struct dm_verity_fec_io *fio, + { + int r, corrected = 0, res; + struct dm_buffer *buf; +- unsigned int n, i, offset; +- u8 *par, *block; ++ unsigned int n, i, offset, par_buf_offset = 0; ++ u8 *par, *block, par_buf[DM_VERITY_FEC_RSM - DM_VERITY_FEC_MIN_RSN]; + +- par = fec_read_parity(v, rsb, block_offset, &offset, &buf); ++ par = fec_read_parity(v, rsb, block_offset, &offset, ++ par_buf_offset, &buf); + if (IS_ERR(par)) + return PTR_ERR(par); + +@@ -140,7 +146,8 @@ static int fec_decode_bufs(struct dm_verity *v, struct dm_verity_fec_io *fio, + */ + fec_for_each_buffer_rs_block(fio, n, i) { + block = fec_buffer_rs_block(v, fio, n, i); +- res = fec_decode_rs8(v, fio, block, &par[offset], neras); ++ memcpy(&par_buf[par_buf_offset], &par[offset], v->fec->roots - par_buf_offset); ++ res = fec_decode_rs8(v, fio, block, par_buf, neras); + if (res < 0) { + r = res; + goto error; +@@ -153,12 +160,21 @@ static int fec_decode_bufs(struct dm_verity *v, struct dm_verity_fec_io *fio, + if (block_offset >= 1 << v->data_dev_block_bits) + goto done; + +- /* read the next block when we run out of parity bytes */ +- offset += v->fec->roots; ++ /* Read the next block when we run out of parity bytes */ ++ offset += (v->fec->roots - par_buf_offset); ++ /* Check if parity bytes are split between blocks */ ++ if (offset < v->fec->io_size && (offset + v->fec->roots) > v->fec->io_size) { ++ par_buf_offset = v->fec->io_size - offset; ++ memcpy(par_buf, &par[offset], par_buf_offset); ++ offset += par_buf_offset; ++ } else ++ par_buf_offset = 0; ++ + if (offset >= v->fec->io_size) { + dm_bufio_release(buf); + +- par = fec_read_parity(v, rsb, block_offset, &offset, &buf); ++ par = fec_read_parity(v, rsb, block_offset, &offset, ++ par_buf_offset, &buf); + if (IS_ERR(par)) + return PTR_ERR(par); + } +@@ -743,10 +759,7 @@ int verity_fec_ctr(struct dm_verity *v) + return -E2BIG; + } + +- if ((f->roots << SECTOR_SHIFT) & ((1 << v->data_dev_block_bits) - 1)) +- f->io_size = 1 << v->data_dev_block_bits; +- else +- f->io_size = v->fec->roots << SECTOR_SHIFT; ++ f->io_size = 1 << v->data_dev_block_bits; + + f->bufio = dm_bufio_client_create(f->dev->bdev, + f->io_size, +diff --git a/drivers/md/persistent-data/dm-array.c b/drivers/md/persistent-data/dm-array.c +index 798c9c53a34353..b1fdfe53e93778 100644 +--- a/drivers/md/persistent-data/dm-array.c ++++ b/drivers/md/persistent-data/dm-array.c +@@ -917,23 +917,27 @@ static int load_ablock(struct dm_array_cursor *c) + if (c->block) + unlock_ablock(c->info, c->block); + +- c->block = NULL; +- c->ab = NULL; + c->index = 0; + + r = dm_btree_cursor_get_value(&c->cursor, &key, &value_le); + if (r) { + DMERR("dm_btree_cursor_get_value failed"); +- dm_btree_cursor_end(&c->cursor); ++ goto out; + + } else { + r = get_ablock(c->info, le64_to_cpu(value_le), &c->block, &c->ab); + if (r) { + DMERR("get_ablock failed"); +- dm_btree_cursor_end(&c->cursor); ++ goto out; + } + } + ++ return 0; ++ ++out: ++ dm_btree_cursor_end(&c->cursor); ++ c->block = NULL; ++ c->ab = NULL; + return r; + } + +@@ -956,10 +960,10 @@ EXPORT_SYMBOL_GPL(dm_array_cursor_begin); + + void dm_array_cursor_end(struct dm_array_cursor *c) + { +- if (c->block) { ++ if (c->block) + unlock_ablock(c->info, c->block); +- dm_btree_cursor_end(&c->cursor); +- } ++ ++ dm_btree_cursor_end(&c->cursor); + } + EXPORT_SYMBOL_GPL(dm_array_cursor_end); + +@@ -999,6 +1003,7 @@ int dm_array_cursor_skip(struct dm_array_cursor *c, uint32_t count) + } + + count -= remaining; ++ c->index += (remaining - 1); + r = dm_array_cursor_next(c); + + } while (!r); +diff --git a/drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gpio.c b/drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gpio.c +index e616e3ec2b42fd..3c1359d8d4e692 100644 +--- a/drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gpio.c ++++ b/drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gpio.c +@@ -148,7 +148,7 @@ static int pci1xxxx_gpio_set_config(struct gpio_chip *gpio, unsigned int offset, + pci1xxx_assign_bit(priv->reg_base, OPENDRAIN_OFFSET(offset), (offset % 32), true); + break; + default: +- ret = -EOPNOTSUPP; ++ ret = -ENOTSUPP; + break; + } + spin_unlock_irqrestore(&priv->lock, flags); +@@ -277,7 +277,7 @@ static irqreturn_t pci1xxxx_gpio_irq_handler(int irq, void *dev_id) + writel(BIT(bit), priv->reg_base + INTR_STATUS_OFFSET(gpiobank)); + spin_unlock_irqrestore(&priv->lock, flags); + irq = irq_find_mapping(gc->irq.domain, (bit + (gpiobank * 32))); +- generic_handle_irq(irq); ++ handle_nested_irq(irq); + } + } + spin_lock_irqsave(&priv->lock, flags); +diff --git a/drivers/net/ethernet/amd/pds_core/devlink.c b/drivers/net/ethernet/amd/pds_core/devlink.c +index d8218bb153d9ed..971d4278280d65 100644 +--- a/drivers/net/ethernet/amd/pds_core/devlink.c ++++ b/drivers/net/ethernet/amd/pds_core/devlink.c +@@ -117,7 +117,7 @@ int pdsc_dl_info_get(struct devlink *dl, struct devlink_info_req *req, + if (err && err != -EIO) + return err; + +- listlen = fw_list.num_fw_slots; ++ listlen = min(fw_list.num_fw_slots, ARRAY_SIZE(fw_list.fw_names)); + for (i = 0; i < listlen; i++) { + if (i < ARRAY_SIZE(fw_slotnames)) + strscpy(buf, fw_slotnames[i], sizeof(buf)); +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c +index 7689086371e03c..2980963208cbf4 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c +@@ -159,7 +159,7 @@ int bnxt_send_msg(struct bnxt_en_dev *edev, + + rc = hwrm_req_replace(bp, req, fw_msg->msg, fw_msg->msg_len); + if (rc) +- return rc; ++ goto drop_req; + + hwrm_req_timeout(bp, req, fw_msg->timeout); + resp = hwrm_req_hold(bp, req); +@@ -171,6 +171,7 @@ int bnxt_send_msg(struct bnxt_en_dev *edev, + + memcpy(fw_msg->resp, resp, resp_len); + } ++drop_req: + hwrm_req_drop(bp, req); + return rc; + } +diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +index b215ff14da1bc4..3989c9491f0f1e 100644 +--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c ++++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +@@ -1799,7 +1799,10 @@ void cxgb4_remove_tid(struct tid_info *t, unsigned int chan, unsigned int tid, + struct adapter *adap = container_of(t, struct adapter, tids); + struct sk_buff *skb; + +- WARN_ON(tid_out_of_range(&adap->tids, tid)); ++ if (tid_out_of_range(&adap->tids, tid)) { ++ dev_err(adap->pdev_dev, "tid %d out of range\n", tid); ++ return; ++ } + + if (t->tid_tab[tid - adap->tids.tid_base]) { + t->tid_tab[tid - adap->tids.tid_base] = NULL; +diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c +index d70305654e7d07..90d433b36799fb 100644 +--- a/drivers/net/ethernet/google/gve/gve_main.c ++++ b/drivers/net/ethernet/google/gve/gve_main.c +@@ -2009,14 +2009,18 @@ static void gve_service_task(struct work_struct *work) + + static void gve_set_netdev_xdp_features(struct gve_priv *priv) + { ++ xdp_features_t xdp_features; ++ + if (priv->queue_format == GVE_GQI_QPL_FORMAT) { +- priv->dev->xdp_features = NETDEV_XDP_ACT_BASIC; +- priv->dev->xdp_features |= NETDEV_XDP_ACT_REDIRECT; +- priv->dev->xdp_features |= NETDEV_XDP_ACT_NDO_XMIT; +- priv->dev->xdp_features |= NETDEV_XDP_ACT_XSK_ZEROCOPY; ++ xdp_features = NETDEV_XDP_ACT_BASIC; ++ xdp_features |= NETDEV_XDP_ACT_REDIRECT; ++ xdp_features |= NETDEV_XDP_ACT_NDO_XMIT; ++ xdp_features |= NETDEV_XDP_ACT_XSK_ZEROCOPY; + } else { +- priv->dev->xdp_features = 0; ++ xdp_features = 0; + } ++ ++ xdp_set_features_flag(priv->dev, xdp_features); + } + + static int gve_init_priv(struct gve_priv *priv, bool skip_describe_device) +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_consts.h b/drivers/net/ethernet/intel/ice/ice_ptp_consts.h +index 4109aa3b2fcd33..87ce20540f572d 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp_consts.h ++++ b/drivers/net/ethernet/intel/ice/ice_ptp_consts.h +@@ -359,9 +359,9 @@ const struct ice_vernier_info_e822 e822_vernier[NUM_ICE_PTP_LNK_SPD] = { + /* rx_desk_rsgb_par */ + 644531250, /* 644.53125 MHz Reed Solomon gearbox */ + /* tx_desk_rsgb_pcs */ +- 644531250, /* 644.53125 MHz Reed Solomon gearbox */ ++ 390625000, /* 390.625 MHz Reed Solomon gearbox */ + /* rx_desk_rsgb_pcs */ +- 644531250, /* 644.53125 MHz Reed Solomon gearbox */ ++ 390625000, /* 390.625 MHz Reed Solomon gearbox */ + /* tx_fixed_delay */ + 1620, + /* pmd_adj_divisor */ +diff --git a/drivers/net/ethernet/intel/igc/igc_base.c b/drivers/net/ethernet/intel/igc/igc_base.c +index a1d815af507d90..1613b562d17c52 100644 +--- a/drivers/net/ethernet/intel/igc/igc_base.c ++++ b/drivers/net/ethernet/intel/igc/igc_base.c +@@ -68,8 +68,11 @@ static s32 igc_init_nvm_params_base(struct igc_hw *hw) + u32 eecd = rd32(IGC_EECD); + u16 size; + +- size = (u16)((eecd & IGC_EECD_SIZE_EX_MASK) >> +- IGC_EECD_SIZE_EX_SHIFT); ++ /* failed to read reg and got all F's */ ++ if (!(~eecd)) ++ return -ENXIO; ++ ++ size = FIELD_GET(IGC_EECD_SIZE_EX_MASK, eecd); + + /* Added to a constant, "size" becomes the left-shift value + * for setting word_size. +@@ -162,8 +165,7 @@ static s32 igc_init_phy_params_base(struct igc_hw *hw) + phy->reset_delay_us = 100; + + /* set lan id */ +- hw->bus.func = (rd32(IGC_STATUS) & IGC_STATUS_FUNC_MASK) >> +- IGC_STATUS_FUNC_SHIFT; ++ hw->bus.func = FIELD_GET(IGC_STATUS_FUNC_MASK, rd32(IGC_STATUS)); + + /* Make sure the PHY is in a good state. Several people have reported + * firmware leaving the PHY's page select register set to something +@@ -223,6 +225,8 @@ static s32 igc_get_invariants_base(struct igc_hw *hw) + + /* NVM initialization */ + ret_val = igc_init_nvm_params_base(hw); ++ if (ret_val) ++ goto out; + switch (hw->mac.type) { + case igc_i225: + ret_val = igc_init_nvm_params_i225(hw); +diff --git a/drivers/net/ethernet/intel/igc/igc_i225.c b/drivers/net/ethernet/intel/igc/igc_i225.c +index d2562c8e8015e7..0dd61719f1edc4 100644 +--- a/drivers/net/ethernet/intel/igc/igc_i225.c ++++ b/drivers/net/ethernet/intel/igc/igc_i225.c +@@ -579,9 +579,8 @@ s32 igc_set_ltr_i225(struct igc_hw *hw, bool link) + + /* Calculate tw_system (nsec). */ + if (speed == SPEED_100) { +- tw_system = ((rd32(IGC_EEE_SU) & +- IGC_TW_SYSTEM_100_MASK) >> +- IGC_TW_SYSTEM_100_SHIFT) * 500; ++ tw_system = FIELD_GET(IGC_TW_SYSTEM_100_MASK, ++ rd32(IGC_EEE_SU)) * 500; + } else { + tw_system = (rd32(IGC_EEE_SU) & + IGC_TW_SYSTEM_1000_MASK) * 500; +diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c +index da1018d8326220..91a4722460f66a 100644 +--- a/drivers/net/ethernet/intel/igc/igc_main.c ++++ b/drivers/net/ethernet/intel/igc/igc_main.c +@@ -3708,8 +3708,7 @@ static int igc_enable_nfc_rule(struct igc_adapter *adapter, + } + + if (rule->filter.match_flags & IGC_FILTER_FLAG_VLAN_TCI) { +- int prio = (rule->filter.vlan_tci & VLAN_PRIO_MASK) >> +- VLAN_PRIO_SHIFT; ++ int prio = FIELD_GET(VLAN_PRIO_MASK, rule->filter.vlan_tci); + + err = igc_add_vlan_prio_filter(adapter, prio, rule->action); + if (err) +@@ -3731,8 +3730,7 @@ static void igc_disable_nfc_rule(struct igc_adapter *adapter, + igc_del_etype_filter(adapter, rule->filter.etype); + + if (rule->filter.match_flags & IGC_FILTER_FLAG_VLAN_TCI) { +- int prio = (rule->filter.vlan_tci & VLAN_PRIO_MASK) >> +- VLAN_PRIO_SHIFT; ++ int prio = FIELD_GET(VLAN_PRIO_MASK, rule->filter.vlan_tci); + + igc_del_vlan_prio_filter(adapter, prio); + } +diff --git a/drivers/net/ethernet/intel/igc/igc_phy.c b/drivers/net/ethernet/intel/igc/igc_phy.c +index d0d9e7170154ca..7cd8716d2ffa3a 100644 +--- a/drivers/net/ethernet/intel/igc/igc_phy.c ++++ b/drivers/net/ethernet/intel/igc/igc_phy.c +@@ -727,7 +727,7 @@ static s32 igc_write_xmdio_reg(struct igc_hw *hw, u16 addr, + */ + s32 igc_write_phy_reg_gpy(struct igc_hw *hw, u32 offset, u16 data) + { +- u8 dev_addr = (offset & GPY_MMD_MASK) >> GPY_MMD_SHIFT; ++ u8 dev_addr = FIELD_GET(GPY_MMD_MASK, offset); + s32 ret_val; + + offset = offset & GPY_REG_MASK; +@@ -758,7 +758,7 @@ s32 igc_write_phy_reg_gpy(struct igc_hw *hw, u32 offset, u16 data) + */ + s32 igc_read_phy_reg_gpy(struct igc_hw *hw, u32 offset, u16 *data) + { +- u8 dev_addr = (offset & GPY_MMD_MASK) >> GPY_MMD_SHIFT; ++ u8 dev_addr = FIELD_GET(GPY_MMD_MASK, offset); + s32 ret_val; + + offset = offset & GPY_REG_MASK; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +index 80af0fc7101fdc..3e6bd27f6315d8 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +@@ -1006,6 +1006,7 @@ static void cmd_work_handler(struct work_struct *work) + complete(&ent->done); + } + up(&cmd->vars.sem); ++ complete(&ent->slotted); + return; + } + } else { +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c +index e2d61a3a7712d3..760405b805f40a 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c +@@ -1,4 +1,5 @@ + // SPDX-License-Identifier: GPL-2.0-only ++#include + #include + #include + #include +@@ -19,6 +20,8 @@ struct tegra_mgbe { + struct reset_control *rst_mac; + struct reset_control *rst_pcs; + ++ u32 iommu_sid; ++ + void __iomem *hv; + void __iomem *regs; + void __iomem *xpcs; +@@ -50,7 +53,6 @@ struct tegra_mgbe { + #define MGBE_WRAP_COMMON_INTR_ENABLE 0x8704 + #define MAC_SBD_INTR BIT(2) + #define MGBE_WRAP_AXI_ASID0_CTRL 0x8400 +-#define MGBE_SID 0x6 + + static int __maybe_unused tegra_mgbe_suspend(struct device *dev) + { +@@ -84,7 +86,7 @@ static int __maybe_unused tegra_mgbe_resume(struct device *dev) + writel(MAC_SBD_INTR, mgbe->regs + MGBE_WRAP_COMMON_INTR_ENABLE); + + /* Program SID */ +- writel(MGBE_SID, mgbe->hv + MGBE_WRAP_AXI_ASID0_CTRL); ++ writel(mgbe->iommu_sid, mgbe->hv + MGBE_WRAP_AXI_ASID0_CTRL); + + value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_STATUS); + if ((value & XPCS_WRAP_UPHY_STATUS_TX_P_UP) == 0) { +@@ -241,6 +243,12 @@ static int tegra_mgbe_probe(struct platform_device *pdev) + if (IS_ERR(mgbe->xpcs)) + return PTR_ERR(mgbe->xpcs); + ++ /* get controller's stream id from iommu property in device tree */ ++ if (!tegra_dev_iommu_get_stream_id(mgbe->dev, &mgbe->iommu_sid)) { ++ dev_err(mgbe->dev, "failed to get iommu stream id\n"); ++ return -EINVAL; ++ } ++ + res.addr = mgbe->regs; + res.irq = irq; + +@@ -346,7 +354,7 @@ static int tegra_mgbe_probe(struct platform_device *pdev) + writel(MAC_SBD_INTR, mgbe->regs + MGBE_WRAP_COMMON_INTR_ENABLE); + + /* Program SID */ +- writel(MGBE_SID, mgbe->hv + MGBE_WRAP_AXI_ASID0_CTRL); ++ writel(mgbe->iommu_sid, mgbe->hv + MGBE_WRAP_AXI_ASID0_CTRL); + + plat->flags |= STMMAC_FLAG_SERDES_UP_AFTER_PHY_LINKUP; + +diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c +index 52130df26aee53..d6bc2309d2a388 100644 +--- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c ++++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c +@@ -242,27 +242,25 @@ int wx_host_interface_command(struct wx *wx, u32 *buffer, + status = read_poll_timeout(rd32, hicr, hicr & WX_MNG_MBOX_CTL_FWRDY, 1000, + timeout * 1000, false, wx, WX_MNG_MBOX_CTL); + ++ buf[0] = rd32(wx, WX_MNG_MBOX); ++ if ((buf[0] & 0xff0000) >> 16 == 0x80) { ++ wx_err(wx, "Unknown FW command: 0x%x\n", buffer[0] & 0xff); ++ status = -EINVAL; ++ goto rel_out; ++ } ++ + /* Check command completion */ + if (status) { +- wx_dbg(wx, "Command has failed with no status valid.\n"); +- +- buf[0] = rd32(wx, WX_MNG_MBOX); +- if ((buffer[0] & 0xff) != (~buf[0] >> 24)) { +- status = -EINVAL; +- goto rel_out; +- } +- if ((buf[0] & 0xff0000) >> 16 == 0x80) { +- wx_dbg(wx, "It's unknown cmd.\n"); +- status = -EINVAL; +- goto rel_out; +- } +- ++ wx_err(wx, "Command has failed with no status valid.\n"); + wx_dbg(wx, "write value:\n"); + for (i = 0; i < dword_len; i++) + wx_dbg(wx, "%x ", buffer[i]); + wx_dbg(wx, "read value:\n"); + for (i = 0; i < dword_len; i++) + wx_dbg(wx, "%x ", buf[i]); ++ wx_dbg(wx, "\ncheck: %x %x\n", buffer[0] & 0xff, ~buf[0] >> 24); ++ ++ goto rel_out; + } + + if (!return_data) +diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c +index 4ec0dab3887299..0a0ad3d77557f9 100644 +--- a/drivers/net/ieee802154/ca8210.c ++++ b/drivers/net/ieee802154/ca8210.c +@@ -3078,7 +3078,11 @@ static int ca8210_probe(struct spi_device *spi_device) + spi_set_drvdata(priv->spi, priv); + if (IS_ENABLED(CONFIG_IEEE802154_CA8210_DEBUGFS)) { + cascoda_api_upstream = ca8210_test_int_driver_write; +- ca8210_test_interface_init(priv); ++ ret = ca8210_test_interface_init(priv); ++ if (ret) { ++ dev_crit(&spi_device->dev, "ca8210_test_interface_init failed\n"); ++ goto error; ++ } + } else { + cascoda_api_upstream = NULL; + } +diff --git a/drivers/platform/x86/amd/pmc/pmc.c b/drivers/platform/x86/amd/pmc/pmc.c +index f49b1bb258c73d..70907e8f3ea96d 100644 +--- a/drivers/platform/x86/amd/pmc/pmc.c ++++ b/drivers/platform/x86/amd/pmc/pmc.c +@@ -878,6 +878,10 @@ static int amd_pmc_suspend_handler(struct device *dev) + { + struct amd_pmc_dev *pdev = dev_get_drvdata(dev); + ++ /* ++ * Must be called only from the same set of dev_pm_ops handlers ++ * as i8042_pm_suspend() is called: currently just from .suspend. ++ */ + if (pdev->disable_8042_wakeup && !disable_workarounds) { + int rc = amd_pmc_wa_irq1(pdev); + +@@ -890,7 +894,9 @@ static int amd_pmc_suspend_handler(struct device *dev) + return 0; + } + +-static DEFINE_SIMPLE_DEV_PM_OPS(amd_pmc_pm, amd_pmc_suspend_handler, NULL); ++static const struct dev_pm_ops amd_pmc_pm = { ++ .suspend = amd_pmc_suspend_handler, ++}; + + static const struct pci_device_id pmc_pci_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_PS) }, +diff --git a/drivers/pmdomain/imx/gpcv2.c b/drivers/pmdomain/imx/gpcv2.c +index fbd3d92f8cd8f2..13fce2b134f60a 100644 +--- a/drivers/pmdomain/imx/gpcv2.c ++++ b/drivers/pmdomain/imx/gpcv2.c +@@ -1449,12 +1449,12 @@ static int imx_gpcv2_probe(struct platform_device *pdev) + .max_register = SZ_4K, + }; + struct device *dev = &pdev->dev; +- struct device_node *pgc_np, *np; ++ struct device_node *pgc_np __free(device_node) = ++ of_get_child_by_name(dev->of_node, "pgc"); + struct regmap *regmap; + void __iomem *base; + int ret; + +- pgc_np = of_get_child_by_name(dev->of_node, "pgc"); + if (!pgc_np) { + dev_err(dev, "No power domains specified in DT\n"); + return -EINVAL; +@@ -1471,7 +1471,7 @@ static int imx_gpcv2_probe(struct platform_device *pdev) + return ret; + } + +- for_each_child_of_node(pgc_np, np) { ++ for_each_child_of_node_scoped(pgc_np, np) { + struct platform_device *pd_pdev; + struct imx_pgc_domain *domain; + u32 domain_index; +@@ -1482,7 +1482,6 @@ static int imx_gpcv2_probe(struct platform_device *pdev) + ret = of_property_read_u32(np, "reg", &domain_index); + if (ret) { + dev_err(dev, "Failed to read 'reg' property\n"); +- of_node_put(np); + return ret; + } + +@@ -1497,7 +1496,6 @@ static int imx_gpcv2_probe(struct platform_device *pdev) + domain_index); + if (!pd_pdev) { + dev_err(dev, "Failed to allocate platform device\n"); +- of_node_put(np); + return -ENOMEM; + } + +@@ -1506,7 +1504,6 @@ static int imx_gpcv2_probe(struct platform_device *pdev) + sizeof(domain_data->domains[domain_index])); + if (ret) { + platform_device_put(pd_pdev); +- of_node_put(np); + return ret; + } + +@@ -1523,7 +1520,6 @@ static int imx_gpcv2_probe(struct platform_device *pdev) + ret = platform_device_add(pd_pdev); + if (ret) { + platform_device_put(pd_pdev); +- of_node_put(np); + return ret; + } + } +diff --git a/drivers/staging/iio/frequency/ad9832.c b/drivers/staging/iio/frequency/ad9832.c +index d58d99d8375ea8..b40609b92980f5 100644 +--- a/drivers/staging/iio/frequency/ad9832.c ++++ b/drivers/staging/iio/frequency/ad9832.c +@@ -158,7 +158,7 @@ static int ad9832_write_frequency(struct ad9832_state *st, + static int ad9832_write_phase(struct ad9832_state *st, + unsigned long addr, unsigned long phase) + { +- if (phase > BIT(AD9832_PHASE_BITS)) ++ if (phase >= BIT(AD9832_PHASE_BITS)) + return -EINVAL; + + st->phase_data[0] = cpu_to_be16((AD9832_CMD_PHA8BITSW << CMD_SHIFT) | +diff --git a/drivers/staging/iio/frequency/ad9834.c b/drivers/staging/iio/frequency/ad9834.c +index cfdfe66d74f17c..bc879f87237cb2 100644 +--- a/drivers/staging/iio/frequency/ad9834.c ++++ b/drivers/staging/iio/frequency/ad9834.c +@@ -131,7 +131,7 @@ static int ad9834_write_frequency(struct ad9834_state *st, + static int ad9834_write_phase(struct ad9834_state *st, + unsigned long addr, unsigned long phase) + { +- if (phase > BIT(AD9834_PHASE_BITS)) ++ if (phase >= BIT(AD9834_PHASE_BITS)) + return -EINVAL; + st->data = cpu_to_be16(addr | phase); + +diff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c +index 4e5f86c2145616..0f520cf923a1e6 100644 +--- a/drivers/thermal/thermal_of.c ++++ b/drivers/thermal/thermal_of.c +@@ -203,6 +203,7 @@ static struct device_node *of_thermal_zone_find(struct device_node *sensor, int + goto out; + } + ++ of_node_put(sensor_specs.np); + if ((sensor == sensor_specs.np) && id == (sensor_specs.args_count ? + sensor_specs.args[0] : 0)) { + pr_debug("sensor %pOFn id=%d belongs to %pOFn\n", sensor, id, child); +diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c +index 3449f8790e462e..c536028e92dc2e 100644 +--- a/drivers/tty/serial/8250/8250_core.c ++++ b/drivers/tty/serial/8250/8250_core.c +@@ -1131,6 +1131,9 @@ int serial8250_register_8250_port(const struct uart_8250_port *up) + uart->dl_write = up->dl_write; + + if (uart->port.type != PORT_8250_CIR) { ++ if (uart_console_registered(&uart->port)) ++ pm_runtime_get_sync(uart->port.dev); ++ + if (serial8250_isa_config != NULL) + serial8250_isa_config(0, &uart->port, + &uart->capabilities); +diff --git a/drivers/ufs/core/ufshcd-priv.h b/drivers/ufs/core/ufshcd-priv.h +index 099a54009a16f3..524863b157e8aa 100644 +--- a/drivers/ufs/core/ufshcd-priv.h ++++ b/drivers/ufs/core/ufshcd-priv.h +@@ -242,12 +242,6 @@ static inline void ufshcd_vops_config_scaling_param(struct ufs_hba *hba, + hba->vops->config_scaling_param(hba, p, data); + } + +-static inline void ufshcd_vops_reinit_notify(struct ufs_hba *hba) +-{ +- if (hba->vops && hba->vops->reinit_notify) +- hba->vops->reinit_notify(hba); +-} +- + static inline int ufshcd_vops_mcq_config_resource(struct ufs_hba *hba) + { + if (hba->vops && hba->vops->mcq_config_resource) +diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c +index 84dac90500746b..02696c7f9beff9 100644 +--- a/drivers/ufs/core/ufshcd.c ++++ b/drivers/ufs/core/ufshcd.c +@@ -8795,7 +8795,6 @@ static int ufshcd_probe_hba(struct ufs_hba *hba, bool init_dev_params) + ufshcd_device_reset(hba); + ufs_put_device_desc(hba); + ufshcd_hba_stop(hba); +- ufshcd_vops_reinit_notify(hba); + ret = ufshcd_hba_enable(hba); + if (ret) { + dev_err(hba->dev, "Host controller enable failed\n"); +diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c +index 643157a92c62a7..c999acba0f30c3 100644 +--- a/drivers/ufs/host/ufs-qcom.c ++++ b/drivers/ufs/host/ufs-qcom.c +@@ -455,6 +455,11 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba *hba) + dev_warn(hba->dev, "%s: host reset returned %d\n", + __func__, ret); + ++ if (phy->power_count) { ++ phy_power_off(phy); ++ phy_exit(phy); ++ } ++ + /* phy initialization - calibrate the phy */ + ret = phy_init(phy); + if (ret) { +@@ -1638,13 +1643,6 @@ static void ufs_qcom_config_scaling_param(struct ufs_hba *hba, + } + #endif + +-static void ufs_qcom_reinit_notify(struct ufs_hba *hba) +-{ +- struct ufs_qcom_host *host = ufshcd_get_variant(hba); +- +- phy_power_off(host->generic_phy); +-} +- + /* Resources */ + static const struct ufshcd_res_info ufs_res_info[RES_MAX] = { + {.name = "ufs_mem",}, +@@ -1887,7 +1885,6 @@ static const struct ufs_hba_variant_ops ufs_hba_qcom_vops = { + .device_reset = ufs_qcom_device_reset, + .config_scaling_param = ufs_qcom_config_scaling_param, + .program_key = ufs_qcom_ice_program_key, +- .reinit_notify = ufs_qcom_reinit_notify, + .mcq_config_resource = ufs_qcom_mcq_config_resource, + .get_hba_mac = ufs_qcom_get_hba_mac, + .op_runtime_config = ufs_qcom_op_runtime_config, +diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c +index 477af457c1a1f0..b3cbca361a9696 100644 +--- a/drivers/usb/chipidea/ci_hdrc_imx.c ++++ b/drivers/usb/chipidea/ci_hdrc_imx.c +@@ -362,25 +362,29 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) + data->pinctrl = devm_pinctrl_get(dev); + if (PTR_ERR(data->pinctrl) == -ENODEV) + data->pinctrl = NULL; +- else if (IS_ERR(data->pinctrl)) +- return dev_err_probe(dev, PTR_ERR(data->pinctrl), ++ else if (IS_ERR(data->pinctrl)) { ++ ret = dev_err_probe(dev, PTR_ERR(data->pinctrl), + "pinctrl get failed\n"); ++ goto err_put; ++ } + + data->hsic_pad_regulator = + devm_regulator_get_optional(dev, "hsic"); + if (PTR_ERR(data->hsic_pad_regulator) == -ENODEV) { + /* no pad regulator is needed */ + data->hsic_pad_regulator = NULL; +- } else if (IS_ERR(data->hsic_pad_regulator)) +- return dev_err_probe(dev, PTR_ERR(data->hsic_pad_regulator), ++ } else if (IS_ERR(data->hsic_pad_regulator)) { ++ ret = dev_err_probe(dev, PTR_ERR(data->hsic_pad_regulator), + "Get HSIC pad regulator error\n"); ++ goto err_put; ++ } + + if (data->hsic_pad_regulator) { + ret = regulator_enable(data->hsic_pad_regulator); + if (ret) { + dev_err(dev, + "Failed to enable HSIC pad regulator\n"); +- return ret; ++ goto err_put; + } + } + } +@@ -394,13 +398,14 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) + dev_err(dev, + "pinctrl_hsic_idle lookup failed, err=%ld\n", + PTR_ERR(pinctrl_hsic_idle)); +- return PTR_ERR(pinctrl_hsic_idle); ++ ret = PTR_ERR(pinctrl_hsic_idle); ++ goto err_put; + } + + ret = pinctrl_select_state(data->pinctrl, pinctrl_hsic_idle); + if (ret) { + dev_err(dev, "hsic_idle select failed, err=%d\n", ret); +- return ret; ++ goto err_put; + } + + data->pinctrl_hsic_active = pinctrl_lookup_state(data->pinctrl, +@@ -409,7 +414,8 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) + dev_err(dev, + "pinctrl_hsic_active lookup failed, err=%ld\n", + PTR_ERR(data->pinctrl_hsic_active)); +- return PTR_ERR(data->pinctrl_hsic_active); ++ ret = PTR_ERR(data->pinctrl_hsic_active); ++ goto err_put; + } + } + +@@ -513,6 +519,8 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) + if (pdata.flags & CI_HDRC_PMQOS) + cpu_latency_qos_remove_request(&data->pm_qos_req); + data->ci_pdev = NULL; ++err_put: ++ put_device(data->usbmisc_data->dev); + return ret; + } + +@@ -536,6 +544,7 @@ static void ci_hdrc_imx_remove(struct platform_device *pdev) + if (data->hsic_pad_regulator) + regulator_disable(data->hsic_pad_regulator); + } ++ put_device(data->usbmisc_data->dev); + } + + static void ci_hdrc_imx_shutdown(struct platform_device *pdev) +diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c +index 5a2e43331064eb..ff1a941fd2ede4 100644 +--- a/drivers/usb/class/usblp.c ++++ b/drivers/usb/class/usblp.c +@@ -1337,11 +1337,12 @@ static int usblp_set_protocol(struct usblp *usblp, int protocol) + if (protocol < USBLP_FIRST_PROTOCOL || protocol > USBLP_LAST_PROTOCOL) + return -EINVAL; + ++ alts = usblp->protocol[protocol].alt_setting; ++ if (alts < 0) ++ return -EINVAL; ++ + /* Don't unnecessarily set the interface if there's a single alt. */ + if (usblp->intf->num_altsetting > 1) { +- alts = usblp->protocol[protocol].alt_setting; +- if (alts < 0) +- return -EINVAL; + r = usb_set_interface(usblp->dev, usblp->ifnum, alts); + if (r < 0) { + printk(KERN_ERR "usblp: can't set desired altsetting %d on interface %d\n", +diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c +index 1ba3feb5e19000..0944cfae8b5567 100644 +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -2633,13 +2633,13 @@ int usb_new_device(struct usb_device *udev) + err = sysfs_create_link(&udev->dev.kobj, + &port_dev->dev.kobj, "port"); + if (err) +- goto fail; ++ goto out_del_dev; + + err = sysfs_create_link(&port_dev->dev.kobj, + &udev->dev.kobj, "device"); + if (err) { + sysfs_remove_link(&udev->dev.kobj, "port"); +- goto fail; ++ goto out_del_dev; + } + + if (!test_and_set_bit(port1, hub->child_usage_bits)) +@@ -2651,6 +2651,8 @@ int usb_new_device(struct usb_device *udev) + pm_runtime_put_sync_autosuspend(&udev->dev); + return err; + ++out_del_dev: ++ device_del(&udev->dev); + fail: + usb_set_device_state(udev, USB_STATE_NOTATTACHED); + pm_runtime_disable(&udev->dev); +diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c +index 5fb3f55ef06db5..9dd4a4ee61e56b 100644 +--- a/drivers/usb/core/port.c ++++ b/drivers/usb/core/port.c +@@ -451,10 +451,11 @@ static int usb_port_runtime_suspend(struct device *dev) + static void usb_port_shutdown(struct device *dev) + { + struct usb_port *port_dev = to_usb_port(dev); ++ struct usb_device *udev = port_dev->child; + +- if (port_dev->child) { +- usb_disable_usb2_hardware_lpm(port_dev->child); +- usb_unlocked_disable_lpm(port_dev->child); ++ if (udev && !udev->port_is_suspended) { ++ usb_disable_usb2_hardware_lpm(udev); ++ usb_unlocked_disable_lpm(udev); + } + } + +diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h +index d00bf714a7ccfb..516bace7e1dced 100644 +--- a/drivers/usb/dwc3/core.h ++++ b/drivers/usb/dwc3/core.h +@@ -451,6 +451,7 @@ + #define DWC3_DCTL_TRGTULST_SS_INACT (DWC3_DCTL_TRGTULST(6)) + + /* These apply for core versions 1.94a and later */ ++#define DWC3_DCTL_NYET_THRES_MASK (0xf << 20) + #define DWC3_DCTL_NYET_THRES(n) (((n) & 0xf) << 20) + + #define DWC3_DCTL_KEEP_CONNECT BIT(19) +diff --git a/drivers/usb/dwc3/dwc3-am62.c b/drivers/usb/dwc3/dwc3-am62.c +index ea6e29091c0c9a..056ab7246a3a2c 100644 +--- a/drivers/usb/dwc3/dwc3-am62.c ++++ b/drivers/usb/dwc3/dwc3-am62.c +@@ -284,6 +284,7 @@ static void dwc3_ti_remove(struct platform_device *pdev) + + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); ++ pm_runtime_dont_use_autosuspend(dev); + pm_runtime_set_suspended(dev); + } + +diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c +index 656460c0c1dd7e..9b8099cba41429 100644 +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -4208,8 +4208,10 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc) + WARN_ONCE(DWC3_VER_IS_PRIOR(DWC3, 240A) && dwc->has_lpm_erratum, + "LPM Erratum not available on dwc3 revisions < 2.40a\n"); + +- if (dwc->has_lpm_erratum && !DWC3_VER_IS_PRIOR(DWC3, 240A)) ++ if (dwc->has_lpm_erratum && !DWC3_VER_IS_PRIOR(DWC3, 240A)) { ++ reg &= ~DWC3_DCTL_NYET_THRES_MASK; + reg |= DWC3_DCTL_NYET_THRES(dwc->lpm_nyet_threshold); ++ } + + dwc3_gadget_dctl_write_safe(dwc, reg); + } else { +diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig +index b3592bcb0f9668..c7fa0ec74f5e69 100644 +--- a/drivers/usb/gadget/Kconfig ++++ b/drivers/usb/gadget/Kconfig +@@ -210,6 +210,8 @@ config USB_F_MIDI + + config USB_F_MIDI2 + tristate ++ select SND_UMP ++ select SND_UMP_LEGACY_RAWMIDI + + config USB_F_HID + tristate +@@ -444,8 +446,6 @@ config USB_CONFIGFS_F_MIDI2 + depends on USB_CONFIGFS + depends on SND + select USB_LIBCOMPOSITE +- select SND_UMP +- select SND_UMP_LEGACY_RAWMIDI + select USB_F_MIDI2 + help + The MIDI 2.0 function driver provides the generic emulated +diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c +index 60a1abfc565474..3a80600d68068f 100644 +--- a/drivers/usb/gadget/configfs.c ++++ b/drivers/usb/gadget/configfs.c +@@ -824,11 +824,15 @@ static ssize_t gadget_string_s_store(struct config_item *item, const char *page, + { + struct gadget_string *string = to_gadget_string(item); + int size = min(sizeof(string->string), len + 1); ++ ssize_t cpy_len; + + if (len > USB_MAX_STRING_LEN) + return -EINVAL; + +- return strscpy(string->string, page, size); ++ cpy_len = strscpy(string->string, page, size); ++ if (cpy_len > 0 && string->string[cpy_len - 1] == '\n') ++ string->string[cpy_len - 1] = 0; ++ return len; + } + CONFIGFS_ATTR(gadget_string_, s); + +diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c +index fd0f4879f38e8b..4a88546b1b1576 100644 +--- a/drivers/usb/gadget/function/f_fs.c ++++ b/drivers/usb/gadget/function/f_fs.c +@@ -1810,7 +1810,7 @@ static int functionfs_bind(struct ffs_data *ffs, struct usb_composite_dev *cdev) + struct usb_gadget_strings **lang; + int first_id; + +- if (WARN_ON(ffs->state != FFS_ACTIVE ++ if ((ffs->state != FFS_ACTIVE + || test_and_set_bit(FFS_FL_BOUND, &ffs->flags))) + return -EBADFD; + +diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c +index b3dc5f5164f42c..eabd10817e1e7b 100644 +--- a/drivers/usb/gadget/function/f_uac2.c ++++ b/drivers/usb/gadget/function/f_uac2.c +@@ -1176,6 +1176,7 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) + uac2->as_in_alt = 0; + } + ++ std_ac_if_desc.bNumEndpoints = 0; + if (FUOUT_EN(uac2_opts) || FUIN_EN(uac2_opts)) { + uac2->int_ep = usb_ep_autoconfig(gadget, &fs_ep_int_desc); + if (!uac2->int_ep) { +diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c +index 729b0472bab098..fe2737e55f8e89 100644 +--- a/drivers/usb/gadget/function/u_serial.c ++++ b/drivers/usb/gadget/function/u_serial.c +@@ -1398,6 +1398,10 @@ void gserial_disconnect(struct gserial *gser) + /* REVISIT as above: how best to track this? */ + port->port_line_coding = gser->port_line_coding; + ++ /* disable endpoints, aborting down any active I/O */ ++ usb_ep_disable(gser->out); ++ usb_ep_disable(gser->in); ++ + port->port_usb = NULL; + gser->ioport = NULL; + if (port->port.count > 0) { +@@ -1409,10 +1413,6 @@ void gserial_disconnect(struct gserial *gser) + spin_unlock(&port->port_lock); + spin_unlock_irqrestore(&serial_port_lock, flags); + +- /* disable endpoints, aborting down any active I/O */ +- usb_ep_disable(gser->out); +- usb_ep_disable(gser->in); +- + /* finally, free any unused/unusable I/O buffers */ + spin_lock_irqsave(&port->port_lock, flags); + if (port->port.count == 0) +diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c +index 21fd26609252be..e3c391397e0f8c 100644 +--- a/drivers/usb/serial/cp210x.c ++++ b/drivers/usb/serial/cp210x.c +@@ -223,6 +223,7 @@ static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x19CF, 0x3000) }, /* Parrot NMEA GPS Flight Recorder */ + { USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */ + { USB_DEVICE(0x1B1C, 0x1C00) }, /* Corsair USB Dongle */ ++ { USB_DEVICE(0x1B93, 0x1013) }, /* Phoenix Contact UPS Device */ + { USB_DEVICE(0x1BA4, 0x0002) }, /* Silicon Labs 358x factory default */ + { USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */ + { USB_DEVICE(0x1D6F, 0x0010) }, /* Seluxit ApS RF Dongle */ +diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c +index ac1c13b269fc0b..86ac20e2874bab 100644 +--- a/drivers/usb/serial/option.c ++++ b/drivers/usb/serial/option.c +@@ -621,7 +621,7 @@ static void option_instat_callback(struct urb *urb); + + /* MeiG Smart Technology products */ + #define MEIGSMART_VENDOR_ID 0x2dee +-/* MeiG Smart SRM825L based on Qualcomm 315 */ ++/* MeiG Smart SRM815/SRM825L based on Qualcomm 315 */ + #define MEIGSMART_PRODUCT_SRM825L 0x4d22 + /* MeiG Smart SLM320 based on UNISOC UIS8910 */ + #define MEIGSMART_PRODUCT_SLM320 0x4d41 +@@ -2405,6 +2405,7 @@ static const struct usb_device_id option_ids[] = { + { USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, LUAT_PRODUCT_AIR720U, 0xff, 0, 0) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SLM320, 0xff, 0, 0) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SLM770A, 0xff, 0, 0) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SRM825L, 0xff, 0, 0) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SRM825L, 0xff, 0xff, 0x30) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SRM825L, 0xff, 0xff, 0x40) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SRM825L, 0xff, 0xff, 0x60) }, +@@ -2412,6 +2413,7 @@ static const struct usb_device_id option_ids[] = { + .driver_info = NCTRL(1) }, + { USB_DEVICE_INTERFACE_CLASS(0x1bbb, 0x0640, 0xff), /* TCL IK512 ECM */ + .driver_info = NCTRL(3) }, ++ { USB_DEVICE_INTERFACE_CLASS(0x2949, 0x8700, 0xff) }, /* Neoway N723-EA */ + { } /* Terminating entry */ + }; + MODULE_DEVICE_TABLE(usb, option_ids); +diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h +index e5ad23d86833d5..54f0b1c83317cd 100644 +--- a/drivers/usb/storage/unusual_devs.h ++++ b/drivers/usb/storage/unusual_devs.h +@@ -255,6 +255,13 @@ UNUSUAL_DEV( 0x0421, 0x06aa, 0x1110, 0x1110, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_MAX_SECTORS_64 ), + ++/* Added by Lubomir Rintel , a very fine chap */ ++UNUSUAL_DEV( 0x0421, 0x06c2, 0x0000, 0x0406, ++ "Nokia", ++ "Nokia 208", ++ USB_SC_DEVICE, USB_PR_DEVICE, NULL, ++ US_FL_MAX_SECTORS_64 ), ++ + #ifdef NO_SDDR09 + UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100, + "Microtech", +diff --git a/drivers/usb/typec/tcpm/maxim_contaminant.c b/drivers/usb/typec/tcpm/maxim_contaminant.c +index f8504a90da2675..60f90272fed315 100644 +--- a/drivers/usb/typec/tcpm/maxim_contaminant.c ++++ b/drivers/usb/typec/tcpm/maxim_contaminant.c +@@ -137,7 +137,7 @@ static int max_contaminant_read_resistance_kohm(struct max_tcpci_chip *chip, + + mv = max_contaminant_read_adc_mv(chip, channel, sleep_msec, raw, true); + if (mv < 0) +- return ret; ++ return mv; + + /* OVP enable */ + ret = regmap_update_bits(regmap, TCPC_VENDOR_CC_CTRL2, CCOVPDIS, 0); +@@ -159,7 +159,7 @@ static int max_contaminant_read_resistance_kohm(struct max_tcpci_chip *chip, + + mv = max_contaminant_read_adc_mv(chip, channel, sleep_msec, raw, true); + if (mv < 0) +- return ret; ++ return mv; + /* Disable current source */ + ret = regmap_update_bits(regmap, TCPC_VENDOR_CC_CTRL2, SBURPCTRL, 0); + if (ret < 0) +diff --git a/fs/Kconfig b/fs/Kconfig +index aa7e03cc1941cb..02a9237807a779 100644 +--- a/fs/Kconfig ++++ b/fs/Kconfig +@@ -253,7 +253,7 @@ config TMPFS_QUOTA + config ARCH_SUPPORTS_HUGETLBFS + def_bool n + +-config HUGETLBFS ++menuconfig HUGETLBFS + bool "HugeTLB file system support" + depends on X86 || IA64 || SPARC64 || ARCH_SUPPORTS_HUGETLBFS || BROKEN + depends on (SYSFS || SYSCTL) +@@ -265,6 +265,17 @@ config HUGETLBFS + + If unsure, say N. + ++if HUGETLBFS ++config HUGETLB_PAGE_OPTIMIZE_VMEMMAP_DEFAULT_ON ++ bool "HugeTLB Vmemmap Optimization (HVO) defaults to on" ++ default n ++ depends on HUGETLB_PAGE_OPTIMIZE_VMEMMAP ++ help ++ The HugeTLB Vmemmap Optimization (HVO) defaults to off. Say Y here to ++ enable HVO by default. It can be disabled via hugetlb_free_vmemmap=off ++ (boot command line) or hugetlb_optimize_vmemmap (sysctl). ++endif # HUGETLBFS ++ + config HUGETLB_PAGE + def_bool HUGETLBFS + +@@ -273,14 +284,9 @@ config HUGETLB_PAGE_OPTIMIZE_VMEMMAP + depends on ARCH_WANT_OPTIMIZE_HUGETLB_VMEMMAP + depends on SPARSEMEM_VMEMMAP + +-config HUGETLB_PAGE_OPTIMIZE_VMEMMAP_DEFAULT_ON +- bool "HugeTLB Vmemmap Optimization (HVO) defaults to on" +- default n +- depends on HUGETLB_PAGE_OPTIMIZE_VMEMMAP +- help +- The HugeTLB VmemmapvOptimization (HVO) defaults to off. Say Y here to +- enable HVO by default. It can be disabled via hugetlb_free_vmemmap=off +- (boot command line) or hugetlb_optimize_vmemmap (sysctl). ++config HUGETLB_PMD_PAGE_TABLE_SHARING ++ def_bool HUGETLB_PAGE ++ depends on ARCH_WANT_HUGE_PMD_SHARE && SPLIT_PMD_PTLOCKS + + config ARCH_HAS_GIGANTIC_PAGE + bool +diff --git a/fs/afs/afs.h b/fs/afs/afs.h +index 81815724db6c9b..25c17100798ba7 100644 +--- a/fs/afs/afs.h ++++ b/fs/afs/afs.h +@@ -10,7 +10,7 @@ + + #include + +-#define AFS_MAXCELLNAME 256 /* Maximum length of a cell name */ ++#define AFS_MAXCELLNAME 253 /* Maximum length of a cell name (DNS limited) */ + #define AFS_MAXVOLNAME 64 /* Maximum length of a volume name */ + #define AFS_MAXNSERVERS 8 /* Maximum servers in a basic volume record */ + #define AFS_NMAXNSERVERS 13 /* Maximum servers in a N/U-class volume record */ +diff --git a/fs/afs/afs_vl.h b/fs/afs/afs_vl.h +index 9c65ffb8a523bd..8da0899fbc0835 100644 +--- a/fs/afs/afs_vl.h ++++ b/fs/afs/afs_vl.h +@@ -13,6 +13,7 @@ + #define AFS_VL_PORT 7003 /* volume location service port */ + #define VL_SERVICE 52 /* RxRPC service ID for the Volume Location service */ + #define YFS_VL_SERVICE 2503 /* Service ID for AuriStor upgraded VL service */ ++#define YFS_VL_MAXCELLNAME 256 /* Maximum length of a cell name in YFS protocol */ + + enum AFSVL_Operations { + VLGETENTRYBYID = 503, /* AFS Get VLDB entry by ID */ +diff --git a/fs/afs/vl_alias.c b/fs/afs/vl_alias.c +index f04a80e4f5c3fa..83cf1bfbe343ae 100644 +--- a/fs/afs/vl_alias.c ++++ b/fs/afs/vl_alias.c +@@ -302,6 +302,7 @@ static char *afs_vl_get_cell_name(struct afs_cell *cell, struct key *key) + static int yfs_check_canonical_cell_name(struct afs_cell *cell, struct key *key) + { + struct afs_cell *master; ++ size_t name_len; + char *cell_name; + + cell_name = afs_vl_get_cell_name(cell, key); +@@ -313,8 +314,11 @@ static int yfs_check_canonical_cell_name(struct afs_cell *cell, struct key *key) + return 0; + } + +- master = afs_lookup_cell(cell->net, cell_name, strlen(cell_name), +- NULL, false); ++ name_len = strlen(cell_name); ++ if (!name_len || name_len > AFS_MAXCELLNAME) ++ master = ERR_PTR(-EOPNOTSUPP); ++ else ++ master = afs_lookup_cell(cell->net, cell_name, name_len, NULL, false); + kfree(cell_name); + if (IS_ERR(master)) + return PTR_ERR(master); +diff --git a/fs/afs/vlclient.c b/fs/afs/vlclient.c +index 00fca3c66ba616..16653f2ffe4f54 100644 +--- a/fs/afs/vlclient.c ++++ b/fs/afs/vlclient.c +@@ -671,7 +671,7 @@ static int afs_deliver_yfsvl_get_cell_name(struct afs_call *call) + return ret; + + namesz = ntohl(call->tmp); +- if (namesz > AFS_MAXCELLNAME) ++ if (namesz > YFS_VL_MAXCELLNAME) + return afs_protocol_error(call, afs_eproto_cellname_len); + paddedsz = (namesz + 3) & ~3; + call->count = namesz; +diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c +index a2d91d9f8a109d..6be092bb814fdc 100644 +--- a/fs/btrfs/scrub.c ++++ b/fs/btrfs/scrub.c +@@ -1538,6 +1538,10 @@ static int scrub_find_fill_first_stripe(struct btrfs_block_group *bg, + u64 extent_gen; + int ret; + ++ if (unlikely(!extent_root)) { ++ btrfs_err(fs_info, "no valid extent root for scrub"); ++ return -EUCLEAN; ++ } + memset(stripe->sectors, 0, sizeof(struct scrub_sector_verification) * + stripe->nr_sectors); + scrub_stripe_reset_bitmaps(stripe); +diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c +index 1c0e6167d8e73b..496e4c7c52a4e0 100644 +--- a/fs/erofs/zdata.c ++++ b/fs/erofs/zdata.c +@@ -1483,14 +1483,13 @@ static struct page *pickup_page_for_submission(struct z_erofs_pcluster *pcl, + goto out; + + lock_page(page); +- +- /* only true if page reclaim goes wrong, should never happen */ +- DBG_BUGON(justfound && PagePrivate(page)); +- +- /* the page is still in manage cache */ +- if (page->mapping == mc) { ++ if (likely(page->mapping == mc)) { + WRITE_ONCE(pcl->compressed_bvecs[nr].page, page); + ++ /* ++ * The cached folio is still in managed cache but without ++ * a valid `->private` pcluster hint. Let's reconnect them. ++ */ + if (!PagePrivate(page)) { + /* + * impossible to be !PagePrivate(page) for +@@ -1504,22 +1503,24 @@ static struct page *pickup_page_for_submission(struct z_erofs_pcluster *pcl, + SetPagePrivate(page); + } + +- /* no need to submit io if it is already up-to-date */ +- if (PageUptodate(page)) { +- unlock_page(page); +- page = NULL; ++ if (likely(page->private == (unsigned long)pcl)) { ++ /* don't submit cache I/Os again if already uptodate */ ++ if (PageUptodate(page)) { ++ unlock_page(page); ++ page = NULL; ++ ++ } ++ goto out; + } +- goto out; ++ /* ++ * Already linked with another pcluster, which only appears in ++ * crafted images by fuzzers for now. But handle this anyway. ++ */ ++ tocache = false; /* use temporary short-lived pages */ ++ } else { ++ DBG_BUGON(1); /* referenced managed folios can't be truncated */ ++ tocache = true; + } +- +- /* +- * the managed page has been truncated, it's unsafe to +- * reuse this one, let's allocate a new cache-managed page. +- */ +- DBG_BUGON(page->mapping); +- DBG_BUGON(!justfound); +- +- tocache = true; + unlock_page(page); + put_page(page); + out_allocpage: +@@ -1677,16 +1678,11 @@ static void z_erofs_submit_queue(struct z_erofs_decompress_frontend *f, + end = cur + pcl->pclusterpages; + + do { +- struct page *page; +- +- page = pickup_page_for_submission(pcl, i++, +- &f->pagepool, mc); +- if (!page) +- continue; ++ struct page *page = NULL; + + if (bio && (cur != last_index + 1 || + last_bdev != mdev.m_bdev)) { +-submit_bio_retry: ++drain_io: + submit_bio(bio); + if (memstall) { + psi_memstall_leave(&pflags); +@@ -1695,6 +1691,13 @@ static void z_erofs_submit_queue(struct z_erofs_decompress_frontend *f, + bio = NULL; + } + ++ if (!page) { ++ page = pickup_page_for_submission(pcl, i++, ++ &f->pagepool, mc); ++ if (!page) ++ continue; ++ } ++ + if (unlikely(PageWorkingset(page)) && !memstall) { + psi_memstall_enter(&pflags); + memstall = 1; +@@ -1715,7 +1718,7 @@ static void z_erofs_submit_queue(struct z_erofs_decompress_frontend *f, + } + + if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) +- goto submit_bio_retry; ++ goto drain_io; + + last_index = cur; + bypass = false; +@@ -1727,11 +1730,10 @@ static void z_erofs_submit_queue(struct z_erofs_decompress_frontend *f, + move_to_bypass_jobqueue(pcl, qtail, owned_head); + } while (owned_head != Z_EROFS_PCLUSTER_TAIL); + +- if (bio) { ++ if (bio) + submit_bio(bio); +- if (memstall) +- psi_memstall_leave(&pflags); +- } ++ if (memstall) ++ psi_memstall_leave(&pflags); + + /* + * although background is preferred, no one is pending for submission. +diff --git a/fs/exfat/dir.c b/fs/exfat/dir.c +index 7a715016b96f34..f4f81e349cefe1 100644 +--- a/fs/exfat/dir.c ++++ b/fs/exfat/dir.c +@@ -125,7 +125,7 @@ static int exfat_readdir(struct inode *inode, loff_t *cpos, struct exfat_dir_ent + type = exfat_get_entry_type(ep); + if (type == TYPE_UNUSED) { + brelse(bh); +- break; ++ goto out; + } + + if (type != TYPE_FILE && type != TYPE_DIR) { +@@ -189,6 +189,7 @@ static int exfat_readdir(struct inode *inode, loff_t *cpos, struct exfat_dir_ent + } + } + ++out: + dir_entry->namebuf.lfn[0] = '\0'; + *cpos = EXFAT_DEN_TO_B(dentry); + return 0; +diff --git a/fs/exfat/fatent.c b/fs/exfat/fatent.c +index 56b870d9cc0def..428d862a1d2bfc 100644 +--- a/fs/exfat/fatent.c ++++ b/fs/exfat/fatent.c +@@ -216,6 +216,16 @@ static int __exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain + + if (err) + goto dec_used_clus; ++ ++ if (num_clusters >= sbi->num_clusters - EXFAT_FIRST_CLUSTER) { ++ /* ++ * The cluster chain includes a loop, scan the ++ * bitmap to get the number of used clusters. ++ */ ++ exfat_count_used_clusters(sb, &sbi->used_clusters); ++ ++ return 0; ++ } + } while (clu != EXFAT_EOF_CLUSTER); + } + +diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c +index b72fa103b9632a..aa0e7cc2489ac9 100644 +--- a/fs/f2fs/super.c ++++ b/fs/f2fs/super.c +@@ -4931,9 +4931,6 @@ static int __init init_f2fs_fs(void) + err = register_shrinker(&f2fs_shrinker_info, "f2fs-shrinker"); + if (err) + goto free_sysfs; +- err = register_filesystem(&f2fs_fs_type); +- if (err) +- goto free_shrinker; + f2fs_create_root_stats(); + err = f2fs_init_post_read_processing(); + if (err) +@@ -4956,7 +4953,12 @@ static int __init init_f2fs_fs(void) + err = f2fs_create_casefold_cache(); + if (err) + goto free_compress_cache; ++ err = register_filesystem(&f2fs_fs_type); ++ if (err) ++ goto free_casefold_cache; + return 0; ++free_casefold_cache: ++ f2fs_destroy_casefold_cache(); + free_compress_cache: + f2fs_destroy_compress_cache(); + free_compress_mempool: +@@ -4971,8 +4973,6 @@ static int __init init_f2fs_fs(void) + f2fs_destroy_post_read_processing(); + free_root_stats: + f2fs_destroy_root_stats(); +- unregister_filesystem(&f2fs_fs_type); +-free_shrinker: + unregister_shrinker(&f2fs_shrinker_info); + free_sysfs: + f2fs_exit_sysfs(); +@@ -4996,6 +4996,7 @@ static int __init init_f2fs_fs(void) + + static void __exit exit_f2fs_fs(void) + { ++ unregister_filesystem(&f2fs_fs_type); + f2fs_destroy_casefold_cache(); + f2fs_destroy_compress_cache(); + f2fs_destroy_compress_mempool(); +@@ -5004,7 +5005,6 @@ static void __exit exit_f2fs_fs(void) + f2fs_destroy_iostat_processing(); + f2fs_destroy_post_read_processing(); + f2fs_destroy_root_stats(); +- unregister_filesystem(&f2fs_fs_type); + unregister_shrinker(&f2fs_shrinker_info); + f2fs_exit_sysfs(); + f2fs_destroy_garbage_collection_cache(); +diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c +index 0cd7439470fc43..84663ff7dc5058 100644 +--- a/fs/jbd2/commit.c ++++ b/fs/jbd2/commit.c +@@ -777,9 +777,9 @@ void jbd2_journal_commit_transaction(journal_t *journal) + /* + * If the journal is not located on the file system device, + * then we must flush the file system device before we issue +- * the commit record ++ * the commit record and update the journal tail sequence. + */ +- if (commit_transaction->t_need_data_flush && ++ if ((commit_transaction->t_need_data_flush || update_tail) && + (journal->j_fs_dev != journal->j_dev) && + (journal->j_flags & JBD2_BARRIER)) + blkdev_issue_flush(journal->j_fs_dev); +diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c +index 4556e468902449..ce63d5fde9c3a8 100644 +--- a/fs/jbd2/revoke.c ++++ b/fs/jbd2/revoke.c +@@ -654,7 +654,7 @@ static void flush_descriptor(journal_t *journal, + set_buffer_jwrite(descriptor); + BUFFER_TRACE(descriptor, "write"); + set_buffer_dirty(descriptor); +- write_dirty_buffer(descriptor, REQ_SYNC); ++ write_dirty_buffer(descriptor, JBD2_JOURNAL_REQ_FLAGS); + } + #endif + +diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c +index ada3fcc9c6d501..f14c412c56097d 100644 +--- a/fs/overlayfs/copy_up.c ++++ b/fs/overlayfs/copy_up.c +@@ -371,13 +371,13 @@ int ovl_set_attr(struct ovl_fs *ofs, struct dentry *upperdentry, + return err; + } + +-struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct dentry *real, ++struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct inode *realinode, + bool is_upper) + { + struct ovl_fh *fh; + int fh_type, dwords; + int buflen = MAX_HANDLE_SZ; +- uuid_t *uuid = &real->d_sb->s_uuid; ++ uuid_t *uuid = &realinode->i_sb->s_uuid; + int err; + + /* Make sure the real fid stays 32bit aligned */ +@@ -394,7 +394,8 @@ struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct dentry *real, + * the price or reconnecting the dentry. + */ + dwords = buflen >> 2; +- fh_type = exportfs_encode_fh(real, (void *)fh->fb.fid, &dwords, 0); ++ fh_type = exportfs_encode_inode_fh(realinode, (void *)fh->fb.fid, ++ &dwords, NULL, 0); + buflen = (dwords << 2); + + err = -EIO; +@@ -426,29 +427,29 @@ struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct dentry *real, + return ERR_PTR(err); + } + +-int ovl_set_origin(struct ovl_fs *ofs, struct dentry *lower, +- struct dentry *upper) ++struct ovl_fh *ovl_get_origin_fh(struct ovl_fs *ofs, struct dentry *origin) + { +- const struct ovl_fh *fh = NULL; +- int err; +- + /* + * When lower layer doesn't support export operations store a 'null' fh, + * so we can use the overlay.origin xattr to distignuish between a copy + * up and a pure upper inode. + */ +- if (ovl_can_decode_fh(lower->d_sb)) { +- fh = ovl_encode_real_fh(ofs, lower, false); +- if (IS_ERR(fh)) +- return PTR_ERR(fh); +- } ++ if (!ovl_can_decode_fh(origin->d_sb)) ++ return NULL; ++ ++ return ovl_encode_real_fh(ofs, d_inode(origin), false); ++} ++ ++int ovl_set_origin_fh(struct ovl_fs *ofs, const struct ovl_fh *fh, ++ struct dentry *upper) ++{ ++ int err; + + /* + * Do not fail when upper doesn't support xattrs. + */ + err = ovl_check_setxattr(ofs, upper, OVL_XATTR_ORIGIN, fh->buf, + fh ? fh->fb.len : 0, 0); +- kfree(fh); + + /* Ignore -EPERM from setting "user.*" on symlink/special */ + return err == -EPERM ? 0 : err; +@@ -461,7 +462,7 @@ static int ovl_set_upper_fh(struct ovl_fs *ofs, struct dentry *upper, + const struct ovl_fh *fh; + int err; + +- fh = ovl_encode_real_fh(ofs, upper, true); ++ fh = ovl_encode_real_fh(ofs, d_inode(upper), true); + if (IS_ERR(fh)) + return PTR_ERR(fh); + +@@ -476,7 +477,7 @@ static int ovl_set_upper_fh(struct ovl_fs *ofs, struct dentry *upper, + * + * Caller must hold i_mutex on indexdir. + */ +-static int ovl_create_index(struct dentry *dentry, struct dentry *origin, ++static int ovl_create_index(struct dentry *dentry, const struct ovl_fh *fh, + struct dentry *upper) + { + struct ovl_fs *ofs = OVL_FS(dentry->d_sb); +@@ -502,7 +503,7 @@ static int ovl_create_index(struct dentry *dentry, struct dentry *origin, + if (WARN_ON(ovl_test_flag(OVL_INDEX, d_inode(dentry)))) + return -EIO; + +- err = ovl_get_index_name(ofs, origin, &name); ++ err = ovl_get_index_name_fh(fh, &name); + if (err) + return err; + +@@ -541,6 +542,7 @@ struct ovl_copy_up_ctx { + struct dentry *destdir; + struct qstr destname; + struct dentry *workdir; ++ const struct ovl_fh *origin_fh; + bool origin; + bool indexed; + bool metacopy; +@@ -637,7 +639,7 @@ static int ovl_copy_up_metadata(struct ovl_copy_up_ctx *c, struct dentry *temp) + * hard link. + */ + if (c->origin) { +- err = ovl_set_origin(ofs, c->lowerpath.dentry, temp); ++ err = ovl_set_origin_fh(ofs, c->origin_fh, temp); + if (err) + return err; + } +@@ -749,7 +751,7 @@ static int ovl_copy_up_workdir(struct ovl_copy_up_ctx *c) + goto cleanup; + + if (S_ISDIR(c->stat.mode) && c->indexed) { +- err = ovl_create_index(c->dentry, c->lowerpath.dentry, temp); ++ err = ovl_create_index(c->dentry, c->origin_fh, temp); + if (err) + goto cleanup; + } +@@ -861,6 +863,8 @@ static int ovl_do_copy_up(struct ovl_copy_up_ctx *c) + { + int err; + struct ovl_fs *ofs = OVL_FS(c->dentry->d_sb); ++ struct dentry *origin = c->lowerpath.dentry; ++ struct ovl_fh *fh = NULL; + bool to_index = false; + + /* +@@ -877,17 +881,25 @@ static int ovl_do_copy_up(struct ovl_copy_up_ctx *c) + to_index = true; + } + +- if (S_ISDIR(c->stat.mode) || c->stat.nlink == 1 || to_index) ++ if (S_ISDIR(c->stat.mode) || c->stat.nlink == 1 || to_index) { ++ fh = ovl_get_origin_fh(ofs, origin); ++ if (IS_ERR(fh)) ++ return PTR_ERR(fh); ++ ++ /* origin_fh may be NULL */ ++ c->origin_fh = fh; + c->origin = true; ++ } + + if (to_index) { + c->destdir = ovl_indexdir(c->dentry->d_sb); +- err = ovl_get_index_name(ofs, c->lowerpath.dentry, &c->destname); ++ err = ovl_get_index_name(ofs, origin, &c->destname); + if (err) +- return err; ++ goto out_free_fh; + } else if (WARN_ON(!c->parent)) { + /* Disconnected dentry must be copied up to index dir */ +- return -EIO; ++ err = -EIO; ++ goto out_free_fh; + } else { + /* + * Mark parent "impure" because it may now contain non-pure +@@ -895,7 +907,7 @@ static int ovl_do_copy_up(struct ovl_copy_up_ctx *c) + */ + err = ovl_set_impure(c->parent, c->destdir); + if (err) +- return err; ++ goto out_free_fh; + } + + /* Should we copyup with O_TMPFILE or with workdir? */ +@@ -927,6 +939,8 @@ static int ovl_do_copy_up(struct ovl_copy_up_ctx *c) + out: + if (to_index) + kfree(c->destname.name); ++out_free_fh: ++ kfree(fh); + return err; + } + +diff --git a/fs/overlayfs/export.c b/fs/overlayfs/export.c +index 611ff567a1aa6f..3a17e4366f28c0 100644 +--- a/fs/overlayfs/export.c ++++ b/fs/overlayfs/export.c +@@ -181,35 +181,37 @@ static int ovl_connect_layer(struct dentry *dentry) + * + * Return 0 for upper file handle, > 0 for lower file handle or < 0 on error. + */ +-static int ovl_check_encode_origin(struct dentry *dentry) ++static int ovl_check_encode_origin(struct inode *inode) + { +- struct ovl_fs *ofs = OVL_FS(dentry->d_sb); ++ struct ovl_fs *ofs = OVL_FS(inode->i_sb); + bool decodable = ofs->config.nfs_export; ++ struct dentry *dentry; ++ int err; + + /* No upper layer? */ + if (!ovl_upper_mnt(ofs)) + return 1; + + /* Lower file handle for non-upper non-decodable */ +- if (!ovl_dentry_upper(dentry) && !decodable) ++ if (!ovl_inode_upper(inode) && !decodable) + return 1; + + /* Upper file handle for pure upper */ +- if (!ovl_dentry_lower(dentry)) ++ if (!ovl_inode_lower(inode)) + return 0; + + /* + * Root is never indexed, so if there's an upper layer, encode upper for + * root. + */ +- if (dentry == dentry->d_sb->s_root) ++ if (inode == d_inode(inode->i_sb->s_root)) + return 0; + + /* + * Upper decodable file handle for non-indexed upper. + */ +- if (ovl_dentry_upper(dentry) && decodable && +- !ovl_test_flag(OVL_INDEX, d_inode(dentry))) ++ if (ovl_inode_upper(inode) && decodable && ++ !ovl_test_flag(OVL_INDEX, inode)) + return 0; + + /* +@@ -218,14 +220,23 @@ static int ovl_check_encode_origin(struct dentry *dentry) + * ovl_connect_layer() will try to make origin's layer "connected" by + * copying up a "connectable" ancestor. + */ +- if (d_is_dir(dentry) && decodable) +- return ovl_connect_layer(dentry); ++ if (!decodable || !S_ISDIR(inode->i_mode)) ++ return 1; ++ ++ dentry = d_find_any_alias(inode); ++ if (!dentry) ++ return -ENOENT; ++ ++ err = ovl_connect_layer(dentry); ++ dput(dentry); ++ if (err < 0) ++ return err; + + /* Lower file handle for indexed and non-upper dir/non-dir */ + return 1; + } + +-static int ovl_dentry_to_fid(struct ovl_fs *ofs, struct dentry *dentry, ++static int ovl_dentry_to_fid(struct ovl_fs *ofs, struct inode *inode, + u32 *fid, int buflen) + { + struct ovl_fh *fh = NULL; +@@ -236,13 +247,13 @@ static int ovl_dentry_to_fid(struct ovl_fs *ofs, struct dentry *dentry, + * Check if we should encode a lower or upper file handle and maybe + * copy up an ancestor to make lower file handle connectable. + */ +- err = enc_lower = ovl_check_encode_origin(dentry); ++ err = enc_lower = ovl_check_encode_origin(inode); + if (enc_lower < 0) + goto fail; + + /* Encode an upper or lower file handle */ +- fh = ovl_encode_real_fh(ofs, enc_lower ? ovl_dentry_lower(dentry) : +- ovl_dentry_upper(dentry), !enc_lower); ++ fh = ovl_encode_real_fh(ofs, enc_lower ? ovl_inode_lower(inode) : ++ ovl_inode_upper(inode), !enc_lower); + if (IS_ERR(fh)) + return PTR_ERR(fh); + +@@ -256,8 +267,8 @@ static int ovl_dentry_to_fid(struct ovl_fs *ofs, struct dentry *dentry, + return err; + + fail: +- pr_warn_ratelimited("failed to encode file handle (%pd2, err=%i)\n", +- dentry, err); ++ pr_warn_ratelimited("failed to encode file handle (ino=%lu, err=%i)\n", ++ inode->i_ino, err); + goto out; + } + +@@ -265,19 +276,13 @@ static int ovl_encode_fh(struct inode *inode, u32 *fid, int *max_len, + struct inode *parent) + { + struct ovl_fs *ofs = OVL_FS(inode->i_sb); +- struct dentry *dentry; + int bytes, buflen = *max_len << 2; + + /* TODO: encode connectable file handles */ + if (parent) + return FILEID_INVALID; + +- dentry = d_find_any_alias(inode); +- if (!dentry) +- return FILEID_INVALID; +- +- bytes = ovl_dentry_to_fid(ofs, dentry, fid, buflen); +- dput(dentry); ++ bytes = ovl_dentry_to_fid(ofs, inode, fid, buflen); + if (bytes <= 0) + return FILEID_INVALID; + +diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c +index 80391c687c2ad8..2d2ef671b36ba5 100644 +--- a/fs/overlayfs/namei.c ++++ b/fs/overlayfs/namei.c +@@ -507,6 +507,19 @@ static int ovl_verify_fh(struct ovl_fs *ofs, struct dentry *dentry, + return err; + } + ++int ovl_verify_set_fh(struct ovl_fs *ofs, struct dentry *dentry, ++ enum ovl_xattr ox, const struct ovl_fh *fh, ++ bool is_upper, bool set) ++{ ++ int err; ++ ++ err = ovl_verify_fh(ofs, dentry, ox, fh); ++ if (set && err == -ENODATA) ++ err = ovl_setxattr(ofs, dentry, ox, fh->buf, fh->fb.len); ++ ++ return err; ++} ++ + /* + * Verify that @real dentry matches the file handle stored in xattr @name. + * +@@ -515,24 +528,22 @@ static int ovl_verify_fh(struct ovl_fs *ofs, struct dentry *dentry, + * + * Return 0 on match, -ESTALE on mismatch, -ENODATA on no xattr, < 0 on error. + */ +-int ovl_verify_set_fh(struct ovl_fs *ofs, struct dentry *dentry, +- enum ovl_xattr ox, struct dentry *real, bool is_upper, +- bool set) ++int ovl_verify_origin_xattr(struct ovl_fs *ofs, struct dentry *dentry, ++ enum ovl_xattr ox, struct dentry *real, ++ bool is_upper, bool set) + { + struct inode *inode; + struct ovl_fh *fh; + int err; + +- fh = ovl_encode_real_fh(ofs, real, is_upper); ++ fh = ovl_encode_real_fh(ofs, d_inode(real), is_upper); + err = PTR_ERR(fh); + if (IS_ERR(fh)) { + fh = NULL; + goto fail; + } + +- err = ovl_verify_fh(ofs, dentry, ox, fh); +- if (set && err == -ENODATA) +- err = ovl_setxattr(ofs, dentry, ox, fh->buf, fh->fb.len); ++ err = ovl_verify_set_fh(ofs, dentry, ox, fh, is_upper, set); + if (err) + goto fail; + +@@ -548,6 +559,7 @@ int ovl_verify_set_fh(struct ovl_fs *ofs, struct dentry *dentry, + goto out; + } + ++ + /* Get upper dentry from index */ + struct dentry *ovl_index_upper(struct ovl_fs *ofs, struct dentry *index, + bool connected) +@@ -684,7 +696,7 @@ int ovl_verify_index(struct ovl_fs *ofs, struct dentry *index) + goto out; + } + +-static int ovl_get_index_name_fh(struct ovl_fh *fh, struct qstr *name) ++int ovl_get_index_name_fh(const struct ovl_fh *fh, struct qstr *name) + { + char *n, *s; + +@@ -720,7 +732,7 @@ int ovl_get_index_name(struct ovl_fs *ofs, struct dentry *origin, + struct ovl_fh *fh; + int err; + +- fh = ovl_encode_real_fh(ofs, origin, false); ++ fh = ovl_encode_real_fh(ofs, d_inode(origin), false); + if (IS_ERR(fh)) + return PTR_ERR(fh); + +@@ -873,20 +885,27 @@ int ovl_path_next(int idx, struct dentry *dentry, struct path *path) + static int ovl_fix_origin(struct ovl_fs *ofs, struct dentry *dentry, + struct dentry *lower, struct dentry *upper) + { ++ const struct ovl_fh *fh; + int err; + + if (ovl_check_origin_xattr(ofs, upper)) + return 0; + ++ fh = ovl_get_origin_fh(ofs, lower); ++ if (IS_ERR(fh)) ++ return PTR_ERR(fh); ++ + err = ovl_want_write(dentry); + if (err) +- return err; ++ goto out; + +- err = ovl_set_origin(ofs, lower, upper); ++ err = ovl_set_origin_fh(ofs, fh, upper); + if (!err) + err = ovl_set_impure(dentry->d_parent, upper->d_parent); + + ovl_drop_write(dentry); ++out: ++ kfree(fh); + return err; + } + +diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h +index 09ca82ed0f8ced..ca63a26a6170b0 100644 +--- a/fs/overlayfs/overlayfs.h ++++ b/fs/overlayfs/overlayfs.h +@@ -632,11 +632,15 @@ struct dentry *ovl_decode_real_fh(struct ovl_fs *ofs, struct ovl_fh *fh, + int ovl_check_origin_fh(struct ovl_fs *ofs, struct ovl_fh *fh, bool connected, + struct dentry *upperdentry, struct ovl_path **stackp); + int ovl_verify_set_fh(struct ovl_fs *ofs, struct dentry *dentry, +- enum ovl_xattr ox, struct dentry *real, bool is_upper, +- bool set); ++ enum ovl_xattr ox, const struct ovl_fh *fh, ++ bool is_upper, bool set); ++int ovl_verify_origin_xattr(struct ovl_fs *ofs, struct dentry *dentry, ++ enum ovl_xattr ox, struct dentry *real, ++ bool is_upper, bool set); + struct dentry *ovl_index_upper(struct ovl_fs *ofs, struct dentry *index, + bool connected); + int ovl_verify_index(struct ovl_fs *ofs, struct dentry *index); ++int ovl_get_index_name_fh(const struct ovl_fh *fh, struct qstr *name); + int ovl_get_index_name(struct ovl_fs *ofs, struct dentry *origin, + struct qstr *name); + struct dentry *ovl_get_index_fh(struct ovl_fs *ofs, struct ovl_fh *fh); +@@ -648,17 +652,24 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, + unsigned int flags); + bool ovl_lower_positive(struct dentry *dentry); + ++static inline int ovl_verify_origin_fh(struct ovl_fs *ofs, struct dentry *upper, ++ const struct ovl_fh *fh, bool set) ++{ ++ return ovl_verify_set_fh(ofs, upper, OVL_XATTR_ORIGIN, fh, false, set); ++} ++ + static inline int ovl_verify_origin(struct ovl_fs *ofs, struct dentry *upper, + struct dentry *origin, bool set) + { +- return ovl_verify_set_fh(ofs, upper, OVL_XATTR_ORIGIN, origin, +- false, set); ++ return ovl_verify_origin_xattr(ofs, upper, OVL_XATTR_ORIGIN, origin, ++ false, set); + } + + static inline int ovl_verify_upper(struct ovl_fs *ofs, struct dentry *index, + struct dentry *upper, bool set) + { +- return ovl_verify_set_fh(ofs, index, OVL_XATTR_UPPER, upper, true, set); ++ return ovl_verify_origin_xattr(ofs, index, OVL_XATTR_UPPER, upper, ++ true, set); + } + + /* readdir.c */ +@@ -821,10 +832,11 @@ int ovl_copy_up_with_data(struct dentry *dentry); + int ovl_maybe_copy_up(struct dentry *dentry, int flags); + int ovl_copy_xattr(struct super_block *sb, const struct path *path, struct dentry *new); + int ovl_set_attr(struct ovl_fs *ofs, struct dentry *upper, struct kstat *stat); +-struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct dentry *real, ++struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct inode *realinode, + bool is_upper); +-int ovl_set_origin(struct ovl_fs *ofs, struct dentry *lower, +- struct dentry *upper); ++struct ovl_fh *ovl_get_origin_fh(struct ovl_fs *ofs, struct dentry *origin); ++int ovl_set_origin_fh(struct ovl_fs *ofs, const struct ovl_fh *fh, ++ struct dentry *upper); + + /* export.c */ + extern const struct export_operations ovl_export_operations; +diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c +index 2c056d737c27c3..e2574034c3fa17 100644 +--- a/fs/overlayfs/super.c ++++ b/fs/overlayfs/super.c +@@ -879,15 +879,20 @@ static int ovl_get_indexdir(struct super_block *sb, struct ovl_fs *ofs, + { + struct vfsmount *mnt = ovl_upper_mnt(ofs); + struct dentry *indexdir; ++ struct dentry *origin = ovl_lowerstack(oe)->dentry; ++ const struct ovl_fh *fh; + int err; + ++ fh = ovl_get_origin_fh(ofs, origin); ++ if (IS_ERR(fh)) ++ return PTR_ERR(fh); ++ + err = mnt_want_write(mnt); + if (err) +- return err; ++ goto out_free_fh; + + /* Verify lower root is upper root origin */ +- err = ovl_verify_origin(ofs, upperpath->dentry, +- ovl_lowerstack(oe)->dentry, true); ++ err = ovl_verify_origin_fh(ofs, upperpath->dentry, fh, true); + if (err) { + pr_err("failed to verify upper root origin\n"); + goto out; +@@ -919,9 +924,10 @@ static int ovl_get_indexdir(struct super_block *sb, struct ovl_fs *ofs, + * directory entries. + */ + if (ovl_check_origin_xattr(ofs, ofs->indexdir)) { +- err = ovl_verify_set_fh(ofs, ofs->indexdir, +- OVL_XATTR_ORIGIN, +- upperpath->dentry, true, false); ++ err = ovl_verify_origin_xattr(ofs, ofs->indexdir, ++ OVL_XATTR_ORIGIN, ++ upperpath->dentry, true, ++ false); + if (err) + pr_err("failed to verify index dir 'origin' xattr\n"); + } +@@ -939,6 +945,8 @@ static int ovl_get_indexdir(struct super_block *sb, struct ovl_fs *ofs, + + out: + mnt_drop_write(mnt); ++out_free_fh: ++ kfree(fh); + return err; + } + +diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c +index 0bf3ffcd072f6a..4e6b747e0f2e25 100644 +--- a/fs/overlayfs/util.c ++++ b/fs/overlayfs/util.c +@@ -976,12 +976,18 @@ static void ovl_cleanup_index(struct dentry *dentry) + struct dentry *index = NULL; + struct inode *inode; + struct qstr name = { }; ++ bool got_write = false; + int err; + + err = ovl_get_index_name(ofs, lowerdentry, &name); + if (err) + goto fail; + ++ err = ovl_want_write(dentry); ++ if (err) ++ goto fail; ++ ++ got_write = true; + inode = d_inode(upperdentry); + if (!S_ISDIR(inode->i_mode) && inode->i_nlink != 1) { + pr_warn_ratelimited("cleanup linked index (%pd2, ino=%lu, nlink=%u)\n", +@@ -1019,6 +1025,8 @@ static void ovl_cleanup_index(struct dentry *dentry) + goto fail; + + out: ++ if (got_write) ++ ovl_drop_write(dentry); + kfree(name.name); + dput(index); + return; +@@ -1089,6 +1097,8 @@ void ovl_nlink_end(struct dentry *dentry) + { + struct inode *inode = d_inode(dentry); + ++ ovl_drop_write(dentry); ++ + if (ovl_test_flag(OVL_INDEX, inode) && inode->i_nlink == 0) { + const struct cred *old_cred; + +diff --git a/fs/smb/client/namespace.c b/fs/smb/client/namespace.c +index 4a517b280f2b79..830f2a292bb00d 100644 +--- a/fs/smb/client/namespace.c ++++ b/fs/smb/client/namespace.c +@@ -196,11 +196,28 @@ static struct vfsmount *cifs_do_automount(struct path *path) + struct smb3_fs_context tmp; + char *full_path; + struct vfsmount *mnt; ++ struct cifs_sb_info *mntpt_sb; ++ struct cifs_ses *ses; + + if (IS_ROOT(mntpt)) + return ERR_PTR(-ESTALE); + +- cur_ctx = CIFS_SB(mntpt->d_sb)->ctx; ++ mntpt_sb = CIFS_SB(mntpt->d_sb); ++ ses = cifs_sb_master_tcon(mntpt_sb)->ses; ++ cur_ctx = mntpt_sb->ctx; ++ ++ /* ++ * At this point, the root session should be in the mntpt sb. We should ++ * bring the sb context passwords in sync with the root session's ++ * passwords. This would help prevent unnecessary retries and password ++ * swaps for automounts. ++ */ ++ mutex_lock(&ses->session_mutex); ++ rc = smb3_sync_session_ctx_passwords(mntpt_sb, ses); ++ mutex_unlock(&ses->session_mutex); ++ ++ if (rc) ++ return ERR_PTR(rc); + + fc = fs_context_for_submount(path->mnt->mnt_sb->s_type, mntpt); + if (IS_ERR(fc)) +diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c +index 2884ebdc0eda02..815a9a5cfa8079 100644 +--- a/fs/smb/server/smb2pdu.c ++++ b/fs/smb/server/smb2pdu.c +@@ -695,6 +695,9 @@ void smb2_send_interim_resp(struct ksmbd_work *work, __le32 status) + struct smb2_hdr *rsp_hdr; + struct ksmbd_work *in_work = ksmbd_alloc_work_struct(); + ++ if (!in_work) ++ return; ++ + if (allocate_interim_rsp_buf(in_work)) { + pr_err("smb_allocate_rsp_buf failed!\n"); + ksmbd_free_work_struct(in_work); +@@ -3986,6 +3989,26 @@ static int smb2_populate_readdir_entry(struct ksmbd_conn *conn, int info_level, + posix_info->DeviceId = cpu_to_le32(ksmbd_kstat->kstat->rdev); + posix_info->HardLinks = cpu_to_le32(ksmbd_kstat->kstat->nlink); + posix_info->Mode = cpu_to_le32(ksmbd_kstat->kstat->mode & 0777); ++ switch (ksmbd_kstat->kstat->mode & S_IFMT) { ++ case S_IFDIR: ++ posix_info->Mode |= cpu_to_le32(POSIX_TYPE_DIR << POSIX_FILETYPE_SHIFT); ++ break; ++ case S_IFLNK: ++ posix_info->Mode |= cpu_to_le32(POSIX_TYPE_SYMLINK << POSIX_FILETYPE_SHIFT); ++ break; ++ case S_IFCHR: ++ posix_info->Mode |= cpu_to_le32(POSIX_TYPE_CHARDEV << POSIX_FILETYPE_SHIFT); ++ break; ++ case S_IFBLK: ++ posix_info->Mode |= cpu_to_le32(POSIX_TYPE_BLKDEV << POSIX_FILETYPE_SHIFT); ++ break; ++ case S_IFIFO: ++ posix_info->Mode |= cpu_to_le32(POSIX_TYPE_FIFO << POSIX_FILETYPE_SHIFT); ++ break; ++ case S_IFSOCK: ++ posix_info->Mode |= cpu_to_le32(POSIX_TYPE_SOCKET << POSIX_FILETYPE_SHIFT); ++ } ++ + posix_info->Inode = cpu_to_le64(ksmbd_kstat->kstat->ino); + posix_info->DosAttributes = + S_ISDIR(ksmbd_kstat->kstat->mode) ? +@@ -5174,6 +5197,26 @@ static int find_file_posix_info(struct smb2_query_info_rsp *rsp, + file_info->AllocationSize = cpu_to_le64(stat.blocks << 9); + file_info->HardLinks = cpu_to_le32(stat.nlink); + file_info->Mode = cpu_to_le32(stat.mode & 0777); ++ switch (stat.mode & S_IFMT) { ++ case S_IFDIR: ++ file_info->Mode |= cpu_to_le32(POSIX_TYPE_DIR << POSIX_FILETYPE_SHIFT); ++ break; ++ case S_IFLNK: ++ file_info->Mode |= cpu_to_le32(POSIX_TYPE_SYMLINK << POSIX_FILETYPE_SHIFT); ++ break; ++ case S_IFCHR: ++ file_info->Mode |= cpu_to_le32(POSIX_TYPE_CHARDEV << POSIX_FILETYPE_SHIFT); ++ break; ++ case S_IFBLK: ++ file_info->Mode |= cpu_to_le32(POSIX_TYPE_BLKDEV << POSIX_FILETYPE_SHIFT); ++ break; ++ case S_IFIFO: ++ file_info->Mode |= cpu_to_le32(POSIX_TYPE_FIFO << POSIX_FILETYPE_SHIFT); ++ break; ++ case S_IFSOCK: ++ file_info->Mode |= cpu_to_le32(POSIX_TYPE_SOCKET << POSIX_FILETYPE_SHIFT); ++ } ++ + file_info->DeviceId = cpu_to_le32(stat.rdev); + + /* +diff --git a/fs/smb/server/smb2pdu.h b/fs/smb/server/smb2pdu.h +index 643f5e1cfe3570..25cc81aac350f2 100644 +--- a/fs/smb/server/smb2pdu.h ++++ b/fs/smb/server/smb2pdu.h +@@ -500,4 +500,14 @@ static inline void *smb2_get_msg(void *buf) + return buf + 4; + } + ++#define POSIX_TYPE_FILE 0 ++#define POSIX_TYPE_DIR 1 ++#define POSIX_TYPE_SYMLINK 2 ++#define POSIX_TYPE_CHARDEV 3 ++#define POSIX_TYPE_BLKDEV 4 ++#define POSIX_TYPE_FIFO 5 ++#define POSIX_TYPE_SOCKET 6 ++ ++#define POSIX_FILETYPE_SHIFT 12 ++ + #endif /* _SMB2PDU_H */ +diff --git a/fs/smb/server/vfs.c b/fs/smb/server/vfs.c +index 2c548e8efef060..d0c19ad9d0145c 100644 +--- a/fs/smb/server/vfs.c ++++ b/fs/smb/server/vfs.c +@@ -1259,6 +1259,8 @@ int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name, + filepath, + flags, + path); ++ if (!is_last) ++ next[0] = '/'; + if (err) + goto out2; + else if (is_last) +@@ -1266,7 +1268,6 @@ int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name, + path_put(parent_path); + *parent_path = *path; + +- next[0] = '/'; + remain_len -= filename_len + 1; + } + +diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h +index 0c50c4fceb95dd..0ca93c7574ad22 100644 +--- a/include/linux/hugetlb.h ++++ b/include/linux/hugetlb.h +@@ -1239,7 +1239,7 @@ static inline __init void hugetlb_cma_reserve(int order) + } + #endif + +-#ifdef CONFIG_ARCH_WANT_HUGE_PMD_SHARE ++#ifdef CONFIG_HUGETLB_PMD_PAGE_TABLE_SHARING + static inline bool hugetlb_pmd_shared(pte_t *pte) + { + return page_count(virt_to_page(pte)) > 1; +@@ -1275,8 +1275,7 @@ bool __vma_private_lock(struct vm_area_struct *vma); + static inline pte_t * + hugetlb_walk(struct vm_area_struct *vma, unsigned long addr, unsigned long sz) + { +-#if defined(CONFIG_HUGETLB_PAGE) && \ +- defined(CONFIG_ARCH_WANT_HUGE_PMD_SHARE) && defined(CONFIG_LOCKDEP) ++#if defined(CONFIG_HUGETLB_PMD_PAGE_TABLE_SHARING) && defined(CONFIG_LOCKDEP) + struct hugetlb_vma_lock *vma_lock = vma->vm_private_data; + + /* +diff --git a/include/linux/mm.h b/include/linux/mm.h +index b6a4d6471b4a72..209370f6443666 100644 +--- a/include/linux/mm.h ++++ b/include/linux/mm.h +@@ -3031,6 +3031,7 @@ static inline bool pagetable_pmd_ctor(struct ptdesc *ptdesc) + if (!pmd_ptlock_init(ptdesc)) + return false; + __folio_set_pgtable(folio); ++ ptdesc_pmd_pts_init(ptdesc); + lruvec_stat_add_folio(folio, NR_PAGETABLE); + return true; + } +diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h +index 20c96ce98751a4..e77d4a5c0baced 100644 +--- a/include/linux/mm_types.h ++++ b/include/linux/mm_types.h +@@ -398,11 +398,12 @@ FOLIO_MATCH(compound_head, _head_2a); + * @pmd_huge_pte: Protected by ptdesc->ptl, used for THPs. + * @__page_mapping: Aliases with page->mapping. Unused for page tables. + * @pt_mm: Used for x86 pgds. +- * @pt_frag_refcount: For fragmented page table tracking. Powerpc and s390 only. ++ * @pt_frag_refcount: For fragmented page table tracking. Powerpc only. ++ * @pt_share_count: Used for HugeTLB PMD page table share count. + * @_pt_pad_2: Padding to ensure proper alignment. + * @ptl: Lock for the page table. + * @__page_type: Same as page->page_type. Unused for page tables. +- * @_refcount: Same as page refcount. Used for s390 page tables. ++ * @_refcount: Same as page refcount. + * @pt_memcg_data: Memcg data. Tracked for page tables here. + * + * This struct overlays struct page for now. Do not modify without a good +@@ -424,6 +425,9 @@ struct ptdesc { + union { + struct mm_struct *pt_mm; + atomic_t pt_frag_refcount; ++#ifdef CONFIG_HUGETLB_PMD_PAGE_TABLE_SHARING ++ atomic_t pt_share_count; ++#endif + }; + + union { +@@ -468,6 +472,32 @@ static_assert(sizeof(struct ptdesc) <= sizeof(struct page)); + const struct page *: (const struct ptdesc *)(p), \ + struct page *: (struct ptdesc *)(p))) + ++#ifdef CONFIG_HUGETLB_PMD_PAGE_TABLE_SHARING ++static inline void ptdesc_pmd_pts_init(struct ptdesc *ptdesc) ++{ ++ atomic_set(&ptdesc->pt_share_count, 0); ++} ++ ++static inline void ptdesc_pmd_pts_inc(struct ptdesc *ptdesc) ++{ ++ atomic_inc(&ptdesc->pt_share_count); ++} ++ ++static inline void ptdesc_pmd_pts_dec(struct ptdesc *ptdesc) ++{ ++ atomic_dec(&ptdesc->pt_share_count); ++} ++ ++static inline int ptdesc_pmd_pts_count(struct ptdesc *ptdesc) ++{ ++ return atomic_read(&ptdesc->pt_share_count); ++} ++#else ++static inline void ptdesc_pmd_pts_init(struct ptdesc *ptdesc) ++{ ++} ++#endif ++ + /* + * Used for sizing the vmemmap region on some architectures + */ +diff --git a/include/linux/numa.h b/include/linux/numa.h +index 1d43371fafd2fc..eb19503604fe36 100644 +--- a/include/linux/numa.h ++++ b/include/linux/numa.h +@@ -15,6 +15,11 @@ + #define NUMA_NO_NODE (-1) + #define NUMA_NO_MEMBLK (-1) + ++static inline bool numa_valid_node(int nid) ++{ ++ return nid >= 0 && nid < MAX_NUMNODES; ++} ++ + /* optionally keep NUMA memory info available post init */ + #ifdef CONFIG_NUMA_KEEP_MEMINFO + #define __initdata_or_meminfo +diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h +index fee1e565055100..e85834722b8f2b 100644 +--- a/include/net/inet_connection_sock.h ++++ b/include/net/inet_connection_sock.h +@@ -282,7 +282,7 @@ static inline int inet_csk_reqsk_queue_len(const struct sock *sk) + + static inline int inet_csk_reqsk_queue_is_full(const struct sock *sk) + { +- return inet_csk_reqsk_queue_len(sk) >= sk->sk_max_ack_backlog; ++ return inet_csk_reqsk_queue_len(sk) > READ_ONCE(sk->sk_max_ack_backlog); + } + + bool inet_csk_reqsk_queue_drop(struct sock *sk, struct request_sock *req); +diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h +index f66a275bf8ccdb..20d129914121d5 100644 +--- a/include/ufs/ufshcd.h ++++ b/include/ufs/ufshcd.h +@@ -324,7 +324,6 @@ struct ufs_pwr_mode_info { + * @config_scaling_param: called to configure clock scaling parameters + * @program_key: program or evict an inline encryption key + * @event_notify: called to notify important events +- * @reinit_notify: called to notify reinit of UFSHCD during max gear switch + * @mcq_config_resource: called to configure MCQ platform resources + * @get_hba_mac: called to get vendor specific mac value, mandatory for mcq mode + * @op_runtime_config: called to config Operation and runtime regs Pointers +@@ -369,7 +368,6 @@ struct ufs_hba_variant_ops { + const union ufs_crypto_cfg_entry *cfg, int slot); + void (*event_notify)(struct ufs_hba *hba, + enum ufs_event_type evt, void *data); +- void (*reinit_notify)(struct ufs_hba *); + int (*mcq_config_resource)(struct ufs_hba *hba); + int (*get_hba_mac)(struct ufs_hba *hba); + int (*op_runtime_config)(struct ufs_hba *hba); +diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c +index 0122f220ef0d2b..c7198fbcf734f7 100644 +--- a/io_uring/io_uring.c ++++ b/io_uring/io_uring.c +@@ -537,6 +537,13 @@ static __cold void io_queue_deferred(struct io_ring_ctx *ctx) + } + } + ++static void io_eventfd_free(struct rcu_head *rcu) ++{ ++ struct io_ev_fd *ev_fd = container_of(rcu, struct io_ev_fd, rcu); ++ ++ eventfd_ctx_put(ev_fd->cq_ev_fd); ++ kfree(ev_fd); ++} + + static void io_eventfd_ops(struct rcu_head *rcu) + { +@@ -550,10 +557,8 @@ static void io_eventfd_ops(struct rcu_head *rcu) + * ordering in a race but if references are 0 we know we have to free + * it regardless. + */ +- if (atomic_dec_and_test(&ev_fd->refs)) { +- eventfd_ctx_put(ev_fd->cq_ev_fd); +- kfree(ev_fd); +- } ++ if (atomic_dec_and_test(&ev_fd->refs)) ++ call_rcu(&ev_fd->rcu, io_eventfd_free); + } + + static void io_eventfd_signal(struct io_ring_ctx *ctx) +diff --git a/io_uring/timeout.c b/io_uring/timeout.c +index 4f1f710197d623..277e22d55c6171 100644 +--- a/io_uring/timeout.c ++++ b/io_uring/timeout.c +@@ -413,10 +413,12 @@ static int io_timeout_update(struct io_ring_ctx *ctx, __u64 user_data, + + timeout->off = 0; /* noseq */ + data = req->async_data; ++ data->ts = *ts; ++ + list_add_tail(&timeout->list, &ctx->timeout_list); + hrtimer_init(&data->timer, io_timeout_get_clock(data), mode); + data->timer.function = io_timeout_fn; +- hrtimer_start(&data->timer, timespec64_to_ktime(*ts), mode); ++ hrtimer_start(&data->timer, timespec64_to_ktime(data->ts), mode); + return 0; + } + +diff --git a/kernel/workqueue.c b/kernel/workqueue.c +index 7fa1c7c9151aef..59b6efb2a11c36 100644 +--- a/kernel/workqueue.c ++++ b/kernel/workqueue.c +@@ -2541,6 +2541,7 @@ __acquires(&pool->lock) + struct pool_workqueue *pwq = get_work_pwq(work); + struct worker_pool *pool = worker->pool; + unsigned long work_data; ++ int lockdep_start_depth, rcu_start_depth; + #ifdef CONFIG_LOCKDEP + /* + * It is permissible to free the struct work_struct from +@@ -2603,6 +2604,8 @@ __acquires(&pool->lock) + pwq->stats[PWQ_STAT_STARTED]++; + raw_spin_unlock_irq(&pool->lock); + ++ rcu_start_depth = rcu_preempt_depth(); ++ lockdep_start_depth = lockdep_depth(current); + lock_map_acquire(&pwq->wq->lockdep_map); + lock_map_acquire(&lockdep_map); + /* +@@ -2638,10 +2641,14 @@ __acquires(&pool->lock) + lock_map_release(&lockdep_map); + lock_map_release(&pwq->wq->lockdep_map); + +- if (unlikely(in_atomic() || lockdep_depth(current) > 0)) { +- pr_err("BUG: workqueue leaked lock or atomic: %s/0x%08x/%d\n" +- " last function: %ps\n", +- current->comm, preempt_count(), task_pid_nr(current), ++ if (unlikely((worker->task && in_atomic()) || ++ lockdep_depth(current) != lockdep_start_depth || ++ rcu_preempt_depth() != rcu_start_depth)) { ++ pr_err("BUG: workqueue leaked atomic, lock or RCU: %s[%d]\n" ++ " preempt=0x%08x lock=%d->%d RCU=%d->%d workfn=%ps\n", ++ current->comm, task_pid_nr(current), preempt_count(), ++ lockdep_start_depth, lockdep_depth(current), ++ rcu_start_depth, rcu_preempt_depth(), + worker->current_func); + debug_show_held_locks(current); + dump_stack(); +@@ -2940,23 +2947,27 @@ static int rescuer_thread(void *__rescuer) + * check_flush_dependency - check for flush dependency sanity + * @target_wq: workqueue being flushed + * @target_work: work item being flushed (NULL for workqueue flushes) ++ * @from_cancel: are we called from the work cancel path + * + * %current is trying to flush the whole @target_wq or @target_work on it. +- * If @target_wq doesn't have %WQ_MEM_RECLAIM, verify that %current is not +- * reclaiming memory or running on a workqueue which doesn't have +- * %WQ_MEM_RECLAIM as that can break forward-progress guarantee leading to +- * a deadlock. ++ * If this is not the cancel path (which implies work being flushed is either ++ * already running, or will not be at all), check if @target_wq doesn't have ++ * %WQ_MEM_RECLAIM and verify that %current is not reclaiming memory or running ++ * on a workqueue which doesn't have %WQ_MEM_RECLAIM as that can break forward- ++ * progress guarantee leading to a deadlock. + */ + static void check_flush_dependency(struct workqueue_struct *target_wq, +- struct work_struct *target_work) ++ struct work_struct *target_work, ++ bool from_cancel) + { +- work_func_t target_func = target_work ? target_work->func : NULL; ++ work_func_t target_func; + struct worker *worker; + +- if (target_wq->flags & WQ_MEM_RECLAIM) ++ if (from_cancel || target_wq->flags & WQ_MEM_RECLAIM) + return; + + worker = current_wq_worker(); ++ target_func = target_work ? target_work->func : NULL; + + WARN_ONCE(current->flags & PF_MEMALLOC, + "workqueue: PF_MEMALLOC task %d(%s) is flushing !WQ_MEM_RECLAIM %s:%ps", +@@ -3122,6 +3133,19 @@ static bool flush_workqueue_prep_pwqs(struct workqueue_struct *wq, + return wait; + } + ++static void touch_wq_lockdep_map(struct workqueue_struct *wq) ++{ ++ lock_map_acquire(&wq->lockdep_map); ++ lock_map_release(&wq->lockdep_map); ++} ++ ++static void touch_work_lockdep_map(struct work_struct *work, ++ struct workqueue_struct *wq) ++{ ++ lock_map_acquire(&work->lockdep_map); ++ lock_map_release(&work->lockdep_map); ++} ++ + /** + * __flush_workqueue - ensure that any scheduled work has run to completion. + * @wq: workqueue to flush +@@ -3141,8 +3165,7 @@ void __flush_workqueue(struct workqueue_struct *wq) + if (WARN_ON(!wq_online)) + return; + +- lock_map_acquire(&wq->lockdep_map); +- lock_map_release(&wq->lockdep_map); ++ touch_wq_lockdep_map(wq); + + mutex_lock(&wq->mutex); + +@@ -3189,7 +3212,7 @@ void __flush_workqueue(struct workqueue_struct *wq) + list_add_tail(&this_flusher.list, &wq->flusher_overflow); + } + +- check_flush_dependency(wq, NULL); ++ check_flush_dependency(wq, NULL, false); + + mutex_unlock(&wq->mutex); + +@@ -3341,6 +3364,7 @@ static bool start_flush_work(struct work_struct *work, struct wq_barrier *barr, + struct worker *worker = NULL; + struct worker_pool *pool; + struct pool_workqueue *pwq; ++ struct workqueue_struct *wq; + + might_sleep(); + +@@ -3364,11 +3388,14 @@ static bool start_flush_work(struct work_struct *work, struct wq_barrier *barr, + pwq = worker->current_pwq; + } + +- check_flush_dependency(pwq->wq, work); ++ wq = pwq->wq; ++ check_flush_dependency(wq, work, from_cancel); + + insert_wq_barrier(pwq, barr, work, worker); + raw_spin_unlock_irq(&pool->lock); + ++ touch_work_lockdep_map(work, wq); ++ + /* + * Force a lock recursion deadlock when using flush_work() inside a + * single-threaded or rescuer equipped workqueue. +@@ -3378,11 +3405,9 @@ static bool start_flush_work(struct work_struct *work, struct wq_barrier *barr, + * workqueues the deadlock happens when the rescuer stalls, blocking + * forward progress. + */ +- if (!from_cancel && +- (pwq->wq->saved_max_active == 1 || pwq->wq->rescuer)) { +- lock_map_acquire(&pwq->wq->lockdep_map); +- lock_map_release(&pwq->wq->lockdep_map); +- } ++ if (!from_cancel && (wq->saved_max_active == 1 || wq->rescuer)) ++ touch_wq_lockdep_map(wq); ++ + rcu_read_unlock(); + return true; + already_gone: +@@ -3401,9 +3426,6 @@ static bool __flush_work(struct work_struct *work, bool from_cancel) + if (WARN_ON(!work->func)) + return false; + +- lock_map_acquire(&work->lockdep_map); +- lock_map_release(&work->lockdep_map); +- + if (start_flush_work(work, &barr, from_cancel)) { + wait_for_completion(&barr.done); + destroy_work_on_stack(&barr.work); +diff --git a/mm/hugetlb.c b/mm/hugetlb.c +index 92b955cc5a41d3..21c12519a7ef3a 100644 +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -6907,7 +6907,7 @@ long hugetlb_unreserve_pages(struct inode *inode, long start, long end, + return 0; + } + +-#ifdef CONFIG_ARCH_WANT_HUGE_PMD_SHARE ++#ifdef CONFIG_HUGETLB_PMD_PAGE_TABLE_SHARING + static unsigned long page_table_shareable(struct vm_area_struct *svma, + struct vm_area_struct *vma, + unsigned long addr, pgoff_t idx) +@@ -7014,7 +7014,7 @@ pte_t *huge_pmd_share(struct mm_struct *mm, struct vm_area_struct *vma, + spte = hugetlb_walk(svma, saddr, + vma_mmu_pagesize(svma)); + if (spte) { +- get_page(virt_to_page(spte)); ++ ptdesc_pmd_pts_inc(virt_to_ptdesc(spte)); + break; + } + } +@@ -7029,7 +7029,7 @@ pte_t *huge_pmd_share(struct mm_struct *mm, struct vm_area_struct *vma, + (pmd_t *)((unsigned long)spte & PAGE_MASK)); + mm_inc_nr_pmds(mm); + } else { +- put_page(virt_to_page(spte)); ++ ptdesc_pmd_pts_dec(virt_to_ptdesc(spte)); + } + spin_unlock(&mm->page_table_lock); + out: +@@ -7041,10 +7041,6 @@ pte_t *huge_pmd_share(struct mm_struct *mm, struct vm_area_struct *vma, + /* + * unmap huge page backed by shared pte. + * +- * Hugetlb pte page is ref counted at the time of mapping. If pte is shared +- * indicated by page_count > 1, unmap is achieved by clearing pud and +- * decrementing the ref count. If count == 1, the pte page is not shared. +- * + * Called with page table lock held. + * + * returns: 1 successfully unmapped a shared pte page +@@ -7053,23 +7049,25 @@ pte_t *huge_pmd_share(struct mm_struct *mm, struct vm_area_struct *vma, + int huge_pmd_unshare(struct mm_struct *mm, struct vm_area_struct *vma, + unsigned long addr, pte_t *ptep) + { ++ unsigned long sz = huge_page_size(hstate_vma(vma)); + pgd_t *pgd = pgd_offset(mm, addr); + p4d_t *p4d = p4d_offset(pgd, addr); + pud_t *pud = pud_offset(p4d, addr); + + i_mmap_assert_write_locked(vma->vm_file->f_mapping); + hugetlb_vma_assert_locked(vma); +- BUG_ON(page_count(virt_to_page(ptep)) == 0); +- if (page_count(virt_to_page(ptep)) == 1) ++ if (sz != PMD_SIZE) ++ return 0; ++ if (!ptdesc_pmd_pts_count(virt_to_ptdesc(ptep))) + return 0; + + pud_clear(pud); +- put_page(virt_to_page(ptep)); ++ ptdesc_pmd_pts_dec(virt_to_ptdesc(ptep)); + mm_dec_nr_pmds(mm); + return 1; + } + +-#else /* !CONFIG_ARCH_WANT_HUGE_PMD_SHARE */ ++#else /* !CONFIG_HUGETLB_PMD_PAGE_TABLE_SHARING */ + + pte_t *huge_pmd_share(struct mm_struct *mm, struct vm_area_struct *vma, + unsigned long addr, pud_t *pud) +@@ -7092,7 +7090,7 @@ bool want_pmd_share(struct vm_area_struct *vma, unsigned long addr) + { + return false; + } +-#endif /* CONFIG_ARCH_WANT_HUGE_PMD_SHARE */ ++#endif /* CONFIG_HUGETLB_PMD_PAGE_TABLE_SHARING */ + + #ifdef CONFIG_ARCH_WANT_GENERAL_HUGETLB + pte_t *huge_pte_alloc(struct mm_struct *mm, struct vm_area_struct *vma, +@@ -7190,7 +7188,7 @@ unsigned long hugetlb_mask_last_page(struct hstate *h) + /* See description above. Architectures can provide their own version. */ + __weak unsigned long hugetlb_mask_last_page(struct hstate *h) + { +-#ifdef CONFIG_ARCH_WANT_HUGE_PMD_SHARE ++#ifdef CONFIG_HUGETLB_PMD_PAGE_TABLE_SHARING + if (huge_page_size(h) == PMD_SIZE) + return PUD_SIZE - PMD_SIZE; + #endif +diff --git a/mm/memblock.c b/mm/memblock.c +index 87a2b4340ce4ea..e8a2a1537d6a85 100644 +--- a/mm/memblock.c ++++ b/mm/memblock.c +@@ -754,7 +754,7 @@ bool __init_memblock memblock_validate_numa_coverage(unsigned long threshold_byt + + /* calculate lose page */ + for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, &nid) { +- if (nid == NUMA_NO_NODE) ++ if (!numa_valid_node(nid)) + nr_pages += end_pfn - start_pfn; + } + +@@ -1043,7 +1043,7 @@ static bool should_skip_region(struct memblock_type *type, + return false; + + /* only memory regions are associated with nodes, check it */ +- if (nid != NUMA_NO_NODE && nid != m_nid) ++ if (numa_valid_node(nid) && nid != m_nid) + return true; + + /* skip hotpluggable memory regions if needed */ +@@ -1100,10 +1100,6 @@ void __next_mem_range(u64 *idx, int nid, enum memblock_flags flags, + int idx_a = *idx & 0xffffffff; + int idx_b = *idx >> 32; + +- if (WARN_ONCE(nid == MAX_NUMNODES, +- "Usage of MAX_NUMNODES is deprecated. Use NUMA_NO_NODE instead\n")) +- nid = NUMA_NO_NODE; +- + for (; idx_a < type_a->cnt; idx_a++) { + struct memblock_region *m = &type_a->regions[idx_a]; + +@@ -1197,9 +1193,6 @@ void __init_memblock __next_mem_range_rev(u64 *idx, int nid, + int idx_a = *idx & 0xffffffff; + int idx_b = *idx >> 32; + +- if (WARN_ONCE(nid == MAX_NUMNODES, "Usage of MAX_NUMNODES is deprecated. Use NUMA_NO_NODE instead\n")) +- nid = NUMA_NO_NODE; +- + if (*idx == (u64)ULLONG_MAX) { + idx_a = type_a->cnt - 1; + if (type_b != NULL) +@@ -1285,7 +1278,7 @@ void __init_memblock __next_mem_pfn_range(int *idx, int nid, + + if (PFN_UP(r->base) >= PFN_DOWN(r->base + r->size)) + continue; +- if (nid == MAX_NUMNODES || nid == r_nid) ++ if (!numa_valid_node(nid) || nid == r_nid) + break; + } + if (*idx >= type->cnt) { +@@ -1430,9 +1423,6 @@ phys_addr_t __init memblock_alloc_range_nid(phys_addr_t size, + enum memblock_flags flags = choose_memblock_flags(); + phys_addr_t found; + +- if (WARN_ONCE(nid == MAX_NUMNODES, "Usage of MAX_NUMNODES is deprecated. Use NUMA_NO_NODE instead\n")) +- nid = NUMA_NO_NODE; +- + if (!align) { + /* Can't use WARNs this early in boot on powerpc */ + dump_stack(); +@@ -1445,7 +1435,7 @@ phys_addr_t __init memblock_alloc_range_nid(phys_addr_t size, + if (found && !memblock_reserve(found, size)) + goto done; + +- if (nid != NUMA_NO_NODE && !exact_nid) { ++ if (numa_valid_node(nid) && !exact_nid) { + found = memblock_find_in_range_node(size, align, start, + end, NUMA_NO_NODE, + flags); +@@ -1965,7 +1955,7 @@ static void __init_memblock memblock_dump(struct memblock_type *type) + end = base + size - 1; + flags = rgn->flags; + #ifdef CONFIG_NUMA +- if (memblock_get_region_node(rgn) != MAX_NUMNODES) ++ if (numa_valid_node(memblock_get_region_node(rgn))) + snprintf(nid_buf, sizeof(nid_buf), " on node %d", + memblock_get_region_node(rgn)); + #endif +@@ -2154,7 +2144,7 @@ static void __init memmap_init_reserved_pages(void) + start = region->base; + end = start + region->size; + +- if (nid == NUMA_NO_NODE || nid >= MAX_NUMNODES) ++ if (!numa_valid_node(nid)) + nid = early_pfn_to_nid(PFN_DOWN(start)); + + reserve_bootmem_region(start, end, nid); +@@ -2243,7 +2233,7 @@ static int memblock_debug_show(struct seq_file *m, void *private) + + seq_printf(m, "%4d: ", i); + seq_printf(m, "%pa..%pa ", ®->base, &end); +- if (nid != MAX_NUMNODES) ++ if (numa_valid_node(nid)) + seq_printf(m, "%4d ", nid); + else + seq_printf(m, "%4c ", 'x'); +diff --git a/net/802/psnap.c b/net/802/psnap.c +index 1406bfdbda13b7..dbd9647f2ef1a0 100644 +--- a/net/802/psnap.c ++++ b/net/802/psnap.c +@@ -55,11 +55,11 @@ static int snap_rcv(struct sk_buff *skb, struct net_device *dev, + goto drop; + + rcu_read_lock(); +- proto = find_snap_client(skb_transport_header(skb)); ++ proto = find_snap_client(skb->data); + if (proto) { + /* Pass the frame on. */ +- skb->transport_header += 5; + skb_pull_rcsum(skb, 5); ++ skb_reset_transport_header(skb); + rc = proto->rcvfunc(skb, dev, &snap_packet_type, orig_dev); + } + rcu_read_unlock(); +diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c +index d95e2b55badb47..d6f40806ee5126 100644 +--- a/net/bluetooth/hci_sync.c ++++ b/net/bluetooth/hci_sync.c +@@ -1049,9 +1049,9 @@ static bool adv_use_rpa(struct hci_dev *hdev, uint32_t flags) + + static int hci_set_random_addr_sync(struct hci_dev *hdev, bdaddr_t *rpa) + { +- /* If we're advertising or initiating an LE connection we can't +- * go ahead and change the random address at this time. This is +- * because the eventual initiator address used for the ++ /* If a random_addr has been set we're advertising or initiating an LE ++ * connection we can't go ahead and change the random address at this ++ * time. This is because the eventual initiator address used for the + * subsequently created connection will be undefined (some + * controllers use the new address and others the one we had + * when the operation started). +@@ -1059,8 +1059,9 @@ static int hci_set_random_addr_sync(struct hci_dev *hdev, bdaddr_t *rpa) + * In this kind of scenario skip the update and let the random + * address be updated at the next cycle. + */ +- if (hci_dev_test_flag(hdev, HCI_LE_ADV) || +- hci_lookup_le_connect(hdev)) { ++ if (bacmp(&hdev->random_addr, BDADDR_ANY) && ++ (hci_dev_test_flag(hdev, HCI_LE_ADV) || ++ hci_lookup_le_connect(hdev))) { + bt_dev_dbg(hdev, "Deferring random address update"); + hci_dev_set_flag(hdev, HCI_RPA_EXPIRED); + return 0; +diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c +index 1175248e4bec4b..e3440f0d7d9d97 100644 +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -7589,6 +7589,24 @@ static void device_added(struct sock *sk, struct hci_dev *hdev, + mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk); + } + ++static void add_device_complete(struct hci_dev *hdev, void *data, int err) ++{ ++ struct mgmt_pending_cmd *cmd = data; ++ struct mgmt_cp_add_device *cp = cmd->param; ++ ++ if (!err) { ++ device_added(cmd->sk, hdev, &cp->addr.bdaddr, cp->addr.type, ++ cp->action); ++ device_flags_changed(NULL, hdev, &cp->addr.bdaddr, ++ cp->addr.type, hdev->conn_flags, ++ PTR_UINT(cmd->user_data)); ++ } ++ ++ mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_ADD_DEVICE, ++ mgmt_status(err), &cp->addr, sizeof(cp->addr)); ++ mgmt_pending_free(cmd); ++} ++ + static int add_device_sync(struct hci_dev *hdev, void *data) + { + return hci_update_passive_scan_sync(hdev); +@@ -7597,6 +7615,7 @@ static int add_device_sync(struct hci_dev *hdev, void *data) + static int add_device(struct sock *sk, struct hci_dev *hdev, + void *data, u16 len) + { ++ struct mgmt_pending_cmd *cmd; + struct mgmt_cp_add_device *cp = data; + u8 auto_conn, addr_type; + struct hci_conn_params *params; +@@ -7677,9 +7696,24 @@ static int add_device(struct sock *sk, struct hci_dev *hdev, + current_flags = params->flags; + } + +- err = hci_cmd_sync_queue(hdev, add_device_sync, NULL, NULL); +- if (err < 0) ++ cmd = mgmt_pending_new(sk, MGMT_OP_ADD_DEVICE, hdev, data, len); ++ if (!cmd) { ++ err = -ENOMEM; + goto unlock; ++ } ++ ++ cmd->user_data = UINT_PTR(current_flags); ++ ++ err = hci_cmd_sync_queue(hdev, add_device_sync, cmd, ++ add_device_complete); ++ if (err < 0) { ++ err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE, ++ MGMT_STATUS_FAILED, &cp->addr, ++ sizeof(cp->addr)); ++ mgmt_pending_free(cmd); ++ } ++ ++ goto unlock; + + added: + device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action); +diff --git a/net/core/link_watch.c b/net/core/link_watch.c +index 66422c95c83c77..e2e8a341318bda 100644 +--- a/net/core/link_watch.c ++++ b/net/core/link_watch.c +@@ -42,14 +42,18 @@ static unsigned char default_operstate(const struct net_device *dev) + * first check whether lower is indeed the source of its down state. + */ + if (!netif_carrier_ok(dev)) { +- int iflink = dev_get_iflink(dev); + struct net_device *peer; ++ int iflink; + + /* If called from netdev_run_todo()/linkwatch_sync_dev(), + * dev_net(dev) can be already freed, and RTNL is not held. + */ +- if (dev->reg_state == NETREG_UNREGISTERED || +- iflink == dev->ifindex) ++ if (dev->reg_state <= NETREG_REGISTERED) ++ iflink = dev_get_iflink(dev); ++ else ++ iflink = dev->ifindex; ++ ++ if (iflink == dev->ifindex) + return IF_OPER_DOWN; + + ASSERT_RTNL(); +diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c +index df3ddf31f8e673..705320f160ac86 100644 +--- a/net/ipv4/tcp_ipv4.c ++++ b/net/ipv4/tcp_ipv4.c +@@ -832,7 +832,7 @@ static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb) + sock_net_set(ctl_sk, net); + if (sk) { + ctl_sk->sk_mark = (sk->sk_state == TCP_TIME_WAIT) ? +- inet_twsk(sk)->tw_mark : sk->sk_mark; ++ inet_twsk(sk)->tw_mark : READ_ONCE(sk->sk_mark); + ctl_sk->sk_priority = (sk->sk_state == TCP_TIME_WAIT) ? + inet_twsk(sk)->tw_priority : sk->sk_priority; + transmit_time = tcp_transmit_time(sk); +diff --git a/net/mptcp/ctrl.c b/net/mptcp/ctrl.c +index de75df904a0034..34ae0ef4f9f396 100644 +--- a/net/mptcp/ctrl.c ++++ b/net/mptcp/ctrl.c +@@ -87,16 +87,15 @@ static void mptcp_pernet_set_defaults(struct mptcp_pernet *pernet) + } + + #ifdef CONFIG_SYSCTL +-static int mptcp_set_scheduler(const struct net *net, const char *name) ++static int mptcp_set_scheduler(char *scheduler, const char *name) + { +- struct mptcp_pernet *pernet = mptcp_get_pernet(net); + struct mptcp_sched_ops *sched; + int ret = 0; + + rcu_read_lock(); + sched = mptcp_sched_find(name); + if (sched) +- strscpy(pernet->scheduler, name, MPTCP_SCHED_NAME_MAX); ++ strscpy(scheduler, name, MPTCP_SCHED_NAME_MAX); + else + ret = -ENOENT; + rcu_read_unlock(); +@@ -107,7 +106,7 @@ static int mptcp_set_scheduler(const struct net *net, const char *name) + static int proc_scheduler(struct ctl_table *ctl, int write, + void *buffer, size_t *lenp, loff_t *ppos) + { +- const struct net *net = current->nsproxy->net_ns; ++ char (*scheduler)[MPTCP_SCHED_NAME_MAX] = ctl->data; + char val[MPTCP_SCHED_NAME_MAX]; + struct ctl_table tbl = { + .data = val, +@@ -115,11 +114,11 @@ static int proc_scheduler(struct ctl_table *ctl, int write, + }; + int ret; + +- strscpy(val, mptcp_get_scheduler(net), MPTCP_SCHED_NAME_MAX); ++ strscpy(val, *scheduler, MPTCP_SCHED_NAME_MAX); + + ret = proc_dostring(&tbl, write, buffer, lenp, ppos); + if (write && ret == 0) +- ret = mptcp_set_scheduler(net, val); ++ ret = mptcp_set_scheduler(*scheduler, val); + + return ret; + } +diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c +index e4ae2a08da6ac3..34ad5975fbf3ba 100644 +--- a/net/netfilter/nf_conntrack_core.c ++++ b/net/netfilter/nf_conntrack_core.c +@@ -2568,12 +2568,15 @@ void *nf_ct_alloc_hashtable(unsigned int *sizep, int nulls) + struct hlist_nulls_head *hash; + unsigned int nr_slots, i; + +- if (*sizep > (UINT_MAX / sizeof(struct hlist_nulls_head))) ++ if (*sizep > (INT_MAX / sizeof(struct hlist_nulls_head))) + return NULL; + + BUILD_BUG_ON(sizeof(struct hlist_nulls_head) != sizeof(struct hlist_head)); + nr_slots = *sizep = roundup(*sizep, PAGE_SIZE / sizeof(struct hlist_nulls_head)); + ++ if (nr_slots > (INT_MAX / sizeof(struct hlist_nulls_head))) ++ return NULL; ++ + hash = kvcalloc(nr_slots, sizeof(struct hlist_nulls_head), GFP_KERNEL); + + if (hash && nulls) +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index a110aad45fe487..1d1e998acd675e 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -8375,6 +8375,7 @@ static void nft_unregister_flowtable_hook(struct net *net, + } + + static void __nft_unregister_flowtable_net_hooks(struct net *net, ++ struct nft_flowtable *flowtable, + struct list_head *hook_list, + bool release_netdev) + { +@@ -8382,6 +8383,8 @@ static void __nft_unregister_flowtable_net_hooks(struct net *net, + + list_for_each_entry_safe(hook, next, hook_list, list) { + nf_unregister_net_hook(net, &hook->ops); ++ flowtable->data.type->setup(&flowtable->data, hook->ops.dev, ++ FLOW_BLOCK_UNBIND); + if (release_netdev) { + list_del(&hook->list); + kfree_rcu(hook, rcu); +@@ -8390,9 +8393,10 @@ static void __nft_unregister_flowtable_net_hooks(struct net *net, + } + + static void nft_unregister_flowtable_net_hooks(struct net *net, ++ struct nft_flowtable *flowtable, + struct list_head *hook_list) + { +- __nft_unregister_flowtable_net_hooks(net, hook_list, false); ++ __nft_unregister_flowtable_net_hooks(net, flowtable, hook_list, false); + } + + static int nft_register_flowtable_net_hooks(struct net *net, +@@ -9028,8 +9032,6 @@ static void nf_tables_flowtable_destroy(struct nft_flowtable *flowtable) + + flowtable->data.type->free(&flowtable->data); + list_for_each_entry_safe(hook, next, &flowtable->hook_list, list) { +- flowtable->data.type->setup(&flowtable->data, hook->ops.dev, +- FLOW_BLOCK_UNBIND); + list_del_rcu(&hook->list); + kfree_rcu(hook, rcu); + } +@@ -10399,6 +10401,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb) + &nft_trans_flowtable_hooks(trans), + trans->msg_type); + nft_unregister_flowtable_net_hooks(net, ++ nft_trans_flowtable(trans), + &nft_trans_flowtable_hooks(trans)); + } else { + list_del_rcu(&nft_trans_flowtable(trans)->list); +@@ -10407,6 +10410,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb) + NULL, + trans->msg_type); + nft_unregister_flowtable_net_hooks(net, ++ nft_trans_flowtable(trans), + &nft_trans_flowtable(trans)->hook_list); + } + break; +@@ -10659,11 +10663,13 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action) + case NFT_MSG_NEWFLOWTABLE: + if (nft_trans_flowtable_update(trans)) { + nft_unregister_flowtable_net_hooks(net, ++ nft_trans_flowtable(trans), + &nft_trans_flowtable_hooks(trans)); + } else { + nft_use_dec_restore(&trans->ctx.table->use); + list_del_rcu(&nft_trans_flowtable(trans)->list); + nft_unregister_flowtable_net_hooks(net, ++ nft_trans_flowtable(trans), + &nft_trans_flowtable(trans)->hook_list); + } + break; +@@ -11224,7 +11230,8 @@ static void __nft_release_hook(struct net *net, struct nft_table *table) + list_for_each_entry(chain, &table->chains, list) + __nf_tables_unregister_hook(net, table, chain, true); + list_for_each_entry(flowtable, &table->flowtables, list) +- __nft_unregister_flowtable_net_hooks(net, &flowtable->hook_list, ++ __nft_unregister_flowtable_net_hooks(net, flowtable, ++ &flowtable->hook_list, + true); + } + +diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c +index 6ab317b48d6c39..815216b564f323 100644 +--- a/net/sched/cls_flow.c ++++ b/net/sched/cls_flow.c +@@ -356,7 +356,8 @@ static const struct nla_policy flow_policy[TCA_FLOW_MAX + 1] = { + [TCA_FLOW_KEYS] = { .type = NLA_U32 }, + [TCA_FLOW_MODE] = { .type = NLA_U32 }, + [TCA_FLOW_BASECLASS] = { .type = NLA_U32 }, +- [TCA_FLOW_RSHIFT] = { .type = NLA_U32 }, ++ [TCA_FLOW_RSHIFT] = NLA_POLICY_MAX(NLA_U32, ++ 31 /* BITS_PER_U32 - 1 */), + [TCA_FLOW_ADDEND] = { .type = NLA_U32 }, + [TCA_FLOW_MASK] = { .type = NLA_U32 }, + [TCA_FLOW_XOR] = { .type = NLA_U32 }, +diff --git a/net/sched/sch_cake.c b/net/sched/sch_cake.c +index a65fad45d55681..09242578dac5bc 100644 +--- a/net/sched/sch_cake.c ++++ b/net/sched/sch_cake.c +@@ -644,6 +644,63 @@ static bool cake_ddst(int flow_mode) + return (flow_mode & CAKE_FLOW_DUAL_DST) == CAKE_FLOW_DUAL_DST; + } + ++static void cake_dec_srchost_bulk_flow_count(struct cake_tin_data *q, ++ struct cake_flow *flow, ++ int flow_mode) ++{ ++ if (likely(cake_dsrc(flow_mode) && ++ q->hosts[flow->srchost].srchost_bulk_flow_count)) ++ q->hosts[flow->srchost].srchost_bulk_flow_count--; ++} ++ ++static void cake_inc_srchost_bulk_flow_count(struct cake_tin_data *q, ++ struct cake_flow *flow, ++ int flow_mode) ++{ ++ if (likely(cake_dsrc(flow_mode) && ++ q->hosts[flow->srchost].srchost_bulk_flow_count < CAKE_QUEUES)) ++ q->hosts[flow->srchost].srchost_bulk_flow_count++; ++} ++ ++static void cake_dec_dsthost_bulk_flow_count(struct cake_tin_data *q, ++ struct cake_flow *flow, ++ int flow_mode) ++{ ++ if (likely(cake_ddst(flow_mode) && ++ q->hosts[flow->dsthost].dsthost_bulk_flow_count)) ++ q->hosts[flow->dsthost].dsthost_bulk_flow_count--; ++} ++ ++static void cake_inc_dsthost_bulk_flow_count(struct cake_tin_data *q, ++ struct cake_flow *flow, ++ int flow_mode) ++{ ++ if (likely(cake_ddst(flow_mode) && ++ q->hosts[flow->dsthost].dsthost_bulk_flow_count < CAKE_QUEUES)) ++ q->hosts[flow->dsthost].dsthost_bulk_flow_count++; ++} ++ ++static u16 cake_get_flow_quantum(struct cake_tin_data *q, ++ struct cake_flow *flow, ++ int flow_mode) ++{ ++ u16 host_load = 1; ++ ++ if (cake_dsrc(flow_mode)) ++ host_load = max(host_load, ++ q->hosts[flow->srchost].srchost_bulk_flow_count); ++ ++ if (cake_ddst(flow_mode)) ++ host_load = max(host_load, ++ q->hosts[flow->dsthost].dsthost_bulk_flow_count); ++ ++ /* The get_random_u16() is a way to apply dithering to avoid ++ * accumulating roundoff errors ++ */ ++ return (q->flow_quantum * quantum_div[host_load] + ++ get_random_u16()) >> 16; ++} ++ + static u32 cake_hash(struct cake_tin_data *q, const struct sk_buff *skb, + int flow_mode, u16 flow_override, u16 host_override) + { +@@ -790,10 +847,8 @@ static u32 cake_hash(struct cake_tin_data *q, const struct sk_buff *skb, + allocate_dst = cake_ddst(flow_mode); + + if (q->flows[outer_hash + k].set == CAKE_SET_BULK) { +- if (allocate_src) +- q->hosts[q->flows[reduced_hash].srchost].srchost_bulk_flow_count--; +- if (allocate_dst) +- q->hosts[q->flows[reduced_hash].dsthost].dsthost_bulk_flow_count--; ++ cake_dec_srchost_bulk_flow_count(q, &q->flows[outer_hash + k], flow_mode); ++ cake_dec_dsthost_bulk_flow_count(q, &q->flows[outer_hash + k], flow_mode); + } + found: + /* reserve queue for future packets in same flow */ +@@ -818,9 +873,10 @@ static u32 cake_hash(struct cake_tin_data *q, const struct sk_buff *skb, + q->hosts[outer_hash + k].srchost_tag = srchost_hash; + found_src: + srchost_idx = outer_hash + k; +- if (q->flows[reduced_hash].set == CAKE_SET_BULK) +- q->hosts[srchost_idx].srchost_bulk_flow_count++; + q->flows[reduced_hash].srchost = srchost_idx; ++ ++ if (q->flows[reduced_hash].set == CAKE_SET_BULK) ++ cake_inc_srchost_bulk_flow_count(q, &q->flows[reduced_hash], flow_mode); + } + + if (allocate_dst) { +@@ -841,9 +897,10 @@ static u32 cake_hash(struct cake_tin_data *q, const struct sk_buff *skb, + q->hosts[outer_hash + k].dsthost_tag = dsthost_hash; + found_dst: + dsthost_idx = outer_hash + k; +- if (q->flows[reduced_hash].set == CAKE_SET_BULK) +- q->hosts[dsthost_idx].dsthost_bulk_flow_count++; + q->flows[reduced_hash].dsthost = dsthost_idx; ++ ++ if (q->flows[reduced_hash].set == CAKE_SET_BULK) ++ cake_inc_dsthost_bulk_flow_count(q, &q->flows[reduced_hash], flow_mode); + } + } + +@@ -1856,10 +1913,6 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch, + + /* flowchain */ + if (!flow->set || flow->set == CAKE_SET_DECAYING) { +- struct cake_host *srchost = &b->hosts[flow->srchost]; +- struct cake_host *dsthost = &b->hosts[flow->dsthost]; +- u16 host_load = 1; +- + if (!flow->set) { + list_add_tail(&flow->flowchain, &b->new_flows); + } else { +@@ -1869,18 +1922,8 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch, + flow->set = CAKE_SET_SPARSE; + b->sparse_flow_count++; + +- if (cake_dsrc(q->flow_mode)) +- host_load = max(host_load, srchost->srchost_bulk_flow_count); +- +- if (cake_ddst(q->flow_mode)) +- host_load = max(host_load, dsthost->dsthost_bulk_flow_count); +- +- flow->deficit = (b->flow_quantum * +- quantum_div[host_load]) >> 16; ++ flow->deficit = cake_get_flow_quantum(b, flow, q->flow_mode); + } else if (flow->set == CAKE_SET_SPARSE_WAIT) { +- struct cake_host *srchost = &b->hosts[flow->srchost]; +- struct cake_host *dsthost = &b->hosts[flow->dsthost]; +- + /* this flow was empty, accounted as a sparse flow, but actually + * in the bulk rotation. + */ +@@ -1888,12 +1931,8 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch, + b->sparse_flow_count--; + b->bulk_flow_count++; + +- if (cake_dsrc(q->flow_mode)) +- srchost->srchost_bulk_flow_count++; +- +- if (cake_ddst(q->flow_mode)) +- dsthost->dsthost_bulk_flow_count++; +- ++ cake_inc_srchost_bulk_flow_count(b, flow, q->flow_mode); ++ cake_inc_dsthost_bulk_flow_count(b, flow, q->flow_mode); + } + + if (q->buffer_used > q->buffer_max_used) +@@ -1950,13 +1989,11 @@ static struct sk_buff *cake_dequeue(struct Qdisc *sch) + { + struct cake_sched_data *q = qdisc_priv(sch); + struct cake_tin_data *b = &q->tins[q->cur_tin]; +- struct cake_host *srchost, *dsthost; + ktime_t now = ktime_get(); + struct cake_flow *flow; + struct list_head *head; + bool first_flow = true; + struct sk_buff *skb; +- u16 host_load; + u64 delay; + u32 len; + +@@ -2056,11 +2093,6 @@ static struct sk_buff *cake_dequeue(struct Qdisc *sch) + q->cur_flow = flow - b->flows; + first_flow = false; + +- /* triple isolation (modified DRR++) */ +- srchost = &b->hosts[flow->srchost]; +- dsthost = &b->hosts[flow->dsthost]; +- host_load = 1; +- + /* flow isolation (DRR++) */ + if (flow->deficit <= 0) { + /* Keep all flows with deficits out of the sparse and decaying +@@ -2072,11 +2104,8 @@ static struct sk_buff *cake_dequeue(struct Qdisc *sch) + b->sparse_flow_count--; + b->bulk_flow_count++; + +- if (cake_dsrc(q->flow_mode)) +- srchost->srchost_bulk_flow_count++; +- +- if (cake_ddst(q->flow_mode)) +- dsthost->dsthost_bulk_flow_count++; ++ cake_inc_srchost_bulk_flow_count(b, flow, q->flow_mode); ++ cake_inc_dsthost_bulk_flow_count(b, flow, q->flow_mode); + + flow->set = CAKE_SET_BULK; + } else { +@@ -2088,19 +2117,7 @@ static struct sk_buff *cake_dequeue(struct Qdisc *sch) + } + } + +- if (cake_dsrc(q->flow_mode)) +- host_load = max(host_load, srchost->srchost_bulk_flow_count); +- +- if (cake_ddst(q->flow_mode)) +- host_load = max(host_load, dsthost->dsthost_bulk_flow_count); +- +- WARN_ON(host_load > CAKE_QUEUES); +- +- /* The get_random_u16() is a way to apply dithering to avoid +- * accumulating roundoff errors +- */ +- flow->deficit += (b->flow_quantum * quantum_div[host_load] + +- get_random_u16()) >> 16; ++ flow->deficit += cake_get_flow_quantum(b, flow, q->flow_mode); + list_move_tail(&flow->flowchain, &b->old_flows); + + goto retry; +@@ -2124,11 +2141,8 @@ static struct sk_buff *cake_dequeue(struct Qdisc *sch) + if (flow->set == CAKE_SET_BULK) { + b->bulk_flow_count--; + +- if (cake_dsrc(q->flow_mode)) +- srchost->srchost_bulk_flow_count--; +- +- if (cake_ddst(q->flow_mode)) +- dsthost->dsthost_bulk_flow_count--; ++ cake_dec_srchost_bulk_flow_count(b, flow, q->flow_mode); ++ cake_dec_dsthost_bulk_flow_count(b, flow, q->flow_mode); + + b->decaying_flow_count++; + } else if (flow->set == CAKE_SET_SPARSE || +@@ -2146,12 +2160,8 @@ static struct sk_buff *cake_dequeue(struct Qdisc *sch) + else if (flow->set == CAKE_SET_BULK) { + b->bulk_flow_count--; + +- if (cake_dsrc(q->flow_mode)) +- srchost->srchost_bulk_flow_count--; +- +- if (cake_ddst(q->flow_mode)) +- dsthost->dsthost_bulk_flow_count--; +- ++ cake_dec_srchost_bulk_flow_count(b, flow, q->flow_mode); ++ cake_dec_dsthost_bulk_flow_count(b, flow, q->flow_mode); + } else + b->decaying_flow_count--; + +diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c +index f65d6f92afcbc2..fd73be940f4607 100644 +--- a/net/sctp/sysctl.c ++++ b/net/sctp/sysctl.c +@@ -391,7 +391,8 @@ static struct ctl_table sctp_net_table[] = { + static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write, + void *buffer, size_t *lenp, loff_t *ppos) + { +- struct net *net = current->nsproxy->net_ns; ++ struct net *net = container_of(ctl->data, struct net, ++ sctp.sctp_hmac_alg); + struct ctl_table tbl; + bool changed = false; + char *none = "none"; +@@ -436,7 +437,7 @@ static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write, + static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write, + void *buffer, size_t *lenp, loff_t *ppos) + { +- struct net *net = current->nsproxy->net_ns; ++ struct net *net = container_of(ctl->data, struct net, sctp.rto_min); + unsigned int min = *(unsigned int *) ctl->extra1; + unsigned int max = *(unsigned int *) ctl->extra2; + struct ctl_table tbl; +@@ -464,7 +465,7 @@ static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write, + static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write, + void *buffer, size_t *lenp, loff_t *ppos) + { +- struct net *net = current->nsproxy->net_ns; ++ struct net *net = container_of(ctl->data, struct net, sctp.rto_max); + unsigned int min = *(unsigned int *) ctl->extra1; + unsigned int max = *(unsigned int *) ctl->extra2; + struct ctl_table tbl; +@@ -502,7 +503,7 @@ static int proc_sctp_do_alpha_beta(struct ctl_table *ctl, int write, + static int proc_sctp_do_auth(struct ctl_table *ctl, int write, + void *buffer, size_t *lenp, loff_t *ppos) + { +- struct net *net = current->nsproxy->net_ns; ++ struct net *net = container_of(ctl->data, struct net, sctp.auth_enable); + struct ctl_table tbl; + int new_value, ret; + +@@ -531,7 +532,7 @@ static int proc_sctp_do_auth(struct ctl_table *ctl, int write, + static int proc_sctp_do_udp_port(struct ctl_table *ctl, int write, + void *buffer, size_t *lenp, loff_t *ppos) + { +- struct net *net = current->nsproxy->net_ns; ++ struct net *net = container_of(ctl->data, struct net, sctp.udp_port); + unsigned int min = *(unsigned int *)ctl->extra1; + unsigned int max = *(unsigned int *)ctl->extra2; + struct ctl_table tbl; +@@ -572,7 +573,8 @@ static int proc_sctp_do_udp_port(struct ctl_table *ctl, int write, + static int proc_sctp_do_probe_interval(struct ctl_table *ctl, int write, + void *buffer, size_t *lenp, loff_t *ppos) + { +- struct net *net = current->nsproxy->net_ns; ++ struct net *net = container_of(ctl->data, struct net, ++ sctp.probe_interval); + struct ctl_table tbl; + int ret, new_value; + +diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c +index df166f6afad823..6e30fe879d538e 100644 +--- a/net/tls/tls_sw.c ++++ b/net/tls/tls_sw.c +@@ -458,7 +458,7 @@ int tls_tx_records(struct sock *sk, int flags) + + tx_err: + if (rc < 0 && rc != -EAGAIN) +- tls_err_abort(sk, -EBADMSG); ++ tls_err_abort(sk, rc); + + return rc; + } +diff --git a/sound/soc/codecs/rt722-sdca.c b/sound/soc/codecs/rt722-sdca.c +index b9b330375addab..0f9f592744ada3 100644 +--- a/sound/soc/codecs/rt722-sdca.c ++++ b/sound/soc/codecs/rt722-sdca.c +@@ -1466,13 +1466,18 @@ static void rt722_sdca_jack_preset(struct rt722_sdca_priv *rt722) + 0x008d); + /* check HP calibration FSM status */ + for (loop_check = 0; loop_check < chk_cnt; loop_check++) { ++ usleep_range(10000, 11000); + ret = rt722_sdca_index_read(rt722, RT722_VENDOR_CALI, + RT722_DAC_DC_CALI_CTL3, &calib_status); +- if (ret < 0 || loop_check == chk_cnt) ++ if (ret < 0) + dev_dbg(&rt722->slave->dev, "calibration failed!, ret=%d\n", ret); + if ((calib_status & 0x0040) == 0x0) + break; + } ++ ++ if (loop_check == chk_cnt) ++ dev_dbg(&rt722->slave->dev, "%s, calibration time-out!\n", __func__); ++ + /* Set ADC09 power entity floating control */ + rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_ADC0A_08_PDE_FLOAT_CTL, + 0x2a12); +diff --git a/sound/soc/mediatek/common/mtk-afe-platform-driver.c b/sound/soc/mediatek/common/mtk-afe-platform-driver.c +index 01501d5747a7c0..52495c930ca3bf 100644 +--- a/sound/soc/mediatek/common/mtk-afe-platform-driver.c ++++ b/sound/soc/mediatek/common/mtk-afe-platform-driver.c +@@ -120,8 +120,8 @@ int mtk_afe_pcm_new(struct snd_soc_component *component, + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); + + size = afe->mtk_afe_hardware->buffer_bytes_max; +- snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, +- afe->dev, size, size); ++ snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, afe->dev, 0, size); ++ + return 0; + } + EXPORT_SYMBOL_GPL(mtk_afe_pcm_new); +diff --git a/tools/include/linux/numa.h b/tools/include/linux/numa.h +index 110b0e5d0fb004..c8b9369335e000 100644 +--- a/tools/include/linux/numa.h ++++ b/tools/include/linux/numa.h +@@ -13,4 +13,9 @@ + + #define NUMA_NO_NODE (-1) + ++static inline bool numa_valid_node(int nid) ++{ ++ return nid >= 0 && nid < MAX_NUMNODES; ++} ++ + #endif /* _LINUX_NUMA_H */ +diff --git a/tools/testing/selftests/alsa/Makefile b/tools/testing/selftests/alsa/Makefile +index 5af9ba8a4645bc..140c7f821727d7 100644 +--- a/tools/testing/selftests/alsa/Makefile ++++ b/tools/testing/selftests/alsa/Makefile +@@ -23,5 +23,5 @@ include ../lib.mk + $(OUTPUT)/libatest.so: conf.c alsa-local.h + $(CC) $(CFLAGS) -shared -fPIC $< $(LDLIBS) -o $@ + +-$(OUTPUT)/%: %.c $(TEST_GEN_PROGS_EXTENDED) alsa-local.h ++$(OUTPUT)/%: %.c $(OUTPUT)/libatest.so alsa-local.h + $(CC) $(CFLAGS) $< $(LDLIBS) -latest -o $@ diff --git a/patch/kernel/archive/odroidxu4-6.6/patch-6.6.72-73.patch b/patch/kernel/archive/odroidxu4-6.6/patch-6.6.72-73.patch new file mode 100644 index 0000000000..73157e52aa --- /dev/null +++ b/patch/kernel/archive/odroidxu4-6.6/patch-6.6.72-73.patch @@ -0,0 +1,586 @@ +diff --git a/Makefile b/Makefile +index fb4949cac6ffbf..2ba627f545901e 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 6 + PATCHLEVEL = 6 +-SUBLEVEL = 72 ++SUBLEVEL = 73 + EXTRAVERSION = + NAME = Pinguïn Aangedreven + +diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c +index f14c412c56097d..ada3fcc9c6d501 100644 +--- a/fs/overlayfs/copy_up.c ++++ b/fs/overlayfs/copy_up.c +@@ -371,13 +371,13 @@ int ovl_set_attr(struct ovl_fs *ofs, struct dentry *upperdentry, + return err; + } + +-struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct inode *realinode, ++struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct dentry *real, + bool is_upper) + { + struct ovl_fh *fh; + int fh_type, dwords; + int buflen = MAX_HANDLE_SZ; +- uuid_t *uuid = &realinode->i_sb->s_uuid; ++ uuid_t *uuid = &real->d_sb->s_uuid; + int err; + + /* Make sure the real fid stays 32bit aligned */ +@@ -394,8 +394,7 @@ struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct inode *realinode, + * the price or reconnecting the dentry. + */ + dwords = buflen >> 2; +- fh_type = exportfs_encode_inode_fh(realinode, (void *)fh->fb.fid, +- &dwords, NULL, 0); ++ fh_type = exportfs_encode_fh(real, (void *)fh->fb.fid, &dwords, 0); + buflen = (dwords << 2); + + err = -EIO; +@@ -427,29 +426,29 @@ struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct inode *realinode, + return ERR_PTR(err); + } + +-struct ovl_fh *ovl_get_origin_fh(struct ovl_fs *ofs, struct dentry *origin) ++int ovl_set_origin(struct ovl_fs *ofs, struct dentry *lower, ++ struct dentry *upper) + { ++ const struct ovl_fh *fh = NULL; ++ int err; ++ + /* + * When lower layer doesn't support export operations store a 'null' fh, + * so we can use the overlay.origin xattr to distignuish between a copy + * up and a pure upper inode. + */ +- if (!ovl_can_decode_fh(origin->d_sb)) +- return NULL; +- +- return ovl_encode_real_fh(ofs, d_inode(origin), false); +-} +- +-int ovl_set_origin_fh(struct ovl_fs *ofs, const struct ovl_fh *fh, +- struct dentry *upper) +-{ +- int err; ++ if (ovl_can_decode_fh(lower->d_sb)) { ++ fh = ovl_encode_real_fh(ofs, lower, false); ++ if (IS_ERR(fh)) ++ return PTR_ERR(fh); ++ } + + /* + * Do not fail when upper doesn't support xattrs. + */ + err = ovl_check_setxattr(ofs, upper, OVL_XATTR_ORIGIN, fh->buf, + fh ? fh->fb.len : 0, 0); ++ kfree(fh); + + /* Ignore -EPERM from setting "user.*" on symlink/special */ + return err == -EPERM ? 0 : err; +@@ -462,7 +461,7 @@ static int ovl_set_upper_fh(struct ovl_fs *ofs, struct dentry *upper, + const struct ovl_fh *fh; + int err; + +- fh = ovl_encode_real_fh(ofs, d_inode(upper), true); ++ fh = ovl_encode_real_fh(ofs, upper, true); + if (IS_ERR(fh)) + return PTR_ERR(fh); + +@@ -477,7 +476,7 @@ static int ovl_set_upper_fh(struct ovl_fs *ofs, struct dentry *upper, + * + * Caller must hold i_mutex on indexdir. + */ +-static int ovl_create_index(struct dentry *dentry, const struct ovl_fh *fh, ++static int ovl_create_index(struct dentry *dentry, struct dentry *origin, + struct dentry *upper) + { + struct ovl_fs *ofs = OVL_FS(dentry->d_sb); +@@ -503,7 +502,7 @@ static int ovl_create_index(struct dentry *dentry, const struct ovl_fh *fh, + if (WARN_ON(ovl_test_flag(OVL_INDEX, d_inode(dentry)))) + return -EIO; + +- err = ovl_get_index_name_fh(fh, &name); ++ err = ovl_get_index_name(ofs, origin, &name); + if (err) + return err; + +@@ -542,7 +541,6 @@ struct ovl_copy_up_ctx { + struct dentry *destdir; + struct qstr destname; + struct dentry *workdir; +- const struct ovl_fh *origin_fh; + bool origin; + bool indexed; + bool metacopy; +@@ -639,7 +637,7 @@ static int ovl_copy_up_metadata(struct ovl_copy_up_ctx *c, struct dentry *temp) + * hard link. + */ + if (c->origin) { +- err = ovl_set_origin_fh(ofs, c->origin_fh, temp); ++ err = ovl_set_origin(ofs, c->lowerpath.dentry, temp); + if (err) + return err; + } +@@ -751,7 +749,7 @@ static int ovl_copy_up_workdir(struct ovl_copy_up_ctx *c) + goto cleanup; + + if (S_ISDIR(c->stat.mode) && c->indexed) { +- err = ovl_create_index(c->dentry, c->origin_fh, temp); ++ err = ovl_create_index(c->dentry, c->lowerpath.dentry, temp); + if (err) + goto cleanup; + } +@@ -863,8 +861,6 @@ static int ovl_do_copy_up(struct ovl_copy_up_ctx *c) + { + int err; + struct ovl_fs *ofs = OVL_FS(c->dentry->d_sb); +- struct dentry *origin = c->lowerpath.dentry; +- struct ovl_fh *fh = NULL; + bool to_index = false; + + /* +@@ -881,25 +877,17 @@ static int ovl_do_copy_up(struct ovl_copy_up_ctx *c) + to_index = true; + } + +- if (S_ISDIR(c->stat.mode) || c->stat.nlink == 1 || to_index) { +- fh = ovl_get_origin_fh(ofs, origin); +- if (IS_ERR(fh)) +- return PTR_ERR(fh); +- +- /* origin_fh may be NULL */ +- c->origin_fh = fh; ++ if (S_ISDIR(c->stat.mode) || c->stat.nlink == 1 || to_index) + c->origin = true; +- } + + if (to_index) { + c->destdir = ovl_indexdir(c->dentry->d_sb); +- err = ovl_get_index_name(ofs, origin, &c->destname); ++ err = ovl_get_index_name(ofs, c->lowerpath.dentry, &c->destname); + if (err) +- goto out_free_fh; ++ return err; + } else if (WARN_ON(!c->parent)) { + /* Disconnected dentry must be copied up to index dir */ +- err = -EIO; +- goto out_free_fh; ++ return -EIO; + } else { + /* + * Mark parent "impure" because it may now contain non-pure +@@ -907,7 +895,7 @@ static int ovl_do_copy_up(struct ovl_copy_up_ctx *c) + */ + err = ovl_set_impure(c->parent, c->destdir); + if (err) +- goto out_free_fh; ++ return err; + } + + /* Should we copyup with O_TMPFILE or with workdir? */ +@@ -939,8 +927,6 @@ static int ovl_do_copy_up(struct ovl_copy_up_ctx *c) + out: + if (to_index) + kfree(c->destname.name); +-out_free_fh: +- kfree(fh); + return err; + } + +diff --git a/fs/overlayfs/export.c b/fs/overlayfs/export.c +index 3a17e4366f28c0..611ff567a1aa6f 100644 +--- a/fs/overlayfs/export.c ++++ b/fs/overlayfs/export.c +@@ -181,37 +181,35 @@ static int ovl_connect_layer(struct dentry *dentry) + * + * Return 0 for upper file handle, > 0 for lower file handle or < 0 on error. + */ +-static int ovl_check_encode_origin(struct inode *inode) ++static int ovl_check_encode_origin(struct dentry *dentry) + { +- struct ovl_fs *ofs = OVL_FS(inode->i_sb); ++ struct ovl_fs *ofs = OVL_FS(dentry->d_sb); + bool decodable = ofs->config.nfs_export; +- struct dentry *dentry; +- int err; + + /* No upper layer? */ + if (!ovl_upper_mnt(ofs)) + return 1; + + /* Lower file handle for non-upper non-decodable */ +- if (!ovl_inode_upper(inode) && !decodable) ++ if (!ovl_dentry_upper(dentry) && !decodable) + return 1; + + /* Upper file handle for pure upper */ +- if (!ovl_inode_lower(inode)) ++ if (!ovl_dentry_lower(dentry)) + return 0; + + /* + * Root is never indexed, so if there's an upper layer, encode upper for + * root. + */ +- if (inode == d_inode(inode->i_sb->s_root)) ++ if (dentry == dentry->d_sb->s_root) + return 0; + + /* + * Upper decodable file handle for non-indexed upper. + */ +- if (ovl_inode_upper(inode) && decodable && +- !ovl_test_flag(OVL_INDEX, inode)) ++ if (ovl_dentry_upper(dentry) && decodable && ++ !ovl_test_flag(OVL_INDEX, d_inode(dentry))) + return 0; + + /* +@@ -220,23 +218,14 @@ static int ovl_check_encode_origin(struct inode *inode) + * ovl_connect_layer() will try to make origin's layer "connected" by + * copying up a "connectable" ancestor. + */ +- if (!decodable || !S_ISDIR(inode->i_mode)) +- return 1; +- +- dentry = d_find_any_alias(inode); +- if (!dentry) +- return -ENOENT; +- +- err = ovl_connect_layer(dentry); +- dput(dentry); +- if (err < 0) +- return err; ++ if (d_is_dir(dentry) && decodable) ++ return ovl_connect_layer(dentry); + + /* Lower file handle for indexed and non-upper dir/non-dir */ + return 1; + } + +-static int ovl_dentry_to_fid(struct ovl_fs *ofs, struct inode *inode, ++static int ovl_dentry_to_fid(struct ovl_fs *ofs, struct dentry *dentry, + u32 *fid, int buflen) + { + struct ovl_fh *fh = NULL; +@@ -247,13 +236,13 @@ static int ovl_dentry_to_fid(struct ovl_fs *ofs, struct inode *inode, + * Check if we should encode a lower or upper file handle and maybe + * copy up an ancestor to make lower file handle connectable. + */ +- err = enc_lower = ovl_check_encode_origin(inode); ++ err = enc_lower = ovl_check_encode_origin(dentry); + if (enc_lower < 0) + goto fail; + + /* Encode an upper or lower file handle */ +- fh = ovl_encode_real_fh(ofs, enc_lower ? ovl_inode_lower(inode) : +- ovl_inode_upper(inode), !enc_lower); ++ fh = ovl_encode_real_fh(ofs, enc_lower ? ovl_dentry_lower(dentry) : ++ ovl_dentry_upper(dentry), !enc_lower); + if (IS_ERR(fh)) + return PTR_ERR(fh); + +@@ -267,8 +256,8 @@ static int ovl_dentry_to_fid(struct ovl_fs *ofs, struct inode *inode, + return err; + + fail: +- pr_warn_ratelimited("failed to encode file handle (ino=%lu, err=%i)\n", +- inode->i_ino, err); ++ pr_warn_ratelimited("failed to encode file handle (%pd2, err=%i)\n", ++ dentry, err); + goto out; + } + +@@ -276,13 +265,19 @@ static int ovl_encode_fh(struct inode *inode, u32 *fid, int *max_len, + struct inode *parent) + { + struct ovl_fs *ofs = OVL_FS(inode->i_sb); ++ struct dentry *dentry; + int bytes, buflen = *max_len << 2; + + /* TODO: encode connectable file handles */ + if (parent) + return FILEID_INVALID; + +- bytes = ovl_dentry_to_fid(ofs, inode, fid, buflen); ++ dentry = d_find_any_alias(inode); ++ if (!dentry) ++ return FILEID_INVALID; ++ ++ bytes = ovl_dentry_to_fid(ofs, dentry, fid, buflen); ++ dput(dentry); + if (bytes <= 0) + return FILEID_INVALID; + +diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c +index 2d2ef671b36ba5..80391c687c2ad8 100644 +--- a/fs/overlayfs/namei.c ++++ b/fs/overlayfs/namei.c +@@ -507,19 +507,6 @@ static int ovl_verify_fh(struct ovl_fs *ofs, struct dentry *dentry, + return err; + } + +-int ovl_verify_set_fh(struct ovl_fs *ofs, struct dentry *dentry, +- enum ovl_xattr ox, const struct ovl_fh *fh, +- bool is_upper, bool set) +-{ +- int err; +- +- err = ovl_verify_fh(ofs, dentry, ox, fh); +- if (set && err == -ENODATA) +- err = ovl_setxattr(ofs, dentry, ox, fh->buf, fh->fb.len); +- +- return err; +-} +- + /* + * Verify that @real dentry matches the file handle stored in xattr @name. + * +@@ -528,22 +515,24 @@ int ovl_verify_set_fh(struct ovl_fs *ofs, struct dentry *dentry, + * + * Return 0 on match, -ESTALE on mismatch, -ENODATA on no xattr, < 0 on error. + */ +-int ovl_verify_origin_xattr(struct ovl_fs *ofs, struct dentry *dentry, +- enum ovl_xattr ox, struct dentry *real, +- bool is_upper, bool set) ++int ovl_verify_set_fh(struct ovl_fs *ofs, struct dentry *dentry, ++ enum ovl_xattr ox, struct dentry *real, bool is_upper, ++ bool set) + { + struct inode *inode; + struct ovl_fh *fh; + int err; + +- fh = ovl_encode_real_fh(ofs, d_inode(real), is_upper); ++ fh = ovl_encode_real_fh(ofs, real, is_upper); + err = PTR_ERR(fh); + if (IS_ERR(fh)) { + fh = NULL; + goto fail; + } + +- err = ovl_verify_set_fh(ofs, dentry, ox, fh, is_upper, set); ++ err = ovl_verify_fh(ofs, dentry, ox, fh); ++ if (set && err == -ENODATA) ++ err = ovl_setxattr(ofs, dentry, ox, fh->buf, fh->fb.len); + if (err) + goto fail; + +@@ -559,7 +548,6 @@ int ovl_verify_origin_xattr(struct ovl_fs *ofs, struct dentry *dentry, + goto out; + } + +- + /* Get upper dentry from index */ + struct dentry *ovl_index_upper(struct ovl_fs *ofs, struct dentry *index, + bool connected) +@@ -696,7 +684,7 @@ int ovl_verify_index(struct ovl_fs *ofs, struct dentry *index) + goto out; + } + +-int ovl_get_index_name_fh(const struct ovl_fh *fh, struct qstr *name) ++static int ovl_get_index_name_fh(struct ovl_fh *fh, struct qstr *name) + { + char *n, *s; + +@@ -732,7 +720,7 @@ int ovl_get_index_name(struct ovl_fs *ofs, struct dentry *origin, + struct ovl_fh *fh; + int err; + +- fh = ovl_encode_real_fh(ofs, d_inode(origin), false); ++ fh = ovl_encode_real_fh(ofs, origin, false); + if (IS_ERR(fh)) + return PTR_ERR(fh); + +@@ -885,27 +873,20 @@ int ovl_path_next(int idx, struct dentry *dentry, struct path *path) + static int ovl_fix_origin(struct ovl_fs *ofs, struct dentry *dentry, + struct dentry *lower, struct dentry *upper) + { +- const struct ovl_fh *fh; + int err; + + if (ovl_check_origin_xattr(ofs, upper)) + return 0; + +- fh = ovl_get_origin_fh(ofs, lower); +- if (IS_ERR(fh)) +- return PTR_ERR(fh); +- + err = ovl_want_write(dentry); + if (err) +- goto out; ++ return err; + +- err = ovl_set_origin_fh(ofs, fh, upper); ++ err = ovl_set_origin(ofs, lower, upper); + if (!err) + err = ovl_set_impure(dentry->d_parent, upper->d_parent); + + ovl_drop_write(dentry); +-out: +- kfree(fh); + return err; + } + +diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h +index ca63a26a6170b0..09ca82ed0f8ced 100644 +--- a/fs/overlayfs/overlayfs.h ++++ b/fs/overlayfs/overlayfs.h +@@ -632,15 +632,11 @@ struct dentry *ovl_decode_real_fh(struct ovl_fs *ofs, struct ovl_fh *fh, + int ovl_check_origin_fh(struct ovl_fs *ofs, struct ovl_fh *fh, bool connected, + struct dentry *upperdentry, struct ovl_path **stackp); + int ovl_verify_set_fh(struct ovl_fs *ofs, struct dentry *dentry, +- enum ovl_xattr ox, const struct ovl_fh *fh, +- bool is_upper, bool set); +-int ovl_verify_origin_xattr(struct ovl_fs *ofs, struct dentry *dentry, +- enum ovl_xattr ox, struct dentry *real, +- bool is_upper, bool set); ++ enum ovl_xattr ox, struct dentry *real, bool is_upper, ++ bool set); + struct dentry *ovl_index_upper(struct ovl_fs *ofs, struct dentry *index, + bool connected); + int ovl_verify_index(struct ovl_fs *ofs, struct dentry *index); +-int ovl_get_index_name_fh(const struct ovl_fh *fh, struct qstr *name); + int ovl_get_index_name(struct ovl_fs *ofs, struct dentry *origin, + struct qstr *name); + struct dentry *ovl_get_index_fh(struct ovl_fs *ofs, struct ovl_fh *fh); +@@ -652,24 +648,17 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, + unsigned int flags); + bool ovl_lower_positive(struct dentry *dentry); + +-static inline int ovl_verify_origin_fh(struct ovl_fs *ofs, struct dentry *upper, +- const struct ovl_fh *fh, bool set) +-{ +- return ovl_verify_set_fh(ofs, upper, OVL_XATTR_ORIGIN, fh, false, set); +-} +- + static inline int ovl_verify_origin(struct ovl_fs *ofs, struct dentry *upper, + struct dentry *origin, bool set) + { +- return ovl_verify_origin_xattr(ofs, upper, OVL_XATTR_ORIGIN, origin, +- false, set); ++ return ovl_verify_set_fh(ofs, upper, OVL_XATTR_ORIGIN, origin, ++ false, set); + } + + static inline int ovl_verify_upper(struct ovl_fs *ofs, struct dentry *index, + struct dentry *upper, bool set) + { +- return ovl_verify_origin_xattr(ofs, index, OVL_XATTR_UPPER, upper, +- true, set); ++ return ovl_verify_set_fh(ofs, index, OVL_XATTR_UPPER, upper, true, set); + } + + /* readdir.c */ +@@ -832,11 +821,10 @@ int ovl_copy_up_with_data(struct dentry *dentry); + int ovl_maybe_copy_up(struct dentry *dentry, int flags); + int ovl_copy_xattr(struct super_block *sb, const struct path *path, struct dentry *new); + int ovl_set_attr(struct ovl_fs *ofs, struct dentry *upper, struct kstat *stat); +-struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct inode *realinode, ++struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct dentry *real, + bool is_upper); +-struct ovl_fh *ovl_get_origin_fh(struct ovl_fs *ofs, struct dentry *origin); +-int ovl_set_origin_fh(struct ovl_fs *ofs, const struct ovl_fh *fh, +- struct dentry *upper); ++int ovl_set_origin(struct ovl_fs *ofs, struct dentry *lower, ++ struct dentry *upper); + + /* export.c */ + extern const struct export_operations ovl_export_operations; +diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c +index e2574034c3fa17..2c056d737c27c3 100644 +--- a/fs/overlayfs/super.c ++++ b/fs/overlayfs/super.c +@@ -879,20 +879,15 @@ static int ovl_get_indexdir(struct super_block *sb, struct ovl_fs *ofs, + { + struct vfsmount *mnt = ovl_upper_mnt(ofs); + struct dentry *indexdir; +- struct dentry *origin = ovl_lowerstack(oe)->dentry; +- const struct ovl_fh *fh; + int err; + +- fh = ovl_get_origin_fh(ofs, origin); +- if (IS_ERR(fh)) +- return PTR_ERR(fh); +- + err = mnt_want_write(mnt); + if (err) +- goto out_free_fh; ++ return err; + + /* Verify lower root is upper root origin */ +- err = ovl_verify_origin_fh(ofs, upperpath->dentry, fh, true); ++ err = ovl_verify_origin(ofs, upperpath->dentry, ++ ovl_lowerstack(oe)->dentry, true); + if (err) { + pr_err("failed to verify upper root origin\n"); + goto out; +@@ -924,10 +919,9 @@ static int ovl_get_indexdir(struct super_block *sb, struct ovl_fs *ofs, + * directory entries. + */ + if (ovl_check_origin_xattr(ofs, ofs->indexdir)) { +- err = ovl_verify_origin_xattr(ofs, ofs->indexdir, +- OVL_XATTR_ORIGIN, +- upperpath->dentry, true, +- false); ++ err = ovl_verify_set_fh(ofs, ofs->indexdir, ++ OVL_XATTR_ORIGIN, ++ upperpath->dentry, true, false); + if (err) + pr_err("failed to verify index dir 'origin' xattr\n"); + } +@@ -945,8 +939,6 @@ static int ovl_get_indexdir(struct super_block *sb, struct ovl_fs *ofs, + + out: + mnt_drop_write(mnt); +-out_free_fh: +- kfree(fh); + return err; + } + +diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c +index 4e6b747e0f2e25..0bf3ffcd072f6a 100644 +--- a/fs/overlayfs/util.c ++++ b/fs/overlayfs/util.c +@@ -976,18 +976,12 @@ static void ovl_cleanup_index(struct dentry *dentry) + struct dentry *index = NULL; + struct inode *inode; + struct qstr name = { }; +- bool got_write = false; + int err; + + err = ovl_get_index_name(ofs, lowerdentry, &name); + if (err) + goto fail; + +- err = ovl_want_write(dentry); +- if (err) +- goto fail; +- +- got_write = true; + inode = d_inode(upperdentry); + if (!S_ISDIR(inode->i_mode) && inode->i_nlink != 1) { + pr_warn_ratelimited("cleanup linked index (%pd2, ino=%lu, nlink=%u)\n", +@@ -1025,8 +1019,6 @@ static void ovl_cleanup_index(struct dentry *dentry) + goto fail; + + out: +- if (got_write) +- ovl_drop_write(dentry); + kfree(name.name); + dput(index); + return; +@@ -1097,8 +1089,6 @@ void ovl_nlink_end(struct dentry *dentry) + { + struct inode *inode = d_inode(dentry); + +- ovl_drop_write(dentry); +- + if (ovl_test_flag(OVL_INDEX, inode) && inode->i_nlink == 0) { + const struct cred *old_cred; + diff --git a/patch/kernel/archive/odroidxu4-6.6/patch-6.6.73-74.patch b/patch/kernel/archive/odroidxu4-6.6/patch-6.6.73-74.patch new file mode 100644 index 0000000000..cc7a6c852a --- /dev/null +++ b/patch/kernel/archive/odroidxu4-6.6/patch-6.6.73-74.patch @@ -0,0 +1,2591 @@ +diff --git a/Makefile b/Makefile +index 2ba627f545901e..b8e5c65910862e 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 6 + PATCHLEVEL = 6 +-SUBLEVEL = 73 ++SUBLEVEL = 74 + EXTRAVERSION = + NAME = Pinguïn Aangedreven + +diff --git a/arch/x86/include/asm/special_insns.h b/arch/x86/include/asm/special_insns.h +index 48f8dd47cf6882..1c5513b04f0387 100644 +--- a/arch/x86/include/asm/special_insns.h ++++ b/arch/x86/include/asm/special_insns.h +@@ -217,7 +217,7 @@ static inline int write_user_shstk_64(u64 __user *addr, u64 val) + + #define nop() asm volatile ("nop") + +-static inline void serialize(void) ++static __always_inline void serialize(void) + { + /* Instruction opcode for SERIALIZE; supported in binutils >= 2.35. */ + asm volatile(".byte 0xf, 0x1, 0xe8" ::: "memory"); +diff --git a/arch/x86/xen/xen-asm.S b/arch/x86/xen/xen-asm.S +index 901b605166834b..6231f6efb4ee13 100644 +--- a/arch/x86/xen/xen-asm.S ++++ b/arch/x86/xen/xen-asm.S +@@ -221,7 +221,7 @@ SYM_CODE_END(xen_early_idt_handler_array) + push %rax + mov $__HYPERVISOR_iret, %eax + syscall /* Do the IRET. */ +-#ifdef CONFIG_MITIGATION_SLS ++#ifdef CONFIG_SLS + int3 + #endif + .endm +diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c +index 63e4812623361d..4990a19e601334 100644 +--- a/block/blk-sysfs.c ++++ b/block/blk-sysfs.c +@@ -842,10 +842,8 @@ int blk_register_queue(struct gendisk *disk) + * faster to shut down and is made fully functional here as + * request_queues for non-existent devices never get registered. + */ +- if (!blk_queue_init_done(q)) { +- blk_queue_flag_set(QUEUE_FLAG_INIT_DONE, q); +- percpu_ref_switch_to_percpu(&q->q_usage_counter); +- } ++ blk_queue_flag_set(QUEUE_FLAG_INIT_DONE, q); ++ percpu_ref_switch_to_percpu(&q->q_usage_counter); + + return ret; + +diff --git a/block/genhd.c b/block/genhd.c +index 203c880c3e1cd2..6d704c37f26e71 100644 +--- a/block/genhd.c ++++ b/block/genhd.c +@@ -710,13 +710,10 @@ void del_gendisk(struct gendisk *disk) + * If the disk does not own the queue, allow using passthrough requests + * again. Else leave the queue frozen to fail all I/O. + */ +- if (!test_bit(GD_OWNS_QUEUE, &disk->state)) { +- blk_queue_flag_clear(QUEUE_FLAG_INIT_DONE, q); ++ if (!test_bit(GD_OWNS_QUEUE, &disk->state)) + __blk_mq_unfreeze_queue(q, true); +- } else { +- if (queue_is_mq(q)) +- blk_mq_exit_queue(q); +- } ++ else if (queue_is_mq(q)) ++ blk_mq_exit_queue(q); + } + EXPORT_SYMBOL(del_gendisk); + +diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c +index c82b255f82bc41..64d83ff3c0d90c 100644 +--- a/drivers/acpi/resource.c ++++ b/drivers/acpi/resource.c +@@ -680,11 +680,11 @@ static bool acpi_dev_irq_override(u32 gsi, u8 triggering, u8 polarity, + for (i = 0; i < ARRAY_SIZE(override_table); i++) { + const struct irq_override_cmp *entry = &override_table[i]; + +- if (dmi_check_system(entry->system) && +- entry->irq == gsi && ++ if (entry->irq == gsi && + entry->triggering == triggering && + entry->polarity == polarity && +- entry->shareable == shareable) ++ entry->shareable == shareable && ++ dmi_check_system(entry->system)) + return entry->override; + } + +diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c +index 1e257ecd624db1..b73038ad86f7f3 100644 +--- a/drivers/block/zram/zram_drv.c ++++ b/drivers/block/zram/zram_drv.c +@@ -1262,6 +1262,7 @@ static bool zram_meta_alloc(struct zram *zram, u64 disksize) + zram->mem_pool = zs_create_pool(zram->disk->disk_name); + if (!zram->mem_pool) { + vfree(zram->table); ++ zram->table = NULL; + return false; + } + +diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c +index a16945e8319e3f..956ea29578336c 100644 +--- a/drivers/gpio/gpio-xilinx.c ++++ b/drivers/gpio/gpio-xilinx.c +@@ -66,7 +66,7 @@ struct xgpio_instance { + DECLARE_BITMAP(state, 64); + DECLARE_BITMAP(last_irq_read, 64); + DECLARE_BITMAP(dir, 64); +- spinlock_t gpio_lock; /* For serializing operations */ ++ raw_spinlock_t gpio_lock; /* For serializing operations */ + int irq; + DECLARE_BITMAP(enable, 64); + DECLARE_BITMAP(rising_edge, 64); +@@ -180,14 +180,14 @@ static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) + struct xgpio_instance *chip = gpiochip_get_data(gc); + int bit = xgpio_to_bit(chip, gpio); + +- spin_lock_irqsave(&chip->gpio_lock, flags); ++ raw_spin_lock_irqsave(&chip->gpio_lock, flags); + + /* Write to GPIO signal and set its direction to output */ + __assign_bit(bit, chip->state, val); + + xgpio_write_ch(chip, XGPIO_DATA_OFFSET, bit, chip->state); + +- spin_unlock_irqrestore(&chip->gpio_lock, flags); ++ raw_spin_unlock_irqrestore(&chip->gpio_lock, flags); + } + + /** +@@ -211,7 +211,7 @@ static void xgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask, + bitmap_remap(hw_mask, mask, chip->sw_map, chip->hw_map, 64); + bitmap_remap(hw_bits, bits, chip->sw_map, chip->hw_map, 64); + +- spin_lock_irqsave(&chip->gpio_lock, flags); ++ raw_spin_lock_irqsave(&chip->gpio_lock, flags); + + bitmap_replace(state, chip->state, hw_bits, hw_mask, 64); + +@@ -219,7 +219,7 @@ static void xgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask, + + bitmap_copy(chip->state, state, 64); + +- spin_unlock_irqrestore(&chip->gpio_lock, flags); ++ raw_spin_unlock_irqrestore(&chip->gpio_lock, flags); + } + + /** +@@ -237,13 +237,13 @@ static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) + struct xgpio_instance *chip = gpiochip_get_data(gc); + int bit = xgpio_to_bit(chip, gpio); + +- spin_lock_irqsave(&chip->gpio_lock, flags); ++ raw_spin_lock_irqsave(&chip->gpio_lock, flags); + + /* Set the GPIO bit in shadow register and set direction as input */ + __set_bit(bit, chip->dir); + xgpio_write_ch(chip, XGPIO_TRI_OFFSET, bit, chip->dir); + +- spin_unlock_irqrestore(&chip->gpio_lock, flags); ++ raw_spin_unlock_irqrestore(&chip->gpio_lock, flags); + + return 0; + } +@@ -266,7 +266,7 @@ static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) + struct xgpio_instance *chip = gpiochip_get_data(gc); + int bit = xgpio_to_bit(chip, gpio); + +- spin_lock_irqsave(&chip->gpio_lock, flags); ++ raw_spin_lock_irqsave(&chip->gpio_lock, flags); + + /* Write state of GPIO signal */ + __assign_bit(bit, chip->state, val); +@@ -276,7 +276,7 @@ static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) + __clear_bit(bit, chip->dir); + xgpio_write_ch(chip, XGPIO_TRI_OFFSET, bit, chip->dir); + +- spin_unlock_irqrestore(&chip->gpio_lock, flags); ++ raw_spin_unlock_irqrestore(&chip->gpio_lock, flags); + + return 0; + } +@@ -404,7 +404,7 @@ static void xgpio_irq_mask(struct irq_data *irq_data) + int bit = xgpio_to_bit(chip, irq_offset); + u32 mask = BIT(bit / 32), temp; + +- spin_lock_irqsave(&chip->gpio_lock, flags); ++ raw_spin_lock_irqsave(&chip->gpio_lock, flags); + + __clear_bit(bit, chip->enable); + +@@ -414,7 +414,7 @@ static void xgpio_irq_mask(struct irq_data *irq_data) + temp &= ~mask; + xgpio_writereg(chip->regs + XGPIO_IPIER_OFFSET, temp); + } +- spin_unlock_irqrestore(&chip->gpio_lock, flags); ++ raw_spin_unlock_irqrestore(&chip->gpio_lock, flags); + + gpiochip_disable_irq(&chip->gc, irq_offset); + } +@@ -434,7 +434,7 @@ static void xgpio_irq_unmask(struct irq_data *irq_data) + + gpiochip_enable_irq(&chip->gc, irq_offset); + +- spin_lock_irqsave(&chip->gpio_lock, flags); ++ raw_spin_lock_irqsave(&chip->gpio_lock, flags); + + __set_bit(bit, chip->enable); + +@@ -453,7 +453,7 @@ static void xgpio_irq_unmask(struct irq_data *irq_data) + xgpio_writereg(chip->regs + XGPIO_IPIER_OFFSET, val); + } + +- spin_unlock_irqrestore(&chip->gpio_lock, flags); ++ raw_spin_unlock_irqrestore(&chip->gpio_lock, flags); + } + + /** +@@ -518,7 +518,7 @@ static void xgpio_irqhandler(struct irq_desc *desc) + + chained_irq_enter(irqchip, desc); + +- spin_lock(&chip->gpio_lock); ++ raw_spin_lock(&chip->gpio_lock); + + xgpio_read_ch_all(chip, XGPIO_DATA_OFFSET, all); + +@@ -535,7 +535,7 @@ static void xgpio_irqhandler(struct irq_desc *desc) + bitmap_copy(chip->last_irq_read, all, 64); + bitmap_or(all, rising, falling, 64); + +- spin_unlock(&chip->gpio_lock); ++ raw_spin_unlock(&chip->gpio_lock); + + dev_dbg(gc->parent, "IRQ rising %*pb falling %*pb\n", 64, rising, 64, falling); + +@@ -626,7 +626,7 @@ static int xgpio_probe(struct platform_device *pdev) + bitmap_set(chip->hw_map, 0, width[0]); + bitmap_set(chip->hw_map, 32, width[1]); + +- spin_lock_init(&chip->gpio_lock); ++ raw_spin_lock_init(&chip->gpio_lock); + + chip->gc.base = -1; + chip->gc.ngpio = bitmap_weight(chip->hw_map, 64); +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +index f4c1cc6df1c830..2e739b80cfccf1 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +@@ -3172,7 +3172,7 @@ static int amdgpu_device_ip_resume_phase1(struct amdgpu_device *adev) + * + * @adev: amdgpu_device pointer + * +- * Second resume function for hardware IPs. The list of all the hardware ++ * First resume function for hardware IPs. The list of all the hardware + * IPs that make up the asic is walked and the resume callbacks are run for + * all blocks except COMMON, GMC, and IH. resume puts the hardware into a + * functional state after a suspend and updates the software state as +@@ -3190,7 +3190,6 @@ static int amdgpu_device_ip_resume_phase2(struct amdgpu_device *adev) + if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_COMMON || + adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC || + adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_IH || +- adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_DCE || + adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_PSP) + continue; + r = adev->ip_blocks[i].version->funcs->resume(adev); +@@ -3205,36 +3204,6 @@ static int amdgpu_device_ip_resume_phase2(struct amdgpu_device *adev) + return 0; + } + +-/** +- * amdgpu_device_ip_resume_phase3 - run resume for hardware IPs +- * +- * @adev: amdgpu_device pointer +- * +- * Third resume function for hardware IPs. The list of all the hardware +- * IPs that make up the asic is walked and the resume callbacks are run for +- * all DCE. resume puts the hardware into a functional state after a suspend +- * and updates the software state as necessary. This function is also used +- * for restoring the GPU after a GPU reset. +- * +- * Returns 0 on success, negative error code on failure. +- */ +-static int amdgpu_device_ip_resume_phase3(struct amdgpu_device *adev) +-{ +- int i, r; +- +- for (i = 0; i < adev->num_ip_blocks; i++) { +- if (!adev->ip_blocks[i].status.valid || adev->ip_blocks[i].status.hw) +- continue; +- if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_DCE) { +- r = adev->ip_blocks[i].version->funcs->resume(adev); +- if (r) +- return r; +- } +- } +- +- return 0; +-} +- + /** + * amdgpu_device_ip_resume - run resume for hardware IPs + * +@@ -3261,13 +3230,6 @@ static int amdgpu_device_ip_resume(struct amdgpu_device *adev) + + r = amdgpu_device_ip_resume_phase2(adev); + +- if (r) +- return r; +- +- amdgpu_fence_driver_hw_init(adev); +- +- r = amdgpu_device_ip_resume_phase3(adev); +- + return r; + } + +@@ -4267,6 +4229,7 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon) + dev_err(adev->dev, "amdgpu_device_ip_resume failed (%d).\n", r); + goto exit; + } ++ amdgpu_fence_driver_hw_init(adev); + + r = amdgpu_device_ip_late_init(adev); + if (r) +@@ -5036,10 +4999,6 @@ int amdgpu_do_asic_reset(struct list_head *device_list_handle, + if (r) + goto out; + +- r = amdgpu_device_ip_resume_phase3(tmp_adev); +- if (r) +- goto out; +- + if (vram_lost) + amdgpu_device_fill_reset_magic(tmp_adev); + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +index 6aa3b1d845abe1..806ec5d021995c 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +@@ -193,8 +193,8 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs, + need_ctx_switch = ring->current_ctx != fence_ctx; + if (ring->funcs->emit_pipeline_sync && job && + ((tmp = amdgpu_sync_get_fence(&job->explicit_sync)) || +- (amdgpu_sriov_vf(adev) && need_ctx_switch) || +- amdgpu_vm_need_pipeline_sync(ring, job))) { ++ need_ctx_switch || amdgpu_vm_need_pipeline_sync(ring, job))) { ++ + need_pipe_sync = true; + + if (tmp) +diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c +index d1a25fe6c44faa..8dffa5b6426e1c 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c +@@ -1315,7 +1315,7 @@ static struct link_encoder *dcn21_link_encoder_create( + kzalloc(sizeof(struct dcn21_link_encoder), GFP_KERNEL); + int link_regs_id; + +- if (!enc21) ++ if (!enc21 || enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs)) + return NULL; + + link_regs_id = +diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c +index 689b7c16d30072..22ae38bacb44a5 100644 +--- a/drivers/gpu/drm/i915/display/intel_fb.c ++++ b/drivers/gpu/drm/i915/display/intel_fb.c +@@ -1625,7 +1625,7 @@ int intel_fill_fb_info(struct drm_i915_private *i915, struct intel_framebuffer * + * arithmetic related to alignment and offset calculation. + */ + if (is_gen12_ccs_cc_plane(&fb->base, i)) { +- if (IS_ALIGNED(fb->base.offsets[i], PAGE_SIZE)) ++ if (IS_ALIGNED(fb->base.offsets[i], 64)) + continue; + else + return -EINVAL; +diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c +index 93f08f9479d89b..03eacb22648ef7 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_fence.c ++++ b/drivers/gpu/drm/nouveau/nouveau_fence.c +@@ -386,11 +386,13 @@ nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, + if (f) { + struct nouveau_channel *prev; + bool must_wait = true; ++ bool local; + + rcu_read_lock(); + prev = rcu_dereference(f->channel); +- if (prev && (prev == chan || +- fctx->sync(f, prev, chan) == 0)) ++ local = prev && prev->cli->drm == chan->cli->drm; ++ if (local && (prev == chan || ++ fctx->sync(f, prev, chan) == 0)) + must_wait = false; + rcu_read_unlock(); + if (!must_wait) +diff --git a/drivers/gpu/drm/v3d/v3d_irq.c b/drivers/gpu/drm/v3d/v3d_irq.c +index e714d5318f3095..76806039691a2c 100644 +--- a/drivers/gpu/drm/v3d/v3d_irq.c ++++ b/drivers/gpu/drm/v3d/v3d_irq.c +@@ -103,6 +103,7 @@ v3d_irq(int irq, void *arg) + + trace_v3d_bcl_irq(&v3d->drm, fence->seqno); + dma_fence_signal(&fence->base); ++ v3d->bin_job = NULL; + status = IRQ_HANDLED; + } + +@@ -112,6 +113,7 @@ v3d_irq(int irq, void *arg) + + trace_v3d_rcl_irq(&v3d->drm, fence->seqno); + dma_fence_signal(&fence->base); ++ v3d->render_job = NULL; + status = IRQ_HANDLED; + } + +@@ -121,6 +123,7 @@ v3d_irq(int irq, void *arg) + + trace_v3d_csd_irq(&v3d->drm, fence->seqno); + dma_fence_signal(&fence->base); ++ v3d->csd_job = NULL; + status = IRQ_HANDLED; + } + +@@ -157,6 +160,7 @@ v3d_hub_irq(int irq, void *arg) + + trace_v3d_tfu_irq(&v3d->drm, fence->seqno); + dma_fence_signal(&fence->base); ++ v3d->tfu_job = NULL; + status = IRQ_HANDLED; + } + +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c +index fdc34283eeb97f..ec6ca264ce11ff 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c +@@ -412,7 +412,8 @@ static int vmw_bo_init(struct vmw_private *dev_priv, + + if (params->pin) + ttm_bo_pin(&vmw_bo->tbo); +- ttm_bo_unreserve(&vmw_bo->tbo); ++ if (!params->keep_resv) ++ ttm_bo_unreserve(&vmw_bo->tbo); + + return 0; + } +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h +index 156ea612fc2a48..a3ac61b991bf66 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h +@@ -53,8 +53,9 @@ struct vmw_bo_params { + u32 domain; + u32 busy_domain; + enum ttm_bo_type bo_type; +- size_t size; + bool pin; ++ bool keep_resv; ++ size_t size; + struct dma_resv *resv; + struct sg_table *sg; + }; +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +index bea576434e475c..4655c266924fed 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +@@ -399,7 +399,8 @@ static int vmw_dummy_query_bo_create(struct vmw_private *dev_priv) + .busy_domain = VMW_BO_DOMAIN_SYS, + .bo_type = ttm_bo_type_kernel, + .size = PAGE_SIZE, +- .pin = true ++ .pin = true, ++ .keep_resv = true, + }; + + /* +@@ -411,10 +412,6 @@ static int vmw_dummy_query_bo_create(struct vmw_private *dev_priv) + if (unlikely(ret != 0)) + return ret; + +- ret = ttm_bo_reserve(&vbo->tbo, false, true, NULL); +- BUG_ON(ret != 0); +- vmw_bo_pin_reserved(vbo, true); +- + ret = ttm_bo_kmap(&vbo->tbo, 0, 1, &map); + if (likely(ret == 0)) { + result = ttm_kmap_obj_virtual(&map, &dummy); +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c +index d6bcaf078b1f40..0dc3dacc5beee8 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c +@@ -163,6 +163,7 @@ struct drm_gem_object *vmw_prime_import_sg_table(struct drm_device *dev, + .bo_type = ttm_bo_type_sg, + .size = attach->dmabuf->size, + .pin = false, ++ .keep_resv = true, + .resv = attach->dmabuf->resv, + .sg = table, + +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c +index a01ca3226d0af8..7fb1c88bcc475f 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c +@@ -896,7 +896,8 @@ int vmw_compat_shader_add(struct vmw_private *dev_priv, + .busy_domain = VMW_BO_DOMAIN_SYS, + .bo_type = ttm_bo_type_device, + .size = size, +- .pin = true ++ .pin = true, ++ .keep_resv = true, + }; + + if (!vmw_shader_id_ok(user_key, shader_type)) +@@ -906,10 +907,6 @@ int vmw_compat_shader_add(struct vmw_private *dev_priv, + if (unlikely(ret != 0)) + goto out; + +- ret = ttm_bo_reserve(&buf->tbo, false, true, NULL); +- if (unlikely(ret != 0)) +- goto no_reserve; +- + /* Map and copy shader bytecode. */ + ret = ttm_bo_kmap(&buf->tbo, 0, PFN_UP(size), &map); + if (unlikely(ret != 0)) { +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c +index fcb87d83760ef6..75cf9e76df2ed4 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c +@@ -604,15 +604,14 @@ int vmw_bo_create_and_populate(struct vmw_private *dev_priv, + .busy_domain = domain, + .bo_type = ttm_bo_type_kernel, + .size = bo_size, +- .pin = true ++ .pin = true, ++ .keep_resv = true, + }; + + ret = vmw_bo_create(dev_priv, &bo_params, &vbo); + if (unlikely(ret != 0)) + return ret; + +- ret = ttm_bo_reserve(&vbo->tbo, false, true, NULL); +- BUG_ON(ret != 0); + ret = vmw_ttm_populate(vbo->tbo.bdev, vbo->tbo.ttm, &ctx); + if (likely(ret == 0)) { + struct vmw_ttm_tt *vmw_tt = +diff --git a/drivers/hwmon/tmp513.c b/drivers/hwmon/tmp513.c +index 070f93226ed696..62d31aadda4bb8 100644 +--- a/drivers/hwmon/tmp513.c ++++ b/drivers/hwmon/tmp513.c +@@ -203,7 +203,8 @@ static int tmp51x_get_value(struct tmp51x_data *data, u8 reg, u8 pos, + *val = sign_extend32(regval, + reg == TMP51X_SHUNT_CURRENT_RESULT ? + 16 - tmp51x_get_pga_shift(data) : 15); +- *val = DIV_ROUND_CLOSEST(*val * 10 * MILLI, data->shunt_uohms); ++ *val = DIV_ROUND_CLOSEST(*val * 10 * (long)MILLI, (long)data->shunt_uohms); ++ + break; + case TMP51X_BUS_VOLTAGE_RESULT: + case TMP51X_BUS_VOLTAGE_H_LIMIT: +@@ -219,7 +220,7 @@ static int tmp51x_get_value(struct tmp51x_data *data, u8 reg, u8 pos, + case TMP51X_BUS_CURRENT_RESULT: + // Current = (ShuntVoltage * CalibrationRegister) / 4096 + *val = sign_extend32(regval, 15) * (long)data->curr_lsb_ua; +- *val = DIV_ROUND_CLOSEST(*val, MILLI); ++ *val = DIV_ROUND_CLOSEST(*val, (long)MILLI); + break; + case TMP51X_LOCAL_TEMP_RESULT: + case TMP51X_REMOTE_TEMP_RESULT_1: +@@ -259,7 +260,7 @@ static int tmp51x_set_value(struct tmp51x_data *data, u8 reg, long val) + * The user enter current value and we convert it to + * voltage. 1lsb = 10uV + */ +- val = DIV_ROUND_CLOSEST(val * data->shunt_uohms, 10 * MILLI); ++ val = DIV_ROUND_CLOSEST(val * (long)data->shunt_uohms, 10 * (long)MILLI); + max_val = U16_MAX >> tmp51x_get_pga_shift(data); + regval = clamp_val(val, -max_val, max_val); + break; +diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c +index 84fdd3f5cc8445..610df67cedaadc 100644 +--- a/drivers/i2c/busses/i2c-rcar.c ++++ b/drivers/i2c/busses/i2c-rcar.c +@@ -110,6 +110,8 @@ + #define ID_P_PM_BLOCKED BIT(31) + #define ID_P_MASK GENMASK(31, 28) + ++#define ID_SLAVE_NACK BIT(0) ++ + enum rcar_i2c_type { + I2C_RCAR_GEN1, + I2C_RCAR_GEN2, +@@ -143,6 +145,7 @@ struct rcar_i2c_priv { + int irq; + + struct i2c_client *host_notify_client; ++ u8 slave_flags; + }; + + #define rcar_i2c_priv_to_dev(p) ((p)->adap.dev.parent) +@@ -597,6 +600,7 @@ static bool rcar_i2c_slave_irq(struct rcar_i2c_priv *priv) + { + u32 ssr_raw, ssr_filtered; + u8 value; ++ int ret; + + ssr_raw = rcar_i2c_read(priv, ICSSR) & 0xff; + ssr_filtered = ssr_raw & rcar_i2c_read(priv, ICSIER); +@@ -612,7 +616,10 @@ static bool rcar_i2c_slave_irq(struct rcar_i2c_priv *priv) + rcar_i2c_write(priv, ICRXTX, value); + rcar_i2c_write(priv, ICSIER, SDE | SSR | SAR); + } else { +- i2c_slave_event(priv->slave, I2C_SLAVE_WRITE_REQUESTED, &value); ++ ret = i2c_slave_event(priv->slave, I2C_SLAVE_WRITE_REQUESTED, &value); ++ if (ret) ++ priv->slave_flags |= ID_SLAVE_NACK; ++ + rcar_i2c_read(priv, ICRXTX); /* dummy read */ + rcar_i2c_write(priv, ICSIER, SDR | SSR | SAR); + } +@@ -625,18 +632,21 @@ static bool rcar_i2c_slave_irq(struct rcar_i2c_priv *priv) + if (ssr_filtered & SSR) { + i2c_slave_event(priv->slave, I2C_SLAVE_STOP, &value); + rcar_i2c_write(priv, ICSCR, SIE | SDBS); /* clear our NACK */ ++ priv->slave_flags &= ~ID_SLAVE_NACK; + rcar_i2c_write(priv, ICSIER, SAR); + rcar_i2c_write(priv, ICSSR, ~SSR & 0xff); + } + + /* master wants to write to us */ + if (ssr_filtered & SDR) { +- int ret; +- + value = rcar_i2c_read(priv, ICRXTX); + ret = i2c_slave_event(priv->slave, I2C_SLAVE_WRITE_RECEIVED, &value); +- /* Send NACK in case of error */ +- rcar_i2c_write(priv, ICSCR, SIE | SDBS | (ret < 0 ? FNA : 0)); ++ if (ret) ++ priv->slave_flags |= ID_SLAVE_NACK; ++ ++ /* Send NACK in case of error, but it will come 1 byte late :( */ ++ rcar_i2c_write(priv, ICSCR, SIE | SDBS | ++ (priv->slave_flags & ID_SLAVE_NACK ? FNA : 0)); + rcar_i2c_write(priv, ICSSR, ~SDR & 0xff); + } + +diff --git a/drivers/i2c/i2c-atr.c b/drivers/i2c/i2c-atr.c +index 8ca1daadec9373..c03196da116351 100644 +--- a/drivers/i2c/i2c-atr.c ++++ b/drivers/i2c/i2c-atr.c +@@ -412,7 +412,7 @@ static int i2c_atr_bus_notifier_call(struct notifier_block *nb, + dev_name(dev), ret); + break; + +- case BUS_NOTIFY_DEL_DEVICE: ++ case BUS_NOTIFY_REMOVED_DEVICE: + i2c_atr_detach_client(client->adapter, client); + break; + +diff --git a/drivers/i2c/muxes/i2c-demux-pinctrl.c b/drivers/i2c/muxes/i2c-demux-pinctrl.c +index 9f2e4aa2815933..299abb6dd9423d 100644 +--- a/drivers/i2c/muxes/i2c-demux-pinctrl.c ++++ b/drivers/i2c/muxes/i2c-demux-pinctrl.c +@@ -261,7 +261,9 @@ static int i2c_demux_pinctrl_probe(struct platform_device *pdev) + pm_runtime_no_callbacks(&pdev->dev); + + /* switch to first parent as active master */ +- i2c_demux_activate_master(priv, 0); ++ err = i2c_demux_activate_master(priv, 0); ++ if (err) ++ goto err_rollback; + + err = device_create_file(&pdev->dev, &dev_attr_available_masters); + if (err) +diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h b/drivers/iio/imu/inv_icm42600/inv_icm42600.h +index 0e290c807b0f91..94c0eb0bf8748a 100644 +--- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h ++++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h +@@ -362,6 +362,7 @@ struct inv_icm42600_state { + typedef int (*inv_icm42600_bus_setup)(struct inv_icm42600_state *); + + extern const struct regmap_config inv_icm42600_regmap_config; ++extern const struct regmap_config inv_icm42600_spi_regmap_config; + extern const struct dev_pm_ops inv_icm42600_pm_ops; + + const struct iio_mount_matrix * +diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c +index d938bc45439729..da65aa4e27242f 100644 +--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c ++++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c +@@ -44,6 +44,17 @@ const struct regmap_config inv_icm42600_regmap_config = { + }; + EXPORT_SYMBOL_NS_GPL(inv_icm42600_regmap_config, IIO_ICM42600); + ++/* define specific regmap for SPI not supporting burst write */ ++const struct regmap_config inv_icm42600_spi_regmap_config = { ++ .reg_bits = 8, ++ .val_bits = 8, ++ .max_register = 0x4FFF, ++ .ranges = inv_icm42600_regmap_ranges, ++ .num_ranges = ARRAY_SIZE(inv_icm42600_regmap_ranges), ++ .use_single_write = true, ++}; ++EXPORT_SYMBOL_NS_GPL(inv_icm42600_spi_regmap_config, IIO_ICM42600); ++ + struct inv_icm42600_hw { + uint8_t whoami; + const char *name; +diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c +index 6be4ac79493794..abfa1b73cf4d35 100644 +--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c ++++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c +@@ -59,7 +59,8 @@ static int inv_icm42600_probe(struct spi_device *spi) + return -EINVAL; + chip = (uintptr_t)match; + +- regmap = devm_regmap_init_spi(spi, &inv_icm42600_regmap_config); ++ /* use SPI specific regmap */ ++ regmap = devm_regmap_init_spi(spi, &inv_icm42600_spi_regmap_config); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + +diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c +index 13c65ec5825687..08da793969ee55 100644 +--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c ++++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c +@@ -2220,6 +2220,7 @@ int bnxt_re_query_qp(struct ib_qp *ib_qp, struct ib_qp_attr *qp_attr, + qp_attr->retry_cnt = qplib_qp->retry_cnt; + qp_attr->rnr_retry = qplib_qp->rnr_retry; + qp_attr->min_rnr_timer = qplib_qp->min_rnr_timer; ++ qp_attr->port_num = __to_ib_port_num(qplib_qp->port_id); + qp_attr->rq_psn = qplib_qp->rq.psn; + qp_attr->max_rd_atomic = qplib_qp->max_rd_atomic; + qp_attr->sq_psn = qplib_qp->sq.psn; +diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.h b/drivers/infiniband/hw/bnxt_re/ib_verbs.h +index 98baea98fc1761..ef910e6e2ccb73 100644 +--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.h ++++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.h +@@ -245,6 +245,10 @@ void bnxt_re_dealloc_ucontext(struct ib_ucontext *context); + int bnxt_re_mmap(struct ib_ucontext *context, struct vm_area_struct *vma); + void bnxt_re_mmap_free(struct rdma_user_mmap_entry *rdma_entry); + ++static inline u32 __to_ib_port_num(u16 port_id) ++{ ++ return (u32)port_id + 1; ++} + + unsigned long bnxt_re_lock_cqs(struct bnxt_re_qp *qp); + void bnxt_re_unlock_cqs(struct bnxt_re_qp *qp, unsigned long flags); +diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.c b/drivers/infiniband/hw/bnxt_re/qplib_fp.c +index 871a49315c880f..c4f10498c79d87 100644 +--- a/drivers/infiniband/hw/bnxt_re/qplib_fp.c ++++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.c +@@ -1460,6 +1460,7 @@ int bnxt_qplib_query_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) + qp->dest_qpn = le32_to_cpu(sb->dest_qp_id); + memcpy(qp->smac, sb->src_mac, 6); + qp->vlan_id = le16_to_cpu(sb->vlan_pcp_vlan_dei_vlan_id); ++ qp->port_id = le16_to_cpu(sb->port_id); + bail: + dma_free_coherent(&rcfw->pdev->dev, sbuf.size, + sbuf.sb, sbuf.dma_addr); +diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.h b/drivers/infiniband/hw/bnxt_re/qplib_fp.h +index b5c53e864fbb39..55fd840359ef23 100644 +--- a/drivers/infiniband/hw/bnxt_re/qplib_fp.h ++++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.h +@@ -297,6 +297,7 @@ struct bnxt_qplib_qp { + u32 dest_qpn; + u8 smac[6]; + u16 vlan_id; ++ u16 port_id; + u8 nw_type; + struct bnxt_qplib_ah ah; + +diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c +index b1e60c13c1e1e7..a1934fe4ad5ab0 100644 +--- a/drivers/irqchip/irq-gic-v3-its.c ++++ b/drivers/irqchip/irq-gic-v3-its.c +@@ -1970,7 +1970,7 @@ static int its_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu_info) + if (!is_v4(its_dev->its)) + return -EINVAL; + +- guard(raw_spinlock_irq)(&its_dev->event_map.vlpi_lock); ++ guard(raw_spinlock)(&its_dev->event_map.vlpi_lock); + + /* Unmap request? */ + if (!info) +diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c +index e7f000f90bb467..6c7943c516eb09 100644 +--- a/drivers/irqchip/irq-gic-v3.c ++++ b/drivers/irqchip/irq-gic-v3.c +@@ -1460,7 +1460,7 @@ static int gic_retrigger(struct irq_data *data) + static int gic_cpu_pm_notifier(struct notifier_block *self, + unsigned long cmd, void *v) + { +- if (cmd == CPU_PM_EXIT) { ++ if (cmd == CPU_PM_EXIT || cmd == CPU_PM_ENTER_FAILED) { + if (gic_dist_security_disabled()) + gic_enable_redist(true); + gic_cpu_sys_reg_init(); +diff --git a/drivers/irqchip/irqchip.c b/drivers/irqchip/irqchip.c +index 1eeb0d0156ce9e..0ee7b6b71f5fa5 100644 +--- a/drivers/irqchip/irqchip.c ++++ b/drivers/irqchip/irqchip.c +@@ -35,11 +35,10 @@ void __init irqchip_init(void) + int platform_irqchip_probe(struct platform_device *pdev) + { + struct device_node *np = pdev->dev.of_node; +- struct device_node *par_np = of_irq_find_parent(np); ++ struct device_node *par_np __free(device_node) = of_irq_find_parent(np); + of_irq_init_cb_t irq_init_cb = of_device_get_match_data(&pdev->dev); + + if (!irq_init_cb) { +- of_node_put(par_np); + return -EINVAL; + } + +@@ -55,7 +54,6 @@ int platform_irqchip_probe(struct platform_device *pdev) + * interrupt controller can check for specific domains as necessary. + */ + if (par_np && !irq_find_matching_host(par_np, DOMAIN_BUS_ANY)) { +- of_node_put(par_np); + return -EPROBE_DEFER; + } + +diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c +index 8d75a66775cb1f..1b0c6770c14e46 100644 +--- a/drivers/mtd/spi-nor/core.c ++++ b/drivers/mtd/spi-nor/core.c +@@ -89,7 +89,7 @@ void spi_nor_spimem_setup_op(const struct spi_nor *nor, + op->addr.buswidth = spi_nor_get_protocol_addr_nbits(proto); + + if (op->dummy.nbytes) +- op->dummy.buswidth = spi_nor_get_protocol_data_nbits(proto); ++ op->dummy.buswidth = spi_nor_get_protocol_addr_nbits(proto); + + if (op->data.nbytes) + op->data.buswidth = spi_nor_get_protocol_data_nbits(proto); +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +index 6a716337f48be1..268399dfcf22f0 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +@@ -923,7 +923,6 @@ static void xgbe_phy_free_phy_device(struct xgbe_prv_data *pdata) + + static bool xgbe_phy_finisar_phy_quirks(struct xgbe_prv_data *pdata) + { +- __ETHTOOL_DECLARE_LINK_MODE_MASK(supported) = { 0, }; + struct xgbe_phy_data *phy_data = pdata->phy_data; + unsigned int phy_id = phy_data->phydev->phy_id; + +@@ -945,14 +944,7 @@ static bool xgbe_phy_finisar_phy_quirks(struct xgbe_prv_data *pdata) + phy_write(phy_data->phydev, 0x04, 0x0d01); + phy_write(phy_data->phydev, 0x00, 0x9140); + +- linkmode_set_bit_array(phy_10_100_features_array, +- ARRAY_SIZE(phy_10_100_features_array), +- supported); +- linkmode_set_bit_array(phy_gbit_features_array, +- ARRAY_SIZE(phy_gbit_features_array), +- supported); +- +- linkmode_copy(phy_data->phydev->supported, supported); ++ linkmode_copy(phy_data->phydev->supported, PHY_GBIT_FEATURES); + + phy_support_asym_pause(phy_data->phydev); + +@@ -964,7 +956,6 @@ static bool xgbe_phy_finisar_phy_quirks(struct xgbe_prv_data *pdata) + + static bool xgbe_phy_belfuse_phy_quirks(struct xgbe_prv_data *pdata) + { +- __ETHTOOL_DECLARE_LINK_MODE_MASK(supported) = { 0, }; + struct xgbe_phy_data *phy_data = pdata->phy_data; + struct xgbe_sfp_eeprom *sfp_eeprom = &phy_data->sfp_eeprom; + unsigned int phy_id = phy_data->phydev->phy_id; +@@ -1028,13 +1019,7 @@ static bool xgbe_phy_belfuse_phy_quirks(struct xgbe_prv_data *pdata) + reg = phy_read(phy_data->phydev, 0x00); + phy_write(phy_data->phydev, 0x00, reg & ~0x00800); + +- linkmode_set_bit_array(phy_10_100_features_array, +- ARRAY_SIZE(phy_10_100_features_array), +- supported); +- linkmode_set_bit_array(phy_gbit_features_array, +- ARRAY_SIZE(phy_gbit_features_array), +- supported); +- linkmode_copy(phy_data->phydev->supported, supported); ++ linkmode_copy(phy_data->phydev->supported, PHY_GBIT_FEATURES); + phy_support_asym_pause(phy_data->phydev); + + netif_dbg(pdata, drv, pdata->netdev, +diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c +index e8d9a0eba4d6b5..8f5cc1f2331884 100644 +--- a/drivers/net/ethernet/freescale/fec_main.c ++++ b/drivers/net/ethernet/freescale/fec_main.c +@@ -1572,19 +1572,22 @@ static void fec_enet_tx(struct net_device *ndev, int budget) + fec_enet_tx_queue(ndev, i, budget); + } + +-static void fec_enet_update_cbd(struct fec_enet_priv_rx_q *rxq, ++static int fec_enet_update_cbd(struct fec_enet_priv_rx_q *rxq, + struct bufdesc *bdp, int index) + { + struct page *new_page; + dma_addr_t phys_addr; + + new_page = page_pool_dev_alloc_pages(rxq->page_pool); +- WARN_ON(!new_page); +- rxq->rx_skb_info[index].page = new_page; ++ if (unlikely(!new_page)) ++ return -ENOMEM; + ++ rxq->rx_skb_info[index].page = new_page; + rxq->rx_skb_info[index].offset = FEC_ENET_XDP_HEADROOM; + phys_addr = page_pool_get_dma_addr(new_page) + FEC_ENET_XDP_HEADROOM; + bdp->cbd_bufaddr = cpu_to_fec32(phys_addr); ++ ++ return 0; + } + + static u32 +@@ -1679,6 +1682,7 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) + int cpu = smp_processor_id(); + struct xdp_buff xdp; + struct page *page; ++ __fec32 cbd_bufaddr; + u32 sub_len = 4; + + #if !defined(CONFIG_M5272) +@@ -1743,12 +1747,17 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) + + index = fec_enet_get_bd_index(bdp, &rxq->bd); + page = rxq->rx_skb_info[index].page; ++ cbd_bufaddr = bdp->cbd_bufaddr; ++ if (fec_enet_update_cbd(rxq, bdp, index)) { ++ ndev->stats.rx_dropped++; ++ goto rx_processing_done; ++ } ++ + dma_sync_single_for_cpu(&fep->pdev->dev, +- fec32_to_cpu(bdp->cbd_bufaddr), ++ fec32_to_cpu(cbd_bufaddr), + pkt_len, + DMA_FROM_DEVICE); + prefetch(page_address(page)); +- fec_enet_update_cbd(rxq, bdp, index); + + if (xdp_prog) { + xdp_buff_clear_frags_flag(&xdp); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c +index 015faddabc8e09..463c23ae0ad1ec 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c +@@ -719,6 +719,12 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x, + /* check esn */ + if (x->props.flags & XFRM_STATE_ESN) + mlx5e_ipsec_update_esn_state(sa_entry); ++ else ++ /* According to RFC4303, section "3.3.3. Sequence Number Generation", ++ * the first packet sent using a given SA will contain a sequence ++ * number of 1. ++ */ ++ sa_entry->esn_state.esn = 1; + + mlx5e_ipsec_build_accel_xfrm_attrs(sa_entry, &sa_entry->attrs); + +@@ -763,9 +769,12 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x, + MLX5_IPSEC_RESCHED); + + if (x->xso.type == XFRM_DEV_OFFLOAD_PACKET && +- x->props.mode == XFRM_MODE_TUNNEL) +- xa_set_mark(&ipsec->sadb, sa_entry->ipsec_obj_id, +- MLX5E_IPSEC_TUNNEL_SA); ++ x->props.mode == XFRM_MODE_TUNNEL) { ++ xa_lock_bh(&ipsec->sadb); ++ __xa_set_mark(&ipsec->sadb, sa_entry->ipsec_obj_id, ++ MLX5E_IPSEC_TUNNEL_SA); ++ xa_unlock_bh(&ipsec->sadb); ++ } + + out: + x->xso.offload_handle = (unsigned long)sa_entry; +@@ -792,7 +801,6 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x, + static void mlx5e_xfrm_del_state(struct xfrm_state *x) + { + struct mlx5e_ipsec_sa_entry *sa_entry = to_ipsec_sa_entry(x); +- struct mlx5_accel_esp_xfrm_attrs *attrs = &sa_entry->attrs; + struct mlx5e_ipsec *ipsec = sa_entry->ipsec; + struct mlx5e_ipsec_sa_entry *old; + +@@ -801,12 +809,6 @@ static void mlx5e_xfrm_del_state(struct xfrm_state *x) + + old = xa_erase_bh(&ipsec->sadb, sa_entry->ipsec_obj_id); + WARN_ON(old != sa_entry); +- +- if (attrs->mode == XFRM_MODE_TUNNEL && +- attrs->type == XFRM_DEV_OFFLOAD_PACKET) +- /* Make sure that no ARP requests are running in parallel */ +- flush_workqueue(ipsec->wq); +- + } + + static void mlx5e_xfrm_free_state(struct xfrm_state *x) +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c +index 61288066830d94..2382c712898574 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c +@@ -1442,23 +1442,21 @@ static int tx_add_rule(struct mlx5e_ipsec_sa_entry *sa_entry) + goto err_alloc; + } + +- if (attrs->family == AF_INET) +- setup_fte_addr4(spec, &attrs->saddr.a4, &attrs->daddr.a4); +- else +- setup_fte_addr6(spec, attrs->saddr.a6, attrs->daddr.a6); +- + setup_fte_no_frags(spec); + setup_fte_upper_proto_match(spec, &attrs->upspec); + + switch (attrs->type) { + case XFRM_DEV_OFFLOAD_CRYPTO: ++ if (attrs->family == AF_INET) ++ setup_fte_addr4(spec, &attrs->saddr.a4, &attrs->daddr.a4); ++ else ++ setup_fte_addr6(spec, attrs->saddr.a6, attrs->daddr.a6); + setup_fte_spi(spec, attrs->spi, false); + setup_fte_esp(spec); + setup_fte_reg_a(spec); + break; + case XFRM_DEV_OFFLOAD_PACKET: +- if (attrs->reqid) +- setup_fte_reg_c4(spec, attrs->reqid); ++ setup_fte_reg_c4(spec, attrs->reqid); + err = setup_pkt_reformat(ipsec, attrs, &flow_act); + if (err) + goto err_pkt_reformat; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c +index de83567aae7913..940e350058d10e 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c +@@ -90,8 +90,9 @@ u32 mlx5_ipsec_device_caps(struct mlx5_core_dev *mdev) + EXPORT_SYMBOL_GPL(mlx5_ipsec_device_caps); + + static void mlx5e_ipsec_packet_setup(void *obj, u32 pdn, +- struct mlx5_accel_esp_xfrm_attrs *attrs) ++ struct mlx5e_ipsec_sa_entry *sa_entry) + { ++ struct mlx5_accel_esp_xfrm_attrs *attrs = &sa_entry->attrs; + void *aso_ctx; + + aso_ctx = MLX5_ADDR_OF(ipsec_obj, obj, ipsec_aso); +@@ -119,8 +120,12 @@ static void mlx5e_ipsec_packet_setup(void *obj, u32 pdn, + * active. + */ + MLX5_SET(ipsec_obj, obj, aso_return_reg, MLX5_IPSEC_ASO_REG_C_4_5); +- if (attrs->dir == XFRM_DEV_OFFLOAD_OUT) ++ if (attrs->dir == XFRM_DEV_OFFLOAD_OUT) { + MLX5_SET(ipsec_aso, aso_ctx, mode, MLX5_IPSEC_ASO_INC_SN); ++ if (!attrs->replay_esn.trigger) ++ MLX5_SET(ipsec_aso, aso_ctx, mode_parameter, ++ sa_entry->esn_state.esn); ++ } + + if (attrs->lft.hard_packet_limit != XFRM_INF) { + MLX5_SET(ipsec_aso, aso_ctx, remove_flow_pkt_cnt, +@@ -173,7 +178,7 @@ static int mlx5_create_ipsec_obj(struct mlx5e_ipsec_sa_entry *sa_entry) + + res = &mdev->mlx5e_res.hw_objs; + if (attrs->type == XFRM_DEV_OFFLOAD_PACKET) +- mlx5e_ipsec_packet_setup(obj, res->pdn, attrs); ++ mlx5e_ipsec_packet_setup(obj, res->pdn, sa_entry); + + err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out)); + if (!err) +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +index 474e63d02ba492..d2dc375f5e49cb 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +@@ -2490,6 +2490,7 @@ struct mlx5_flow_namespace *mlx5_get_flow_namespace(struct mlx5_core_dev *dev, + break; + case MLX5_FLOW_NAMESPACE_RDMA_TX: + root_ns = steering->rdma_tx_root_ns; ++ prio = RDMA_TX_BYPASS_PRIO; + break; + case MLX5_FLOW_NAMESPACE_RDMA_RX_COUNTERS: + root_ns = steering->rdma_rx_root_ns; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c +index 005661248c7e9c..9faa9ef863a1b6 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c +@@ -540,7 +540,7 @@ int mlx5_lag_port_sel_create(struct mlx5_lag *ldev, + set_tt_map(port_sel, hash_type); + err = mlx5_lag_create_definers(ldev, hash_type, ports); + if (err) +- return err; ++ goto clear_port_sel; + + if (port_sel->tunnel) { + err = mlx5_lag_create_inner_ttc_table(ldev); +@@ -559,6 +559,8 @@ int mlx5_lag_port_sel_create(struct mlx5_lag *ldev, + mlx5_destroy_ttc_table(port_sel->inner.ttc); + destroy_definers: + mlx5_lag_destroy_definers(ldev); ++clear_port_sel: ++ memset(port_sel, 0, sizeof(*port_sel)); + return err; + } + +diff --git a/drivers/net/ethernet/netronome/nfp/bpf/offload.c b/drivers/net/ethernet/netronome/nfp/bpf/offload.c +index 9d97cd281f18e4..c03558adda91eb 100644 +--- a/drivers/net/ethernet/netronome/nfp/bpf/offload.c ++++ b/drivers/net/ethernet/netronome/nfp/bpf/offload.c +@@ -458,7 +458,8 @@ int nfp_bpf_event_output(struct nfp_app_bpf *bpf, const void *data, + map_id_full = be64_to_cpu(cbe->map_ptr); + map_id = map_id_full; + +- if (len < sizeof(struct cmsg_bpf_event) + pkt_size + data_size) ++ if (size_add(pkt_size, data_size) > INT_MAX || ++ len < sizeof(struct cmsg_bpf_event) + pkt_size + data_size) + return -EINVAL; + if (cbe->hdr.ver != NFP_CCM_ABI_VERSION) + return -EINVAL; +diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c +index 64bf22cd860c9a..9eccc7064c2b05 100644 +--- a/drivers/net/ethernet/ti/cpsw_ale.c ++++ b/drivers/net/ethernet/ti/cpsw_ale.c +@@ -106,15 +106,15 @@ struct cpsw_ale_dev_id { + + static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits) + { +- int idx, idx2; ++ int idx, idx2, index; + u32 hi_val = 0; + + idx = start / 32; + idx2 = (start + bits - 1) / 32; + /* Check if bits to be fetched exceed a word */ + if (idx != idx2) { +- idx2 = 2 - idx2; /* flip */ +- hi_val = ale_entry[idx2] << ((idx2 * 32) - start); ++ index = 2 - idx2; /* flip */ ++ hi_val = ale_entry[index] << ((idx2 * 32) - start); + } + start -= idx * 32; + idx = 2 - idx; /* flip */ +@@ -124,16 +124,16 @@ static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits) + static inline void cpsw_ale_set_field(u32 *ale_entry, u32 start, u32 bits, + u32 value) + { +- int idx, idx2; ++ int idx, idx2, index; + + value &= BITMASK(bits); + idx = start / 32; + idx2 = (start + bits - 1) / 32; + /* Check if bits to be set exceed a word */ + if (idx != idx2) { +- idx2 = 2 - idx2; /* flip */ +- ale_entry[idx2] &= ~(BITMASK(bits + start - (idx2 * 32))); +- ale_entry[idx2] |= (value >> ((idx2 * 32) - start)); ++ index = 2 - idx2; /* flip */ ++ ale_entry[index] &= ~(BITMASK(bits + start - (idx2 * 32))); ++ ale_entry[index] |= (value >> ((idx2 * 32) - start)); + } + start -= idx * 32; + idx = 2 - idx; /* flip */ +diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +index 9f779653ed6225..02e11827440b5c 100644 +--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c ++++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +@@ -1571,6 +1571,12 @@ axienet_ethtools_set_coalesce(struct net_device *ndev, + return -EFAULT; + } + ++ if (ecoalesce->rx_max_coalesced_frames > 255 || ++ ecoalesce->tx_max_coalesced_frames > 255) { ++ NL_SET_ERR_MSG(extack, "frames must be less than 256"); ++ return -EINVAL; ++ } ++ + if (ecoalesce->rx_max_coalesced_frames) + lp->coalesce_count_rx = ecoalesce->rx_max_coalesced_frames; + if (ecoalesce->rx_coalesce_usecs) +diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c +index 9dd8f66610ce6b..47238c3ec82e75 100644 +--- a/drivers/net/gtp.c ++++ b/drivers/net/gtp.c +@@ -1095,8 +1095,8 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, + goto out_encap; + } + +- gn = net_generic(dev_net(dev), gtp_net_id); +- list_add_rcu(>p->list, &gn->gtp_dev_list); ++ gn = net_generic(src_net, gtp_net_id); ++ list_add(>p->list, &gn->gtp_dev_list); + dev->priv_destructor = gtp_destructor; + + netdev_dbg(dev, "registered new GTP interface\n"); +@@ -1122,7 +1122,7 @@ static void gtp_dellink(struct net_device *dev, struct list_head *head) + hlist_for_each_entry_safe(pctx, next, >p->tid_hash[i], hlist_tid) + pdp_context_delete(pctx); + +- list_del_rcu(>p->list); ++ list_del(>p->list); + unregister_netdevice_queue(dev, head); + } + +@@ -1690,16 +1690,19 @@ static int gtp_genl_dump_pdp(struct sk_buff *skb, + struct gtp_dev *last_gtp = (struct gtp_dev *)cb->args[2], *gtp; + int i, j, bucket = cb->args[0], skip = cb->args[1]; + struct net *net = sock_net(skb->sk); ++ struct net_device *dev; + struct pdp_ctx *pctx; +- struct gtp_net *gn; +- +- gn = net_generic(net, gtp_net_id); + + if (cb->args[4]) + return 0; + + rcu_read_lock(); +- list_for_each_entry_rcu(gtp, &gn->gtp_dev_list, list) { ++ for_each_netdev_rcu(net, dev) { ++ if (dev->rtnl_link_ops != >p_link_ops) ++ continue; ++ ++ gtp = netdev_priv(dev); ++ + if (last_gtp && last_gtp != gtp) + continue; + else +@@ -1884,23 +1887,28 @@ static int __net_init gtp_net_init(struct net *net) + return 0; + } + +-static void __net_exit gtp_net_exit(struct net *net) ++static void __net_exit gtp_net_exit_batch_rtnl(struct list_head *net_list, ++ struct list_head *dev_to_kill) + { +- struct gtp_net *gn = net_generic(net, gtp_net_id); +- struct gtp_dev *gtp; +- LIST_HEAD(list); ++ struct net *net; + +- rtnl_lock(); +- list_for_each_entry(gtp, &gn->gtp_dev_list, list) +- gtp_dellink(gtp->dev, &list); ++ list_for_each_entry(net, net_list, exit_list) { ++ struct gtp_net *gn = net_generic(net, gtp_net_id); ++ struct gtp_dev *gtp, *gtp_next; ++ struct net_device *dev; + +- unregister_netdevice_many(&list); +- rtnl_unlock(); ++ for_each_netdev(net, dev) ++ if (dev->rtnl_link_ops == >p_link_ops) ++ gtp_dellink(dev, dev_to_kill); ++ ++ list_for_each_entry_safe(gtp, gtp_next, &gn->gtp_dev_list, list) ++ gtp_dellink(gtp->dev, dev_to_kill); ++ } + } + + static struct pernet_operations gtp_net_ops = { + .init = gtp_net_init, +- .exit = gtp_net_exit, ++ .exit_batch_rtnl = gtp_net_exit_batch_rtnl, + .id = >p_net_id, + .size = sizeof(struct gtp_net), + }; +diff --git a/drivers/nvme/target/io-cmd-bdev.c b/drivers/nvme/target/io-cmd-bdev.c +index 468833675cc949..c0b342cc93db39 100644 +--- a/drivers/nvme/target/io-cmd-bdev.c ++++ b/drivers/nvme/target/io-cmd-bdev.c +@@ -36,7 +36,7 @@ void nvmet_bdev_set_limits(struct block_device *bdev, struct nvme_id_ns *id) + */ + id->nsfeat |= 1 << 4; + /* NPWG = Namespace Preferred Write Granularity. 0's based */ +- id->npwg = lpp0b; ++ id->npwg = to0based(bdev_io_min(bdev) / bdev_logical_block_size(bdev)); + /* NPWA = Namespace Preferred Write Alignment. 0's based */ + id->npwa = id->npwg; + /* NPDG = Namespace Preferred Deallocate Granularity. 0's based */ +diff --git a/drivers/pci/controller/pci-host-common.c b/drivers/pci/controller/pci-host-common.c +index e2602e38ae4526..6be3266cd7b5b2 100644 +--- a/drivers/pci/controller/pci-host-common.c ++++ b/drivers/pci/controller/pci-host-common.c +@@ -73,6 +73,10 @@ int pci_host_common_probe(struct platform_device *pdev) + if (IS_ERR(cfg)) + return PTR_ERR(cfg); + ++ /* Do not reassign resources if probe only */ ++ if (!pci_has_flag(PCI_PROBE_ONLY)) ++ pci_add_flags(PCI_REASSIGN_ALL_BUS); ++ + bridge->sysdata = cfg; + bridge->ops = (struct pci_ops *)&ops->pci_ops; + bridge->msi_domain = true; +diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c +index 7e84e472b3383c..03b519a2284038 100644 +--- a/drivers/pci/probe.c ++++ b/drivers/pci/probe.c +@@ -3096,18 +3096,20 @@ int pci_host_probe(struct pci_host_bridge *bridge) + + bus = bridge->bus; + +- /* If we must preserve the resource configuration, claim now */ +- if (bridge->preserve_config) +- pci_bus_claim_resources(bus); +- + /* +- * Assign whatever was left unassigned. If we didn't claim above, +- * this will reassign everything. ++ * We insert PCI resources into the iomem_resource and ++ * ioport_resource trees in either pci_bus_claim_resources() ++ * or pci_bus_assign_resources(). + */ +- pci_assign_unassigned_root_bus_resources(bus); ++ if (pci_has_flag(PCI_PROBE_ONLY)) { ++ pci_bus_claim_resources(bus); ++ } else { ++ pci_bus_size_bridges(bus); ++ pci_bus_assign_resources(bus); + +- list_for_each_entry(child, &bus->children, node) +- pcie_bus_configure_settings(child); ++ list_for_each_entry(child, &bus->children, node) ++ pcie_bus_configure_settings(child); ++ } + + pci_bus_add_devices(bus); + return 0; +diff --git a/drivers/pmdomain/imx/imx8mp-blk-ctrl.c b/drivers/pmdomain/imx/imx8mp-blk-ctrl.c +index 31693add7d633f..faf643a4a5d06b 100644 +--- a/drivers/pmdomain/imx/imx8mp-blk-ctrl.c ++++ b/drivers/pmdomain/imx/imx8mp-blk-ctrl.c +@@ -767,7 +767,7 @@ static int imx8mp_blk_ctrl_remove(struct platform_device *pdev) + + of_genpd_del_provider(pdev->dev.of_node); + +- for (i = 0; bc->onecell_data.num_domains; i++) { ++ for (i = 0; i < bc->onecell_data.num_domains; i++) { + struct imx8mp_blk_ctrl_domain *domain = &bc->domains[i]; + + pm_genpd_remove(&domain->genpd); +diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c +index 02696c7f9beff9..0ac0b6aaf9c62c 100644 +--- a/drivers/ufs/core/ufshcd.c ++++ b/drivers/ufs/core/ufshcd.c +@@ -10483,14 +10483,17 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) + } + + /* +- * Set the default power management level for runtime and system PM. ++ * Set the default power management level for runtime and system PM if ++ * not set by the host controller drivers. + * Default power saving mode is to keep UFS link in Hibern8 state + * and UFS device in sleep state. + */ +- hba->rpm_lvl = ufs_get_desired_pm_lvl_for_dev_link_state( ++ if (!hba->rpm_lvl) ++ hba->rpm_lvl = ufs_get_desired_pm_lvl_for_dev_link_state( + UFS_SLEEP_PWR_MODE, + UIC_LINK_HIBERN8_STATE); +- hba->spm_lvl = ufs_get_desired_pm_lvl_for_dev_link_state( ++ if (!hba->spm_lvl) ++ hba->spm_lvl = ufs_get_desired_pm_lvl_for_dev_link_state( + UFS_SLEEP_PWR_MODE, + UIC_LINK_HIBERN8_STATE); + +diff --git a/fs/cachefiles/daemon.c b/fs/cachefiles/daemon.c +index 89b11336a83697..1806bff8e59bc3 100644 +--- a/fs/cachefiles/daemon.c ++++ b/fs/cachefiles/daemon.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -576,7 +577,7 @@ static int cachefiles_daemon_dir(struct cachefiles_cache *cache, char *args) + */ + static int cachefiles_daemon_secctx(struct cachefiles_cache *cache, char *args) + { +- char *secctx; ++ int err; + + _enter(",%s", args); + +@@ -585,16 +586,16 @@ static int cachefiles_daemon_secctx(struct cachefiles_cache *cache, char *args) + return -EINVAL; + } + +- if (cache->secctx) { ++ if (cache->have_secid) { + pr_err("Second security context specified\n"); + return -EINVAL; + } + +- secctx = kstrdup(args, GFP_KERNEL); +- if (!secctx) +- return -ENOMEM; ++ err = security_secctx_to_secid(args, strlen(args), &cache->secid); ++ if (err) ++ return err; + +- cache->secctx = secctx; ++ cache->have_secid = true; + return 0; + } + +@@ -820,7 +821,6 @@ static void cachefiles_daemon_unbind(struct cachefiles_cache *cache) + put_cred(cache->cache_cred); + + kfree(cache->rootdirname); +- kfree(cache->secctx); + kfree(cache->tag); + + _leave(""); +diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h +index 111ad6ecd4baf3..4421a12960a662 100644 +--- a/fs/cachefiles/internal.h ++++ b/fs/cachefiles/internal.h +@@ -122,7 +122,6 @@ struct cachefiles_cache { + #define CACHEFILES_STATE_CHANGED 3 /* T if state changed (poll trigger) */ + #define CACHEFILES_ONDEMAND_MODE 4 /* T if in on-demand read mode */ + char *rootdirname; /* name of cache root directory */ +- char *secctx; /* LSM security context */ + char *tag; /* cache binding tag */ + refcount_t unbind_pincount;/* refcount to do daemon unbind */ + struct xarray reqs; /* xarray of pending on-demand requests */ +@@ -130,6 +129,8 @@ struct cachefiles_cache { + struct xarray ondemand_ids; /* xarray for ondemand_id allocation */ + u32 ondemand_id_next; + u32 msg_id_next; ++ u32 secid; /* LSM security id */ ++ bool have_secid; /* whether "secid" was set */ + }; + + static inline bool cachefiles_in_ondemand_mode(struct cachefiles_cache *cache) +diff --git a/fs/cachefiles/security.c b/fs/cachefiles/security.c +index fe777164f1d894..fc6611886b3b5e 100644 +--- a/fs/cachefiles/security.c ++++ b/fs/cachefiles/security.c +@@ -18,7 +18,7 @@ int cachefiles_get_security_ID(struct cachefiles_cache *cache) + struct cred *new; + int ret; + +- _enter("{%s}", cache->secctx); ++ _enter("{%u}", cache->have_secid ? cache->secid : 0); + + new = prepare_kernel_cred(current); + if (!new) { +@@ -26,8 +26,8 @@ int cachefiles_get_security_ID(struct cachefiles_cache *cache) + goto error; + } + +- if (cache->secctx) { +- ret = set_security_override_from_ctx(new, cache->secctx); ++ if (cache->have_secid) { ++ ret = set_security_override(new, cache->secid); + if (ret < 0) { + put_cred(new); + pr_err("Security denies permission to nominate security context: error %d\n", +diff --git a/fs/file.c b/fs/file.c +index bd817e31d79866..a178efc8cf4b5c 100644 +--- a/fs/file.c ++++ b/fs/file.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + + #include "internal.h" + +diff --git a/fs/hfs/super.c b/fs/hfs/super.c +index 6764afa98a6ff1..431bdc65f72312 100644 +--- a/fs/hfs/super.c ++++ b/fs/hfs/super.c +@@ -418,11 +418,13 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent) + goto bail_no_root; + res = hfs_cat_find_brec(sb, HFS_ROOT_CNID, &fd); + if (!res) { +- if (fd.entrylength > sizeof(rec) || fd.entrylength < 0) { ++ if (fd.entrylength != sizeof(rec.dir)) { + res = -EIO; + goto bail_hfs_find; + } + hfs_bnode_read(fd.bnode, &rec, fd.entryoffset, fd.entrylength); ++ if (rec.type != HFS_CDR_DIR) ++ res = -EIO; + } + if (res) + goto bail_hfs_find; +diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c +index a05ee2cbb77936..e7e6701806ad26 100644 +--- a/fs/iomap/buffered-io.c ++++ b/fs/iomap/buffered-io.c +@@ -1095,7 +1095,7 @@ static int iomap_write_delalloc_scan(struct inode *inode, + } + + /* move offset to start of next folio in range */ +- start_byte = folio_next_index(folio) << PAGE_SHIFT; ++ start_byte = folio_pos(folio) + folio_size(folio); + folio_unlock(folio); + folio_put(folio); + } +diff --git a/fs/nfsd/filecache.c b/fs/nfsd/filecache.c +index 6f2bcbfde45e69..0ff07d53931f2f 100644 +--- a/fs/nfsd/filecache.c ++++ b/fs/nfsd/filecache.c +@@ -219,6 +219,7 @@ nfsd_file_alloc(struct net *net, struct inode *inode, unsigned char need, + return NULL; + + INIT_LIST_HEAD(&nf->nf_lru); ++ INIT_LIST_HEAD(&nf->nf_gc); + nf->nf_birthtime = ktime_get(); + nf->nf_file = NULL; + nf->nf_cred = get_current_cred(); +@@ -396,8 +397,8 @@ nfsd_file_dispose_list(struct list_head *dispose) + struct nfsd_file *nf; + + while (!list_empty(dispose)) { +- nf = list_first_entry(dispose, struct nfsd_file, nf_lru); +- list_del_init(&nf->nf_lru); ++ nf = list_first_entry(dispose, struct nfsd_file, nf_gc); ++ list_del_init(&nf->nf_gc); + nfsd_file_free(nf); + } + } +@@ -414,12 +415,12 @@ nfsd_file_dispose_list_delayed(struct list_head *dispose) + { + while(!list_empty(dispose)) { + struct nfsd_file *nf = list_first_entry(dispose, +- struct nfsd_file, nf_lru); ++ struct nfsd_file, nf_gc); + struct nfsd_net *nn = net_generic(nf->nf_net, nfsd_net_id); + struct nfsd_fcache_disposal *l = nn->fcache_disposal; + + spin_lock(&l->lock); +- list_move_tail(&nf->nf_lru, &l->freeme); ++ list_move_tail(&nf->nf_gc, &l->freeme); + spin_unlock(&l->lock); + queue_work(nfsd_filecache_wq, &l->work); + } +@@ -476,7 +477,8 @@ nfsd_file_lru_cb(struct list_head *item, struct list_lru_one *lru, + + /* Refcount went to zero. Unhash it and queue it to the dispose list */ + nfsd_file_unhash(nf); +- list_lru_isolate_move(lru, &nf->nf_lru, head); ++ list_lru_isolate(lru, &nf->nf_lru); ++ list_add(&nf->nf_gc, head); + this_cpu_inc(nfsd_file_evictions); + trace_nfsd_file_gc_disposed(nf); + return LRU_REMOVED; +@@ -555,7 +557,7 @@ nfsd_file_cond_queue(struct nfsd_file *nf, struct list_head *dispose) + + /* If refcount goes to 0, then put on the dispose list */ + if (refcount_sub_and_test(decrement, &nf->nf_ref)) { +- list_add(&nf->nf_lru, dispose); ++ list_add(&nf->nf_gc, dispose); + trace_nfsd_file_closing(nf); + } + } +@@ -631,8 +633,8 @@ nfsd_file_close_inode_sync(struct inode *inode) + + nfsd_file_queue_for_close(inode, &dispose); + while (!list_empty(&dispose)) { +- nf = list_first_entry(&dispose, struct nfsd_file, nf_lru); +- list_del_init(&nf->nf_lru); ++ nf = list_first_entry(&dispose, struct nfsd_file, nf_gc); ++ list_del_init(&nf->nf_gc); + nfsd_file_free(nf); + } + flush_delayed_fput(); +diff --git a/fs/nfsd/filecache.h b/fs/nfsd/filecache.h +index e54165a3224f0b..bf7a630f1a4561 100644 +--- a/fs/nfsd/filecache.h ++++ b/fs/nfsd/filecache.h +@@ -44,6 +44,7 @@ struct nfsd_file { + + struct nfsd_file_mark *nf_mark; + struct list_head nf_lru; ++ struct list_head nf_gc; + struct rcu_head nf_rcu; + ktime_t nf_birthtime; + }; +diff --git a/fs/notify/fdinfo.c b/fs/notify/fdinfo.c +index 5c430736ec12c4..26655572975d3d 100644 +--- a/fs/notify/fdinfo.c ++++ b/fs/notify/fdinfo.c +@@ -51,10 +51,8 @@ static void show_mark_fhandle(struct seq_file *m, struct inode *inode) + size = f.handle.handle_bytes >> 2; + + ret = exportfs_encode_fid(inode, (struct fid *)f.handle.f_handle, &size); +- if ((ret == FILEID_INVALID) || (ret < 0)) { +- WARN_ONCE(1, "Can't encode file handler for inotify: %d\n", ret); ++ if ((ret == FILEID_INVALID) || (ret < 0)) + return; +- } + + f.handle.handle_type = ret; + f.handle.handle_bytes = size * sizeof(u32); +diff --git a/fs/ocfs2/extent_map.c b/fs/ocfs2/extent_map.c +index 70a768b623cf40..f7672472fa8279 100644 +--- a/fs/ocfs2/extent_map.c ++++ b/fs/ocfs2/extent_map.c +@@ -973,7 +973,13 @@ int ocfs2_read_virt_blocks(struct inode *inode, u64 v_block, int nr, + } + + while (done < nr) { +- down_read(&OCFS2_I(inode)->ip_alloc_sem); ++ if (!down_read_trylock(&OCFS2_I(inode)->ip_alloc_sem)) { ++ rc = -EAGAIN; ++ mlog(ML_ERROR, ++ "Inode #%llu ip_alloc_sem is temporarily unavailable\n", ++ (unsigned long long)OCFS2_I(inode)->ip_blkno); ++ break; ++ } + rc = ocfs2_extent_map_get_blocks(inode, v_block + done, + &p_block, &p_count, NULL); + up_read(&OCFS2_I(inode)->ip_alloc_sem); +diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c +index ada3fcc9c6d501..18e018cb181179 100644 +--- a/fs/overlayfs/copy_up.c ++++ b/fs/overlayfs/copy_up.c +@@ -371,13 +371,13 @@ int ovl_set_attr(struct ovl_fs *ofs, struct dentry *upperdentry, + return err; + } + +-struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct dentry *real, ++struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct inode *realinode, + bool is_upper) + { + struct ovl_fh *fh; + int fh_type, dwords; + int buflen = MAX_HANDLE_SZ; +- uuid_t *uuid = &real->d_sb->s_uuid; ++ uuid_t *uuid = &realinode->i_sb->s_uuid; + int err; + + /* Make sure the real fid stays 32bit aligned */ +@@ -394,13 +394,13 @@ struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct dentry *real, + * the price or reconnecting the dentry. + */ + dwords = buflen >> 2; +- fh_type = exportfs_encode_fh(real, (void *)fh->fb.fid, &dwords, 0); ++ fh_type = exportfs_encode_inode_fh(realinode, (void *)fh->fb.fid, ++ &dwords, NULL, 0); + buflen = (dwords << 2); + + err = -EIO; +- if (WARN_ON(fh_type < 0) || +- WARN_ON(buflen > MAX_HANDLE_SZ) || +- WARN_ON(fh_type == FILEID_INVALID)) ++ if (fh_type < 0 || fh_type == FILEID_INVALID || ++ WARN_ON(buflen > MAX_HANDLE_SZ)) + goto out_err; + + fh->fb.version = OVL_FH_VERSION; +@@ -438,7 +438,7 @@ int ovl_set_origin(struct ovl_fs *ofs, struct dentry *lower, + * up and a pure upper inode. + */ + if (ovl_can_decode_fh(lower->d_sb)) { +- fh = ovl_encode_real_fh(ofs, lower, false); ++ fh = ovl_encode_real_fh(ofs, d_inode(lower), false); + if (IS_ERR(fh)) + return PTR_ERR(fh); + } +@@ -461,7 +461,7 @@ static int ovl_set_upper_fh(struct ovl_fs *ofs, struct dentry *upper, + const struct ovl_fh *fh; + int err; + +- fh = ovl_encode_real_fh(ofs, upper, true); ++ fh = ovl_encode_real_fh(ofs, d_inode(upper), true); + if (IS_ERR(fh)) + return PTR_ERR(fh); + +diff --git a/fs/overlayfs/export.c b/fs/overlayfs/export.c +index 611ff567a1aa6f..3a17e4366f28c0 100644 +--- a/fs/overlayfs/export.c ++++ b/fs/overlayfs/export.c +@@ -181,35 +181,37 @@ static int ovl_connect_layer(struct dentry *dentry) + * + * Return 0 for upper file handle, > 0 for lower file handle or < 0 on error. + */ +-static int ovl_check_encode_origin(struct dentry *dentry) ++static int ovl_check_encode_origin(struct inode *inode) + { +- struct ovl_fs *ofs = OVL_FS(dentry->d_sb); ++ struct ovl_fs *ofs = OVL_FS(inode->i_sb); + bool decodable = ofs->config.nfs_export; ++ struct dentry *dentry; ++ int err; + + /* No upper layer? */ + if (!ovl_upper_mnt(ofs)) + return 1; + + /* Lower file handle for non-upper non-decodable */ +- if (!ovl_dentry_upper(dentry) && !decodable) ++ if (!ovl_inode_upper(inode) && !decodable) + return 1; + + /* Upper file handle for pure upper */ +- if (!ovl_dentry_lower(dentry)) ++ if (!ovl_inode_lower(inode)) + return 0; + + /* + * Root is never indexed, so if there's an upper layer, encode upper for + * root. + */ +- if (dentry == dentry->d_sb->s_root) ++ if (inode == d_inode(inode->i_sb->s_root)) + return 0; + + /* + * Upper decodable file handle for non-indexed upper. + */ +- if (ovl_dentry_upper(dentry) && decodable && +- !ovl_test_flag(OVL_INDEX, d_inode(dentry))) ++ if (ovl_inode_upper(inode) && decodable && ++ !ovl_test_flag(OVL_INDEX, inode)) + return 0; + + /* +@@ -218,14 +220,23 @@ static int ovl_check_encode_origin(struct dentry *dentry) + * ovl_connect_layer() will try to make origin's layer "connected" by + * copying up a "connectable" ancestor. + */ +- if (d_is_dir(dentry) && decodable) +- return ovl_connect_layer(dentry); ++ if (!decodable || !S_ISDIR(inode->i_mode)) ++ return 1; ++ ++ dentry = d_find_any_alias(inode); ++ if (!dentry) ++ return -ENOENT; ++ ++ err = ovl_connect_layer(dentry); ++ dput(dentry); ++ if (err < 0) ++ return err; + + /* Lower file handle for indexed and non-upper dir/non-dir */ + return 1; + } + +-static int ovl_dentry_to_fid(struct ovl_fs *ofs, struct dentry *dentry, ++static int ovl_dentry_to_fid(struct ovl_fs *ofs, struct inode *inode, + u32 *fid, int buflen) + { + struct ovl_fh *fh = NULL; +@@ -236,13 +247,13 @@ static int ovl_dentry_to_fid(struct ovl_fs *ofs, struct dentry *dentry, + * Check if we should encode a lower or upper file handle and maybe + * copy up an ancestor to make lower file handle connectable. + */ +- err = enc_lower = ovl_check_encode_origin(dentry); ++ err = enc_lower = ovl_check_encode_origin(inode); + if (enc_lower < 0) + goto fail; + + /* Encode an upper or lower file handle */ +- fh = ovl_encode_real_fh(ofs, enc_lower ? ovl_dentry_lower(dentry) : +- ovl_dentry_upper(dentry), !enc_lower); ++ fh = ovl_encode_real_fh(ofs, enc_lower ? ovl_inode_lower(inode) : ++ ovl_inode_upper(inode), !enc_lower); + if (IS_ERR(fh)) + return PTR_ERR(fh); + +@@ -256,8 +267,8 @@ static int ovl_dentry_to_fid(struct ovl_fs *ofs, struct dentry *dentry, + return err; + + fail: +- pr_warn_ratelimited("failed to encode file handle (%pd2, err=%i)\n", +- dentry, err); ++ pr_warn_ratelimited("failed to encode file handle (ino=%lu, err=%i)\n", ++ inode->i_ino, err); + goto out; + } + +@@ -265,19 +276,13 @@ static int ovl_encode_fh(struct inode *inode, u32 *fid, int *max_len, + struct inode *parent) + { + struct ovl_fs *ofs = OVL_FS(inode->i_sb); +- struct dentry *dentry; + int bytes, buflen = *max_len << 2; + + /* TODO: encode connectable file handles */ + if (parent) + return FILEID_INVALID; + +- dentry = d_find_any_alias(inode); +- if (!dentry) +- return FILEID_INVALID; +- +- bytes = ovl_dentry_to_fid(ofs, dentry, fid, buflen); +- dput(dentry); ++ bytes = ovl_dentry_to_fid(ofs, inode, fid, buflen); + if (bytes <= 0) + return FILEID_INVALID; + +diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c +index 80391c687c2ad8..273a39d3e95133 100644 +--- a/fs/overlayfs/namei.c ++++ b/fs/overlayfs/namei.c +@@ -523,7 +523,7 @@ int ovl_verify_set_fh(struct ovl_fs *ofs, struct dentry *dentry, + struct ovl_fh *fh; + int err; + +- fh = ovl_encode_real_fh(ofs, real, is_upper); ++ fh = ovl_encode_real_fh(ofs, d_inode(real), is_upper); + err = PTR_ERR(fh); + if (IS_ERR(fh)) { + fh = NULL; +@@ -720,7 +720,7 @@ int ovl_get_index_name(struct ovl_fs *ofs, struct dentry *origin, + struct ovl_fh *fh; + int err; + +- fh = ovl_encode_real_fh(ofs, origin, false); ++ fh = ovl_encode_real_fh(ofs, d_inode(origin), false); + if (IS_ERR(fh)) + return PTR_ERR(fh); + +diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h +index 09ca82ed0f8ced..981967e507b3e1 100644 +--- a/fs/overlayfs/overlayfs.h ++++ b/fs/overlayfs/overlayfs.h +@@ -821,7 +821,7 @@ int ovl_copy_up_with_data(struct dentry *dentry); + int ovl_maybe_copy_up(struct dentry *dentry, int flags); + int ovl_copy_xattr(struct super_block *sb, const struct path *path, struct dentry *new); + int ovl_set_attr(struct ovl_fs *ofs, struct dentry *upper, struct kstat *stat); +-struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct dentry *real, ++struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct inode *realinode, + bool is_upper); + int ovl_set_origin(struct ovl_fs *ofs, struct dentry *lower, + struct dentry *upper); +diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c +index 8319bcbe3ee36b..3303cb04e12c36 100644 +--- a/fs/proc/vmcore.c ++++ b/fs/proc/vmcore.c +@@ -404,6 +404,8 @@ static ssize_t __read_vmcore(struct iov_iter *iter, loff_t *fpos) + if (!iov_iter_count(iter)) + return acc; + } ++ ++ cond_resched(); + } + + return acc; +diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c +index 20f303f2a5d75a..dbcaaa274abdbf 100644 +--- a/fs/smb/client/connect.c ++++ b/fs/smb/client/connect.c +@@ -1061,6 +1061,7 @@ clean_demultiplex_info(struct TCP_Server_Info *server) + /* Release netns reference for this server. */ + put_net(cifs_net_ns(server)); + kfree(server->leaf_fullpath); ++ kfree(server->hostname); + kfree(server); + + length = atomic_dec_return(&tcpSesAllocCount); +@@ -1684,8 +1685,6 @@ cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect) + kfree_sensitive(server->session_key.response); + server->session_key.response = NULL; + server->session_key.len = 0; +- kfree(server->hostname); +- server->hostname = NULL; + + task = xchg(&server->tsk, NULL); + if (task) +diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h +index 254d4a898179c0..8f77bb0f4ae0ca 100644 +--- a/include/linux/hrtimer.h ++++ b/include/linux/hrtimer.h +@@ -532,6 +532,7 @@ extern void __init hrtimers_init(void); + extern void sysrq_timer_list_show(void); + + int hrtimers_prepare_cpu(unsigned int cpu); ++int hrtimers_cpu_starting(unsigned int cpu); + #ifdef CONFIG_HOTPLUG_CPU + int hrtimers_cpu_dying(unsigned int cpu); + #else +diff --git a/include/linux/poll.h b/include/linux/poll.h +index d1ea4f3714a848..fc641b50f1298e 100644 +--- a/include/linux/poll.h ++++ b/include/linux/poll.h +@@ -41,8 +41,16 @@ typedef struct poll_table_struct { + + static inline void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p) + { +- if (p && p->_qproc && wait_address) ++ if (p && p->_qproc && wait_address) { + p->_qproc(filp, wait_address, p); ++ /* ++ * This memory barrier is paired in the wq_has_sleeper(). ++ * See the comment above prepare_to_wait(), we need to ++ * ensure that subsequent tests in this thread can't be ++ * reordered with __add_wait_queue() in _qproc() paths. ++ */ ++ smp_mb(); ++ } + } + + /* +diff --git a/include/linux/pruss_driver.h b/include/linux/pruss_driver.h +index c9a31c567e85bf..2e18fef1a2e109 100644 +--- a/include/linux/pruss_driver.h ++++ b/include/linux/pruss_driver.h +@@ -144,32 +144,32 @@ static inline int pruss_release_mem_region(struct pruss *pruss, + static inline int pruss_cfg_get_gpmux(struct pruss *pruss, + enum pruss_pru_id pru_id, u8 *mux) + { +- return ERR_PTR(-EOPNOTSUPP); ++ return -EOPNOTSUPP; + } + + static inline int pruss_cfg_set_gpmux(struct pruss *pruss, + enum pruss_pru_id pru_id, u8 mux) + { +- return ERR_PTR(-EOPNOTSUPP); ++ return -EOPNOTSUPP; + } + + static inline int pruss_cfg_gpimode(struct pruss *pruss, + enum pruss_pru_id pru_id, + enum pruss_gpi_mode mode) + { +- return ERR_PTR(-EOPNOTSUPP); ++ return -EOPNOTSUPP; + } + + static inline int pruss_cfg_miirt_enable(struct pruss *pruss, bool enable) + { +- return ERR_PTR(-EOPNOTSUPP); ++ return -EOPNOTSUPP; + } + + static inline int pruss_cfg_xfr_enable(struct pruss *pruss, + enum pru_type pru_type, +- bool enable); ++ bool enable) + { +- return ERR_PTR(-EOPNOTSUPP); ++ return -EOPNOTSUPP; + } + + #endif /* CONFIG_TI_PRUSS */ +diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h +index 958c805df1915b..1befad79a67349 100644 +--- a/include/net/net_namespace.h ++++ b/include/net/net_namespace.h +@@ -442,6 +442,9 @@ struct pernet_operations { + void (*pre_exit)(struct net *net); + void (*exit)(struct net *net); + void (*exit_batch)(struct list_head *net_exit_list); ++ /* Following method is called with RTNL held. */ ++ void (*exit_batch_rtnl)(struct list_head *net_exit_list, ++ struct list_head *dev_kill_list); + unsigned int *id; + size_t size; + }; +diff --git a/kernel/cpu.c b/kernel/cpu.c +index 0c72b94ed076a3..7ab11b45976842 100644 +--- a/kernel/cpu.c ++++ b/kernel/cpu.c +@@ -2206,7 +2206,7 @@ static struct cpuhp_step cpuhp_hp_states[] = { + }, + [CPUHP_AP_HRTIMERS_DYING] = { + .name = "hrtimers:dying", +- .startup.single = NULL, ++ .startup.single = hrtimers_cpu_starting, + .teardown.single = hrtimers_cpu_dying, + }, + +diff --git a/kernel/gen_kheaders.sh b/kernel/gen_kheaders.sh +index 383fd43ac61222..7e1340da5acae6 100755 +--- a/kernel/gen_kheaders.sh ++++ b/kernel/gen_kheaders.sh +@@ -89,6 +89,7 @@ find $cpio_dir -type f -print0 | + + # Create archive and try to normalize metadata for reproducibility. + tar "${KBUILD_BUILD_TIMESTAMP:+--mtime=$KBUILD_BUILD_TIMESTAMP}" \ ++ --exclude=".__afs*" --exclude=".nfs*" \ + --owner=0 --group=0 --sort=name --numeric-owner --mode=u=rw,go=r,a+X \ + -I $XZ -cf $tarfile -C $cpio_dir/ . > /dev/null + +diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c +index 57e5cb36f1bc93..e99b1305e1a5f4 100644 +--- a/kernel/time/hrtimer.c ++++ b/kernel/time/hrtimer.c +@@ -2180,6 +2180,15 @@ int hrtimers_prepare_cpu(unsigned int cpu) + } + + cpu_base->cpu = cpu; ++ hrtimer_cpu_base_init_expiry_lock(cpu_base); ++ return 0; ++} ++ ++int hrtimers_cpu_starting(unsigned int cpu) ++{ ++ struct hrtimer_cpu_base *cpu_base = this_cpu_ptr(&hrtimer_bases); ++ ++ /* Clear out any left over state from a CPU down operation */ + cpu_base->active_bases = 0; + cpu_base->hres_active = 0; + cpu_base->hang_detected = 0; +@@ -2188,7 +2197,6 @@ int hrtimers_prepare_cpu(unsigned int cpu) + cpu_base->expires_next = KTIME_MAX; + cpu_base->softirq_expires_next = KTIME_MAX; + cpu_base->online = 1; +- hrtimer_cpu_base_init_expiry_lock(cpu_base); + return 0; + } + +@@ -2266,6 +2274,7 @@ int hrtimers_cpu_dying(unsigned int dying_cpu) + void __init hrtimers_init(void) + { + hrtimers_prepare_cpu(smp_processor_id()); ++ hrtimers_cpu_starting(smp_processor_id()); + open_softirq(HRTIMER_SOFTIRQ, hrtimer_run_softirq); + } + +diff --git a/mm/filemap.c b/mm/filemap.c +index 2c308413387ffb..6a3d62de1cca7b 100644 +--- a/mm/filemap.c ++++ b/mm/filemap.c +@@ -3037,7 +3037,7 @@ static inline loff_t folio_seek_hole_data(struct xa_state *xas, + if (ops->is_partially_uptodate(folio, offset, bsz) == + seek_data) + break; +- start = (start + bsz) & ~(bsz - 1); ++ start = (start + bsz) & ~((u64)bsz - 1); + offset += bsz; + } while (offset < folio_size(folio)); + unlock: +diff --git a/net/core/filter.c b/net/core/filter.c +index 34320ce70096ac..5881944f1681c9 100644 +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -11190,6 +11190,7 @@ BPF_CALL_4(sk_select_reuseport, struct sk_reuseport_kern *, reuse_kern, + bool is_sockarray = map->map_type == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY; + struct sock_reuseport *reuse; + struct sock *selected_sk; ++ int err; + + selected_sk = map->ops->map_lookup_elem(map, key); + if (!selected_sk) +@@ -11197,10 +11198,6 @@ BPF_CALL_4(sk_select_reuseport, struct sk_reuseport_kern *, reuse_kern, + + reuse = rcu_dereference(selected_sk->sk_reuseport_cb); + if (!reuse) { +- /* Lookup in sock_map can return TCP ESTABLISHED sockets. */ +- if (sk_is_refcounted(selected_sk)) +- sock_put(selected_sk); +- + /* reuseport_array has only sk with non NULL sk_reuseport_cb. + * The only (!reuse) case here is - the sk has already been + * unhashed (e.g. by close()), so treat it as -ENOENT. +@@ -11208,24 +11205,33 @@ BPF_CALL_4(sk_select_reuseport, struct sk_reuseport_kern *, reuse_kern, + * Other maps (e.g. sock_map) do not provide this guarantee and + * the sk may never be in the reuseport group to begin with. + */ +- return is_sockarray ? -ENOENT : -EINVAL; ++ err = is_sockarray ? -ENOENT : -EINVAL; ++ goto error; + } + + if (unlikely(reuse->reuseport_id != reuse_kern->reuseport_id)) { + struct sock *sk = reuse_kern->sk; + +- if (sk->sk_protocol != selected_sk->sk_protocol) +- return -EPROTOTYPE; +- else if (sk->sk_family != selected_sk->sk_family) +- return -EAFNOSUPPORT; +- +- /* Catch all. Likely bound to a different sockaddr. */ +- return -EBADFD; ++ if (sk->sk_protocol != selected_sk->sk_protocol) { ++ err = -EPROTOTYPE; ++ } else if (sk->sk_family != selected_sk->sk_family) { ++ err = -EAFNOSUPPORT; ++ } else { ++ /* Catch all. Likely bound to a different sockaddr. */ ++ err = -EBADFD; ++ } ++ goto error; + } + + reuse_kern->selected_sk = selected_sk; + + return 0; ++error: ++ /* Lookup in sock_map can return TCP ESTABLISHED sockets. */ ++ if (sk_is_refcounted(selected_sk)) ++ sock_put(selected_sk); ++ ++ return err; + } + + static const struct bpf_func_proto sk_select_reuseport_proto = { +diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c +index 92b7fea4d495cf..70ac9d9bc87708 100644 +--- a/net/core/net_namespace.c ++++ b/net/core/net_namespace.c +@@ -321,8 +321,9 @@ static __net_init int setup_net(struct net *net, struct user_namespace *user_ns) + { + /* Must be called with pernet_ops_rwsem held */ + const struct pernet_operations *ops, *saved_ops; +- int error = 0; + LIST_HEAD(net_exit_list); ++ LIST_HEAD(dev_kill_list); ++ int error = 0; + + refcount_set(&net->ns.count, 1); + ref_tracker_dir_init(&net->refcnt_tracker, 128, "net refcnt"); +@@ -360,6 +361,15 @@ static __net_init int setup_net(struct net *net, struct user_namespace *user_ns) + + synchronize_rcu(); + ++ ops = saved_ops; ++ rtnl_lock(); ++ list_for_each_entry_continue_reverse(ops, &pernet_list, list) { ++ if (ops->exit_batch_rtnl) ++ ops->exit_batch_rtnl(&net_exit_list, &dev_kill_list); ++ } ++ unregister_netdevice_many(&dev_kill_list); ++ rtnl_unlock(); ++ + ops = saved_ops; + list_for_each_entry_continue_reverse(ops, &pernet_list, list) + ops_exit_list(ops, &net_exit_list); +@@ -588,6 +598,7 @@ static void cleanup_net(struct work_struct *work) + struct net *net, *tmp, *last; + struct llist_node *net_kill_list; + LIST_HEAD(net_exit_list); ++ LIST_HEAD(dev_kill_list); + + /* Atomically snapshot the list of namespaces to cleanup */ + net_kill_list = llist_del_all(&cleanup_list); +@@ -628,6 +639,14 @@ static void cleanup_net(struct work_struct *work) + */ + synchronize_rcu(); + ++ rtnl_lock(); ++ list_for_each_entry_reverse(ops, &pernet_list, list) { ++ if (ops->exit_batch_rtnl) ++ ops->exit_batch_rtnl(&net_exit_list, &dev_kill_list); ++ } ++ unregister_netdevice_many(&dev_kill_list); ++ rtnl_unlock(); ++ + /* Run all of the network namespace exit methods */ + list_for_each_entry_reverse(ops, &pernet_list, list) + ops_exit_list(ops, &net_exit_list); +@@ -1170,7 +1189,17 @@ static void free_exit_list(struct pernet_operations *ops, struct list_head *net_ + { + ops_pre_exit_list(ops, net_exit_list); + synchronize_rcu(); ++ ++ if (ops->exit_batch_rtnl) { ++ LIST_HEAD(dev_kill_list); ++ ++ rtnl_lock(); ++ ops->exit_batch_rtnl(net_exit_list, &dev_kill_list); ++ unregister_netdevice_many(&dev_kill_list); ++ rtnl_unlock(); ++ } + ops_exit_list(ops, net_exit_list); ++ + ops_free_list(ops, net_exit_list); + } + +diff --git a/net/core/pktgen.c b/net/core/pktgen.c +index 0e472f6fab8538..359e24c3f22cab 100644 +--- a/net/core/pktgen.c ++++ b/net/core/pktgen.c +@@ -850,6 +850,9 @@ static ssize_t get_imix_entries(const char __user *buffer, + unsigned long weight; + unsigned long size; + ++ if (pkt_dev->n_imix_entries >= MAX_IMIX_ENTRIES) ++ return -E2BIG; ++ + len = num_arg(&buffer[i], max_digits, &size); + if (len < 0) + return len; +@@ -879,9 +882,6 @@ static ssize_t get_imix_entries(const char __user *buffer, + + i++; + pkt_dev->n_imix_entries++; +- +- if (pkt_dev->n_imix_entries > MAX_IMIX_ENTRIES) +- return -E2BIG; + } while (c == ' '); + + return i; +diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c +index d25e962b18a53e..2839ca8053ba6d 100644 +--- a/net/dccp/ipv6.c ++++ b/net/dccp/ipv6.c +@@ -616,7 +616,7 @@ static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) + by tcp. Feel free to propose better solution. + --ANK (980728) + */ +- if (np->rxopt.all) ++ if (np->rxopt.all && sk->sk_state != DCCP_LISTEN) + opt_skb = skb_clone_and_charge_r(skb, sk); + + if (sk->sk_state == DCCP_OPEN) { /* Fast path */ +diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c +index 64bdb6d978eed4..f285e52b8b8579 100644 +--- a/net/ipv6/tcp_ipv6.c ++++ b/net/ipv6/tcp_ipv6.c +@@ -1456,7 +1456,7 @@ int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) + by tcp. Feel free to propose better solution. + --ANK (980728) + */ +- if (np->rxopt.all) ++ if (np->rxopt.all && sk->sk_state != TCP_LISTEN) + opt_skb = skb_clone_and_charge_r(skb, sk); + + reason = SKB_DROP_REASON_NOT_SPECIFIED; +@@ -1495,8 +1495,6 @@ int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) + if (nsk != sk) { + if (tcp_child_process(sk, nsk, skb)) + goto reset; +- if (opt_skb) +- __kfree_skb(opt_skb); + return 0; + } + } else +diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c +index c0e2da5072bea2..9e4631fade90c9 100644 +--- a/net/mac802154/iface.c ++++ b/net/mac802154/iface.c +@@ -684,6 +684,10 @@ void ieee802154_if_remove(struct ieee802154_sub_if_data *sdata) + ASSERT_RTNL(); + + mutex_lock(&sdata->local->iflist_mtx); ++ if (list_empty(&sdata->local->interfaces)) { ++ mutex_unlock(&sdata->local->iflist_mtx); ++ return; ++ } + list_del_rcu(&sdata->list); + mutex_unlock(&sdata->local->iflist_mtx); + +diff --git a/net/mptcp/options.c b/net/mptcp/options.c +index 2e1539027e6d33..8e6a6dc6e0a409 100644 +--- a/net/mptcp/options.c ++++ b/net/mptcp/options.c +@@ -607,7 +607,6 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb, + } + opts->ext_copy.use_ack = 1; + opts->suboptions = OPTION_MPTCP_DSS; +- WRITE_ONCE(msk->old_wspace, __mptcp_space((struct sock *)msk)); + + /* Add kind/length/subtype/flag overhead if mapping is not populated */ + if (dss_size == 0) +@@ -1287,7 +1286,7 @@ static void mptcp_set_rwin(struct tcp_sock *tp, struct tcphdr *th) + } + MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_RCVWNDCONFLICT); + } +- return; ++ goto update_wspace; + } + + if (rcv_wnd_new != rcv_wnd_old) { +@@ -1312,6 +1311,9 @@ static void mptcp_set_rwin(struct tcp_sock *tp, struct tcphdr *th) + th->window = htons(new_win); + MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_RCVWNDSHARED); + } ++ ++update_wspace: ++ WRITE_ONCE(msk->old_wspace, tp->rcv_wnd); + } + + __sum16 __mptcp_make_csum(u64 data_seq, u32 subflow_seq, u16 data_len, __wsum sum) +diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h +index 89d1c299ff2b9f..88c762de772875 100644 +--- a/net/mptcp/protocol.h ++++ b/net/mptcp/protocol.h +@@ -685,10 +685,15 @@ static inline u64 mptcp_data_avail(const struct mptcp_sock *msk) + + static inline bool mptcp_epollin_ready(const struct sock *sk) + { ++ u64 data_avail = mptcp_data_avail(mptcp_sk(sk)); ++ ++ if (!data_avail) ++ return false; ++ + /* mptcp doesn't have to deal with small skbs in the receive queue, +- * at it can always coalesce them ++ * as it can always coalesce them + */ +- return (mptcp_data_avail(mptcp_sk(sk)) >= sk->sk_rcvlowat) || ++ return (data_avail >= sk->sk_rcvlowat) || + (mem_cgroup_sockets_enabled && sk->sk_memcg && + mem_cgroup_under_socket_pressure(sk->sk_memcg)) || + READ_ONCE(tcp_memory_pressure); +diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c +index 4f5cbcaa38386f..9445ca97163b40 100644 +--- a/net/openvswitch/actions.c ++++ b/net/openvswitch/actions.c +@@ -918,7 +918,9 @@ static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port, + { + struct vport *vport = ovs_vport_rcu(dp, out_port); + +- if (likely(vport && netif_carrier_ok(vport->dev))) { ++ if (likely(vport && ++ netif_running(vport->dev) && ++ netif_carrier_ok(vport->dev))) { + u16 mru = OVS_CB(skb)->mru; + u32 cutlen = OVS_CB(skb)->cutlen; + +diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c +index 6e1cd71d33a599..2050d888df2ae1 100644 +--- a/net/vmw_vsock/af_vsock.c ++++ b/net/vmw_vsock/af_vsock.c +@@ -490,6 +490,15 @@ int vsock_assign_transport(struct vsock_sock *vsk, struct vsock_sock *psk) + */ + vsk->transport->release(vsk); + vsock_deassign_transport(vsk); ++ ++ /* transport's release() and destruct() can touch some socket ++ * state, since we are reassigning the socket to a new transport ++ * during vsock_connect(), let's reset these fields to have a ++ * clean state. ++ */ ++ sock_reset_flag(sk, SOCK_DONE); ++ sk->sk_state = TCP_CLOSE; ++ vsk->peer_shutdown = 0; + } + + /* We increase the module refcnt to prevent the transport unloading +@@ -866,6 +875,9 @@ EXPORT_SYMBOL_GPL(vsock_create_connected); + + s64 vsock_stream_has_data(struct vsock_sock *vsk) + { ++ if (WARN_ON(!vsk->transport)) ++ return 0; ++ + return vsk->transport->stream_has_data(vsk); + } + EXPORT_SYMBOL_GPL(vsock_stream_has_data); +@@ -874,6 +886,9 @@ s64 vsock_connectible_has_data(struct vsock_sock *vsk) + { + struct sock *sk = sk_vsock(vsk); + ++ if (WARN_ON(!vsk->transport)) ++ return 0; ++ + if (sk->sk_type == SOCK_SEQPACKET) + return vsk->transport->seqpacket_has_data(vsk); + else +@@ -883,6 +898,9 @@ EXPORT_SYMBOL_GPL(vsock_connectible_has_data); + + s64 vsock_stream_has_space(struct vsock_sock *vsk) + { ++ if (WARN_ON(!vsk->transport)) ++ return 0; ++ + return vsk->transport->stream_has_space(vsk); + } + EXPORT_SYMBOL_GPL(vsock_stream_has_space); +diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c +index 43495820b64fb1..c57fe7ddcf73bf 100644 +--- a/net/vmw_vsock/virtio_transport_common.c ++++ b/net/vmw_vsock/virtio_transport_common.c +@@ -26,6 +26,9 @@ + /* Threshold for detecting small packets to copy */ + #define GOOD_COPY_LEN 128 + ++static void virtio_transport_cancel_close_work(struct vsock_sock *vsk, ++ bool cancel_timeout); ++ + static const struct virtio_transport * + virtio_transport_get_ops(struct vsock_sock *vsk) + { +@@ -922,6 +925,8 @@ void virtio_transport_destruct(struct vsock_sock *vsk) + { + struct virtio_vsock_sock *vvs = vsk->trans; + ++ virtio_transport_cancel_close_work(vsk, true); ++ + kfree(vvs); + vsk->trans = NULL; + } +@@ -1004,17 +1009,11 @@ static void virtio_transport_wait_close(struct sock *sk, long timeout) + } + } + +-static void virtio_transport_do_close(struct vsock_sock *vsk, +- bool cancel_timeout) ++static void virtio_transport_cancel_close_work(struct vsock_sock *vsk, ++ bool cancel_timeout) + { + struct sock *sk = sk_vsock(vsk); + +- sock_set_flag(sk, SOCK_DONE); +- vsk->peer_shutdown = SHUTDOWN_MASK; +- if (vsock_stream_has_data(vsk) <= 0) +- sk->sk_state = TCP_CLOSING; +- sk->sk_state_change(sk); +- + if (vsk->close_work_scheduled && + (!cancel_timeout || cancel_delayed_work(&vsk->close_work))) { + vsk->close_work_scheduled = false; +@@ -1026,6 +1025,20 @@ static void virtio_transport_do_close(struct vsock_sock *vsk, + } + } + ++static void virtio_transport_do_close(struct vsock_sock *vsk, ++ bool cancel_timeout) ++{ ++ struct sock *sk = sk_vsock(vsk); ++ ++ sock_set_flag(sk, SOCK_DONE); ++ vsk->peer_shutdown = SHUTDOWN_MASK; ++ if (vsock_stream_has_data(vsk) <= 0) ++ sk->sk_state = TCP_CLOSING; ++ sk->sk_state_change(sk); ++ ++ virtio_transport_cancel_close_work(vsk, cancel_timeout); ++} ++ + static void virtio_transport_close_timeout(struct work_struct *work) + { + struct vsock_sock *vsk = +@@ -1428,8 +1441,11 @@ void virtio_transport_recv_pkt(struct virtio_transport *t, + + lock_sock(sk); + +- /* Check if sk has been closed before lock_sock */ +- if (sock_flag(sk, SOCK_DONE)) { ++ /* Check if sk has been closed or assigned to another transport before ++ * lock_sock (note: listener sockets are not assigned to any transport) ++ */ ++ if (sock_flag(sk, SOCK_DONE) || ++ (sk->sk_state != TCP_LISTEN && vsk->transport != &t->transport)) { + (void)virtio_transport_reset_no_sock(t, skb); + release_sock(sk); + sock_put(sk); +diff --git a/net/vmw_vsock/vsock_bpf.c b/net/vmw_vsock/vsock_bpf.c +index 4aa6e74ec2957b..f201d9eca1df2f 100644 +--- a/net/vmw_vsock/vsock_bpf.c ++++ b/net/vmw_vsock/vsock_bpf.c +@@ -77,6 +77,7 @@ static int vsock_bpf_recvmsg(struct sock *sk, struct msghdr *msg, + size_t len, int flags, int *addr_len) + { + struct sk_psock *psock; ++ struct vsock_sock *vsk; + int copied; + + psock = sk_psock_get(sk); +@@ -84,6 +85,13 @@ static int vsock_bpf_recvmsg(struct sock *sk, struct msghdr *msg, + return __vsock_recvmsg(sk, msg, len, flags); + + lock_sock(sk); ++ vsk = vsock_sk(sk); ++ ++ if (!vsk->transport) { ++ copied = -ENODEV; ++ goto out; ++ } ++ + if (vsock_has_data(sk, psock) && sk_psock_queue_empty(psock)) { + release_sock(sk); + sk_psock_put(sk, psock); +@@ -108,6 +116,7 @@ static int vsock_bpf_recvmsg(struct sock *sk, struct msghdr *msg, + copied = sk_msg_recvmsg(sk, psock, msg, len, flags); + } + ++out: + release_sock(sk); + sk_psock_put(sk, psock); + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index fc93af80f0bffe..739f8fd1792bd5 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -10430,6 +10430,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x1d72, 0x1901, "RedmiBook 14", ALC256_FIXUP_ASUS_HEADSET_MIC), + SND_PCI_QUIRK(0x1d72, 0x1945, "Redmi G", ALC256_FIXUP_ASUS_HEADSET_MIC), + SND_PCI_QUIRK(0x1d72, 0x1947, "RedmiBook Air", ALC255_FIXUP_XIAOMI_HEADSET_MIC), ++ SND_PCI_QUIRK(0x1f66, 0x0105, "Ayaneo Portable Game Player", ALC287_FIXUP_CS35L41_I2C_2), + SND_PCI_QUIRK(0x2782, 0x0214, "VAIO VJFE-CL", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), + SND_PCI_QUIRK(0x2782, 0x0228, "Infinix ZERO BOOK 13", ALC269VB_FIXUP_INFINIX_ZERO_BOOK_13), + SND_PCI_QUIRK(0x2782, 0x0232, "CHUWI CoreBook XPro", ALC269VB_FIXUP_CHUWI_COREBOOK_XPRO), +diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.c b/tools/testing/selftests/net/mptcp/mptcp_connect.c +index 4209b95690394b..414addef9a4514 100644 +--- a/tools/testing/selftests/net/mptcp/mptcp_connect.c ++++ b/tools/testing/selftests/net/mptcp/mptcp_connect.c +@@ -25,6 +25,8 @@ + #include + #include + ++#include ++ + #include + #include + +@@ -1211,23 +1213,42 @@ static void parse_setsock_options(const char *name) + exit(1); + } + +-void xdisconnect(int fd, int addrlen) ++void xdisconnect(int fd) + { +- struct sockaddr_storage empty; ++ socklen_t addrlen = sizeof(struct sockaddr_storage); ++ struct sockaddr_storage addr, empty; + int msec_sleep = 10; +- int queued = 1; +- int i; ++ void *raw_addr; ++ int i, cmdlen; ++ char cmd[128]; ++ ++ /* get the local address and convert it to string */ ++ if (getsockname(fd, (struct sockaddr *)&addr, &addrlen) < 0) ++ xerror("getsockname"); ++ ++ if (addr.ss_family == AF_INET) ++ raw_addr = &(((struct sockaddr_in *)&addr)->sin_addr); ++ else if (addr.ss_family == AF_INET6) ++ raw_addr = &(((struct sockaddr_in6 *)&addr)->sin6_addr); ++ else ++ xerror("bad family"); ++ ++ strcpy(cmd, "ss -M | grep -q "); ++ cmdlen = strlen(cmd); ++ if (!inet_ntop(addr.ss_family, raw_addr, &cmd[cmdlen], ++ sizeof(cmd) - cmdlen)) ++ xerror("inet_ntop"); + + shutdown(fd, SHUT_WR); + +- /* while until the pending data is completely flushed, the later ++ /* ++ * wait until the pending data is completely flushed and all ++ * the MPTCP sockets reached the closed status. + * disconnect will bypass/ignore/drop any pending data. + */ + for (i = 0; ; i += msec_sleep) { +- if (ioctl(fd, SIOCOUTQ, &queued) < 0) +- xerror("can't query out socket queue: %d", errno); +- +- if (!queued) ++ /* closed socket are not listed by 'ss' */ ++ if (system(cmd) != 0) + break; + + if (i > poll_timeout) +@@ -1281,9 +1302,9 @@ int main_loop(void) + return ret; + + if (cfg_truncate > 0) { +- xdisconnect(fd, peer->ai_addrlen); ++ xdisconnect(fd); + } else if (--cfg_repeat > 0) { +- xdisconnect(fd, peer->ai_addrlen); ++ xdisconnect(fd); + + /* the socket could be unblocking at this point, we need the + * connect to be blocking +diff --git a/tools/testing/selftests/tc-testing/tc-tests/filters/flow.json b/tools/testing/selftests/tc-testing/tc-tests/filters/flow.json +index 58189327f6444a..383fbda07245c8 100644 +--- a/tools/testing/selftests/tc-testing/tc-tests/filters/flow.json ++++ b/tools/testing/selftests/tc-testing/tc-tests/filters/flow.json +@@ -78,10 +78,10 @@ + "setup": [ + "$TC qdisc add dev $DEV1 ingress" + ], +- "cmdUnderTest": "$TC filter add dev $DEV1 parent ffff: handle 1 prio 1 protocol ip flow map key dst rshift 0xff", ++ "cmdUnderTest": "$TC filter add dev $DEV1 parent ffff: handle 1 prio 1 protocol ip flow map key dst rshift 0x1f", + "expExitCode": "0", + "verifyCmd": "$TC filter get dev $DEV1 parent ffff: handle 1 protocol ip prio 1 flow", +- "matchPattern": "filter parent ffff: protocol ip pref 1 flow chain [0-9]+ handle 0x1 map keys dst rshift 255 baseclass", ++ "matchPattern": "filter parent ffff: protocol ip pref 1 flow chain [0-9]+ handle 0x1 map keys dst rshift 31 baseclass", + "matchCount": "1", + "teardown": [ + "$TC qdisc del dev $DEV1 ingress" diff --git a/patch/kernel/archive/odroidxu4-6.6/patch-6.6.74-75.patch b/patch/kernel/archive/odroidxu4-6.6/patch-6.6.74-75.patch new file mode 100644 index 0000000000..38dace8c9f --- /dev/null +++ b/patch/kernel/archive/odroidxu4-6.6/patch-6.6.74-75.patch @@ -0,0 +1,1630 @@ +diff --git a/Makefile b/Makefile +index b8e5c65910862e..b8041104f248d3 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 6 + PATCHLEVEL = 6 +-SUBLEVEL = 74 ++SUBLEVEL = 75 + EXTRAVERSION = + NAME = Pinguïn Aangedreven + +diff --git a/block/ioctl.c b/block/ioctl.c +index 3786033342848d..231537f79a8cb4 100644 +--- a/block/ioctl.c ++++ b/block/ioctl.c +@@ -115,7 +115,7 @@ static int blk_ioctl_discard(struct block_device *bdev, blk_mode_t mode, + return -EINVAL; + + filemap_invalidate_lock(inode->i_mapping); +- err = truncate_bdev_range(bdev, mode, start, start + len - 1); ++ err = truncate_bdev_range(bdev, mode, start, end - 1); + if (err) + goto fail; + err = blkdev_issue_discard(bdev, start >> 9, len >> 9, GFP_KERNEL); +@@ -127,7 +127,7 @@ static int blk_ioctl_discard(struct block_device *bdev, blk_mode_t mode, + static int blk_ioctl_secure_erase(struct block_device *bdev, blk_mode_t mode, + void __user *argp) + { +- uint64_t start, len; ++ uint64_t start, len, end; + uint64_t range[2]; + int err; + +@@ -142,11 +142,12 @@ static int blk_ioctl_secure_erase(struct block_device *bdev, blk_mode_t mode, + len = range[1]; + if ((start & 511) || (len & 511)) + return -EINVAL; +- if (start + len > bdev_nr_bytes(bdev)) ++ if (check_add_overflow(start, len, &end) || ++ end > bdev_nr_bytes(bdev)) + return -EINVAL; + + filemap_invalidate_lock(bdev->bd_inode->i_mapping); +- err = truncate_bdev_range(bdev, mode, start, start + len - 1); ++ err = truncate_bdev_range(bdev, mode, start, end - 1); + if (!err) + err = blkdev_issue_secure_erase(bdev, start >> 9, len >> 9, + GFP_KERNEL); +diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c +index f1263364fa97fa..86fa5dc7dd99a8 100644 +--- a/drivers/ata/libahci.c ++++ b/drivers/ata/libahci.c +@@ -2082,13 +2082,6 @@ static void ahci_qc_fill_rtf(struct ata_queued_cmd *qc) + struct ahci_port_priv *pp = qc->ap->private_data; + u8 *rx_fis = pp->rx_fis; + +- /* +- * rtf may already be filled (e.g. for successful NCQ commands). +- * If that is the case, we have nothing to do. +- */ +- if (qc->flags & ATA_QCFLAG_RTF_FILLED) +- return; +- + if (pp->fbs_enabled) + rx_fis += qc->dev->link->pmp * AHCI_RX_FIS_SZ; + +@@ -2102,7 +2095,6 @@ static void ahci_qc_fill_rtf(struct ata_queued_cmd *qc) + !(qc->flags & ATA_QCFLAG_EH)) { + ata_tf_from_fis(rx_fis + RX_FIS_PIO_SETUP, &qc->result_tf); + qc->result_tf.status = (rx_fis + RX_FIS_PIO_SETUP)[15]; +- qc->flags |= ATA_QCFLAG_RTF_FILLED; + return; + } + +@@ -2125,12 +2117,10 @@ static void ahci_qc_fill_rtf(struct ata_queued_cmd *qc) + */ + qc->result_tf.status = fis[2]; + qc->result_tf.error = fis[3]; +- qc->flags |= ATA_QCFLAG_RTF_FILLED; + return; + } + + ata_tf_from_fis(rx_fis + RX_FIS_D2H_REG, &qc->result_tf); +- qc->flags |= ATA_QCFLAG_RTF_FILLED; + } + + static void ahci_qc_ncq_fill_rtf(struct ata_port *ap, u64 done_mask) +@@ -2165,6 +2155,7 @@ static void ahci_qc_ncq_fill_rtf(struct ata_port *ap, u64 done_mask) + if (qc && ata_is_ncq(qc->tf.protocol)) { + qc->result_tf.status = status; + qc->result_tf.error = error; ++ qc->result_tf.flags = qc->tf.flags; + qc->flags |= ATA_QCFLAG_RTF_FILLED; + } + done_mask &= ~(1ULL << tag); +@@ -2189,6 +2180,7 @@ static void ahci_qc_ncq_fill_rtf(struct ata_port *ap, u64 done_mask) + fis += RX_FIS_SDB; + qc->result_tf.status = fis[2]; + qc->result_tf.error = fis[3]; ++ qc->result_tf.flags = qc->tf.flags; + qc->flags |= ATA_QCFLAG_RTF_FILLED; + } + done_mask &= ~(1ULL << tag); +diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c +index 4ed90d46a017a8..f627753519b978 100644 +--- a/drivers/ata/libata-core.c ++++ b/drivers/ata/libata-core.c +@@ -4792,8 +4792,16 @@ static void fill_result_tf(struct ata_queued_cmd *qc) + { + struct ata_port *ap = qc->ap; + ++ /* ++ * rtf may already be filled (e.g. for successful NCQ commands). ++ * If that is the case, we have nothing to do. ++ */ ++ if (qc->flags & ATA_QCFLAG_RTF_FILLED) ++ return; ++ + qc->result_tf.flags = qc->tf.flags; + ap->ops->qc_fill_rtf(qc); ++ qc->flags |= ATA_QCFLAG_RTF_FILLED; + } + + static void ata_verify_xfer(struct ata_queued_cmd *qc) +diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c +index cdead37d0823ad..a64baa97e3583d 100644 +--- a/drivers/cpufreq/amd-pstate.c ++++ b/drivers/cpufreq/amd-pstate.c +@@ -579,8 +579,13 @@ static void amd_pstate_adjust_perf(unsigned int cpu, + unsigned long max_perf, min_perf, des_perf, + cap_perf, lowest_nonlinear_perf, max_freq; + struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); +- struct amd_cpudata *cpudata = policy->driver_data; + unsigned int target_freq; ++ struct amd_cpudata *cpudata; ++ ++ if (!policy) ++ return; ++ ++ cpudata = policy->driver_data; + + if (policy->min != cpudata->min_limit_freq || policy->max != cpudata->max_limit_freq) + amd_pstate_update_min_max_limit(policy); +diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c +index 2aa0e01a6891b0..f11b071a896f59 100644 +--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c ++++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c +@@ -63,7 +63,8 @@ void dmub_hw_lock_mgr_inbox0_cmd(struct dc_dmub_srv *dmub_srv, + + bool should_use_dmub_lock(struct dc_link *link) + { +- if (link->psr_settings.psr_version == DC_PSR_VERSION_SU_1) ++ if (link->psr_settings.psr_version == DC_PSR_VERSION_SU_1 || ++ link->psr_settings.psr_version == DC_PSR_VERSION_1) + return true; + return false; + } +diff --git a/drivers/gpu/drm/v3d/v3d_irq.c b/drivers/gpu/drm/v3d/v3d_irq.c +index 76806039691a2c..b2d59a16869728 100644 +--- a/drivers/gpu/drm/v3d/v3d_irq.c ++++ b/drivers/gpu/drm/v3d/v3d_irq.c +@@ -102,8 +102,10 @@ v3d_irq(int irq, void *arg) + to_v3d_fence(v3d->bin_job->base.irq_fence); + + trace_v3d_bcl_irq(&v3d->drm, fence->seqno); +- dma_fence_signal(&fence->base); ++ + v3d->bin_job = NULL; ++ dma_fence_signal(&fence->base); ++ + status = IRQ_HANDLED; + } + +@@ -112,8 +114,10 @@ v3d_irq(int irq, void *arg) + to_v3d_fence(v3d->render_job->base.irq_fence); + + trace_v3d_rcl_irq(&v3d->drm, fence->seqno); +- dma_fence_signal(&fence->base); ++ + v3d->render_job = NULL; ++ dma_fence_signal(&fence->base); ++ + status = IRQ_HANDLED; + } + +@@ -122,8 +126,10 @@ v3d_irq(int irq, void *arg) + to_v3d_fence(v3d->csd_job->base.irq_fence); + + trace_v3d_csd_irq(&v3d->drm, fence->seqno); +- dma_fence_signal(&fence->base); ++ + v3d->csd_job = NULL; ++ dma_fence_signal(&fence->base); ++ + status = IRQ_HANDLED; + } + +@@ -159,8 +165,10 @@ v3d_hub_irq(int irq, void *arg) + to_v3d_fence(v3d->tfu_job->base.irq_fence); + + trace_v3d_tfu_irq(&v3d->drm, fence->seqno); +- dma_fence_signal(&fence->base); ++ + v3d->tfu_job = NULL; ++ dma_fence_signal(&fence->base); ++ + status = IRQ_HANDLED; + } + +diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h +index f16940f3d93d46..1174626904cb02 100644 +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -506,7 +506,6 @@ + #define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_E100 0xe100 + + #define I2C_VENDOR_ID_GOODIX 0x27c6 +-#define I2C_DEVICE_ID_GOODIX_01E0 0x01e0 + #define I2C_DEVICE_ID_GOODIX_01E8 0x01e8 + #define I2C_DEVICE_ID_GOODIX_01E9 0x01e9 + #define I2C_DEVICE_ID_GOODIX_01F0 0x01f0 +diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c +index bf9cad71125923..e62104e1a6038b 100644 +--- a/drivers/hid/hid-multitouch.c ++++ b/drivers/hid/hid-multitouch.c +@@ -1447,8 +1447,7 @@ static __u8 *mt_report_fixup(struct hid_device *hdev, __u8 *rdesc, + { + if (hdev->vendor == I2C_VENDOR_ID_GOODIX && + (hdev->product == I2C_DEVICE_ID_GOODIX_01E8 || +- hdev->product == I2C_DEVICE_ID_GOODIX_01E9 || +- hdev->product == I2C_DEVICE_ID_GOODIX_01E0)) { ++ hdev->product == I2C_DEVICE_ID_GOODIX_01E9)) { + if (rdesc[607] == 0x15) { + rdesc[607] = 0x25; + dev_info( +@@ -2073,10 +2072,7 @@ static const struct hid_device_id mt_devices[] = { + I2C_DEVICE_ID_GOODIX_01E8) }, + { .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT_NSMU, + HID_DEVICE(BUS_I2C, HID_GROUP_ANY, I2C_VENDOR_ID_GOODIX, +- I2C_DEVICE_ID_GOODIX_01E9) }, +- { .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT_NSMU, +- HID_DEVICE(BUS_I2C, HID_GROUP_ANY, I2C_VENDOR_ID_GOODIX, +- I2C_DEVICE_ID_GOODIX_01E0) }, ++ I2C_DEVICE_ID_GOODIX_01E8) }, + + /* GoodTouch panels */ + { .driver_data = MT_CLS_NSMU, +diff --git a/drivers/hwmon/drivetemp.c b/drivers/hwmon/drivetemp.c +index 2a4ec55ddb47ed..291d91f6864676 100644 +--- a/drivers/hwmon/drivetemp.c ++++ b/drivers/hwmon/drivetemp.c +@@ -194,7 +194,7 @@ static int drivetemp_scsi_command(struct drivetemp_data *st, + scsi_cmd[14] = ata_command; + + err = scsi_execute_cmd(st->sdev, scsi_cmd, op, st->smartdata, +- ATA_SECT_SIZE, HZ, 5, NULL); ++ ATA_SECT_SIZE, 10 * HZ, 5, NULL); + if (err > 0) + err = -EIO; + return err; +diff --git a/drivers/infiniband/hw/bnxt_re/main.c b/drivers/infiniband/hw/bnxt_re/main.c +index c7e51cc2ea2687..082a383c4913ec 100644 +--- a/drivers/infiniband/hw/bnxt_re/main.c ++++ b/drivers/infiniband/hw/bnxt_re/main.c +@@ -485,6 +485,8 @@ static void bnxt_re_set_default_pacing_data(struct bnxt_re_dev *rdev) + static void __wait_for_fifo_occupancy_below_th(struct bnxt_re_dev *rdev) + { + u32 read_val, fifo_occup; ++ struct bnxt_qplib_db_pacing_data *pacing_data = rdev->qplib_res.pacing_data; ++ u32 retry_fifo_check = 1000; + + /* loop shouldn't run infintely as the occupancy usually goes + * below pacing algo threshold as soon as pacing kicks in. +@@ -500,6 +502,14 @@ static void __wait_for_fifo_occupancy_below_th(struct bnxt_re_dev *rdev) + + if (fifo_occup < rdev->qplib_res.pacing_data->pacing_th) + break; ++ if (!retry_fifo_check--) { ++ dev_info_once(rdev_to_dev(rdev), ++ "%s: fifo_occup = 0x%xfifo_max_depth = 0x%x pacing_th = 0x%x\n", ++ __func__, fifo_occup, pacing_data->fifo_max_depth, ++ pacing_data->pacing_th); ++ break; ++ } ++ + } + } + +diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c +index 0cfcad8348a6da..198a44c87e8411 100644 +--- a/drivers/input/joystick/xpad.c ++++ b/drivers/input/joystick/xpad.c +@@ -150,6 +150,7 @@ static const struct xpad_device { + { 0x045e, 0x028e, "Microsoft X-Box 360 pad", 0, XTYPE_XBOX360 }, + { 0x045e, 0x028f, "Microsoft X-Box 360 pad v2", 0, XTYPE_XBOX360 }, + { 0x045e, 0x0291, "Xbox 360 Wireless Receiver (XBOX)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W }, ++ { 0x045e, 0x02a9, "Xbox 360 Wireless Receiver (Unofficial)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W }, + { 0x045e, 0x02d1, "Microsoft X-Box One pad", 0, XTYPE_XBOXONE }, + { 0x045e, 0x02dd, "Microsoft X-Box One pad (Firmware 2015)", 0, XTYPE_XBOXONE }, + { 0x045e, 0x02e3, "Microsoft X-Box One Elite pad", MAP_PADDLES, XTYPE_XBOXONE }, +@@ -305,6 +306,7 @@ static const struct xpad_device { + { 0x1689, 0xfe00, "Razer Sabertooth", 0, XTYPE_XBOX360 }, + { 0x17ef, 0x6182, "Lenovo Legion Controller for Windows", 0, XTYPE_XBOX360 }, + { 0x1949, 0x041a, "Amazon Game Controller", 0, XTYPE_XBOX360 }, ++ { 0x1a86, 0xe310, "QH Electronics Controller", 0, XTYPE_XBOX360 }, + { 0x1bad, 0x0002, "Harmonix Rock Band Guitar", 0, XTYPE_XBOX360 }, + { 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x1bad, 0x0130, "Ion Drum Rocker", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, +@@ -372,16 +374,19 @@ static const struct xpad_device { + { 0x294b, 0x3303, "Snakebyte GAMEPAD BASE X", 0, XTYPE_XBOXONE }, + { 0x294b, 0x3404, "Snakebyte GAMEPAD RGB X", 0, XTYPE_XBOXONE }, + { 0x2dc8, 0x2000, "8BitDo Pro 2 Wired Controller fox Xbox", 0, XTYPE_XBOXONE }, +- { 0x2dc8, 0x3106, "8BitDo Pro 2 Wired Controller", 0, XTYPE_XBOX360 }, ++ { 0x2dc8, 0x3106, "8BitDo Ultimate Wireless / Pro 2 Wired Controller", 0, XTYPE_XBOX360 }, + { 0x2dc8, 0x310a, "8BitDo Ultimate 2C Wireless Controller", 0, XTYPE_XBOX360 }, + { 0x2e24, 0x0652, "Hyperkin Duke X-Box One pad", 0, XTYPE_XBOXONE }, + { 0x31e3, 0x1100, "Wooting One", 0, XTYPE_XBOX360 }, + { 0x31e3, 0x1200, "Wooting Two", 0, XTYPE_XBOX360 }, + { 0x31e3, 0x1210, "Wooting Lekker", 0, XTYPE_XBOX360 }, + { 0x31e3, 0x1220, "Wooting Two HE", 0, XTYPE_XBOX360 }, ++ { 0x31e3, 0x1230, "Wooting Two HE (ARM)", 0, XTYPE_XBOX360 }, + { 0x31e3, 0x1300, "Wooting 60HE (AVR)", 0, XTYPE_XBOX360 }, + { 0x31e3, 0x1310, "Wooting 60HE (ARM)", 0, XTYPE_XBOX360 }, + { 0x3285, 0x0607, "Nacon GC-100", 0, XTYPE_XBOX360 }, ++ { 0x3285, 0x0646, "Nacon Pro Compact", 0, XTYPE_XBOXONE }, ++ { 0x3285, 0x0663, "Nacon Evol-X", 0, XTYPE_XBOXONE }, + { 0x3537, 0x1004, "GameSir T4 Kaleid", 0, XTYPE_XBOX360 }, + { 0x3767, 0x0101, "Fanatec Speedster 3 Forceshock Wheel", 0, XTYPE_XBOX }, + { 0xffff, 0xffff, "Chinese-made Xbox Controller", 0, XTYPE_XBOX }, +@@ -513,6 +518,7 @@ static const struct usb_device_id xpad_table[] = { + XPAD_XBOX360_VENDOR(0x1689), /* Razer Onza */ + XPAD_XBOX360_VENDOR(0x17ef), /* Lenovo */ + XPAD_XBOX360_VENDOR(0x1949), /* Amazon controllers */ ++ XPAD_XBOX360_VENDOR(0x1a86), /* QH Electronics */ + XPAD_XBOX360_VENDOR(0x1bad), /* Harmonix Rock Band guitar and drums */ + XPAD_XBOX360_VENDOR(0x20d6), /* PowerA controllers */ + XPAD_XBOXONE_VENDOR(0x20d6), /* PowerA controllers */ +@@ -528,6 +534,7 @@ static const struct usb_device_id xpad_table[] = { + XPAD_XBOX360_VENDOR(0x2f24), /* GameSir controllers */ + XPAD_XBOX360_VENDOR(0x31e3), /* Wooting Keyboards */ + XPAD_XBOX360_VENDOR(0x3285), /* Nacon GC-100 */ ++ XPAD_XBOXONE_VENDOR(0x3285), /* Nacon Evol-X */ + XPAD_XBOX360_VENDOR(0x3537), /* GameSir Controllers */ + XPAD_XBOXONE_VENDOR(0x3537), /* GameSir Controllers */ + { } +diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c +index c229bd6b3f7f2f..aad2d75c036781 100644 +--- a/drivers/input/keyboard/atkbd.c ++++ b/drivers/input/keyboard/atkbd.c +@@ -89,7 +89,7 @@ static const unsigned short atkbd_set2_keycode[ATKBD_KEYMAP_SIZE] = { + 0, 46, 45, 32, 18, 5, 4, 95, 0, 57, 47, 33, 20, 19, 6,183, + 0, 49, 48, 35, 34, 21, 7,184, 0, 0, 50, 36, 22, 8, 9,185, + 0, 51, 37, 23, 24, 11, 10, 0, 0, 52, 53, 38, 39, 25, 12, 0, +- 0, 89, 40, 0, 26, 13, 0, 0, 58, 54, 28, 27, 0, 43, 0, 85, ++ 0, 89, 40, 0, 26, 13, 0,193, 58, 54, 28, 27, 0, 43, 0, 85, + 0, 86, 91, 90, 92, 0, 14, 94, 0, 79,124, 75, 71,121, 0, 0, + 82, 83, 80, 76, 77, 72, 1, 69, 87, 78, 81, 74, 55, 73, 70, 99, + +diff --git a/drivers/irqchip/irq-sunxi-nmi.c b/drivers/irqchip/irq-sunxi-nmi.c +index e760b1278143dd..262b625c30c102 100644 +--- a/drivers/irqchip/irq-sunxi-nmi.c ++++ b/drivers/irqchip/irq-sunxi-nmi.c +@@ -186,7 +186,8 @@ static int __init sunxi_sc_nmi_irq_init(struct device_node *node, + gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit; + gc->chip_types[0].chip.irq_eoi = irq_gc_ack_set_bit; + gc->chip_types[0].chip.irq_set_type = sunxi_sc_nmi_set_type; +- gc->chip_types[0].chip.flags = IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED; ++ gc->chip_types[0].chip.flags = IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED | ++ IRQCHIP_SKIP_SET_WAKE; + gc->chip_types[0].regs.ack = reg_offs->pend; + gc->chip_types[0].regs.mask = reg_offs->enable; + gc->chip_types[0].regs.type = reg_offs->ctrl; +diff --git a/drivers/of/unittest-data/tests-platform.dtsi b/drivers/of/unittest-data/tests-platform.dtsi +index fa39611071b32f..cd310b26b50c81 100644 +--- a/drivers/of/unittest-data/tests-platform.dtsi ++++ b/drivers/of/unittest-data/tests-platform.dtsi +@@ -34,5 +34,18 @@ dev@100 { + }; + }; + }; ++ ++ platform-tests-2 { ++ // No #address-cells or #size-cells ++ node { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ test-device@100 { ++ compatible = "test-sub-device"; ++ reg = <0x100 1>; ++ }; ++ }; ++ }; + }; + }; +diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c +index 7986113adc7d31..3b22c36bfb0b7c 100644 +--- a/drivers/of/unittest.c ++++ b/drivers/of/unittest.c +@@ -1186,6 +1186,7 @@ static void __init of_unittest_bus_3cell_ranges(void) + static void __init of_unittest_reg(void) + { + struct device_node *np; ++ struct resource res; + int ret; + u64 addr, size; + +@@ -1202,6 +1203,19 @@ static void __init of_unittest_reg(void) + np, addr); + + of_node_put(np); ++ ++ np = of_find_node_by_path("/testcase-data/platform-tests-2/node/test-device@100"); ++ if (!np) { ++ pr_err("missing testcase data\n"); ++ return; ++ } ++ ++ ret = of_address_to_resource(np, 0, &res); ++ unittest(ret == -EINVAL, "of_address_to_resource(%pOF) expected error on untranslatable address\n", ++ np); ++ ++ of_node_put(np); ++ + } + + static void __init of_unittest_parse_interrupts(void) +diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c +index 3075b2ddf7a697..deeb657981a690 100644 +--- a/drivers/scsi/scsi_transport_iscsi.c ++++ b/drivers/scsi/scsi_transport_iscsi.c +@@ -4103,7 +4103,7 @@ iscsi_if_rx(struct sk_buff *skb) + } + do { + /* +- * special case for GET_STATS: ++ * special case for GET_STATS, GET_CHAP and GET_HOST_STATS: + * on success - sending reply and stats from + * inside of if_recv_msg(), + * on error - fall through. +@@ -4112,6 +4112,8 @@ iscsi_if_rx(struct sk_buff *skb) + break; + if (ev->type == ISCSI_UEVENT_GET_CHAP && !err) + break; ++ if (ev->type == ISCSI_UEVENT_GET_HOST_STATS && !err) ++ break; + err = iscsi_if_send_reply(portid, nlh->nlmsg_type, + ev, sizeof(*ev)); + if (err == -EAGAIN && --retries < 0) { +diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c +index d0b55c1fa908a5..b3c588b102d900 100644 +--- a/drivers/scsi/storvsc_drv.c ++++ b/drivers/scsi/storvsc_drv.c +@@ -171,6 +171,12 @@ do { \ + dev_warn(&(dev)->device, fmt, ##__VA_ARGS__); \ + } while (0) + ++#define storvsc_log_ratelimited(dev, level, fmt, ...) \ ++do { \ ++ if (do_logging(level)) \ ++ dev_warn_ratelimited(&(dev)->device, fmt, ##__VA_ARGS__); \ ++} while (0) ++ + struct vmscsi_request { + u16 length; + u8 srb_status; +@@ -1177,7 +1183,7 @@ static void storvsc_on_io_completion(struct storvsc_device *stor_device, + int loglevel = (stor_pkt->vm_srb.cdb[0] == TEST_UNIT_READY) ? + STORVSC_LOGGING_WARN : STORVSC_LOGGING_ERROR; + +- storvsc_log(device, loglevel, ++ storvsc_log_ratelimited(device, loglevel, + "tag#%d cmd 0x%x status: scsi 0x%x srb 0x%x hv 0x%x\n", + scsi_cmd_to_rq(request->cmd)->tag, + stor_pkt->vm_srb.cdb[0], +diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c +index fe2737e55f8e89..729b0472bab098 100644 +--- a/drivers/usb/gadget/function/u_serial.c ++++ b/drivers/usb/gadget/function/u_serial.c +@@ -1398,10 +1398,6 @@ void gserial_disconnect(struct gserial *gser) + /* REVISIT as above: how best to track this? */ + port->port_line_coding = gser->port_line_coding; + +- /* disable endpoints, aborting down any active I/O */ +- usb_ep_disable(gser->out); +- usb_ep_disable(gser->in); +- + port->port_usb = NULL; + gser->ioport = NULL; + if (port->port.count > 0) { +@@ -1413,6 +1409,10 @@ void gserial_disconnect(struct gserial *gser) + spin_unlock(&port->port_lock); + spin_unlock_irqrestore(&serial_port_lock, flags); + ++ /* disable endpoints, aborting down any active I/O */ ++ usb_ep_disable(gser->out); ++ usb_ep_disable(gser->in); ++ + /* finally, free any unused/unusable I/O buffers */ + spin_lock_irqsave(&port->port_lock, flags); + if (port->port.count == 0) +diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c +index 821f25e52ec24c..4cde2bd3885f13 100644 +--- a/drivers/usb/serial/quatech2.c ++++ b/drivers/usb/serial/quatech2.c +@@ -503,7 +503,7 @@ static void qt2_process_read_urb(struct urb *urb) + + newport = *(ch + 3); + +- if (newport > serial->num_ports) { ++ if (newport >= serial->num_ports) { + dev_err(&port->dev, + "%s - port change to invalid port: %i\n", + __func__, newport); +diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c +index e53757d1d0958a..3bf1043cd7957c 100644 +--- a/drivers/vfio/platform/vfio_platform_common.c ++++ b/drivers/vfio/platform/vfio_platform_common.c +@@ -388,6 +388,11 @@ static ssize_t vfio_platform_read_mmio(struct vfio_platform_region *reg, + { + unsigned int done = 0; + ++ if (off >= reg->size) ++ return -EINVAL; ++ ++ count = min_t(size_t, count, reg->size - off); ++ + if (!reg->ioaddr) { + reg->ioaddr = + ioremap(reg->addr, reg->size); +@@ -467,6 +472,11 @@ static ssize_t vfio_platform_write_mmio(struct vfio_platform_region *reg, + { + unsigned int done = 0; + ++ if (off >= reg->size) ++ return -EINVAL; ++ ++ count = min_t(size_t, count, reg->size - off); ++ + if (!reg->ioaddr) { + reg->ioaddr = + ioremap(reg->addr, reg->size); +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index 71ced0ada9a2e5..f019ce64eba48e 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -5366,6 +5366,8 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) + INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */ + mutex_init(&sbi->s_orphan_lock); + ++ spin_lock_init(&sbi->s_bdev_wb_lock); ++ + ext4_fast_commit_init(sb); + + sb->s_root = NULL; +@@ -5586,7 +5588,6 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) + * Save the original bdev mapping's wb_err value which could be + * used to detect the metadata async write error. + */ +- spin_lock_init(&sbi->s_bdev_wb_lock); + errseq_check_and_advance(&sb->s_bdev->bd_inode->i_mapping->wb_err, + &sbi->s_bdev_wb_err); + EXT4_SB(sb)->s_mount_state |= EXT4_ORPHAN_FS; +diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c +index 9296e0e282bcd8..2adaffa58e88b4 100644 +--- a/fs/gfs2/file.c ++++ b/fs/gfs2/file.c +@@ -251,6 +251,7 @@ static int do_gfs2_set_flags(struct inode *inode, u32 reqflags, u32 mask) + error = filemap_fdatawait(inode->i_mapping); + if (error) + goto out; ++ truncate_inode_pages(inode->i_mapping, 0); + if (new_flags & GFS2_DIF_JDATA) + gfs2_ordered_del_inode(ip); + } +diff --git a/fs/libfs.c b/fs/libfs.c +index dc0f7519045f11..f5566964aa7d13 100644 +--- a/fs/libfs.c ++++ b/fs/libfs.c +@@ -239,6 +239,18 @@ const struct inode_operations simple_dir_inode_operations = { + }; + EXPORT_SYMBOL(simple_dir_inode_operations); + ++/* simple_offset_add() never assigns these to a dentry */ ++enum { ++ DIR_OFFSET_FIRST = 2, /* Find first real entry */ ++ DIR_OFFSET_EOD = S32_MAX, ++}; ++ ++/* simple_offset_add() allocation range */ ++enum { ++ DIR_OFFSET_MIN = DIR_OFFSET_FIRST + 1, ++ DIR_OFFSET_MAX = DIR_OFFSET_EOD - 1, ++}; ++ + static void offset_set(struct dentry *dentry, u32 offset) + { + dentry->d_fsdata = (void *)((uintptr_t)(offset)); +@@ -260,9 +272,7 @@ void simple_offset_init(struct offset_ctx *octx) + { + xa_init_flags(&octx->xa, XA_FLAGS_ALLOC1); + lockdep_set_class(&octx->xa.xa_lock, &simple_offset_xa_lock); +- +- /* 0 is '.', 1 is '..', so always start with offset 2 */ +- octx->next_offset = 2; ++ octx->next_offset = DIR_OFFSET_MIN; + } + + /** +@@ -275,7 +285,8 @@ void simple_offset_init(struct offset_ctx *octx) + */ + int simple_offset_add(struct offset_ctx *octx, struct dentry *dentry) + { +- static const struct xa_limit limit = XA_LIMIT(2, U32_MAX); ++ static const struct xa_limit limit = XA_LIMIT(DIR_OFFSET_MIN, ++ DIR_OFFSET_MAX); + u32 offset; + int ret; + +@@ -284,9 +295,21 @@ int simple_offset_add(struct offset_ctx *octx, struct dentry *dentry) + + ret = xa_alloc_cyclic(&octx->xa, &offset, dentry, limit, + &octx->next_offset, GFP_KERNEL); +- if (ret < 0) +- return ret; ++ if (unlikely(ret < 0)) ++ return ret == -EBUSY ? -ENOSPC : ret; ++ ++ offset_set(dentry, offset); ++ return 0; ++} + ++static int simple_offset_replace(struct offset_ctx *octx, struct dentry *dentry, ++ long offset) ++{ ++ void *ret; ++ ++ ret = xa_store(&octx->xa, offset, dentry, GFP_KERNEL); ++ if (xa_is_err(ret)) ++ return xa_err(ret); + offset_set(dentry, offset); + return 0; + } +@@ -309,6 +332,36 @@ void simple_offset_remove(struct offset_ctx *octx, struct dentry *dentry) + offset_set(dentry, 0); + } + ++/** ++ * simple_offset_rename - handle directory offsets for rename ++ * @old_dir: parent directory of source entry ++ * @old_dentry: dentry of source entry ++ * @new_dir: parent_directory of destination entry ++ * @new_dentry: dentry of destination ++ * ++ * Caller provides appropriate serialization. ++ * ++ * User space expects the directory offset value of the replaced ++ * (new) directory entry to be unchanged after a rename. ++ * ++ * Returns zero on success, a negative errno value on failure. ++ */ ++int simple_offset_rename(struct inode *old_dir, struct dentry *old_dentry, ++ struct inode *new_dir, struct dentry *new_dentry) ++{ ++ struct offset_ctx *old_ctx = old_dir->i_op->get_offset_ctx(old_dir); ++ struct offset_ctx *new_ctx = new_dir->i_op->get_offset_ctx(new_dir); ++ long new_offset = dentry2offset(new_dentry); ++ ++ simple_offset_remove(old_ctx, old_dentry); ++ ++ if (new_offset) { ++ offset_set(new_dentry, 0); ++ return simple_offset_replace(new_ctx, old_dentry, new_offset); ++ } ++ return simple_offset_add(new_ctx, old_dentry); ++} ++ + /** + * simple_offset_rename_exchange - exchange rename with directory offsets + * @old_dir: parent of dentry being moved +@@ -316,6 +369,9 @@ void simple_offset_remove(struct offset_ctx *octx, struct dentry *dentry) + * @new_dir: destination parent + * @new_dentry: destination dentry + * ++ * This API preserves the directory offset values. Caller provides ++ * appropriate serialization. ++ * + * Returns zero on success. Otherwise a negative errno is returned and the + * rename is rolled back. + */ +@@ -333,11 +389,11 @@ int simple_offset_rename_exchange(struct inode *old_dir, + simple_offset_remove(old_ctx, old_dentry); + simple_offset_remove(new_ctx, new_dentry); + +- ret = simple_offset_add(new_ctx, old_dentry); ++ ret = simple_offset_replace(new_ctx, old_dentry, new_index); + if (ret) + goto out_restore; + +- ret = simple_offset_add(old_ctx, new_dentry); ++ ret = simple_offset_replace(old_ctx, new_dentry, old_index); + if (ret) { + simple_offset_remove(new_ctx, old_dentry); + goto out_restore; +@@ -352,10 +408,8 @@ int simple_offset_rename_exchange(struct inode *old_dir, + return 0; + + out_restore: +- offset_set(old_dentry, old_index); +- xa_store(&old_ctx->xa, old_index, old_dentry, GFP_KERNEL); +- offset_set(new_dentry, new_index); +- xa_store(&new_ctx->xa, new_index, new_dentry, GFP_KERNEL); ++ (void)simple_offset_replace(old_ctx, old_dentry, old_index); ++ (void)simple_offset_replace(new_ctx, new_dentry, new_index); + return ret; + } + +@@ -396,57 +450,91 @@ static loff_t offset_dir_llseek(struct file *file, loff_t offset, int whence) + return -EINVAL; + } + +- /* In this case, ->private_data is protected by f_pos_lock */ +- file->private_data = NULL; + return vfs_setpos(file, offset, U32_MAX); + } + +-static struct dentry *offset_find_next(struct xa_state *xas) ++static struct dentry *find_positive_dentry(struct dentry *parent, ++ struct dentry *dentry, ++ bool next) + { ++ struct dentry *found = NULL; ++ ++ spin_lock(&parent->d_lock); ++ if (next) ++ dentry = list_next_entry(dentry, d_child); ++ else if (!dentry) ++ dentry = list_first_entry_or_null(&parent->d_subdirs, ++ struct dentry, d_child); ++ for (; dentry && !list_entry_is_head(dentry, &parent->d_subdirs, d_child); ++ dentry = list_next_entry(dentry, d_child)) { ++ if (!simple_positive(dentry)) ++ continue; ++ spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); ++ if (simple_positive(dentry)) ++ found = dget_dlock(dentry); ++ spin_unlock(&dentry->d_lock); ++ if (likely(found)) ++ break; ++ } ++ spin_unlock(&parent->d_lock); ++ return found; ++} ++ ++static noinline_for_stack struct dentry * ++offset_dir_lookup(struct dentry *parent, loff_t offset) ++{ ++ struct inode *inode = d_inode(parent); ++ struct offset_ctx *octx = inode->i_op->get_offset_ctx(inode); + struct dentry *child, *found = NULL; + +- rcu_read_lock(); +- child = xas_next_entry(xas, U32_MAX); +- if (!child) +- goto out; +- spin_lock(&child->d_lock); +- if (simple_positive(child)) +- found = dget_dlock(child); +- spin_unlock(&child->d_lock); +-out: +- rcu_read_unlock(); ++ XA_STATE(xas, &octx->xa, offset); ++ ++ if (offset == DIR_OFFSET_FIRST) ++ found = find_positive_dentry(parent, NULL, false); ++ else { ++ rcu_read_lock(); ++ child = xas_next_entry(&xas, DIR_OFFSET_MAX); ++ found = find_positive_dentry(parent, child, false); ++ rcu_read_unlock(); ++ } + return found; + } + + static bool offset_dir_emit(struct dir_context *ctx, struct dentry *dentry) + { +- u32 offset = dentry2offset(dentry); + struct inode *inode = d_inode(dentry); + +- return ctx->actor(ctx, dentry->d_name.name, dentry->d_name.len, offset, +- inode->i_ino, fs_umode_to_dtype(inode->i_mode)); ++ return dir_emit(ctx, dentry->d_name.name, dentry->d_name.len, ++ inode->i_ino, fs_umode_to_dtype(inode->i_mode)); + } + +-static void *offset_iterate_dir(struct inode *inode, struct dir_context *ctx) ++static void offset_iterate_dir(struct file *file, struct dir_context *ctx) + { +- struct offset_ctx *so_ctx = inode->i_op->get_offset_ctx(inode); +- XA_STATE(xas, &so_ctx->xa, ctx->pos); ++ struct dentry *dir = file->f_path.dentry; + struct dentry *dentry; + ++ dentry = offset_dir_lookup(dir, ctx->pos); ++ if (!dentry) ++ goto out_eod; + while (true) { +- dentry = offset_find_next(&xas); +- if (!dentry) +- return ERR_PTR(-ENOENT); ++ struct dentry *next; + +- if (!offset_dir_emit(ctx, dentry)) { +- dput(dentry); ++ ctx->pos = dentry2offset(dentry); ++ if (!offset_dir_emit(ctx, dentry)) + break; +- } + ++ next = find_positive_dentry(dir, dentry, true); + dput(dentry); +- ctx->pos = xas.xa_index + 1; ++ ++ if (!next) ++ goto out_eod; ++ dentry = next; + } +- return NULL; ++ dput(dentry); ++ return; ++ ++out_eod: ++ ctx->pos = DIR_OFFSET_EOD; + } + + /** +@@ -466,6 +554,8 @@ static void *offset_iterate_dir(struct inode *inode, struct dir_context *ctx) + * + * On return, @ctx->pos contains an offset that will read the next entry + * in this directory when offset_readdir() is called again with @ctx. ++ * Caller places this value in the d_off field of the last entry in the ++ * user's buffer. + * + * Return values: + * %0 - Complete +@@ -478,13 +568,8 @@ static int offset_readdir(struct file *file, struct dir_context *ctx) + + if (!dir_emit_dots(file, ctx)) + return 0; +- +- /* In this case, ->private_data is protected by f_pos_lock */ +- if (ctx->pos == 2) +- file->private_data = NULL; +- else if (file->private_data == ERR_PTR(-ENOENT)) +- return 0; +- file->private_data = offset_iterate_dir(d_inode(dir), ctx); ++ if (ctx->pos != DIR_OFFSET_EOD) ++ offset_iterate_dir(file, ctx); + return 0; + } + +diff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c +index e695df1dbb23b2..9ebd7a5ee23c21 100644 +--- a/fs/smb/client/smb2inode.c ++++ b/fs/smb/client/smb2inode.c +@@ -176,27 +176,27 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, + struct kvec *out_iov, int *out_buftype, struct dentry *dentry) + { + +- struct reparse_data_buffer *rbuf; ++ struct smb2_query_info_rsp *qi_rsp = NULL; + struct smb2_compound_vars *vars = NULL; +- struct kvec *rsp_iov, *iov; +- struct smb_rqst *rqst; +- int rc; +- __le16 *utf16_path = NULL; + __u8 oplock = SMB2_OPLOCK_LEVEL_NONE; +- struct cifs_fid fid; ++ struct cifs_open_info_data *idata; + struct cifs_ses *ses = tcon->ses; ++ struct reparse_data_buffer *rbuf; + struct TCP_Server_Info *server; +- int num_rqst = 0, i; + int resp_buftype[MAX_COMPOUND]; +- struct smb2_query_info_rsp *qi_rsp = NULL; +- struct cifs_open_info_data *idata; ++ int retries = 0, cur_sleep = 1; ++ __u8 delete_pending[8] = {1,}; ++ struct kvec *rsp_iov, *iov; + struct inode *inode = NULL; +- int flags = 0; +- __u8 delete_pending[8] = {1, 0, 0, 0, 0, 0, 0, 0}; ++ __le16 *utf16_path = NULL; ++ struct smb_rqst *rqst; + unsigned int size[2]; +- void *data[2]; ++ struct cifs_fid fid; ++ int num_rqst = 0, i; + unsigned int len; +- int retries = 0, cur_sleep = 1; ++ int tmp_rc, rc; ++ int flags = 0; ++ void *data[2]; + + replay_again: + /* reinitialize for possible replay */ +@@ -637,7 +637,14 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, + tcon->need_reconnect = true; + } + ++ tmp_rc = rc; + for (i = 0; i < num_cmds; i++) { ++ char *buf = rsp_iov[i + i].iov_base; ++ ++ if (buf && resp_buftype[i + 1] != CIFS_NO_BUFFER) ++ rc = server->ops->map_error(buf, false); ++ else ++ rc = tmp_rc; + switch (cmds[i]) { + case SMB2_OP_QUERY_INFO: + idata = in_iov[i].iov_base; +@@ -803,6 +810,7 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, + } + } + SMB2_close_free(&rqst[num_rqst]); ++ rc = tmp_rc; + + num_cmds += 2; + if (out_iov && out_buftype) { +@@ -858,22 +866,52 @@ static int parse_create_response(struct cifs_open_info_data *data, + return rc; + } + ++/* Check only if SMB2_OP_QUERY_WSL_EA command failed in the compound chain */ ++static bool ea_unsupported(int *cmds, int num_cmds, ++ struct kvec *out_iov, int *out_buftype) ++{ ++ int i; ++ ++ if (cmds[num_cmds - 1] != SMB2_OP_QUERY_WSL_EA) ++ return false; ++ ++ for (i = 1; i < num_cmds - 1; i++) { ++ struct smb2_hdr *hdr = out_iov[i].iov_base; ++ ++ if (out_buftype[i] == CIFS_NO_BUFFER || !hdr || ++ hdr->Status != STATUS_SUCCESS) ++ return false; ++ } ++ return true; ++} ++ ++static inline void free_rsp_iov(struct kvec *iovs, int *buftype, int count) ++{ ++ int i; ++ ++ for (i = 0; i < count; i++) { ++ free_rsp_buf(buftype[i], iovs[i].iov_base); ++ memset(&iovs[i], 0, sizeof(*iovs)); ++ buftype[i] = CIFS_NO_BUFFER; ++ } ++} ++ + int smb2_query_path_info(const unsigned int xid, + struct cifs_tcon *tcon, + struct cifs_sb_info *cifs_sb, + const char *full_path, + struct cifs_open_info_data *data) + { ++ struct kvec in_iov[3], out_iov[5] = {}; ++ struct cached_fid *cfid = NULL; + struct cifs_open_parms oparms; +- __u32 create_options = 0; + struct cifsFileInfo *cfile; +- struct cached_fid *cfid = NULL; ++ __u32 create_options = 0; ++ int out_buftype[5] = {}; + struct smb2_hdr *hdr; +- struct kvec in_iov[3], out_iov[3] = {}; +- int out_buftype[3] = {}; ++ int num_cmds = 0; + int cmds[3]; + bool islink; +- int i, num_cmds = 0; + int rc, rc2; + + data->adjust_tz = false; +@@ -943,14 +981,14 @@ int smb2_query_path_info(const unsigned int xid, + if (rc || !data->reparse_point) + goto out; + +- if (!tcon->posix_extensions) +- cmds[num_cmds++] = SMB2_OP_QUERY_WSL_EA; + /* + * Skip SMB2_OP_GET_REPARSE if symlink already parsed in create + * response. + */ + if (data->reparse.tag != IO_REPARSE_TAG_SYMLINK) + cmds[num_cmds++] = SMB2_OP_GET_REPARSE; ++ if (!tcon->posix_extensions) ++ cmds[num_cmds++] = SMB2_OP_QUERY_WSL_EA; + + oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, + FILE_READ_ATTRIBUTES | +@@ -958,9 +996,18 @@ int smb2_query_path_info(const unsigned int xid, + FILE_OPEN, create_options | + OPEN_REPARSE_POINT, ACL_NO_MODE); + cifs_get_readable_path(tcon, full_path, &cfile); ++ free_rsp_iov(out_iov, out_buftype, ARRAY_SIZE(out_iov)); + rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, + &oparms, in_iov, cmds, num_cmds, +- cfile, NULL, NULL, NULL); ++ cfile, out_iov, out_buftype, NULL); ++ if (rc && ea_unsupported(cmds, num_cmds, ++ out_iov, out_buftype)) { ++ if (data->reparse.tag != IO_REPARSE_TAG_LX_BLK && ++ data->reparse.tag != IO_REPARSE_TAG_LX_CHR) ++ rc = 0; ++ else ++ rc = -EOPNOTSUPP; ++ } + break; + case -EREMOTE: + break; +@@ -978,8 +1025,7 @@ int smb2_query_path_info(const unsigned int xid, + } + + out: +- for (i = 0; i < ARRAY_SIZE(out_buftype); i++) +- free_rsp_buf(out_buftype[i], out_iov[i].iov_base); ++ free_rsp_iov(out_iov, out_buftype, ARRAY_SIZE(out_iov)); + return rc; + } + +diff --git a/include/linux/fs.h b/include/linux/fs.h +index 6c3d86532e3f91..e47596d354ff75 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -3197,6 +3197,8 @@ struct offset_ctx { + void simple_offset_init(struct offset_ctx *octx); + int simple_offset_add(struct offset_ctx *octx, struct dentry *dentry); + void simple_offset_remove(struct offset_ctx *octx, struct dentry *dentry); ++int simple_offset_rename(struct inode *old_dir, struct dentry *old_dentry, ++ struct inode *new_dir, struct dentry *new_dentry); + int simple_offset_rename_exchange(struct inode *old_dir, + struct dentry *old_dentry, + struct inode *new_dir, +diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h +index 175079552f68da..8cf31bb8871988 100644 +--- a/include/linux/seccomp.h ++++ b/include/linux/seccomp.h +@@ -70,10 +70,10 @@ struct seccomp_data; + + #ifdef CONFIG_HAVE_ARCH_SECCOMP_FILTER + static inline int secure_computing(void) { return 0; } +-static inline int __secure_computing(const struct seccomp_data *sd) { return 0; } + #else + static inline void secure_computing_strict(int this_syscall) { return; } + #endif ++static inline int __secure_computing(const struct seccomp_data *sd) { return 0; } + + static inline long prctl_get_seccomp(void) + { +diff --git a/mm/filemap.c b/mm/filemap.c +index 6a3d62de1cca7b..056422e6a0be8f 100644 +--- a/mm/filemap.c ++++ b/mm/filemap.c +@@ -4270,6 +4270,20 @@ static void filemap_cachestat(struct address_space *mapping, + rcu_read_unlock(); + } + ++/* ++ * See mincore: reveal pagecache information only for files ++ * that the calling process has write access to, or could (if ++ * tried) open for writing. ++ */ ++static inline bool can_do_cachestat(struct file *f) ++{ ++ if (f->f_mode & FMODE_WRITE) ++ return true; ++ if (inode_owner_or_capable(file_mnt_idmap(f), file_inode(f))) ++ return true; ++ return file_permission(f, MAY_WRITE) == 0; ++} ++ + /* + * The cachestat(2) system call. + * +@@ -4329,6 +4343,11 @@ SYSCALL_DEFINE4(cachestat, unsigned int, fd, + return -EOPNOTSUPP; + } + ++ if (!can_do_cachestat(f.file)) { ++ fdput(f); ++ return -EPERM; ++ } ++ + if (flags != 0) { + fdput(f); + return -EINVAL; +diff --git a/mm/shmem.c b/mm/shmem.c +index db7dd45c918158..283fb62084d454 100644 +--- a/mm/shmem.c ++++ b/mm/shmem.c +@@ -3434,8 +3434,7 @@ static int shmem_rename2(struct mnt_idmap *idmap, + return error; + } + +- simple_offset_remove(shmem_get_offset_ctx(old_dir), old_dentry); +- error = simple_offset_add(shmem_get_offset_ctx(new_dir), old_dentry); ++ error = simple_offset_rename(old_dir, old_dentry, new_dir, new_dentry); + if (error) + return error; + +diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c +index dd1803bf9c5c63..b5d64cd3ab0a23 100644 +--- a/net/ipv4/ip_tunnel.c ++++ b/net/ipv4/ip_tunnel.c +@@ -218,7 +218,7 @@ static struct ip_tunnel *ip_tunnel_find(struct ip_tunnel_net *itn, + struct ip_tunnel *t = NULL; + struct hlist_head *head = ip_bucket(itn, parms); + +- hlist_for_each_entry_rcu(t, head, hash_node) { ++ hlist_for_each_entry_rcu(t, head, hash_node, lockdep_rtnl_is_held()) { + if (local == t->parms.iph.saddr && + remote == t->parms.iph.daddr && + link == READ_ONCE(t->parms.link) && +diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c +index afa9073567dc40..023ac39041a214 100644 +--- a/net/ipv6/ip6_fib.c ++++ b/net/ipv6/ip6_fib.c +@@ -1179,8 +1179,8 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt, + while (sibling) { + if (sibling->fib6_metric == rt->fib6_metric && + rt6_qualify_for_ecmp(sibling)) { +- list_add_tail(&rt->fib6_siblings, +- &sibling->fib6_siblings); ++ list_add_tail_rcu(&rt->fib6_siblings, ++ &sibling->fib6_siblings); + break; + } + sibling = rcu_dereference_protected(sibling->fib6_next, +@@ -1241,7 +1241,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt, + fib6_siblings) + sibling->fib6_nsiblings--; + rt->fib6_nsiblings = 0; +- list_del_init(&rt->fib6_siblings); ++ list_del_rcu(&rt->fib6_siblings); + rt6_multipath_rebalance(next_sibling); + return err; + } +@@ -1954,7 +1954,7 @@ static void fib6_del_route(struct fib6_table *table, struct fib6_node *fn, + &rt->fib6_siblings, fib6_siblings) + sibling->fib6_nsiblings--; + rt->fib6_nsiblings = 0; +- list_del_init(&rt->fib6_siblings); ++ list_del_rcu(&rt->fib6_siblings); + rt6_multipath_rebalance(next_sibling); + } + +diff --git a/net/ipv6/route.c b/net/ipv6/route.c +index fc5c5346202530..c5cee40a658b46 100644 +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -418,8 +418,8 @@ void fib6_select_path(const struct net *net, struct fib6_result *res, + struct flowi6 *fl6, int oif, bool have_oif_match, + const struct sk_buff *skb, int strict) + { +- struct fib6_info *sibling, *next_sibling; + struct fib6_info *match = res->f6i; ++ struct fib6_info *sibling; + + if (!match->nh && (!match->fib6_nsiblings || have_oif_match)) + goto out; +@@ -445,8 +445,8 @@ void fib6_select_path(const struct net *net, struct fib6_result *res, + if (fl6->mp_hash <= atomic_read(&match->fib6_nh->fib_nh_upper_bound)) + goto out; + +- list_for_each_entry_safe(sibling, next_sibling, &match->fib6_siblings, +- fib6_siblings) { ++ list_for_each_entry_rcu(sibling, &match->fib6_siblings, ++ fib6_siblings) { + const struct fib6_nh *nh = sibling->fib6_nh; + int nh_upper_bound; + +@@ -5186,14 +5186,18 @@ static void ip6_route_mpath_notify(struct fib6_info *rt, + * nexthop. Since sibling routes are always added at the end of + * the list, find the first sibling of the last route appended + */ ++ rcu_read_lock(); ++ + if ((nlflags & NLM_F_APPEND) && rt_last && rt_last->fib6_nsiblings) { +- rt = list_first_entry(&rt_last->fib6_siblings, +- struct fib6_info, +- fib6_siblings); ++ rt = list_first_or_null_rcu(&rt_last->fib6_siblings, ++ struct fib6_info, ++ fib6_siblings); + } + + if (rt) + inet6_rt_notify(RTM_NEWROUTE, rt, info, nlflags); ++ ++ rcu_read_unlock(); + } + + static bool ip6_route_mpath_should_notify(const struct fib6_info *rt) +@@ -5538,17 +5542,21 @@ static size_t rt6_nlmsg_size(struct fib6_info *f6i) + nexthop_for_each_fib6_nh(f6i->nh, rt6_nh_nlmsg_size, + &nexthop_len); + } else { +- struct fib6_info *sibling, *next_sibling; + struct fib6_nh *nh = f6i->fib6_nh; ++ struct fib6_info *sibling; + + nexthop_len = 0; + if (f6i->fib6_nsiblings) { + rt6_nh_nlmsg_size(nh, &nexthop_len); + +- list_for_each_entry_safe(sibling, next_sibling, +- &f6i->fib6_siblings, fib6_siblings) { ++ rcu_read_lock(); ++ ++ list_for_each_entry_rcu(sibling, &f6i->fib6_siblings, ++ fib6_siblings) { + rt6_nh_nlmsg_size(sibling->fib6_nh, &nexthop_len); + } ++ ++ rcu_read_unlock(); + } + nexthop_len += lwtunnel_get_encap_size(nh->fib_nh_lws); + } +@@ -5712,7 +5720,7 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb, + lwtunnel_fill_encap(skb, dst->lwtstate, RTA_ENCAP, RTA_ENCAP_TYPE) < 0) + goto nla_put_failure; + } else if (rt->fib6_nsiblings) { +- struct fib6_info *sibling, *next_sibling; ++ struct fib6_info *sibling; + struct nlattr *mp; + + mp = nla_nest_start_noflag(skb, RTA_MULTIPATH); +@@ -5724,14 +5732,21 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb, + 0) < 0) + goto nla_put_failure; + +- list_for_each_entry_safe(sibling, next_sibling, +- &rt->fib6_siblings, fib6_siblings) { ++ rcu_read_lock(); ++ ++ list_for_each_entry_rcu(sibling, &rt->fib6_siblings, ++ fib6_siblings) { + if (fib_add_nexthop(skb, &sibling->fib6_nh->nh_common, + sibling->fib6_nh->fib_nh_weight, +- AF_INET6, 0) < 0) ++ AF_INET6, 0) < 0) { ++ rcu_read_unlock(); ++ + goto nla_put_failure; ++ } + } + ++ rcu_read_unlock(); ++ + nla_nest_end(skb, mp); + } else if (rt->nh) { + if (nla_put_u32(skb, RTA_NH_ID, rt->nh->id)) +@@ -6168,7 +6183,7 @@ void inet6_rt_notify(int event, struct fib6_info *rt, struct nl_info *info, + err = -ENOBUFS; + seq = info->nlh ? info->nlh->nlmsg_seq : 0; + +- skb = nlmsg_new(rt6_nlmsg_size(rt), gfp_any()); ++ skb = nlmsg_new(rt6_nlmsg_size(rt), GFP_ATOMIC); + if (!skb) + goto errout; + +@@ -6181,7 +6196,7 @@ void inet6_rt_notify(int event, struct fib6_info *rt, struct nl_info *info, + goto errout; + } + rtnl_notify(skb, net, info->portid, RTNLGRP_IPV6_ROUTE, +- info->nlh, gfp_any()); ++ info->nlh, GFP_ATOMIC); + return; + errout: + if (err < 0) +diff --git a/net/sched/sch_ets.c b/net/sched/sch_ets.c +index b10efeaf0629d2..9fd70462b41d5a 100644 +--- a/net/sched/sch_ets.c ++++ b/net/sched/sch_ets.c +@@ -91,6 +91,8 @@ ets_class_from_arg(struct Qdisc *sch, unsigned long arg) + { + struct ets_sched *q = qdisc_priv(sch); + ++ if (arg == 0 || arg > q->nbands) ++ return NULL; + return &q->classes[arg - 1]; + } + +diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig +index f1e1dbc509f6e4..6d105a23c8284c 100644 +--- a/sound/soc/codecs/Kconfig ++++ b/sound/soc/codecs/Kconfig +@@ -2209,6 +2209,7 @@ config SND_SOC_WM8993 + + config SND_SOC_WM8994 + tristate ++ depends on MFD_WM8994 + + config SND_SOC_WM8995 + tristate +diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig +index 93c2b1b08d0a6f..e8716501685bce 100644 +--- a/sound/soc/samsung/Kconfig ++++ b/sound/soc/samsung/Kconfig +@@ -127,8 +127,9 @@ config SND_SOC_SAMSUNG_TM2_WM5110 + + config SND_SOC_SAMSUNG_ARIES_WM8994 + tristate "SoC I2S Audio support for WM8994 on Aries" +- depends on SND_SOC_SAMSUNG && MFD_WM8994 && IIO && EXTCON ++ depends on SND_SOC_SAMSUNG && I2C && IIO && EXTCON + select SND_SOC_BT_SCO ++ select MFD_WM8994 + select SND_SOC_WM8994 + select SND_SAMSUNG_I2S + help +@@ -140,8 +141,9 @@ config SND_SOC_SAMSUNG_ARIES_WM8994 + + config SND_SOC_SAMSUNG_MIDAS_WM1811 + tristate "SoC I2S Audio support for Midas boards" +- depends on SND_SOC_SAMSUNG ++ depends on SND_SOC_SAMSUNG && I2C + select SND_SAMSUNG_I2S ++ select MFD_WM8994 + select SND_SOC_WM8994 + help + Say Y if you want to add support for SoC audio on the Midas boards. +diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c +index ec81b47c41c9ea..9cdd6cfd8219a7 100644 +--- a/sound/usb/quirks.c ++++ b/sound/usb/quirks.c +@@ -2139,6 +2139,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { + QUIRK_FLAG_CTL_MSG_DELAY_1M), + DEVICE_FLG(0x0c45, 0x6340, /* Sonix HD USB Camera */ + QUIRK_FLAG_GET_SAMPLE_RATE), ++ DEVICE_FLG(0x0d8c, 0x0014, /* USB Audio Device */ ++ QUIRK_FLAG_CTL_MSG_DELAY_1M), + DEVICE_FLG(0x0ecb, 0x205c, /* JBL Quantum610 Wireless */ + QUIRK_FLAG_FIXED_RATE), + DEVICE_FLG(0x0ecb, 0x2069, /* JBL Quantum810 Wireless */ +diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile +index 91a48efb140bef..efaf0e0bc4592b 100644 +--- a/tools/testing/selftests/net/Makefile ++++ b/tools/testing/selftests/net/Makefile +@@ -91,6 +91,7 @@ TEST_PROGS += test_vxlan_mdb.sh + TEST_PROGS += test_bridge_neigh_suppress.sh + TEST_PROGS += test_vxlan_nolocalbypass.sh + TEST_PROGS += test_bridge_backup_port.sh ++TEST_PROGS += ipv6_route_update_soft_lockup.sh + + TEST_FILES := settings + TEST_FILES += in_netns.sh lib.sh net_helper.sh setup_loopback.sh setup_veth.sh +diff --git a/tools/testing/selftests/net/ipv6_route_update_soft_lockup.sh b/tools/testing/selftests/net/ipv6_route_update_soft_lockup.sh +new file mode 100644 +index 00000000000000..a6b2b1f9c641c9 +--- /dev/null ++++ b/tools/testing/selftests/net/ipv6_route_update_soft_lockup.sh +@@ -0,0 +1,262 @@ ++#!/bin/bash ++# SPDX-License-Identifier: GPL-2.0 ++# ++# Testing for potential kernel soft lockup during IPv6 routing table ++# refresh under heavy outgoing IPv6 traffic. If a kernel soft lockup ++# occurs, a kernel panic will be triggered to prevent associated issues. ++# ++# ++# Test Environment Layout ++# ++# ┌----------------┐ ┌----------------┐ ++# | SOURCE_NS | | SINK_NS | ++# | NAMESPACE | | NAMESPACE | ++# |(iperf3 clients)| |(iperf3 servers)| ++# | | | | ++# | | | | ++# | ┌-----------| nexthops |---------┐ | ++# | |veth_source|<--------------------------------------->|veth_sink|<┐ | ++# | └-----------|2001:0DB8:1::0:1/96 2001:0DB8:1::1:1/96 |---------┘ | | ++# | | ^ 2001:0DB8:1::1:2/96 | | | ++# | | . . | fwd | | ++# | ┌---------┐ | . . | | | ++# | | IPv6 | | . . | V | ++# | | routing | | . 2001:0DB8:1::1:80/96| ┌-----┐ | ++# | | table | | . | | lo | | ++# | | nexthop | | . └--------┴-----┴-┘ ++# | | update | | ............................> 2001:0DB8:2::1:1/128 ++# | └-------- ┘ | ++# └----------------┘ ++# ++# The test script sets up two network namespaces, source_ns and sink_ns, ++# connected via a veth link. Within source_ns, it continuously updates the ++# IPv6 routing table by flushing and inserting IPV6_NEXTHOP_ADDR_COUNT nexthop ++# IPs destined for SINK_LOOPBACK_IP_ADDR in sink_ns. This refresh occurs at a ++# rate of 1/ROUTING_TABLE_REFRESH_PERIOD per second for TEST_DURATION seconds. ++# ++# Simultaneously, multiple iperf3 clients within source_ns generate heavy ++# outgoing IPv6 traffic. Each client is assigned a unique port number starting ++# at 5000 and incrementing sequentially. Each client targets a unique iperf3 ++# server running in sink_ns, connected to the SINK_LOOPBACK_IFACE interface ++# using the same port number. ++# ++# The number of iperf3 servers and clients is set to half of the total ++# available cores on each machine. ++# ++# NOTE: We have tested this script on machines with various CPU specifications, ++# ranging from lower to higher performance as listed below. The test script ++# effectively triggered a kernel soft lockup on machines running an unpatched ++# kernel in under a minute: ++# ++# - 1x Intel Xeon E-2278G 8-Core Processor @ 3.40GHz ++# - 1x Intel Xeon E-2378G Processor 8-Core @ 2.80GHz ++# - 1x AMD EPYC 7401P 24-Core Processor @ 2.00GHz ++# - 1x AMD EPYC 7402P 24-Core Processor @ 2.80GHz ++# - 2x Intel Xeon Gold 5120 14-Core Processor @ 2.20GHz ++# - 1x Ampere Altra Q80-30 80-Core Processor @ 3.00GHz ++# - 2x Intel Xeon Gold 5120 14-Core Processor @ 2.20GHz ++# - 2x Intel Xeon Silver 4214 24-Core Processor @ 2.20GHz ++# - 1x AMD EPYC 7502P 32-Core @ 2.50GHz ++# - 1x Intel Xeon Gold 6314U 32-Core Processor @ 2.30GHz ++# - 2x Intel Xeon Gold 6338 32-Core Processor @ 2.00GHz ++# ++# On less performant machines, you may need to increase the TEST_DURATION ++# parameter to enhance the likelihood of encountering a race condition leading ++# to a kernel soft lockup and avoid a false negative result. ++# ++# NOTE: The test may not produce the expected result in virtualized ++# environments (e.g., qemu) due to differences in timing and CPU handling, ++# which can affect the conditions needed to trigger a soft lockup. ++ ++source lib.sh ++source net_helper.sh ++ ++TEST_DURATION=300 ++ROUTING_TABLE_REFRESH_PERIOD=0.01 ++ ++IPERF3_BITRATE="300m" ++ ++ ++IPV6_NEXTHOP_ADDR_COUNT="128" ++IPV6_NEXTHOP_ADDR_MASK="96" ++IPV6_NEXTHOP_PREFIX="2001:0DB8:1" ++ ++ ++SOURCE_TEST_IFACE="veth_source" ++SOURCE_TEST_IP_ADDR="2001:0DB8:1::0:1/96" ++ ++SINK_TEST_IFACE="veth_sink" ++# ${SINK_TEST_IFACE} is populated with the following range of IPv6 addresses: ++# 2001:0DB8:1::1:1 to 2001:0DB8:1::1:${IPV6_NEXTHOP_ADDR_COUNT} ++SINK_LOOPBACK_IFACE="lo" ++SINK_LOOPBACK_IP_MASK="128" ++SINK_LOOPBACK_IP_ADDR="2001:0DB8:2::1:1" ++ ++nexthop_ip_list="" ++termination_signal="" ++kernel_softlokup_panic_prev_val="" ++ ++terminate_ns_processes_by_pattern() { ++ local ns=$1 ++ local pattern=$2 ++ ++ for pid in $(ip netns pids ${ns}); do ++ [ -e /proc/$pid/cmdline ] && grep -qe "${pattern}" /proc/$pid/cmdline && kill -9 $pid ++ done ++} ++ ++cleanup() { ++ echo "info: cleaning up namespaces and terminating all processes within them..." ++ ++ ++ # Terminate iperf3 instances running in the source_ns. To avoid race ++ # conditions, first iterate over the PIDs and terminate those ++ # associated with the bash shells running the ++ # `while true; do iperf3 -c ...; done` loops. In a second iteration, ++ # terminate the individual `iperf3 -c ...` instances. ++ terminate_ns_processes_by_pattern ${source_ns} while ++ terminate_ns_processes_by_pattern ${source_ns} iperf3 ++ ++ # Repeat the same process for sink_ns ++ terminate_ns_processes_by_pattern ${sink_ns} while ++ terminate_ns_processes_by_pattern ${sink_ns} iperf3 ++ ++ # Check if any iperf3 instances are still running. This could happen ++ # if a core has entered an infinite loop and the timeout for detecting ++ # the soft lockup has not expired, but either the test interval has ++ # already elapsed or the test was terminated manually (e.g., with ^C) ++ for pid in $(ip netns pids ${source_ns}); do ++ if [ -e /proc/$pid/cmdline ] && grep -qe 'iperf3' /proc/$pid/cmdline; then ++ echo "FAIL: unable to terminate some iperf3 instances. Soft lockup is underway. A kernel panic is on the way!" ++ exit ${ksft_fail} ++ fi ++ done ++ ++ if [ "$termination_signal" == "SIGINT" ]; then ++ echo "SKIP: Termination due to ^C (SIGINT)" ++ elif [ "$termination_signal" == "SIGALRM" ]; then ++ echo "PASS: No kernel soft lockup occurred during this ${TEST_DURATION} second test" ++ fi ++ ++ cleanup_ns ${source_ns} ${sink_ns} ++ ++ sysctl -qw kernel.softlockup_panic=${kernel_softlokup_panic_prev_val} ++} ++ ++setup_prepare() { ++ setup_ns source_ns sink_ns ++ ++ ip -n ${source_ns} link add name ${SOURCE_TEST_IFACE} type veth peer name ${SINK_TEST_IFACE} netns ${sink_ns} ++ ++ # Setting up the Source namespace ++ ip -n ${source_ns} addr add ${SOURCE_TEST_IP_ADDR} dev ${SOURCE_TEST_IFACE} ++ ip -n ${source_ns} link set dev ${SOURCE_TEST_IFACE} qlen 10000 ++ ip -n ${source_ns} link set dev ${SOURCE_TEST_IFACE} up ++ ip netns exec ${source_ns} sysctl -qw net.ipv6.fib_multipath_hash_policy=1 ++ ++ # Setting up the Sink namespace ++ ip -n ${sink_ns} addr add ${SINK_LOOPBACK_IP_ADDR}/${SINK_LOOPBACK_IP_MASK} dev ${SINK_LOOPBACK_IFACE} ++ ip -n ${sink_ns} link set dev ${SINK_LOOPBACK_IFACE} up ++ ip netns exec ${sink_ns} sysctl -qw net.ipv6.conf.${SINK_LOOPBACK_IFACE}.forwarding=1 ++ ++ ip -n ${sink_ns} link set ${SINK_TEST_IFACE} up ++ ip netns exec ${sink_ns} sysctl -qw net.ipv6.conf.${SINK_TEST_IFACE}.forwarding=1 ++ ++ ++ # Populate nexthop IPv6 addresses on the test interface in the sink_ns ++ echo "info: populating ${IPV6_NEXTHOP_ADDR_COUNT} IPv6 addresses on the ${SINK_TEST_IFACE} interface ..." ++ for IP in $(seq 1 ${IPV6_NEXTHOP_ADDR_COUNT}); do ++ ip -n ${sink_ns} addr add ${IPV6_NEXTHOP_PREFIX}::$(printf "1:%x" "${IP}")/${IPV6_NEXTHOP_ADDR_MASK} dev ${SINK_TEST_IFACE}; ++ done ++ ++ # Preparing list of nexthops ++ for IP in $(seq 1 ${IPV6_NEXTHOP_ADDR_COUNT}); do ++ nexthop_ip_list=$nexthop_ip_list" nexthop via ${IPV6_NEXTHOP_PREFIX}::$(printf "1:%x" $IP) dev ${SOURCE_TEST_IFACE} weight 1" ++ done ++} ++ ++ ++test_soft_lockup_during_routing_table_refresh() { ++ # Start num_of_iperf_servers iperf3 servers in the sink_ns namespace, ++ # each listening on ports starting at 5001 and incrementing ++ # sequentially. Since iperf3 instances may terminate unexpectedly, a ++ # while loop is used to automatically restart them in such cases. ++ echo "info: starting ${num_of_iperf_servers} iperf3 servers in the sink_ns namespace ..." ++ for i in $(seq 1 ${num_of_iperf_servers}); do ++ cmd="iperf3 --bind ${SINK_LOOPBACK_IP_ADDR} -s -p $(printf '5%03d' ${i}) --rcv-timeout 200 &>/dev/null" ++ ip netns exec ${sink_ns} bash -c "while true; do ${cmd}; done &" &>/dev/null ++ done ++ ++ # Wait for the iperf3 servers to be ready ++ for i in $(seq ${num_of_iperf_servers}); do ++ port=$(printf '5%03d' ${i}); ++ wait_local_port_listen ${sink_ns} ${port} tcp ++ done ++ ++ # Continuously refresh the routing table in the background within ++ # the source_ns namespace ++ ip netns exec ${source_ns} bash -c " ++ while \$(ip netns list | grep -q ${source_ns}); do ++ ip -6 route add ${SINK_LOOPBACK_IP_ADDR}/${SINK_LOOPBACK_IP_MASK} ${nexthop_ip_list}; ++ sleep ${ROUTING_TABLE_REFRESH_PERIOD}; ++ ip -6 route delete ${SINK_LOOPBACK_IP_ADDR}/${SINK_LOOPBACK_IP_MASK}; ++ done &" ++ ++ # Start num_of_iperf_servers iperf3 clients in the source_ns namespace, ++ # each sending TCP traffic on sequential ports starting at 5001. ++ # Since iperf3 instances may terminate unexpectedly (e.g., if the route ++ # to the server is deleted in the background during a route refresh), a ++ # while loop is used to automatically restart them in such cases. ++ echo "info: starting ${num_of_iperf_servers} iperf3 clients in the source_ns namespace ..." ++ for i in $(seq 1 ${num_of_iperf_servers}); do ++ cmd="iperf3 -c ${SINK_LOOPBACK_IP_ADDR} -p $(printf '5%03d' ${i}) --length 64 --bitrate ${IPERF3_BITRATE} -t 0 --connect-timeout 150 &>/dev/null" ++ ip netns exec ${source_ns} bash -c "while true; do ${cmd}; done &" &>/dev/null ++ done ++ ++ echo "info: IPv6 routing table is being updated at the rate of $(echo "1/${ROUTING_TABLE_REFRESH_PERIOD}" | bc)/s for ${TEST_DURATION} seconds ..." ++ echo "info: A kernel soft lockup, if detected, results in a kernel panic!" ++ ++ wait ++} ++ ++# Make sure 'iperf3' is installed, skip the test otherwise ++if [ ! -x "$(command -v "iperf3")" ]; then ++ echo "SKIP: 'iperf3' is not installed. Skipping the test." ++ exit ${ksft_skip} ++fi ++ ++# Determine the number of cores on the machine ++num_of_iperf_servers=$(( $(nproc)/2 )) ++ ++# Check if we are running on a multi-core machine, skip the test otherwise ++if [ "${num_of_iperf_servers}" -eq 0 ]; then ++ echo "SKIP: This test is not valid on a single core machine!" ++ exit ${ksft_skip} ++fi ++ ++# Since the kernel soft lockup we're testing causes at least one core to enter ++# an infinite loop, destabilizing the host and likely affecting subsequent ++# tests, we trigger a kernel panic instead of reporting a failure and ++# continuing ++kernel_softlokup_panic_prev_val=$(sysctl -n kernel.softlockup_panic) ++sysctl -qw kernel.softlockup_panic=1 ++ ++handle_sigint() { ++ termination_signal="SIGINT" ++ cleanup ++ exit ${ksft_skip} ++} ++ ++handle_sigalrm() { ++ termination_signal="SIGALRM" ++ cleanup ++ exit ${ksft_pass} ++} ++ ++trap handle_sigint SIGINT ++trap handle_sigalrm SIGALRM ++ ++(sleep ${TEST_DURATION} && kill -s SIGALRM $$)& ++ ++setup_prepare ++test_soft_lockup_during_routing_table_refresh