From: "Mike Pagano" <mpagano@gentoo.org>
To: gentoo-commits@lists.gentoo.org
Subject: [gentoo-commits] proj/linux-patches:6.12 commit in: /
Date: Thu, 19 Dec 2024 18:07:28 +0000 (UTC) [thread overview]
Message-ID: <1734631630.1d0712601fc0cfb16d2abc9bf8d0e34c43b6afe4.mpagano@gentoo> (raw)
commit: 1d0712601fc0cfb16d2abc9bf8d0e34c43b6afe4
Author: Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Thu Dec 19 18:07:10 2024 +0000
Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Thu Dec 19 18:07:10 2024 +0000
URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=1d071260
Linuxpatch 6.12.6
Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org>
0000_README | 4 +
1005_linux-6.12.6.patch | 8402 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 8406 insertions(+)
diff --git a/0000_README b/0000_README
index a2c9782d..1bb8df77 100644
--- a/0000_README
+++ b/0000_README
@@ -63,6 +63,10 @@ Patch: 1004_linux-6.12.5.patch
From: https://www.kernel.org
Desc: Linux 6.12.5
+Patch: 1005_linux-6.12.6.patch
+From: https://www.kernel.org
+Desc: Linux 6.12.6
+
Patch: 1510_fs-enable-link-security-restrictions-by-default.patch
From: http://sources.debian.net/src/linux/3.16.7-ckt4-3/debian/patches/debian/fs-enable-link-security-restrictions-by-default.patch/
Desc: Enable link security restrictions by default.
diff --git a/1005_linux-6.12.6.patch b/1005_linux-6.12.6.patch
new file mode 100644
index 00000000..e9bbd96e
--- /dev/null
+++ b/1005_linux-6.12.6.patch
@@ -0,0 +1,8402 @@
+diff --git a/Documentation/networking/ip-sysctl.rst b/Documentation/networking/ip-sysctl.rst
+index eacf8983e23074..dcbb6f6caf6de3 100644
+--- a/Documentation/networking/ip-sysctl.rst
++++ b/Documentation/networking/ip-sysctl.rst
+@@ -2170,6 +2170,12 @@ nexthop_compat_mode - BOOLEAN
+ understands the new API, this sysctl can be disabled to achieve full
+ performance benefits of the new API by disabling the nexthop expansion
+ and extraneous notifications.
++
++ Note that as a backward-compatible mode, dumping of modern features
++ might be incomplete or wrong. For example, resilient groups will not be
++ shown as such, but rather as just a list of next hops. Also weights that
++ do not fit into 8 bits will show incorrectly.
++
+ Default: true (backward compat mode)
+
+ fib_notify_on_flag_change - INTEGER
+diff --git a/Documentation/power/runtime_pm.rst b/Documentation/power/runtime_pm.rst
+index 53d1996460abfc..12f429359a823e 100644
+--- a/Documentation/power/runtime_pm.rst
++++ b/Documentation/power/runtime_pm.rst
+@@ -347,7 +347,9 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
+
+ `int pm_runtime_resume_and_get(struct device *dev);`
+ - run pm_runtime_resume(dev) and if successful, increment the device's
+- usage counter; return the result of pm_runtime_resume
++ usage counter; returns 0 on success (whether or not the device's
++ runtime PM status was already 'active') or the error code from
++ pm_runtime_resume() on failure.
+
+ `int pm_request_idle(struct device *dev);`
+ - submit a request to execute the subsystem-level idle callback for the
+diff --git a/Makefile b/Makefile
+index f158bfe6407ac9..c10952585c14b0 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ VERSION = 6
+ PATCHLEVEL = 12
+-SUBLEVEL = 5
++SUBLEVEL = 6
+ EXTRAVERSION =
+ NAME = Baby Opossum Posse
+
+diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
+index ff8c4e1b847ed4..fbed433283c9b9 100644
+--- a/arch/arm64/kvm/sys_regs.c
++++ b/arch/arm64/kvm/sys_regs.c
+@@ -1535,6 +1535,7 @@ static u64 __kvm_read_sanitised_id_reg(const struct kvm_vcpu *vcpu,
+ val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_MTEX);
+ val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_DF2);
+ val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_PFAR);
++ val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_MPAM_frac);
+ break;
+ case SYS_ID_AA64PFR2_EL1:
+ /* We only expose FPMR */
+@@ -1724,6 +1725,13 @@ static u64 read_sanitised_id_aa64pfr0_el1(struct kvm_vcpu *vcpu,
+
+ val &= ~ID_AA64PFR0_EL1_AMU_MASK;
+
++ /*
++ * MPAM is disabled by default as KVM also needs a set of PARTID to
++ * program the MPAMVPMx_EL2 PARTID remapping registers with. But some
++ * older kernels let the guest see the ID bit.
++ */
++ val &= ~ID_AA64PFR0_EL1_MPAM_MASK;
++
+ return val;
+ }
+
+@@ -1834,6 +1842,42 @@ static int set_id_dfr0_el1(struct kvm_vcpu *vcpu,
+ return set_id_reg(vcpu, rd, val);
+ }
+
++static int set_id_aa64pfr0_el1(struct kvm_vcpu *vcpu,
++ const struct sys_reg_desc *rd, u64 user_val)
++{
++ u64 hw_val = read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1);
++ u64 mpam_mask = ID_AA64PFR0_EL1_MPAM_MASK;
++
++ /*
++ * Commit 011e5f5bf529f ("arm64/cpufeature: Add remaining feature bits
++ * in ID_AA64PFR0 register") exposed the MPAM field of AA64PFR0_EL1 to
++ * guests, but didn't add trap handling. KVM doesn't support MPAM and
++ * always returns an UNDEF for these registers. The guest must see 0
++ * for this field.
++ *
++ * But KVM must also accept values from user-space that were provided
++ * by KVM. On CPUs that support MPAM, permit user-space to write
++ * the sanitizied value to ID_AA64PFR0_EL1.MPAM, but ignore this field.
++ */
++ if ((hw_val & mpam_mask) == (user_val & mpam_mask))
++ user_val &= ~ID_AA64PFR0_EL1_MPAM_MASK;
++
++ return set_id_reg(vcpu, rd, user_val);
++}
++
++static int set_id_aa64pfr1_el1(struct kvm_vcpu *vcpu,
++ const struct sys_reg_desc *rd, u64 user_val)
++{
++ u64 hw_val = read_sanitised_ftr_reg(SYS_ID_AA64PFR1_EL1);
++ u64 mpam_mask = ID_AA64PFR1_EL1_MPAM_frac_MASK;
++
++ /* See set_id_aa64pfr0_el1 for comment about MPAM */
++ if ((hw_val & mpam_mask) == (user_val & mpam_mask))
++ user_val &= ~ID_AA64PFR1_EL1_MPAM_frac_MASK;
++
++ return set_id_reg(vcpu, rd, user_val);
++}
++
+ /*
+ * cpufeature ID register user accessors
+ *
+@@ -2377,7 +2421,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
+ { SYS_DESC(SYS_ID_AA64PFR0_EL1),
+ .access = access_id_reg,
+ .get_user = get_id_reg,
+- .set_user = set_id_reg,
++ .set_user = set_id_aa64pfr0_el1,
+ .reset = read_sanitised_id_aa64pfr0_el1,
+ .val = ~(ID_AA64PFR0_EL1_AMU |
+ ID_AA64PFR0_EL1_MPAM |
+@@ -2385,7 +2429,12 @@ static const struct sys_reg_desc sys_reg_descs[] = {
+ ID_AA64PFR0_EL1_RAS |
+ ID_AA64PFR0_EL1_AdvSIMD |
+ ID_AA64PFR0_EL1_FP), },
+- ID_WRITABLE(ID_AA64PFR1_EL1, ~(ID_AA64PFR1_EL1_PFAR |
++ { SYS_DESC(SYS_ID_AA64PFR1_EL1),
++ .access = access_id_reg,
++ .get_user = get_id_reg,
++ .set_user = set_id_aa64pfr1_el1,
++ .reset = kvm_read_sanitised_id_reg,
++ .val = ~(ID_AA64PFR1_EL1_PFAR |
+ ID_AA64PFR1_EL1_DF2 |
+ ID_AA64PFR1_EL1_MTEX |
+ ID_AA64PFR1_EL1_THE |
+@@ -2397,7 +2446,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
+ ID_AA64PFR1_EL1_RES0 |
+ ID_AA64PFR1_EL1_MPAM_frac |
+ ID_AA64PFR1_EL1_RAS_frac |
+- ID_AA64PFR1_EL1_MTE)),
++ ID_AA64PFR1_EL1_MTE), },
+ ID_WRITABLE(ID_AA64PFR2_EL1, ID_AA64PFR2_EL1_FPMR),
+ ID_UNALLOCATED(4,3),
+ ID_WRITABLE(ID_AA64ZFR0_EL1, ~ID_AA64ZFR0_EL1_RES0),
+diff --git a/arch/riscv/include/asm/kfence.h b/arch/riscv/include/asm/kfence.h
+index 7388edd88986f9..d08bf7fb3aee61 100644
+--- a/arch/riscv/include/asm/kfence.h
++++ b/arch/riscv/include/asm/kfence.h
+@@ -22,7 +22,9 @@ static inline bool kfence_protect_page(unsigned long addr, bool protect)
+ else
+ set_pte(pte, __pte(pte_val(ptep_get(pte)) | _PAGE_PRESENT));
+
+- flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
++ preempt_disable();
++ local_flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
++ preempt_enable();
+
+ return true;
+ }
+diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c
+index 26c886db4fb3d1..2b3c152d3c91f5 100644
+--- a/arch/riscv/kernel/setup.c
++++ b/arch/riscv/kernel/setup.c
+@@ -227,7 +227,7 @@ static void __init init_resources(void)
+ static void __init parse_dtb(void)
+ {
+ /* Early scan of device tree from init memory */
+- if (early_init_dt_scan(dtb_early_va, __pa(dtb_early_va))) {
++ if (early_init_dt_scan(dtb_early_va, dtb_early_pa)) {
+ const char *name = of_flat_dt_get_machine_name();
+
+ if (name) {
+diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
+index 0e8c20adcd98df..fc53ce748c8049 100644
+--- a/arch/riscv/mm/init.c
++++ b/arch/riscv/mm/init.c
+@@ -1566,7 +1566,7 @@ static void __meminit free_pte_table(pte_t *pte_start, pmd_t *pmd)
+ pmd_clear(pmd);
+ }
+
+-static void __meminit free_pmd_table(pmd_t *pmd_start, pud_t *pud)
++static void __meminit free_pmd_table(pmd_t *pmd_start, pud_t *pud, bool is_vmemmap)
+ {
+ struct page *page = pud_page(*pud);
+ struct ptdesc *ptdesc = page_ptdesc(page);
+@@ -1579,7 +1579,8 @@ static void __meminit free_pmd_table(pmd_t *pmd_start, pud_t *pud)
+ return;
+ }
+
+- pagetable_pmd_dtor(ptdesc);
++ if (!is_vmemmap)
++ pagetable_pmd_dtor(ptdesc);
+ if (PageReserved(page))
+ free_reserved_page(page);
+ else
+@@ -1703,7 +1704,7 @@ static void __meminit remove_pud_mapping(pud_t *pud_base, unsigned long addr, un
+ remove_pmd_mapping(pmd_base, addr, next, is_vmemmap, altmap);
+
+ if (pgtable_l4_enabled)
+- free_pmd_table(pmd_base, pudp);
++ free_pmd_table(pmd_base, pudp, is_vmemmap);
+ }
+ }
+
+diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c
+index fa5ea65de0d0fa..6188650707ab27 100644
+--- a/arch/x86/events/intel/ds.c
++++ b/arch/x86/events/intel/ds.c
+@@ -1468,7 +1468,7 @@ void intel_pmu_pebs_enable(struct perf_event *event)
+ * hence we need to drain when changing said
+ * size.
+ */
+- intel_pmu_drain_large_pebs(cpuc);
++ intel_pmu_drain_pebs_buffer();
+ adaptive_pebs_record_size_update();
+ wrmsrl(MSR_PEBS_DATA_CFG, pebs_data_cfg);
+ cpuc->active_pebs_data_cfg = pebs_data_cfg;
+diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
+index 4a686f0e5dbf6d..2d776635aa539e 100644
+--- a/arch/x86/include/asm/processor.h
++++ b/arch/x86/include/asm/processor.h
+@@ -212,6 +212,8 @@ static inline unsigned long long l1tf_pfn_limit(void)
+ return BIT_ULL(boot_cpu_data.x86_cache_bits - 1 - PAGE_SHIFT);
+ }
+
++void init_cpu_devs(void);
++void get_cpu_vendor(struct cpuinfo_x86 *c);
+ extern void early_cpu_init(void);
+ extern void identify_secondary_cpu(struct cpuinfo_x86 *);
+ extern void print_cpu_info(struct cpuinfo_x86 *);
+diff --git a/arch/x86/include/asm/static_call.h b/arch/x86/include/asm/static_call.h
+index 125c407e2abe6d..41502bd2afd646 100644
+--- a/arch/x86/include/asm/static_call.h
++++ b/arch/x86/include/asm/static_call.h
+@@ -65,4 +65,19 @@
+
+ extern bool __static_call_fixup(void *tramp, u8 op, void *dest);
+
++extern void __static_call_update_early(void *tramp, void *func);
++
++#define static_call_update_early(name, _func) \
++({ \
++ typeof(&STATIC_CALL_TRAMP(name)) __F = (_func); \
++ if (static_call_initialized) { \
++ __static_call_update(&STATIC_CALL_KEY(name), \
++ STATIC_CALL_TRAMP_ADDR(name), __F);\
++ } else { \
++ WRITE_ONCE(STATIC_CALL_KEY(name).func, _func); \
++ __static_call_update_early(STATIC_CALL_TRAMP_ADDR(name),\
++ __F); \
++ } \
++})
++
+ #endif /* _ASM_STATIC_CALL_H */
+diff --git a/arch/x86/include/asm/sync_core.h b/arch/x86/include/asm/sync_core.h
+index ab7382f92aff27..96bda43538ee70 100644
+--- a/arch/x86/include/asm/sync_core.h
++++ b/arch/x86/include/asm/sync_core.h
+@@ -8,7 +8,7 @@
+ #include <asm/special_insns.h>
+
+ #ifdef CONFIG_X86_32
+-static inline void iret_to_self(void)
++static __always_inline void iret_to_self(void)
+ {
+ asm volatile (
+ "pushfl\n\t"
+@@ -19,7 +19,7 @@ static inline void iret_to_self(void)
+ : ASM_CALL_CONSTRAINT : : "memory");
+ }
+ #else
+-static inline void iret_to_self(void)
++static __always_inline void iret_to_self(void)
+ {
+ unsigned int tmp;
+
+@@ -55,7 +55,7 @@ static inline void iret_to_self(void)
+ * Like all of Linux's memory ordering operations, this is a
+ * compiler barrier as well.
+ */
+-static inline void sync_core(void)
++static __always_inline void sync_core(void)
+ {
+ /*
+ * The SERIALIZE instruction is the most straightforward way to
+diff --git a/arch/x86/include/asm/xen/hypercall.h b/arch/x86/include/asm/xen/hypercall.h
+index a2dd24947eb85a..97771b9d33af30 100644
+--- a/arch/x86/include/asm/xen/hypercall.h
++++ b/arch/x86/include/asm/xen/hypercall.h
+@@ -39,9 +39,11 @@
+ #include <linux/string.h>
+ #include <linux/types.h>
+ #include <linux/pgtable.h>
++#include <linux/instrumentation.h>
+
+ #include <trace/events/xen.h>
+
++#include <asm/alternative.h>
+ #include <asm/page.h>
+ #include <asm/smap.h>
+ #include <asm/nospec-branch.h>
+@@ -86,11 +88,20 @@ struct xen_dm_op_buf;
+ * there aren't more than 5 arguments...)
+ */
+
+-extern struct { char _entry[32]; } hypercall_page[];
++void xen_hypercall_func(void);
++DECLARE_STATIC_CALL(xen_hypercall, xen_hypercall_func);
+
+-#define __HYPERCALL "call hypercall_page+%c[offset]"
+-#define __HYPERCALL_ENTRY(x) \
+- [offset] "i" (__HYPERVISOR_##x * sizeof(hypercall_page[0]))
++#ifdef MODULE
++#define __ADDRESSABLE_xen_hypercall
++#else
++#define __ADDRESSABLE_xen_hypercall __ADDRESSABLE_ASM_STR(__SCK__xen_hypercall)
++#endif
++
++#define __HYPERCALL \
++ __ADDRESSABLE_xen_hypercall \
++ "call __SCT__xen_hypercall"
++
++#define __HYPERCALL_ENTRY(x) "a" (x)
+
+ #ifdef CONFIG_X86_32
+ #define __HYPERCALL_RETREG "eax"
+@@ -148,7 +159,7 @@ extern struct { char _entry[32]; } hypercall_page[];
+ __HYPERCALL_0ARG(); \
+ asm volatile (__HYPERCALL \
+ : __HYPERCALL_0PARAM \
+- : __HYPERCALL_ENTRY(name) \
++ : __HYPERCALL_ENTRY(__HYPERVISOR_ ## name) \
+ : __HYPERCALL_CLOBBER0); \
+ (type)__res; \
+ })
+@@ -159,7 +170,7 @@ extern struct { char _entry[32]; } hypercall_page[];
+ __HYPERCALL_1ARG(a1); \
+ asm volatile (__HYPERCALL \
+ : __HYPERCALL_1PARAM \
+- : __HYPERCALL_ENTRY(name) \
++ : __HYPERCALL_ENTRY(__HYPERVISOR_ ## name) \
+ : __HYPERCALL_CLOBBER1); \
+ (type)__res; \
+ })
+@@ -170,7 +181,7 @@ extern struct { char _entry[32]; } hypercall_page[];
+ __HYPERCALL_2ARG(a1, a2); \
+ asm volatile (__HYPERCALL \
+ : __HYPERCALL_2PARAM \
+- : __HYPERCALL_ENTRY(name) \
++ : __HYPERCALL_ENTRY(__HYPERVISOR_ ## name) \
+ : __HYPERCALL_CLOBBER2); \
+ (type)__res; \
+ })
+@@ -181,7 +192,7 @@ extern struct { char _entry[32]; } hypercall_page[];
+ __HYPERCALL_3ARG(a1, a2, a3); \
+ asm volatile (__HYPERCALL \
+ : __HYPERCALL_3PARAM \
+- : __HYPERCALL_ENTRY(name) \
++ : __HYPERCALL_ENTRY(__HYPERVISOR_ ## name) \
+ : __HYPERCALL_CLOBBER3); \
+ (type)__res; \
+ })
+@@ -192,7 +203,7 @@ extern struct { char _entry[32]; } hypercall_page[];
+ __HYPERCALL_4ARG(a1, a2, a3, a4); \
+ asm volatile (__HYPERCALL \
+ : __HYPERCALL_4PARAM \
+- : __HYPERCALL_ENTRY(name) \
++ : __HYPERCALL_ENTRY(__HYPERVISOR_ ## name) \
+ : __HYPERCALL_CLOBBER4); \
+ (type)__res; \
+ })
+@@ -206,12 +217,9 @@ xen_single_call(unsigned int call,
+ __HYPERCALL_DECLS;
+ __HYPERCALL_5ARG(a1, a2, a3, a4, a5);
+
+- if (call >= PAGE_SIZE / sizeof(hypercall_page[0]))
+- return -EINVAL;
+-
+- asm volatile(CALL_NOSPEC
++ asm volatile(__HYPERCALL
+ : __HYPERCALL_5PARAM
+- : [thunk_target] "a" (&hypercall_page[call])
++ : __HYPERCALL_ENTRY(call)
+ : __HYPERCALL_CLOBBER5);
+
+ return (long)__res;
+diff --git a/arch/x86/kernel/callthunks.c b/arch/x86/kernel/callthunks.c
+index 4656474567533b..f17d166078823c 100644
+--- a/arch/x86/kernel/callthunks.c
++++ b/arch/x86/kernel/callthunks.c
+@@ -142,11 +142,6 @@ static bool skip_addr(void *dest)
+ if (dest >= (void *)relocate_kernel &&
+ dest < (void*)relocate_kernel + KEXEC_CONTROL_CODE_MAX_SIZE)
+ return true;
+-#endif
+-#ifdef CONFIG_XEN
+- if (dest >= (void *)hypercall_page &&
+- dest < (void*)hypercall_page + PAGE_SIZE)
+- return true;
+ #endif
+ return false;
+ }
+diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
+index b17bcf9b67eed4..f439763f45ae6f 100644
+--- a/arch/x86/kernel/cpu/common.c
++++ b/arch/x86/kernel/cpu/common.c
+@@ -868,7 +868,7 @@ static void cpu_detect_tlb(struct cpuinfo_x86 *c)
+ tlb_lld_4m[ENTRIES], tlb_lld_1g[ENTRIES]);
+ }
+
+-static void get_cpu_vendor(struct cpuinfo_x86 *c)
++void get_cpu_vendor(struct cpuinfo_x86 *c)
+ {
+ char *v = c->x86_vendor_id;
+ int i;
+@@ -1652,15 +1652,11 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)
+ detect_nopl();
+ }
+
+-void __init early_cpu_init(void)
++void __init init_cpu_devs(void)
+ {
+ const struct cpu_dev *const *cdev;
+ int count = 0;
+
+-#ifdef CONFIG_PROCESSOR_SELECT
+- pr_info("KERNEL supported cpus:\n");
+-#endif
+-
+ for (cdev = __x86_cpu_dev_start; cdev < __x86_cpu_dev_end; cdev++) {
+ const struct cpu_dev *cpudev = *cdev;
+
+@@ -1668,20 +1664,30 @@ void __init early_cpu_init(void)
+ break;
+ cpu_devs[count] = cpudev;
+ count++;
++ }
++}
+
++void __init early_cpu_init(void)
++{
+ #ifdef CONFIG_PROCESSOR_SELECT
+- {
+- unsigned int j;
+-
+- for (j = 0; j < 2; j++) {
+- if (!cpudev->c_ident[j])
+- continue;
+- pr_info(" %s %s\n", cpudev->c_vendor,
+- cpudev->c_ident[j]);
+- }
+- }
++ unsigned int i, j;
++
++ pr_info("KERNEL supported cpus:\n");
+ #endif
++
++ init_cpu_devs();
++
++#ifdef CONFIG_PROCESSOR_SELECT
++ for (i = 0; i < X86_VENDOR_NUM && cpu_devs[i]; i++) {
++ for (j = 0; j < 2; j++) {
++ if (!cpu_devs[i]->c_ident[j])
++ continue;
++ pr_info(" %s %s\n", cpu_devs[i]->c_vendor,
++ cpu_devs[i]->c_ident[j]);
++ }
+ }
++#endif
++
+ early_identify_cpu(&boot_cpu_data);
+ }
+
+diff --git a/arch/x86/kernel/static_call.c b/arch/x86/kernel/static_call.c
+index 4eefaac64c6cba..9eed0c144dad51 100644
+--- a/arch/x86/kernel/static_call.c
++++ b/arch/x86/kernel/static_call.c
+@@ -172,6 +172,15 @@ void arch_static_call_transform(void *site, void *tramp, void *func, bool tail)
+ }
+ EXPORT_SYMBOL_GPL(arch_static_call_transform);
+
++noinstr void __static_call_update_early(void *tramp, void *func)
++{
++ BUG_ON(system_state != SYSTEM_BOOTING);
++ BUG_ON(!early_boot_irqs_disabled);
++ BUG_ON(static_call_initialized);
++ __text_gen_insn(tramp, JMP32_INSN_OPCODE, tramp, func, JMP32_INSN_SIZE);
++ sync_core();
++}
++
+ #ifdef CONFIG_MITIGATION_RETHUNK
+ /*
+ * This is called by apply_returns() to fix up static call trampolines,
+diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
+index 84e5adbd0925cb..b4f3784f27e956 100644
+--- a/arch/x86/xen/enlighten.c
++++ b/arch/x86/xen/enlighten.c
+@@ -2,6 +2,7 @@
+
+ #include <linux/console.h>
+ #include <linux/cpu.h>
++#include <linux/instrumentation.h>
+ #include <linux/kexec.h>
+ #include <linux/memblock.h>
+ #include <linux/slab.h>
+@@ -21,7 +22,8 @@
+
+ #include "xen-ops.h"
+
+-EXPORT_SYMBOL_GPL(hypercall_page);
++DEFINE_STATIC_CALL(xen_hypercall, xen_hypercall_hvm);
++EXPORT_STATIC_CALL_TRAMP(xen_hypercall);
+
+ /*
+ * Pointer to the xen_vcpu_info structure or
+@@ -68,6 +70,66 @@ EXPORT_SYMBOL(xen_start_flags);
+ */
+ struct shared_info *HYPERVISOR_shared_info = &xen_dummy_shared_info;
+
++static __ref void xen_get_vendor(void)
++{
++ init_cpu_devs();
++ cpu_detect(&boot_cpu_data);
++ get_cpu_vendor(&boot_cpu_data);
++}
++
++void xen_hypercall_setfunc(void)
++{
++ if (static_call_query(xen_hypercall) != xen_hypercall_hvm)
++ return;
++
++ if ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD ||
++ boot_cpu_data.x86_vendor == X86_VENDOR_HYGON))
++ static_call_update(xen_hypercall, xen_hypercall_amd);
++ else
++ static_call_update(xen_hypercall, xen_hypercall_intel);
++}
++
++/*
++ * Evaluate processor vendor in order to select the correct hypercall
++ * function for HVM/PVH guests.
++ * Might be called very early in boot before vendor has been set by
++ * early_cpu_init().
++ */
++noinstr void *__xen_hypercall_setfunc(void)
++{
++ void (*func)(void);
++
++ /*
++ * Xen is supported only on CPUs with CPUID, so testing for
++ * X86_FEATURE_CPUID is a test for early_cpu_init() having been
++ * run.
++ *
++ * Note that __xen_hypercall_setfunc() is noinstr only due to a nasty
++ * dependency chain: it is being called via the xen_hypercall static
++ * call when running as a PVH or HVM guest. Hypercalls need to be
++ * noinstr due to PV guests using hypercalls in noinstr code. So we
++ * the PV guest requirement is not of interest here (xen_get_vendor()
++ * calls noinstr functions, and static_call_update_early() might do
++ * so, too).
++ */
++ instrumentation_begin();
++
++ if (!boot_cpu_has(X86_FEATURE_CPUID))
++ xen_get_vendor();
++
++ if ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD ||
++ boot_cpu_data.x86_vendor == X86_VENDOR_HYGON))
++ func = xen_hypercall_amd;
++ else
++ func = xen_hypercall_intel;
++
++ static_call_update_early(xen_hypercall, func);
++
++ instrumentation_end();
++
++ return func;
++}
++
+ static int xen_cpu_up_online(unsigned int cpu)
+ {
+ xen_init_lock_cpu(cpu);
+diff --git a/arch/x86/xen/enlighten_hvm.c b/arch/x86/xen/enlighten_hvm.c
+index 24d2957a4726d8..fe57ff85d004ba 100644
+--- a/arch/x86/xen/enlighten_hvm.c
++++ b/arch/x86/xen/enlighten_hvm.c
+@@ -106,15 +106,8 @@ static void __init init_hvm_pv_info(void)
+ /* PVH set up hypercall page in xen_prepare_pvh(). */
+ if (xen_pvh_domain())
+ pv_info.name = "Xen PVH";
+- else {
+- u64 pfn;
+- uint32_t msr;
+-
++ else
+ pv_info.name = "Xen HVM";
+- msr = cpuid_ebx(base + 2);
+- pfn = __pa(hypercall_page);
+- wrmsr_safe(msr, (u32)pfn, (u32)(pfn >> 32));
+- }
+
+ xen_setup_features();
+
+@@ -300,6 +293,10 @@ static uint32_t __init xen_platform_hvm(void)
+ if (xen_pv_domain())
+ return 0;
+
++ /* Set correct hypercall function. */
++ if (xen_domain)
++ xen_hypercall_setfunc();
++
+ if (xen_pvh_domain() && nopv) {
+ /* Guest booting via the Xen-PVH boot entry goes here */
+ pr_info("\"nopv\" parameter is ignored in PVH guest\n");
+diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
+index d6818c6cafda16..a8eb7e0c473cf6 100644
+--- a/arch/x86/xen/enlighten_pv.c
++++ b/arch/x86/xen/enlighten_pv.c
+@@ -1341,6 +1341,9 @@ asmlinkage __visible void __init xen_start_kernel(struct start_info *si)
+
+ xen_domain_type = XEN_PV_DOMAIN;
+ xen_start_flags = xen_start_info->flags;
++ /* Interrupts are guaranteed to be off initially. */
++ early_boot_irqs_disabled = true;
++ static_call_update_early(xen_hypercall, xen_hypercall_pv);
+
+ xen_setup_features();
+
+@@ -1431,7 +1434,6 @@ asmlinkage __visible void __init xen_start_kernel(struct start_info *si)
+ WARN_ON(xen_cpuhp_setup(xen_cpu_up_prepare_pv, xen_cpu_dead_pv));
+
+ local_irq_disable();
+- early_boot_irqs_disabled = true;
+
+ xen_raw_console_write("mapping kernel into physical memory\n");
+ xen_setup_kernel_pagetable((pgd_t *)xen_start_info->pt_base,
+diff --git a/arch/x86/xen/enlighten_pvh.c b/arch/x86/xen/enlighten_pvh.c
+index bf68c329fc013e..0e3d930bcb89e8 100644
+--- a/arch/x86/xen/enlighten_pvh.c
++++ b/arch/x86/xen/enlighten_pvh.c
+@@ -129,17 +129,10 @@ static void __init pvh_arch_setup(void)
+
+ void __init xen_pvh_init(struct boot_params *boot_params)
+ {
+- u32 msr;
+- u64 pfn;
+-
+ xen_pvh = 1;
+ xen_domain_type = XEN_HVM_DOMAIN;
+ xen_start_flags = pvh_start_info.flags;
+
+- msr = cpuid_ebx(xen_cpuid_base() + 2);
+- pfn = __pa(hypercall_page);
+- wrmsr_safe(msr, (u32)pfn, (u32)(pfn >> 32));
+-
+ x86_init.oem.arch_setup = pvh_arch_setup;
+ x86_init.oem.banner = xen_banner;
+
+diff --git a/arch/x86/xen/xen-asm.S b/arch/x86/xen/xen-asm.S
+index 83189cf5cdce93..b518f36d1ca2e7 100644
+--- a/arch/x86/xen/xen-asm.S
++++ b/arch/x86/xen/xen-asm.S
+@@ -20,9 +20,32 @@
+
+ #include <linux/init.h>
+ #include <linux/linkage.h>
++#include <linux/objtool.h>
+ #include <../entry/calling.h>
+
+ .pushsection .noinstr.text, "ax"
++/*
++ * PV hypercall interface to the hypervisor.
++ *
++ * Called via inline asm(), so better preserve %rcx and %r11.
++ *
++ * Input:
++ * %eax: hypercall number
++ * %rdi, %rsi, %rdx, %r10, %r8: args 1..5 for the hypercall
++ * Output: %rax
++ */
++SYM_FUNC_START(xen_hypercall_pv)
++ ANNOTATE_NOENDBR
++ push %rcx
++ push %r11
++ UNWIND_HINT_SAVE
++ syscall
++ UNWIND_HINT_RESTORE
++ pop %r11
++ pop %rcx
++ RET
++SYM_FUNC_END(xen_hypercall_pv)
++
+ /*
+ * Disabling events is simply a matter of making the event mask
+ * non-zero.
+@@ -176,7 +199,6 @@ SYM_CODE_START(xen_early_idt_handler_array)
+ SYM_CODE_END(xen_early_idt_handler_array)
+ __FINIT
+
+-hypercall_iret = hypercall_page + __HYPERVISOR_iret * 32
+ /*
+ * Xen64 iret frame:
+ *
+@@ -186,17 +208,28 @@ hypercall_iret = hypercall_page + __HYPERVISOR_iret * 32
+ * cs
+ * rip <-- standard iret frame
+ *
+- * flags
++ * flags <-- xen_iret must push from here on
+ *
+- * rcx }
+- * r11 }<-- pushed by hypercall page
+- * rsp->rax }
++ * rcx
++ * r11
++ * rsp->rax
+ */
++.macro xen_hypercall_iret
++ pushq $0 /* Flags */
++ push %rcx
++ push %r11
++ push %rax
++ mov $__HYPERVISOR_iret, %eax
++ syscall /* Do the IRET. */
++#ifdef CONFIG_MITIGATION_SLS
++ int3
++#endif
++.endm
++
+ SYM_CODE_START(xen_iret)
+ UNWIND_HINT_UNDEFINED
+ ANNOTATE_NOENDBR
+- pushq $0
+- jmp hypercall_iret
++ xen_hypercall_iret
+ SYM_CODE_END(xen_iret)
+
+ /*
+@@ -301,8 +334,7 @@ SYM_CODE_START(xen_entry_SYSENTER_compat)
+ ENDBR
+ lea 16(%rsp), %rsp /* strip %rcx, %r11 */
+ mov $-ENOSYS, %rax
+- pushq $0
+- jmp hypercall_iret
++ xen_hypercall_iret
+ SYM_CODE_END(xen_entry_SYSENTER_compat)
+ SYM_CODE_END(xen_entry_SYSCALL_compat)
+
+diff --git a/arch/x86/xen/xen-head.S b/arch/x86/xen/xen-head.S
+index 758bcd47b72d32..721a57700a3b05 100644
+--- a/arch/x86/xen/xen-head.S
++++ b/arch/x86/xen/xen-head.S
+@@ -6,9 +6,11 @@
+
+ #include <linux/elfnote.h>
+ #include <linux/init.h>
++#include <linux/instrumentation.h>
+
+ #include <asm/boot.h>
+ #include <asm/asm.h>
++#include <asm/frame.h>
+ #include <asm/msr.h>
+ #include <asm/page_types.h>
+ #include <asm/percpu.h>
+@@ -20,28 +22,6 @@
+ #include <xen/interface/xen-mca.h>
+ #include <asm/xen/interface.h>
+
+-.pushsection .noinstr.text, "ax"
+- .balign PAGE_SIZE
+-SYM_CODE_START(hypercall_page)
+- .rept (PAGE_SIZE / 32)
+- UNWIND_HINT_FUNC
+- ANNOTATE_NOENDBR
+- ANNOTATE_UNRET_SAFE
+- ret
+- /*
+- * Xen will write the hypercall page, and sort out ENDBR.
+- */
+- .skip 31, 0xcc
+- .endr
+-
+-#define HYPERCALL(n) \
+- .equ xen_hypercall_##n, hypercall_page + __HYPERVISOR_##n * 32; \
+- .type xen_hypercall_##n, @function; .size xen_hypercall_##n, 32
+-#include <asm/xen-hypercalls.h>
+-#undef HYPERCALL
+-SYM_CODE_END(hypercall_page)
+-.popsection
+-
+ #ifdef CONFIG_XEN_PV
+ __INIT
+ SYM_CODE_START(startup_xen)
+@@ -87,6 +67,87 @@ SYM_CODE_END(xen_cpu_bringup_again)
+ #endif
+ #endif
+
++ .pushsection .noinstr.text, "ax"
++/*
++ * Xen hypercall interface to the hypervisor.
++ *
++ * Input:
++ * %eax: hypercall number
++ * 32-bit:
++ * %ebx, %ecx, %edx, %esi, %edi: args 1..5 for the hypercall
++ * 64-bit:
++ * %rdi, %rsi, %rdx, %r10, %r8: args 1..5 for the hypercall
++ * Output: %[er]ax
++ */
++SYM_FUNC_START(xen_hypercall_hvm)
++ ENDBR
++ FRAME_BEGIN
++ /* Save all relevant registers (caller save and arguments). */
++#ifdef CONFIG_X86_32
++ push %eax
++ push %ebx
++ push %ecx
++ push %edx
++ push %esi
++ push %edi
++#else
++ push %rax
++ push %rcx
++ push %rdx
++ push %rdi
++ push %rsi
++ push %r11
++ push %r10
++ push %r9
++ push %r8
++#ifdef CONFIG_FRAME_POINTER
++ pushq $0 /* Dummy push for stack alignment. */
++#endif
++#endif
++ /* Set the vendor specific function. */
++ call __xen_hypercall_setfunc
++ /* Set ZF = 1 if AMD, Restore saved registers. */
++#ifdef CONFIG_X86_32
++ lea xen_hypercall_amd, %ebx
++ cmp %eax, %ebx
++ pop %edi
++ pop %esi
++ pop %edx
++ pop %ecx
++ pop %ebx
++ pop %eax
++#else
++ lea xen_hypercall_amd(%rip), %rbx
++ cmp %rax, %rbx
++#ifdef CONFIG_FRAME_POINTER
++ pop %rax /* Dummy pop. */
++#endif
++ pop %r8
++ pop %r9
++ pop %r10
++ pop %r11
++ pop %rsi
++ pop %rdi
++ pop %rdx
++ pop %rcx
++ pop %rax
++#endif
++ /* Use correct hypercall function. */
++ jz xen_hypercall_amd
++ jmp xen_hypercall_intel
++SYM_FUNC_END(xen_hypercall_hvm)
++
++SYM_FUNC_START(xen_hypercall_amd)
++ vmmcall
++ RET
++SYM_FUNC_END(xen_hypercall_amd)
++
++SYM_FUNC_START(xen_hypercall_intel)
++ vmcall
++ RET
++SYM_FUNC_END(xen_hypercall_intel)
++ .popsection
++
+ ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS, .asciz "linux")
+ ELFNOTE(Xen, XEN_ELFNOTE_GUEST_VERSION, .asciz "2.6")
+ ELFNOTE(Xen, XEN_ELFNOTE_XEN_VERSION, .asciz "xen-3.0")
+@@ -115,7 +176,6 @@ SYM_CODE_END(xen_cpu_bringup_again)
+ #else
+ # define FEATURES_DOM0 0
+ #endif
+- ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, _ASM_PTR hypercall_page)
+ ELFNOTE(Xen, XEN_ELFNOTE_SUPPORTED_FEATURES,
+ .long FEATURES_PV | FEATURES_PVH | FEATURES_DOM0)
+ ELFNOTE(Xen, XEN_ELFNOTE_LOADER, .asciz "generic")
+diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
+index e1b782e823e6b4..63c13a2ccf556a 100644
+--- a/arch/x86/xen/xen-ops.h
++++ b/arch/x86/xen/xen-ops.h
+@@ -326,4 +326,13 @@ static inline void xen_smp_intr_free_pv(unsigned int cpu) {}
+ static inline void xen_smp_count_cpus(void) { }
+ #endif /* CONFIG_SMP */
+
++#ifdef CONFIG_XEN_PV
++void xen_hypercall_pv(void);
++#endif
++void xen_hypercall_hvm(void);
++void xen_hypercall_amd(void);
++void xen_hypercall_intel(void);
++void xen_hypercall_setfunc(void);
++void *__xen_hypercall_setfunc(void);
++
+ #endif /* XEN_OPS_H */
+diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
+index e68c725cf8d975..45a395862fbc88 100644
+--- a/block/blk-cgroup.c
++++ b/block/blk-cgroup.c
+@@ -1324,10 +1324,14 @@ void blkcg_unpin_online(struct cgroup_subsys_state *blkcg_css)
+ struct blkcg *blkcg = css_to_blkcg(blkcg_css);
+
+ do {
++ struct blkcg *parent;
++
+ if (!refcount_dec_and_test(&blkcg->online_pin))
+ break;
++
++ parent = blkcg_parent(blkcg);
+ blkcg_destroy_blkgs(blkcg);
+- blkcg = blkcg_parent(blkcg);
++ blkcg = parent;
+ } while (blkcg);
+ }
+
+diff --git a/block/blk-iocost.c b/block/blk-iocost.c
+index 384aa15e8260bd..a5894ec9696e7e 100644
+--- a/block/blk-iocost.c
++++ b/block/blk-iocost.c
+@@ -1098,7 +1098,14 @@ static void __propagate_weights(struct ioc_gq *iocg, u32 active, u32 inuse,
+ inuse = DIV64_U64_ROUND_UP(active * iocg->child_inuse_sum,
+ iocg->child_active_sum);
+ } else {
+- inuse = clamp_t(u32, inuse, 1, active);
++ /*
++ * It may be tempting to turn this into a clamp expression with
++ * a lower limit of 1 but active may be 0, which cannot be used
++ * as an upper limit in that situation. This expression allows
++ * active to clamp inuse unless it is 0, in which case inuse
++ * becomes 1.
++ */
++ inuse = min(inuse, active) ?: 1;
+ }
+
+ iocg->last_inuse = iocg->inuse;
+diff --git a/block/blk-mq-sysfs.c b/block/blk-mq-sysfs.c
+index 156e9bb07abf1a..cd5ea6eaa76b09 100644
+--- a/block/blk-mq-sysfs.c
++++ b/block/blk-mq-sysfs.c
+@@ -275,15 +275,13 @@ void blk_mq_sysfs_unregister_hctxs(struct request_queue *q)
+ struct blk_mq_hw_ctx *hctx;
+ unsigned long i;
+
+- mutex_lock(&q->sysfs_dir_lock);
++ lockdep_assert_held(&q->sysfs_dir_lock);
++
+ if (!q->mq_sysfs_init_done)
+- goto unlock;
++ return;
+
+ queue_for_each_hw_ctx(q, hctx, i)
+ blk_mq_unregister_hctx(hctx);
+-
+-unlock:
+- mutex_unlock(&q->sysfs_dir_lock);
+ }
+
+ int blk_mq_sysfs_register_hctxs(struct request_queue *q)
+@@ -292,9 +290,10 @@ int blk_mq_sysfs_register_hctxs(struct request_queue *q)
+ unsigned long i;
+ int ret = 0;
+
+- mutex_lock(&q->sysfs_dir_lock);
++ lockdep_assert_held(&q->sysfs_dir_lock);
++
+ if (!q->mq_sysfs_init_done)
+- goto unlock;
++ return ret;
+
+ queue_for_each_hw_ctx(q, hctx, i) {
+ ret = blk_mq_register_hctx(hctx);
+@@ -302,8 +301,5 @@ int blk_mq_sysfs_register_hctxs(struct request_queue *q)
+ break;
+ }
+
+-unlock:
+- mutex_unlock(&q->sysfs_dir_lock);
+-
+ return ret;
+ }
+diff --git a/block/blk-mq.c b/block/blk-mq.c
+index b4fba7b398e5bc..cc1b3202383840 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,
+@@ -3740,13 +3741,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);
+ }
+
+ /*
+@@ -3797,8 +3876,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);
+@@ -3815,6 +3892,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);
+ }
+ }
+@@ -3878,6 +3956,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;
+
+@@ -4382,7 +4462,8 @@ static void blk_mq_realloc_hw_ctxs(struct blk_mq_tag_set *set,
+ unsigned long i, j;
+
+ /* protect against switching io scheduler */
+- mutex_lock(&q->sysfs_lock);
++ lockdep_assert_held(&q->sysfs_lock);
++
+ for (i = 0; i < set->nr_hw_queues; i++) {
+ int old_node;
+ int node = blk_mq_get_hctx_node(set, i);
+@@ -4415,7 +4496,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);
+ }
+
+ int blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
+@@ -4441,10 +4527,14 @@ int blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
+
+ xa_init(&q->hctx_table);
+
++ mutex_lock(&q->sysfs_lock);
++
+ blk_mq_realloc_hw_ctxs(set, q);
+ if (!q->nr_hw_queues)
+ goto err_hctxs;
+
++ mutex_unlock(&q->sysfs_lock);
++
+ INIT_WORK(&q->timeout_work, blk_mq_timeout_work);
+ blk_queue_rq_timeout(q, set->timeout ? set->timeout : 30 * HZ);
+
+@@ -4463,6 +4553,7 @@ int blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
+ return 0;
+
+ err_hctxs:
++ mutex_unlock(&q->sysfs_lock);
+ blk_mq_release(q);
+ err_exit:
+ q->mq_ops = NULL;
+@@ -4843,12 +4934,12 @@ static bool blk_mq_elv_switch_none(struct list_head *head,
+ return false;
+
+ /* q->elevator needs protection from ->sysfs_lock */
+- mutex_lock(&q->sysfs_lock);
++ lockdep_assert_held(&q->sysfs_lock);
+
+ /* the check has to be done with holding sysfs_lock */
+ if (!q->elevator) {
+ kfree(qe);
+- goto unlock;
++ goto out;
+ }
+
+ INIT_LIST_HEAD(&qe->node);
+@@ -4858,9 +4949,7 @@ static bool blk_mq_elv_switch_none(struct list_head *head,
+ __elevator_get(qe->type);
+ list_add(&qe->node, head);
+ elevator_disable(q);
+-unlock:
+- mutex_unlock(&q->sysfs_lock);
+-
++out:
+ return true;
+ }
+
+@@ -4889,11 +4978,9 @@ static void blk_mq_elv_switch_back(struct list_head *head,
+ list_del(&qe->node);
+ kfree(qe);
+
+- mutex_lock(&q->sysfs_lock);
+ elevator_switch(q, t);
+ /* drop the reference acquired in blk_mq_elv_switch_none */
+ elevator_put(t);
+- mutex_unlock(&q->sysfs_lock);
+ }
+
+ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
+@@ -4913,8 +5000,11 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
+ if (set->nr_maps == 1 && nr_hw_queues == set->nr_hw_queues)
+ return;
+
+- list_for_each_entry(q, &set->tag_list, tag_set_list)
++ list_for_each_entry(q, &set->tag_list, tag_set_list) {
++ mutex_lock(&q->sysfs_dir_lock);
++ mutex_lock(&q->sysfs_lock);
+ blk_mq_freeze_queue(q);
++ }
+ /*
+ * Switch IO scheduler to 'none', cleaning up the data associated
+ * with the previous scheduler. We will switch back once we are done
+@@ -4970,8 +5060,11 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
+ list_for_each_entry(q, &set->tag_list, tag_set_list)
+ blk_mq_elv_switch_back(&head, q);
+
+- list_for_each_entry(q, &set->tag_list, tag_set_list)
++ list_for_each_entry(q, &set->tag_list, tag_set_list) {
+ blk_mq_unfreeze_queue(q);
++ mutex_unlock(&q->sysfs_lock);
++ mutex_unlock(&q->sysfs_dir_lock);
++ }
+
+ /* Free the excess tags when nr_hw_queues shrink. */
+ for (i = set->nr_hw_queues; i < prev_nr_hw_queues; i++)
+diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
+index 207577145c54f4..42c2cb97d778af 100644
+--- a/block/blk-sysfs.c
++++ b/block/blk-sysfs.c
+@@ -690,11 +690,11 @@ queue_attr_store(struct kobject *kobj, struct attribute *attr,
+ return res;
+ }
+
+- blk_mq_freeze_queue(q);
+ mutex_lock(&q->sysfs_lock);
++ blk_mq_freeze_queue(q);
+ res = entry->store(disk, page, length);
+- mutex_unlock(&q->sysfs_lock);
+ blk_mq_unfreeze_queue(q);
++ mutex_unlock(&q->sysfs_lock);
+ return res;
+ }
+
+diff --git a/block/blk-zoned.c b/block/blk-zoned.c
+index 0b1184176ce77a..767bcbce74facb 100644
+--- a/block/blk-zoned.c
++++ b/block/blk-zoned.c
+@@ -18,7 +18,7 @@
+ #include <linux/vmalloc.h>
+ #include <linux/sched/mm.h>
+ #include <linux/spinlock.h>
+-#include <linux/atomic.h>
++#include <linux/refcount.h>
+ #include <linux/mempool.h>
+
+ #include "blk.h"
+@@ -41,7 +41,6 @@ static const char *const zone_cond_name[] = {
+ /*
+ * Per-zone write plug.
+ * @node: hlist_node structure for managing the plug using a hash table.
+- * @link: To list the plug in the zone write plug error list of the disk.
+ * @ref: Zone write plug reference counter. A zone write plug reference is
+ * always at least 1 when the plug is hashed in the disk plug hash table.
+ * The reference is incremented whenever a new BIO needing plugging is
+@@ -63,8 +62,7 @@ static const char *const zone_cond_name[] = {
+ */
+ struct blk_zone_wplug {
+ struct hlist_node node;
+- struct list_head link;
+- atomic_t ref;
++ refcount_t ref;
+ spinlock_t lock;
+ unsigned int flags;
+ unsigned int zone_no;
+@@ -80,8 +78,8 @@ struct blk_zone_wplug {
+ * - BLK_ZONE_WPLUG_PLUGGED: Indicates that the zone write plug is plugged,
+ * that is, that write BIOs are being throttled due to a write BIO already
+ * being executed or the zone write plug bio list is not empty.
+- * - BLK_ZONE_WPLUG_ERROR: Indicates that a write error happened which will be
+- * recovered with a report zone to update the zone write pointer offset.
++ * - BLK_ZONE_WPLUG_NEED_WP_UPDATE: Indicates that we lost track of a zone
++ * write pointer offset and need to update it.
+ * - BLK_ZONE_WPLUG_UNHASHED: Indicates that the zone write plug was removed
+ * from the disk hash table and that the initial reference to the zone
+ * write plug set when the plug was first added to the hash table has been
+@@ -91,11 +89,9 @@ struct blk_zone_wplug {
+ * freed once all remaining references from BIOs or functions are dropped.
+ */
+ #define BLK_ZONE_WPLUG_PLUGGED (1U << 0)
+-#define BLK_ZONE_WPLUG_ERROR (1U << 1)
++#define BLK_ZONE_WPLUG_NEED_WP_UPDATE (1U << 1)
+ #define BLK_ZONE_WPLUG_UNHASHED (1U << 2)
+
+-#define BLK_ZONE_WPLUG_BUSY (BLK_ZONE_WPLUG_PLUGGED | BLK_ZONE_WPLUG_ERROR)
+-
+ /**
+ * blk_zone_cond_str - Return string XXX in BLK_ZONE_COND_XXX.
+ * @zone_cond: BLK_ZONE_COND_XXX.
+@@ -115,6 +111,30 @@ const char *blk_zone_cond_str(enum blk_zone_cond zone_cond)
+ }
+ EXPORT_SYMBOL_GPL(blk_zone_cond_str);
+
++struct disk_report_zones_cb_args {
++ struct gendisk *disk;
++ report_zones_cb user_cb;
++ void *user_data;
++};
++
++static void disk_zone_wplug_sync_wp_offset(struct gendisk *disk,
++ struct blk_zone *zone);
++
++static int disk_report_zones_cb(struct blk_zone *zone, unsigned int idx,
++ void *data)
++{
++ struct disk_report_zones_cb_args *args = data;
++ struct gendisk *disk = args->disk;
++
++ if (disk->zone_wplugs_hash)
++ disk_zone_wplug_sync_wp_offset(disk, zone);
++
++ if (!args->user_cb)
++ return 0;
++
++ return args->user_cb(zone, idx, args->user_data);
++}
++
+ /**
+ * blkdev_report_zones - Get zones information
+ * @bdev: Target block device
+@@ -139,6 +159,11 @@ int blkdev_report_zones(struct block_device *bdev, sector_t sector,
+ {
+ struct gendisk *disk = bdev->bd_disk;
+ sector_t capacity = get_capacity(disk);
++ struct disk_report_zones_cb_args args = {
++ .disk = disk,
++ .user_cb = cb,
++ .user_data = data,
++ };
+
+ if (!bdev_is_zoned(bdev) || WARN_ON_ONCE(!disk->fops->report_zones))
+ return -EOPNOTSUPP;
+@@ -146,7 +171,8 @@ int blkdev_report_zones(struct block_device *bdev, sector_t sector,
+ if (!nr_zones || sector >= capacity)
+ return 0;
+
+- return disk->fops->report_zones(disk, sector, nr_zones, cb, data);
++ return disk->fops->report_zones(disk, sector, nr_zones,
++ disk_report_zones_cb, &args);
+ }
+ EXPORT_SYMBOL_GPL(blkdev_report_zones);
+
+@@ -417,7 +443,7 @@ static struct blk_zone_wplug *disk_get_zone_wplug(struct gendisk *disk,
+
+ hlist_for_each_entry_rcu(zwplug, &disk->zone_wplugs_hash[idx], node) {
+ if (zwplug->zone_no == zno &&
+- atomic_inc_not_zero(&zwplug->ref)) {
++ refcount_inc_not_zero(&zwplug->ref)) {
+ rcu_read_unlock();
+ return zwplug;
+ }
+@@ -438,9 +464,9 @@ static void disk_free_zone_wplug_rcu(struct rcu_head *rcu_head)
+
+ static inline void disk_put_zone_wplug(struct blk_zone_wplug *zwplug)
+ {
+- if (atomic_dec_and_test(&zwplug->ref)) {
++ if (refcount_dec_and_test(&zwplug->ref)) {
+ WARN_ON_ONCE(!bio_list_empty(&zwplug->bio_list));
+- WARN_ON_ONCE(!list_empty(&zwplug->link));
++ WARN_ON_ONCE(zwplug->flags & BLK_ZONE_WPLUG_PLUGGED);
+ WARN_ON_ONCE(!(zwplug->flags & BLK_ZONE_WPLUG_UNHASHED));
+
+ call_rcu(&zwplug->rcu_head, disk_free_zone_wplug_rcu);
+@@ -454,8 +480,8 @@ static inline bool disk_should_remove_zone_wplug(struct gendisk *disk,
+ if (zwplug->flags & BLK_ZONE_WPLUG_UNHASHED)
+ return false;
+
+- /* If the zone write plug is still busy, it cannot be removed. */
+- if (zwplug->flags & BLK_ZONE_WPLUG_BUSY)
++ /* If the zone write plug is still plugged, it cannot be removed. */
++ if (zwplug->flags & BLK_ZONE_WPLUG_PLUGGED)
+ return false;
+
+ /*
+@@ -469,7 +495,7 @@ static inline bool disk_should_remove_zone_wplug(struct gendisk *disk,
+ * taken when the plug was allocated and another reference taken by the
+ * caller context).
+ */
+- if (atomic_read(&zwplug->ref) > 2)
++ if (refcount_read(&zwplug->ref) > 2)
+ return false;
+
+ /* We can remove zone write plugs for zones that are empty or full. */
+@@ -538,12 +564,11 @@ static struct blk_zone_wplug *disk_get_and_lock_zone_wplug(struct gendisk *disk,
+ return NULL;
+
+ INIT_HLIST_NODE(&zwplug->node);
+- INIT_LIST_HEAD(&zwplug->link);
+- atomic_set(&zwplug->ref, 2);
++ refcount_set(&zwplug->ref, 2);
+ spin_lock_init(&zwplug->lock);
+ zwplug->flags = 0;
+ zwplug->zone_no = zno;
+- zwplug->wp_offset = sector & (disk->queue->limits.chunk_sectors - 1);
++ zwplug->wp_offset = bdev_offset_from_zone_start(disk->part0, sector);
+ bio_list_init(&zwplug->bio_list);
+ INIT_WORK(&zwplug->bio_work, blk_zone_wplug_bio_work);
+ zwplug->disk = disk;
+@@ -587,124 +612,81 @@ static void disk_zone_wplug_abort(struct blk_zone_wplug *zwplug)
+ }
+
+ /*
+- * Abort (fail) all plugged BIOs of a zone write plug that are not aligned
+- * with the assumed write pointer location of the zone when the BIO will
+- * be unplugged.
++ * Set a zone write plug write pointer offset to the specified value.
++ * This aborts all plugged BIOs, which is fine as this function is called for
++ * a zone reset operation, a zone finish operation or if the zone needs a wp
++ * update from a report zone after a write error.
+ */
+-static void disk_zone_wplug_abort_unaligned(struct gendisk *disk,
+- struct blk_zone_wplug *zwplug)
+-{
+- unsigned int wp_offset = zwplug->wp_offset;
+- struct bio_list bl = BIO_EMPTY_LIST;
+- struct bio *bio;
+-
+- while ((bio = bio_list_pop(&zwplug->bio_list))) {
+- if (disk_zone_is_full(disk, zwplug->zone_no, wp_offset) ||
+- (bio_op(bio) != REQ_OP_ZONE_APPEND &&
+- bio_offset_from_zone_start(bio) != wp_offset)) {
+- blk_zone_wplug_bio_io_error(zwplug, bio);
+- continue;
+- }
+-
+- wp_offset += bio_sectors(bio);
+- bio_list_add(&bl, bio);
+- }
+-
+- bio_list_merge(&zwplug->bio_list, &bl);
+-}
+-
+-static inline void disk_zone_wplug_set_error(struct gendisk *disk,
+- struct blk_zone_wplug *zwplug)
++static void disk_zone_wplug_set_wp_offset(struct gendisk *disk,
++ struct blk_zone_wplug *zwplug,
++ unsigned int wp_offset)
+ {
+- unsigned long flags;
++ lockdep_assert_held(&zwplug->lock);
+
+- if (zwplug->flags & BLK_ZONE_WPLUG_ERROR)
+- return;
++ /* Update the zone write pointer and abort all plugged BIOs. */
++ zwplug->flags &= ~BLK_ZONE_WPLUG_NEED_WP_UPDATE;
++ zwplug->wp_offset = wp_offset;
++ disk_zone_wplug_abort(zwplug);
+
+ /*
+- * At this point, we already have a reference on the zone write plug.
+- * However, since we are going to add the plug to the disk zone write
+- * plugs work list, increase its reference count. This reference will
+- * be dropped in disk_zone_wplugs_work() once the error state is
+- * handled, or in disk_zone_wplug_clear_error() if the zone is reset or
+- * finished.
++ * The zone write plug now has no BIO plugged: remove it from the
++ * hash table so that it cannot be seen. The plug will be freed
++ * when the last reference is dropped.
+ */
+- zwplug->flags |= BLK_ZONE_WPLUG_ERROR;
+- atomic_inc(&zwplug->ref);
+-
+- spin_lock_irqsave(&disk->zone_wplugs_lock, flags);
+- list_add_tail(&zwplug->link, &disk->zone_wplugs_err_list);
+- spin_unlock_irqrestore(&disk->zone_wplugs_lock, flags);
++ if (disk_should_remove_zone_wplug(disk, zwplug))
++ disk_remove_zone_wplug(disk, zwplug);
+ }
+
+-static inline void disk_zone_wplug_clear_error(struct gendisk *disk,
+- struct blk_zone_wplug *zwplug)
++static unsigned int blk_zone_wp_offset(struct blk_zone *zone)
+ {
+- unsigned long flags;
+-
+- if (!(zwplug->flags & BLK_ZONE_WPLUG_ERROR))
+- return;
+-
+- /*
+- * We are racing with the error handling work which drops the reference
+- * on the zone write plug after handling the error state. So remove the
+- * plug from the error list and drop its reference count only if the
+- * error handling has not yet started, that is, if the zone write plug
+- * is still listed.
+- */
+- spin_lock_irqsave(&disk->zone_wplugs_lock, flags);
+- if (!list_empty(&zwplug->link)) {
+- list_del_init(&zwplug->link);
+- zwplug->flags &= ~BLK_ZONE_WPLUG_ERROR;
+- disk_put_zone_wplug(zwplug);
++ switch (zone->cond) {
++ case BLK_ZONE_COND_IMP_OPEN:
++ case BLK_ZONE_COND_EXP_OPEN:
++ case BLK_ZONE_COND_CLOSED:
++ return zone->wp - zone->start;
++ case BLK_ZONE_COND_FULL:
++ return zone->len;
++ case BLK_ZONE_COND_EMPTY:
++ return 0;
++ case BLK_ZONE_COND_NOT_WP:
++ case BLK_ZONE_COND_OFFLINE:
++ case BLK_ZONE_COND_READONLY:
++ default:
++ /*
++ * Conventional, offline and read-only zones do not have a valid
++ * write pointer.
++ */
++ return UINT_MAX;
+ }
+- spin_unlock_irqrestore(&disk->zone_wplugs_lock, flags);
+ }
+
+-/*
+- * Set a zone write plug write pointer offset to either 0 (zone reset case)
+- * or to the zone size (zone finish case). This aborts all plugged BIOs, which
+- * is fine to do as doing a zone reset or zone finish while writes are in-flight
+- * is a mistake from the user which will most likely cause all plugged BIOs to
+- * fail anyway.
+- */
+-static void disk_zone_wplug_set_wp_offset(struct gendisk *disk,
+- struct blk_zone_wplug *zwplug,
+- unsigned int wp_offset)
++static void disk_zone_wplug_sync_wp_offset(struct gendisk *disk,
++ struct blk_zone *zone)
+ {
++ struct blk_zone_wplug *zwplug;
+ unsigned long flags;
+
+- spin_lock_irqsave(&zwplug->lock, flags);
+-
+- /*
+- * Make sure that a BIO completion or another zone reset or finish
+- * operation has not already removed the plug from the hash table.
+- */
+- if (zwplug->flags & BLK_ZONE_WPLUG_UNHASHED) {
+- spin_unlock_irqrestore(&zwplug->lock, flags);
++ zwplug = disk_get_zone_wplug(disk, zone->start);
++ if (!zwplug)
+ return;
+- }
+
+- /* Update the zone write pointer and abort all plugged BIOs. */
+- zwplug->wp_offset = wp_offset;
+- disk_zone_wplug_abort(zwplug);
++ spin_lock_irqsave(&zwplug->lock, flags);
++ if (zwplug->flags & BLK_ZONE_WPLUG_NEED_WP_UPDATE)
++ disk_zone_wplug_set_wp_offset(disk, zwplug,
++ blk_zone_wp_offset(zone));
++ spin_unlock_irqrestore(&zwplug->lock, flags);
+
+- /*
+- * Updating the write pointer offset puts back the zone
+- * in a good state. So clear the error flag and decrement the
+- * error count if we were in error state.
+- */
+- disk_zone_wplug_clear_error(disk, zwplug);
++ disk_put_zone_wplug(zwplug);
++}
+
+- /*
+- * The zone write plug now has no BIO plugged: remove it from the
+- * hash table so that it cannot be seen. The plug will be freed
+- * when the last reference is dropped.
+- */
+- if (disk_should_remove_zone_wplug(disk, zwplug))
+- disk_remove_zone_wplug(disk, zwplug);
++static int disk_zone_sync_wp_offset(struct gendisk *disk, sector_t sector)
++{
++ struct disk_report_zones_cb_args args = {
++ .disk = disk,
++ };
+
+- spin_unlock_irqrestore(&zwplug->lock, flags);
++ return disk->fops->report_zones(disk, sector, 1,
++ disk_report_zones_cb, &args);
+ }
+
+ static bool blk_zone_wplug_handle_reset_or_finish(struct bio *bio,
+@@ -713,6 +695,7 @@ static bool blk_zone_wplug_handle_reset_or_finish(struct bio *bio,
+ struct gendisk *disk = bio->bi_bdev->bd_disk;
+ sector_t sector = bio->bi_iter.bi_sector;
+ struct blk_zone_wplug *zwplug;
++ unsigned long flags;
+
+ /* Conventional zones cannot be reset nor finished. */
+ if (disk_zone_is_conv(disk, sector)) {
+@@ -720,6 +703,15 @@ static bool blk_zone_wplug_handle_reset_or_finish(struct bio *bio,
+ return true;
+ }
+
++ /*
++ * No-wait reset or finish BIOs do not make much sense as the callers
++ * issue these as blocking operations in most cases. To avoid issues
++ * the BIO execution potentially failing with BLK_STS_AGAIN, warn about
++ * REQ_NOWAIT being set and ignore that flag.
++ */
++ if (WARN_ON_ONCE(bio->bi_opf & REQ_NOWAIT))
++ bio->bi_opf &= ~REQ_NOWAIT;
++
+ /*
+ * If we have a zone write plug, set its write pointer offset to 0
+ * (reset case) or to the zone size (finish case). This will abort all
+@@ -729,7 +721,9 @@ static bool blk_zone_wplug_handle_reset_or_finish(struct bio *bio,
+ */
+ zwplug = disk_get_zone_wplug(disk, sector);
+ if (zwplug) {
++ spin_lock_irqsave(&zwplug->lock, flags);
+ disk_zone_wplug_set_wp_offset(disk, zwplug, wp_offset);
++ spin_unlock_irqrestore(&zwplug->lock, flags);
+ disk_put_zone_wplug(zwplug);
+ }
+
+@@ -740,6 +734,7 @@ static bool blk_zone_wplug_handle_reset_all(struct bio *bio)
+ {
+ struct gendisk *disk = bio->bi_bdev->bd_disk;
+ struct blk_zone_wplug *zwplug;
++ unsigned long flags;
+ sector_t sector;
+
+ /*
+@@ -751,7 +746,9 @@ static bool blk_zone_wplug_handle_reset_all(struct bio *bio)
+ sector += disk->queue->limits.chunk_sectors) {
+ zwplug = disk_get_zone_wplug(disk, sector);
+ if (zwplug) {
++ spin_lock_irqsave(&zwplug->lock, flags);
+ disk_zone_wplug_set_wp_offset(disk, zwplug, 0);
++ spin_unlock_irqrestore(&zwplug->lock, flags);
+ disk_put_zone_wplug(zwplug);
+ }
+ }
+@@ -759,9 +756,25 @@ static bool blk_zone_wplug_handle_reset_all(struct bio *bio)
+ return false;
+ }
+
+-static inline void blk_zone_wplug_add_bio(struct blk_zone_wplug *zwplug,
+- struct bio *bio, unsigned int nr_segs)
++static void disk_zone_wplug_schedule_bio_work(struct gendisk *disk,
++ struct blk_zone_wplug *zwplug)
+ {
++ /*
++ * Take a reference on the zone write plug and schedule the submission
++ * of the next plugged BIO. blk_zone_wplug_bio_work() will release the
++ * reference we take here.
++ */
++ WARN_ON_ONCE(!(zwplug->flags & BLK_ZONE_WPLUG_PLUGGED));
++ refcount_inc(&zwplug->ref);
++ queue_work(disk->zone_wplugs_wq, &zwplug->bio_work);
++}
++
++static inline void disk_zone_wplug_add_bio(struct gendisk *disk,
++ struct blk_zone_wplug *zwplug,
++ struct bio *bio, unsigned int nr_segs)
++{
++ bool schedule_bio_work = false;
++
+ /*
+ * Grab an extra reference on the BIO request queue usage counter.
+ * This reference will be reused to submit a request for the BIO for
+@@ -777,6 +790,16 @@ static inline void blk_zone_wplug_add_bio(struct blk_zone_wplug *zwplug,
+ */
+ bio_clear_polled(bio);
+
++ /*
++ * REQ_NOWAIT BIOs are always handled using the zone write plug BIO
++ * work, which can block. So clear the REQ_NOWAIT flag and schedule the
++ * work if this is the first BIO we are plugging.
++ */
++ if (bio->bi_opf & REQ_NOWAIT) {
++ schedule_bio_work = !(zwplug->flags & BLK_ZONE_WPLUG_PLUGGED);
++ bio->bi_opf &= ~REQ_NOWAIT;
++ }
++
+ /*
+ * Reuse the poll cookie field to store the number of segments when
+ * split to the hardware limits.
+@@ -790,6 +813,11 @@ static inline void blk_zone_wplug_add_bio(struct blk_zone_wplug *zwplug,
+ * at the tail of the list to preserve the sequential write order.
+ */
+ bio_list_add(&zwplug->bio_list, bio);
++
++ zwplug->flags |= BLK_ZONE_WPLUG_PLUGGED;
++
++ if (schedule_bio_work)
++ disk_zone_wplug_schedule_bio_work(disk, zwplug);
+ }
+
+ /*
+@@ -902,13 +930,23 @@ static bool blk_zone_wplug_prepare_bio(struct blk_zone_wplug *zwplug,
+ {
+ struct gendisk *disk = bio->bi_bdev->bd_disk;
+
++ /*
++ * If we lost track of the zone write pointer due to a write error,
++ * the user must either execute a report zones, reset the zone or finish
++ * the to recover a reliable write pointer position. Fail BIOs if the
++ * user did not do that as we cannot handle emulated zone append
++ * otherwise.
++ */
++ if (zwplug->flags & BLK_ZONE_WPLUG_NEED_WP_UPDATE)
++ return false;
++
+ /*
+ * Check that the user is not attempting to write to a full zone.
+ * We know such BIO will fail, and that would potentially overflow our
+ * write pointer offset beyond the end of the zone.
+ */
+ if (disk_zone_wplug_is_full(disk, zwplug))
+- goto err;
++ return false;
+
+ if (bio_op(bio) == REQ_OP_ZONE_APPEND) {
+ /*
+@@ -927,24 +965,18 @@ static bool blk_zone_wplug_prepare_bio(struct blk_zone_wplug *zwplug,
+ bio_set_flag(bio, BIO_EMULATES_ZONE_APPEND);
+ } else {
+ /*
+- * Check for non-sequential writes early because we avoid a
+- * whole lot of error handling trouble if we don't send it off
+- * to the driver.
++ * Check for non-sequential writes early as we know that BIOs
++ * with a start sector not unaligned to the zone write pointer
++ * will fail.
+ */
+ if (bio_offset_from_zone_start(bio) != zwplug->wp_offset)
+- goto err;
++ return false;
+ }
+
+ /* Advance the zone write pointer offset. */
+ zwplug->wp_offset += bio_sectors(bio);
+
+ return true;
+-
+-err:
+- /* We detected an invalid write BIO: schedule error recovery. */
+- disk_zone_wplug_set_error(disk, zwplug);
+- kblockd_schedule_work(&disk->zone_wplugs_work);
+- return false;
+ }
+
+ static bool blk_zone_wplug_handle_write(struct bio *bio, unsigned int nr_segs)
+@@ -983,7 +1015,10 @@ static bool blk_zone_wplug_handle_write(struct bio *bio, unsigned int nr_segs)
+
+ zwplug = disk_get_and_lock_zone_wplug(disk, sector, gfp_mask, &flags);
+ if (!zwplug) {
+- bio_io_error(bio);
++ if (bio->bi_opf & REQ_NOWAIT)
++ bio_wouldblock_error(bio);
++ else
++ bio_io_error(bio);
+ return true;
+ }
+
+@@ -991,18 +1026,20 @@ static bool blk_zone_wplug_handle_write(struct bio *bio, unsigned int nr_segs)
+ bio_set_flag(bio, BIO_ZONE_WRITE_PLUGGING);
+
+ /*
+- * If the zone is already plugged or has a pending error, add the BIO
+- * to the plug BIO list. Otherwise, plug and let the BIO execute.
++ * If the zone is already plugged, add the BIO to the plug BIO list.
++ * Do the same for REQ_NOWAIT BIOs to ensure that we will not see a
++ * BLK_STS_AGAIN failure if we let the BIO execute.
++ * Otherwise, plug and let the BIO execute.
+ */
+- if (zwplug->flags & BLK_ZONE_WPLUG_BUSY)
++ if ((zwplug->flags & BLK_ZONE_WPLUG_PLUGGED) ||
++ (bio->bi_opf & REQ_NOWAIT))
+ goto plug;
+
+- /*
+- * If an error is detected when preparing the BIO, add it to the BIO
+- * list so that error recovery can deal with it.
+- */
+- if (!blk_zone_wplug_prepare_bio(zwplug, bio))
+- goto plug;
++ if (!blk_zone_wplug_prepare_bio(zwplug, bio)) {
++ spin_unlock_irqrestore(&zwplug->lock, flags);
++ bio_io_error(bio);
++ return true;
++ }
+
+ zwplug->flags |= BLK_ZONE_WPLUG_PLUGGED;
+
+@@ -1011,8 +1048,7 @@ static bool blk_zone_wplug_handle_write(struct bio *bio, unsigned int nr_segs)
+ return false;
+
+ plug:
+- zwplug->flags |= BLK_ZONE_WPLUG_PLUGGED;
+- blk_zone_wplug_add_bio(zwplug, bio, nr_segs);
++ disk_zone_wplug_add_bio(disk, zwplug, bio, nr_segs);
+
+ spin_unlock_irqrestore(&zwplug->lock, flags);
+
+@@ -1096,19 +1132,6 @@ bool blk_zone_plug_bio(struct bio *bio, unsigned int nr_segs)
+ }
+ EXPORT_SYMBOL_GPL(blk_zone_plug_bio);
+
+-static void disk_zone_wplug_schedule_bio_work(struct gendisk *disk,
+- struct blk_zone_wplug *zwplug)
+-{
+- /*
+- * Take a reference on the zone write plug and schedule the submission
+- * of the next plugged BIO. blk_zone_wplug_bio_work() will release the
+- * reference we take here.
+- */
+- WARN_ON_ONCE(!(zwplug->flags & BLK_ZONE_WPLUG_PLUGGED));
+- atomic_inc(&zwplug->ref);
+- queue_work(disk->zone_wplugs_wq, &zwplug->bio_work);
+-}
+-
+ static void disk_zone_wplug_unplug_bio(struct gendisk *disk,
+ struct blk_zone_wplug *zwplug)
+ {
+@@ -1116,16 +1139,6 @@ static void disk_zone_wplug_unplug_bio(struct gendisk *disk,
+
+ spin_lock_irqsave(&zwplug->lock, flags);
+
+- /*
+- * If we had an error, schedule error recovery. The recovery work
+- * will restart submission of plugged BIOs.
+- */
+- if (zwplug->flags & BLK_ZONE_WPLUG_ERROR) {
+- spin_unlock_irqrestore(&zwplug->lock, flags);
+- kblockd_schedule_work(&disk->zone_wplugs_work);
+- return;
+- }
+-
+ /* Schedule submission of the next plugged BIO if we have one. */
+ if (!bio_list_empty(&zwplug->bio_list)) {
+ disk_zone_wplug_schedule_bio_work(disk, zwplug);
+@@ -1168,12 +1181,13 @@ void blk_zone_write_plug_bio_endio(struct bio *bio)
+ }
+
+ /*
+- * If the BIO failed, mark the plug as having an error to trigger
+- * recovery.
++ * If the BIO failed, abort all plugged BIOs and mark the plug as
++ * needing a write pointer update.
+ */
+ if (bio->bi_status != BLK_STS_OK) {
+ spin_lock_irqsave(&zwplug->lock, flags);
+- disk_zone_wplug_set_error(disk, zwplug);
++ disk_zone_wplug_abort(zwplug);
++ zwplug->flags |= BLK_ZONE_WPLUG_NEED_WP_UPDATE;
+ spin_unlock_irqrestore(&zwplug->lock, flags);
+ }
+
+@@ -1229,6 +1243,7 @@ static void blk_zone_wplug_bio_work(struct work_struct *work)
+ */
+ spin_lock_irqsave(&zwplug->lock, flags);
+
++again:
+ bio = bio_list_pop(&zwplug->bio_list);
+ if (!bio) {
+ zwplug->flags &= ~BLK_ZONE_WPLUG_PLUGGED;
+@@ -1237,10 +1252,8 @@ static void blk_zone_wplug_bio_work(struct work_struct *work)
+ }
+
+ if (!blk_zone_wplug_prepare_bio(zwplug, bio)) {
+- /* Error recovery will decide what to do with the BIO. */
+- bio_list_add_head(&zwplug->bio_list, bio);
+- spin_unlock_irqrestore(&zwplug->lock, flags);
+- goto put_zwplug;
++ blk_zone_wplug_bio_io_error(zwplug, bio);
++ goto again;
+ }
+
+ spin_unlock_irqrestore(&zwplug->lock, flags);
+@@ -1262,120 +1275,6 @@ static void blk_zone_wplug_bio_work(struct work_struct *work)
+ disk_put_zone_wplug(zwplug);
+ }
+
+-static unsigned int blk_zone_wp_offset(struct blk_zone *zone)
+-{
+- switch (zone->cond) {
+- case BLK_ZONE_COND_IMP_OPEN:
+- case BLK_ZONE_COND_EXP_OPEN:
+- case BLK_ZONE_COND_CLOSED:
+- return zone->wp - zone->start;
+- case BLK_ZONE_COND_FULL:
+- return zone->len;
+- case BLK_ZONE_COND_EMPTY:
+- return 0;
+- case BLK_ZONE_COND_NOT_WP:
+- case BLK_ZONE_COND_OFFLINE:
+- case BLK_ZONE_COND_READONLY:
+- default:
+- /*
+- * Conventional, offline and read-only zones do not have a valid
+- * write pointer.
+- */
+- return UINT_MAX;
+- }
+-}
+-
+-static int blk_zone_wplug_report_zone_cb(struct blk_zone *zone,
+- unsigned int idx, void *data)
+-{
+- struct blk_zone *zonep = data;
+-
+- *zonep = *zone;
+- return 0;
+-}
+-
+-static void disk_zone_wplug_handle_error(struct gendisk *disk,
+- struct blk_zone_wplug *zwplug)
+-{
+- sector_t zone_start_sector =
+- bdev_zone_sectors(disk->part0) * zwplug->zone_no;
+- unsigned int noio_flag;
+- struct blk_zone zone;
+- unsigned long flags;
+- int ret;
+-
+- /* Get the current zone information from the device. */
+- noio_flag = memalloc_noio_save();
+- ret = disk->fops->report_zones(disk, zone_start_sector, 1,
+- blk_zone_wplug_report_zone_cb, &zone);
+- memalloc_noio_restore(noio_flag);
+-
+- spin_lock_irqsave(&zwplug->lock, flags);
+-
+- /*
+- * A zone reset or finish may have cleared the error already. In such
+- * case, do nothing as the report zones may have seen the "old" write
+- * pointer value before the reset/finish operation completed.
+- */
+- if (!(zwplug->flags & BLK_ZONE_WPLUG_ERROR))
+- goto unlock;
+-
+- zwplug->flags &= ~BLK_ZONE_WPLUG_ERROR;
+-
+- if (ret != 1) {
+- /*
+- * We failed to get the zone information, meaning that something
+- * is likely really wrong with the device. Abort all remaining
+- * plugged BIOs as otherwise we could endup waiting forever on
+- * plugged BIOs to complete if there is a queue freeze on-going.
+- */
+- disk_zone_wplug_abort(zwplug);
+- goto unplug;
+- }
+-
+- /* Update the zone write pointer offset. */
+- zwplug->wp_offset = blk_zone_wp_offset(&zone);
+- disk_zone_wplug_abort_unaligned(disk, zwplug);
+-
+- /* Restart BIO submission if we still have any BIO left. */
+- if (!bio_list_empty(&zwplug->bio_list)) {
+- disk_zone_wplug_schedule_bio_work(disk, zwplug);
+- goto unlock;
+- }
+-
+-unplug:
+- zwplug->flags &= ~BLK_ZONE_WPLUG_PLUGGED;
+- if (disk_should_remove_zone_wplug(disk, zwplug))
+- disk_remove_zone_wplug(disk, zwplug);
+-
+-unlock:
+- spin_unlock_irqrestore(&zwplug->lock, flags);
+-}
+-
+-static void disk_zone_wplugs_work(struct work_struct *work)
+-{
+- struct gendisk *disk =
+- container_of(work, struct gendisk, zone_wplugs_work);
+- struct blk_zone_wplug *zwplug;
+- unsigned long flags;
+-
+- spin_lock_irqsave(&disk->zone_wplugs_lock, flags);
+-
+- while (!list_empty(&disk->zone_wplugs_err_list)) {
+- zwplug = list_first_entry(&disk->zone_wplugs_err_list,
+- struct blk_zone_wplug, link);
+- list_del_init(&zwplug->link);
+- spin_unlock_irqrestore(&disk->zone_wplugs_lock, flags);
+-
+- disk_zone_wplug_handle_error(disk, zwplug);
+- disk_put_zone_wplug(zwplug);
+-
+- spin_lock_irqsave(&disk->zone_wplugs_lock, flags);
+- }
+-
+- spin_unlock_irqrestore(&disk->zone_wplugs_lock, flags);
+-}
+-
+ static inline unsigned int disk_zone_wplugs_hash_size(struct gendisk *disk)
+ {
+ return 1U << disk->zone_wplugs_hash_bits;
+@@ -1384,8 +1283,6 @@ static inline unsigned int disk_zone_wplugs_hash_size(struct gendisk *disk)
+ void disk_init_zone_resources(struct gendisk *disk)
+ {
+ spin_lock_init(&disk->zone_wplugs_lock);
+- INIT_LIST_HEAD(&disk->zone_wplugs_err_list);
+- INIT_WORK(&disk->zone_wplugs_work, disk_zone_wplugs_work);
+ }
+
+ /*
+@@ -1450,7 +1347,7 @@ static void disk_destroy_zone_wplugs_hash_table(struct gendisk *disk)
+ while (!hlist_empty(&disk->zone_wplugs_hash[i])) {
+ zwplug = hlist_entry(disk->zone_wplugs_hash[i].first,
+ struct blk_zone_wplug, node);
+- atomic_inc(&zwplug->ref);
++ refcount_inc(&zwplug->ref);
+ disk_remove_zone_wplug(disk, zwplug);
+ disk_put_zone_wplug(zwplug);
+ }
+@@ -1484,8 +1381,6 @@ void disk_free_zone_resources(struct gendisk *disk)
+ if (!disk->zone_wplugs_pool)
+ return;
+
+- cancel_work_sync(&disk->zone_wplugs_work);
+-
+ if (disk->zone_wplugs_wq) {
+ destroy_workqueue(disk->zone_wplugs_wq);
+ disk->zone_wplugs_wq = NULL;
+@@ -1682,6 +1577,8 @@ static int blk_revalidate_seq_zone(struct blk_zone *zone, unsigned int idx,
+ if (!disk->zone_wplugs_hash)
+ return 0;
+
++ disk_zone_wplug_sync_wp_offset(disk, zone);
++
+ wp_offset = blk_zone_wp_offset(zone);
+ if (!wp_offset || wp_offset >= zone->capacity)
+ return 0;
+@@ -1818,6 +1715,7 @@ int blk_revalidate_disk_zones(struct gendisk *disk)
+ memalloc_noio_restore(noio_flag);
+ return ret;
+ }
++
+ ret = disk->fops->report_zones(disk, 0, UINT_MAX,
+ blk_revalidate_zone_cb, &args);
+ if (!ret) {
+@@ -1854,6 +1752,48 @@ int blk_revalidate_disk_zones(struct gendisk *disk)
+ }
+ EXPORT_SYMBOL_GPL(blk_revalidate_disk_zones);
+
++/**
++ * blk_zone_issue_zeroout - zero-fill a block range in a zone
++ * @bdev: blockdev to write
++ * @sector: start sector
++ * @nr_sects: number of sectors to write
++ * @gfp_mask: memory allocation flags (for bio_alloc)
++ *
++ * Description:
++ * Zero-fill a block range in a zone (@sector must be equal to the zone write
++ * pointer), handling potential errors due to the (initially unknown) lack of
++ * hardware offload (See blkdev_issue_zeroout()).
++ */
++int blk_zone_issue_zeroout(struct block_device *bdev, sector_t sector,
++ sector_t nr_sects, gfp_t gfp_mask)
++{
++ int ret;
++
++ if (WARN_ON_ONCE(!bdev_is_zoned(bdev)))
++ return -EIO;
++
++ ret = blkdev_issue_zeroout(bdev, sector, nr_sects, gfp_mask,
++ BLKDEV_ZERO_NOFALLBACK);
++ if (ret != -EOPNOTSUPP)
++ return ret;
++
++ /*
++ * The failed call to blkdev_issue_zeroout() advanced the zone write
++ * pointer. Undo this using a report zone to update the zone write
++ * pointer to the correct current value.
++ */
++ ret = disk_zone_sync_wp_offset(bdev->bd_disk, sector);
++ if (ret != 1)
++ return ret < 0 ? ret : -EIO;
++
++ /*
++ * Retry without BLKDEV_ZERO_NOFALLBACK to force the fallback to a
++ * regular write with zero-pages.
++ */
++ return blkdev_issue_zeroout(bdev, sector, nr_sects, gfp_mask, 0);
++}
++EXPORT_SYMBOL_GPL(blk_zone_issue_zeroout);
++
+ #ifdef CONFIG_BLK_DEBUG_FS
+
+ int queue_zone_wplugs_show(void *data, struct seq_file *m)
+@@ -1876,7 +1816,7 @@ int queue_zone_wplugs_show(void *data, struct seq_file *m)
+ spin_lock_irqsave(&zwplug->lock, flags);
+ zwp_zone_no = zwplug->zone_no;
+ zwp_flags = zwplug->flags;
+- zwp_ref = atomic_read(&zwplug->ref);
++ zwp_ref = refcount_read(&zwplug->ref);
+ zwp_wp_offset = zwplug->wp_offset;
+ zwp_bio_list_size = bio_list_size(&zwplug->bio_list);
+ spin_unlock_irqrestore(&zwplug->lock, flags);
+diff --git a/drivers/acpi/acpica/evxfregn.c b/drivers/acpi/acpica/evxfregn.c
+index 95f78383bbdba1..bff2d099f4691e 100644
+--- a/drivers/acpi/acpica/evxfregn.c
++++ b/drivers/acpi/acpica/evxfregn.c
+@@ -232,8 +232,6 @@ acpi_remove_address_space_handler(acpi_handle device,
+
+ /* Now we can delete the handler object */
+
+- acpi_os_release_mutex(handler_obj->address_space.
+- context_mutex);
+ acpi_ut_remove_reference(handler_obj);
+ goto unlock_and_exit;
+ }
+diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
+index 5429ec9ef06f06..a5d47819b3a4e2 100644
+--- a/drivers/acpi/nfit/core.c
++++ b/drivers/acpi/nfit/core.c
+@@ -454,8 +454,13 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
+ if (cmd_rc)
+ *cmd_rc = -EINVAL;
+
+- if (cmd == ND_CMD_CALL)
++ if (cmd == ND_CMD_CALL) {
++ if (!buf || buf_len < sizeof(*call_pkg))
++ return -EINVAL;
++
+ call_pkg = buf;
++ }
++
+ func = cmd_to_func(nfit_mem, cmd, call_pkg, &family);
+ if (func < 0)
+ return func;
+diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
+index 7fe842dae1ec05..821867de43bea3 100644
+--- a/drivers/acpi/resource.c
++++ b/drivers/acpi/resource.c
+@@ -250,6 +250,9 @@ static bool acpi_decode_space(struct resource_win *win,
+ switch (addr->resource_type) {
+ case ACPI_MEMORY_RANGE:
+ acpi_dev_memresource_flags(res, len, wp);
++
++ if (addr->info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
++ res->flags |= IORESOURCE_PREFETCH;
+ break;
+ case ACPI_IO_RANGE:
+ acpi_dev_ioresource_flags(res, len, iodec,
+@@ -265,9 +268,6 @@ static bool acpi_decode_space(struct resource_win *win,
+ if (addr->producer_consumer == ACPI_PRODUCER)
+ res->flags |= IORESOURCE_WINDOW;
+
+- if (addr->info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
+- res->flags |= IORESOURCE_PREFETCH;
+-
+ return !(res->flags & IORESOURCE_DISABLED);
+ }
+
+diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c
+index 63ef7bb073ce03..596c6d294da906 100644
+--- a/drivers/ata/sata_highbank.c
++++ b/drivers/ata/sata_highbank.c
+@@ -348,6 +348,7 @@ static int highbank_initialize_phys(struct device *dev, void __iomem *addr)
+ phy_nodes[phy] = phy_data.np;
+ cphy_base[phy] = of_iomap(phy_nodes[phy], 0);
+ if (cphy_base[phy] == NULL) {
++ of_node_put(phy_data.np);
+ return 0;
+ }
+ phy_count += 1;
+diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
+index 480e4adba9faa6..85e99641eaae02 100644
+--- a/drivers/bluetooth/btmtk.c
++++ b/drivers/bluetooth/btmtk.c
+@@ -395,6 +395,7 @@ int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb)
+ {
+ struct btmtk_data *data = hci_get_priv(hdev);
+ int err;
++ bool complete = false;
+
+ if (!IS_ENABLED(CONFIG_DEV_COREDUMP)) {
+ kfree_skb(skb);
+@@ -416,19 +417,22 @@ int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb)
+ fallthrough;
+ case HCI_DEVCOREDUMP_ACTIVE:
+ default:
++ /* Mediatek coredump data would be more than MTK_COREDUMP_NUM */
++ if (data->cd_info.cnt >= MTK_COREDUMP_NUM &&
++ skb->len > MTK_COREDUMP_END_LEN)
++ if (!memcmp((char *)&skb->data[skb->len - MTK_COREDUMP_END_LEN],
++ MTK_COREDUMP_END, MTK_COREDUMP_END_LEN - 1))
++ complete = true;
++
+ err = hci_devcd_append(hdev, skb);
+ if (err < 0)
+ break;
+ data->cd_info.cnt++;
+
+- /* Mediatek coredump data would be more than MTK_COREDUMP_NUM */
+- if (data->cd_info.cnt > MTK_COREDUMP_NUM &&
+- skb->len > MTK_COREDUMP_END_LEN)
+- if (!memcmp((char *)&skb->data[skb->len - MTK_COREDUMP_END_LEN],
+- MTK_COREDUMP_END, MTK_COREDUMP_END_LEN - 1)) {
+- bt_dev_info(hdev, "Mediatek coredump end");
+- hci_devcd_complete(hdev);
+- }
++ if (complete) {
++ bt_dev_info(hdev, "Mediatek coredump end");
++ hci_devcd_complete(hdev);
++ }
+
+ break;
+ }
+diff --git a/drivers/clk/clk-en7523.c b/drivers/clk/clk-en7523.c
+index bc21b292144926..62a62eaba2aad8 100644
+--- a/drivers/clk/clk-en7523.c
++++ b/drivers/clk/clk-en7523.c
+@@ -92,6 +92,7 @@ static const u32 slic_base[] = { 100000000, 3125000 };
+ static const u32 npu_base[] = { 333000000, 400000000, 500000000 };
+ /* EN7581 */
+ static const u32 emi7581_base[] = { 540000000, 480000000, 400000000, 300000000 };
++static const u32 bus7581_base[] = { 600000000, 540000000 };
+ static const u32 npu7581_base[] = { 800000000, 750000000, 720000000, 600000000 };
+ static const u32 crypto_base[] = { 540000000, 480000000 };
+
+@@ -227,8 +228,8 @@ static const struct en_clk_desc en7581_base_clks[] = {
+ .base_reg = REG_BUS_CLK_DIV_SEL,
+ .base_bits = 1,
+ .base_shift = 8,
+- .base_values = bus_base,
+- .n_base_values = ARRAY_SIZE(bus_base),
++ .base_values = bus7581_base,
++ .n_base_values = ARRAY_SIZE(bus7581_base),
+
+ .div_bits = 3,
+ .div_shift = 0,
+diff --git a/drivers/crypto/hisilicon/debugfs.c b/drivers/crypto/hisilicon/debugfs.c
+index 1b9b7bccdeff08..45e130b901eb5e 100644
+--- a/drivers/crypto/hisilicon/debugfs.c
++++ b/drivers/crypto/hisilicon/debugfs.c
+@@ -192,7 +192,7 @@ static int qm_sqc_dump(struct hisi_qm *qm, char *s, char *name)
+
+ down_read(&qm->qps_lock);
+ if (qm->sqc) {
+- memcpy(&sqc, qm->sqc + qp_id * sizeof(struct qm_sqc), sizeof(struct qm_sqc));
++ memcpy(&sqc, qm->sqc + qp_id, sizeof(struct qm_sqc));
+ sqc.base_h = cpu_to_le32(QM_XQC_ADDR_MASK);
+ sqc.base_l = cpu_to_le32(QM_XQC_ADDR_MASK);
+ dump_show(qm, &sqc, sizeof(struct qm_sqc), "SOFT SQC");
+@@ -229,7 +229,7 @@ static int qm_cqc_dump(struct hisi_qm *qm, char *s, char *name)
+
+ down_read(&qm->qps_lock);
+ if (qm->cqc) {
+- memcpy(&cqc, qm->cqc + qp_id * sizeof(struct qm_cqc), sizeof(struct qm_cqc));
++ memcpy(&cqc, qm->cqc + qp_id, sizeof(struct qm_cqc));
+ cqc.base_h = cpu_to_le32(QM_XQC_ADDR_MASK);
+ cqc.base_l = cpu_to_le32(QM_XQC_ADDR_MASK);
+ dump_show(qm, &cqc, sizeof(struct qm_cqc), "SOFT CQC");
+diff --git a/drivers/gpio/gpio-graniterapids.c b/drivers/gpio/gpio-graniterapids.c
+index f2e911a3d2ca02..ad6a045fd3d2d2 100644
+--- a/drivers/gpio/gpio-graniterapids.c
++++ b/drivers/gpio/gpio-graniterapids.c
+@@ -32,12 +32,14 @@
+ #define GNR_PINS_PER_REG 32
+ #define GNR_NUM_REGS DIV_ROUND_UP(GNR_NUM_PINS, GNR_PINS_PER_REG)
+
+-#define GNR_CFG_BAR 0x00
++#define GNR_CFG_PADBAR 0x00
+ #define GNR_CFG_LOCK_OFFSET 0x04
+-#define GNR_GPI_STATUS_OFFSET 0x20
++#define GNR_GPI_STATUS_OFFSET 0x14
+ #define GNR_GPI_ENABLE_OFFSET 0x24
+
+-#define GNR_CFG_DW_RX_MASK GENMASK(25, 22)
++#define GNR_CFG_DW_HOSTSW_MODE BIT(27)
++#define GNR_CFG_DW_RX_MASK GENMASK(23, 22)
++#define GNR_CFG_DW_INTSEL_MASK GENMASK(21, 14)
+ #define GNR_CFG_DW_RX_DISABLE FIELD_PREP(GNR_CFG_DW_RX_MASK, 2)
+ #define GNR_CFG_DW_RX_EDGE FIELD_PREP(GNR_CFG_DW_RX_MASK, 1)
+ #define GNR_CFG_DW_RX_LEVEL FIELD_PREP(GNR_CFG_DW_RX_MASK, 0)
+@@ -50,6 +52,7 @@
+ * struct gnr_gpio - Intel Granite Rapids-D vGPIO driver state
+ * @gc: GPIO controller interface
+ * @reg_base: base address of the GPIO registers
++ * @pad_base: base address of the vGPIO pad configuration registers
+ * @ro_bitmap: bitmap of read-only pins
+ * @lock: guard the registers
+ * @pad_backup: backup of the register state for suspend
+@@ -57,6 +60,7 @@
+ struct gnr_gpio {
+ struct gpio_chip gc;
+ void __iomem *reg_base;
++ void __iomem *pad_base;
+ DECLARE_BITMAP(ro_bitmap, GNR_NUM_PINS);
+ raw_spinlock_t lock;
+ u32 pad_backup[];
+@@ -65,7 +69,7 @@ struct gnr_gpio {
+ static void __iomem *gnr_gpio_get_padcfg_addr(const struct gnr_gpio *priv,
+ unsigned int gpio)
+ {
+- return priv->reg_base + gpio * sizeof(u32);
++ return priv->pad_base + gpio * sizeof(u32);
+ }
+
+ static int gnr_gpio_configure_line(struct gpio_chip *gc, unsigned int gpio,
+@@ -88,6 +92,20 @@ static int gnr_gpio_configure_line(struct gpio_chip *gc, unsigned int gpio,
+ return 0;
+ }
+
++static int gnr_gpio_request(struct gpio_chip *gc, unsigned int gpio)
++{
++ struct gnr_gpio *priv = gpiochip_get_data(gc);
++ u32 dw;
++
++ dw = readl(gnr_gpio_get_padcfg_addr(priv, gpio));
++ if (!(dw & GNR_CFG_DW_HOSTSW_MODE)) {
++ dev_warn(gc->parent, "GPIO %u is not owned by host", gpio);
++ return -EBUSY;
++ }
++
++ return 0;
++}
++
+ static int gnr_gpio_get(struct gpio_chip *gc, unsigned int gpio)
+ {
+ const struct gnr_gpio *priv = gpiochip_get_data(gc);
+@@ -139,6 +157,7 @@ static int gnr_gpio_direction_output(struct gpio_chip *gc, unsigned int gpio, in
+
+ static const struct gpio_chip gnr_gpio_chip = {
+ .owner = THIS_MODULE,
++ .request = gnr_gpio_request,
+ .get = gnr_gpio_get,
+ .set = gnr_gpio_set,
+ .get_direction = gnr_gpio_get_direction,
+@@ -166,7 +185,7 @@ static void gnr_gpio_irq_ack(struct irq_data *d)
+ guard(raw_spinlock_irqsave)(&priv->lock);
+
+ reg = readl(addr);
+- reg &= ~BIT(bit_idx);
++ reg |= BIT(bit_idx);
+ writel(reg, addr);
+ }
+
+@@ -209,10 +228,18 @@ static void gnr_gpio_irq_unmask(struct irq_data *d)
+ static int gnr_gpio_irq_set_type(struct irq_data *d, unsigned int type)
+ {
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+- irq_hw_number_t pin = irqd_to_hwirq(d);
+- u32 mask = GNR_CFG_DW_RX_MASK;
++ struct gnr_gpio *priv = gpiochip_get_data(gc);
++ irq_hw_number_t hwirq = irqd_to_hwirq(d);
++ u32 reg;
+ u32 set;
+
++ /* Allow interrupts only if Interrupt Select field is non-zero */
++ reg = readl(gnr_gpio_get_padcfg_addr(priv, hwirq));
++ if (!(reg & GNR_CFG_DW_INTSEL_MASK)) {
++ dev_dbg(gc->parent, "GPIO %lu cannot be used as IRQ", hwirq);
++ return -EPERM;
++ }
++
+ /* Falling edge and level low triggers not supported by the GPIO controller */
+ switch (type) {
+ case IRQ_TYPE_NONE:
+@@ -230,10 +257,11 @@ static int gnr_gpio_irq_set_type(struct irq_data *d, unsigned int type)
+ return -EINVAL;
+ }
+
+- return gnr_gpio_configure_line(gc, pin, mask, set);
++ return gnr_gpio_configure_line(gc, hwirq, GNR_CFG_DW_RX_MASK, set);
+ }
+
+ static const struct irq_chip gnr_gpio_irq_chip = {
++ .name = "gpio-graniterapids",
+ .irq_ack = gnr_gpio_irq_ack,
+ .irq_mask = gnr_gpio_irq_mask,
+ .irq_unmask = gnr_gpio_irq_unmask,
+@@ -291,6 +319,7 @@ static int gnr_gpio_probe(struct platform_device *pdev)
+ struct gnr_gpio *priv;
+ void __iomem *regs;
+ int irq, ret;
++ u32 offset;
+
+ priv = devm_kzalloc(dev, struct_size(priv, pad_backup, num_backup_pins), GFP_KERNEL);
+ if (!priv)
+@@ -302,6 +331,10 @@ static int gnr_gpio_probe(struct platform_device *pdev)
+ if (IS_ERR(regs))
+ return PTR_ERR(regs);
+
++ priv->reg_base = regs;
++ offset = readl(priv->reg_base + GNR_CFG_PADBAR);
++ priv->pad_base = priv->reg_base + offset;
++
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+@@ -311,8 +344,6 @@ static int gnr_gpio_probe(struct platform_device *pdev)
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to request interrupt\n");
+
+- priv->reg_base = regs + readl(regs + GNR_CFG_BAR);
+-
+ gnr_gpio_init_pin_ro_bits(dev, priv->reg_base + GNR_CFG_LOCK_OFFSET,
+ priv->ro_bitmap);
+
+@@ -324,7 +355,6 @@ static int gnr_gpio_probe(struct platform_device *pdev)
+
+ girq = &priv->gc.irq;
+ gpio_irq_chip_set_chip(girq, &gnr_gpio_irq_chip);
+- girq->chip->name = dev_name(dev);
+ girq->parent_handler = NULL;
+ girq->num_parents = 0;
+ girq->parents = NULL;
+diff --git a/drivers/gpio/gpio-ljca.c b/drivers/gpio/gpio-ljca.c
+index dfec9fbfc7a9bd..c2a9b425397441 100644
+--- a/drivers/gpio/gpio-ljca.c
++++ b/drivers/gpio/gpio-ljca.c
+@@ -82,9 +82,9 @@ static int ljca_gpio_config(struct ljca_gpio_dev *ljca_gpio, u8 gpio_id,
+ int ret;
+
+ mutex_lock(&ljca_gpio->trans_lock);
++ packet->num = 1;
+ packet->item[0].index = gpio_id;
+ packet->item[0].value = config | ljca_gpio->connect_mode[gpio_id];
+- packet->num = 1;
+
+ ret = ljca_transfer(ljca_gpio->ljca, LJCA_GPIO_CONFIG, (u8 *)packet,
+ struct_size(packet, item, packet->num), NULL, 0);
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+index d891ab779ca7f5..5df21529b3b13e 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+@@ -1801,13 +1801,18 @@ int amdgpu_cs_find_mapping(struct amdgpu_cs_parser *parser,
+ if (dma_resv_locking_ctx((*bo)->tbo.base.resv) != &parser->exec.ticket)
+ return -EINVAL;
+
++ /* Make sure VRAM is allocated contigiously */
+ (*bo)->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;
+- amdgpu_bo_placement_from_domain(*bo, (*bo)->allowed_domains);
+- for (i = 0; i < (*bo)->placement.num_placement; i++)
+- (*bo)->placements[i].flags |= TTM_PL_FLAG_CONTIGUOUS;
+- r = ttm_bo_validate(&(*bo)->tbo, &(*bo)->placement, &ctx);
+- if (r)
+- return r;
++ if ((*bo)->tbo.resource->mem_type == TTM_PL_VRAM &&
++ !((*bo)->tbo.resource->placement & TTM_PL_FLAG_CONTIGUOUS)) {
++
++ amdgpu_bo_placement_from_domain(*bo, (*bo)->allowed_domains);
++ for (i = 0; i < (*bo)->placement.num_placement; i++)
++ (*bo)->placements[i].flags |= TTM_PL_FLAG_CONTIGUOUS;
++ r = ttm_bo_validate(&(*bo)->tbo, &(*bo)->placement, &ctx);
++ if (r)
++ return r;
++ }
+
+ return amdgpu_ttm_alloc_gart(&(*bo)->tbo);
+ }
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
+index 31fd30dcd593ba..65bb26215e867a 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
+@@ -551,6 +551,8 @@ static void amdgpu_uvd_force_into_uvd_segment(struct amdgpu_bo *abo)
+ for (i = 0; i < abo->placement.num_placement; ++i) {
+ abo->placements[i].fpfn = 0 >> PAGE_SHIFT;
+ abo->placements[i].lpfn = (256 * 1024 * 1024) >> PAGE_SHIFT;
++ if (abo->placements[i].mem_type == TTM_PL_VRAM)
++ abo->placements[i].flags |= TTM_PL_FLAG_CONTIGUOUS;
+ }
+ }
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+index 6005280f5f38f0..8d2562d0f143c7 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+@@ -674,12 +674,8 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
+ pasid_mapping_needed &= adev->gmc.gmc_funcs->emit_pasid_mapping &&
+ ring->funcs->emit_wreg;
+
+- if (adev->gfx.enable_cleaner_shader &&
+- ring->funcs->emit_cleaner_shader &&
+- job->enforce_isolation)
+- ring->funcs->emit_cleaner_shader(ring);
+-
+- if (!vm_flush_needed && !gds_switch_needed && !need_pipe_sync)
++ if (!vm_flush_needed && !gds_switch_needed && !need_pipe_sync &&
++ !(job->enforce_isolation && !job->vmid))
+ return 0;
+
+ amdgpu_ring_ib_begin(ring);
+@@ -690,6 +686,11 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
+ if (need_pipe_sync)
+ amdgpu_ring_emit_pipeline_sync(ring);
+
++ if (adev->gfx.enable_cleaner_shader &&
++ ring->funcs->emit_cleaner_shader &&
++ job->enforce_isolation)
++ ring->funcs->emit_cleaner_shader(ring);
++
+ if (vm_flush_needed) {
+ trace_amdgpu_vm_flush(ring, job->vmid, job->vm_pd_addr);
+ amdgpu_ring_emit_vm_flush(ring, job->vmid, job->vm_pd_addr);
+diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c
+index 6068b784dc6938..9a30b8c10838c1 100644
+--- a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c
+@@ -1289,7 +1289,7 @@ static int uvd_v7_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
+ struct amdgpu_job *job,
+ struct amdgpu_ib *ib)
+ {
+- struct amdgpu_ring *ring = to_amdgpu_ring(job->base.sched);
++ struct amdgpu_ring *ring = amdgpu_job_ring(job);
+ unsigned i;
+
+ /* No patching necessary for the first instance */
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
+index 8de61cc524c943..d2993594c848ad 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
+@@ -1422,6 +1422,7 @@ int kfd_parse_crat_table(void *crat_image, struct list_head *device_list,
+
+
+ static int kfd_fill_gpu_cache_info_from_gfx_config(struct kfd_dev *kdev,
++ bool cache_line_size_missing,
+ struct kfd_gpu_cache_info *pcache_info)
+ {
+ struct amdgpu_device *adev = kdev->adev;
+@@ -1436,6 +1437,8 @@ static int kfd_fill_gpu_cache_info_from_gfx_config(struct kfd_dev *kdev,
+ CRAT_CACHE_FLAGS_SIMD_CACHE);
+ pcache_info[i].num_cu_shared = adev->gfx.config.gc_num_tcp_per_wpg / 2;
+ pcache_info[i].cache_line_size = adev->gfx.config.gc_tcp_cache_line_size;
++ if (cache_line_size_missing && !pcache_info[i].cache_line_size)
++ pcache_info[i].cache_line_size = 128;
+ i++;
+ }
+ /* Scalar L1 Instruction Cache per SQC */
+@@ -1448,6 +1451,8 @@ static int kfd_fill_gpu_cache_info_from_gfx_config(struct kfd_dev *kdev,
+ CRAT_CACHE_FLAGS_SIMD_CACHE);
+ pcache_info[i].num_cu_shared = adev->gfx.config.gc_num_sqc_per_wgp * 2;
+ pcache_info[i].cache_line_size = adev->gfx.config.gc_instruction_cache_line_size;
++ if (cache_line_size_missing && !pcache_info[i].cache_line_size)
++ pcache_info[i].cache_line_size = 128;
+ i++;
+ }
+ /* Scalar L1 Data Cache per SQC */
+@@ -1459,6 +1464,8 @@ static int kfd_fill_gpu_cache_info_from_gfx_config(struct kfd_dev *kdev,
+ CRAT_CACHE_FLAGS_SIMD_CACHE);
+ pcache_info[i].num_cu_shared = adev->gfx.config.gc_num_sqc_per_wgp * 2;
+ pcache_info[i].cache_line_size = adev->gfx.config.gc_scalar_data_cache_line_size;
++ if (cache_line_size_missing && !pcache_info[i].cache_line_size)
++ pcache_info[i].cache_line_size = 64;
+ i++;
+ }
+ /* GL1 Data Cache per SA */
+@@ -1471,7 +1478,8 @@ static int kfd_fill_gpu_cache_info_from_gfx_config(struct kfd_dev *kdev,
+ CRAT_CACHE_FLAGS_DATA_CACHE |
+ CRAT_CACHE_FLAGS_SIMD_CACHE);
+ pcache_info[i].num_cu_shared = adev->gfx.config.max_cu_per_sh;
+- pcache_info[i].cache_line_size = 0;
++ if (cache_line_size_missing)
++ pcache_info[i].cache_line_size = 128;
+ i++;
+ }
+ /* L2 Data Cache per GPU (Total Tex Cache) */
+@@ -1483,6 +1491,8 @@ static int kfd_fill_gpu_cache_info_from_gfx_config(struct kfd_dev *kdev,
+ CRAT_CACHE_FLAGS_SIMD_CACHE);
+ pcache_info[i].num_cu_shared = adev->gfx.config.max_cu_per_sh;
+ pcache_info[i].cache_line_size = adev->gfx.config.gc_tcc_cache_line_size;
++ if (cache_line_size_missing && !pcache_info[i].cache_line_size)
++ pcache_info[i].cache_line_size = 128;
+ i++;
+ }
+ /* L3 Data Cache per GPU */
+@@ -1493,7 +1503,7 @@ static int kfd_fill_gpu_cache_info_from_gfx_config(struct kfd_dev *kdev,
+ CRAT_CACHE_FLAGS_DATA_CACHE |
+ CRAT_CACHE_FLAGS_SIMD_CACHE);
+ pcache_info[i].num_cu_shared = adev->gfx.config.max_cu_per_sh;
+- pcache_info[i].cache_line_size = 0;
++ pcache_info[i].cache_line_size = 64;
+ i++;
+ }
+ return i;
+@@ -1568,6 +1578,7 @@ static int kfd_fill_gpu_cache_info_from_gfx_config_v2(struct kfd_dev *kdev,
+ int kfd_get_gpu_cache_info(struct kfd_node *kdev, struct kfd_gpu_cache_info **pcache_info)
+ {
+ int num_of_cache_types = 0;
++ bool cache_line_size_missing = false;
+
+ switch (kdev->adev->asic_type) {
+ case CHIP_KAVERI:
+@@ -1691,10 +1702,17 @@ int kfd_get_gpu_cache_info(struct kfd_node *kdev, struct kfd_gpu_cache_info **pc
+ case IP_VERSION(11, 5, 0):
+ case IP_VERSION(11, 5, 1):
+ case IP_VERSION(11, 5, 2):
++ /* Cacheline size not available in IP discovery for gc11.
++ * kfd_fill_gpu_cache_info_from_gfx_config to hard code it
++ */
++ cache_line_size_missing = true;
++ fallthrough;
+ case IP_VERSION(12, 0, 0):
+ case IP_VERSION(12, 0, 1):
+ num_of_cache_types =
+- kfd_fill_gpu_cache_info_from_gfx_config(kdev->kfd, *pcache_info);
++ kfd_fill_gpu_cache_info_from_gfx_config(kdev->kfd,
++ cache_line_size_missing,
++ *pcache_info);
+ break;
+ default:
+ *pcache_info = dummy_cache_info;
+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 648f40091aa395..f5b3ed20e891b3 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
+@@ -205,6 +205,21 @@ static int add_queue_mes(struct device_queue_manager *dqm, struct queue *q,
+ if (!down_read_trylock(&adev->reset_domain->sem))
+ 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_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+index ff34bb1ac9db79..3139987b82b100 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+@@ -1076,7 +1076,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);
+ /*
+@@ -1610,7 +1611,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;
+@@ -1634,21 +1634,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) {
+- dev_err(dev->adev->dev,
+- "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(
+@@ -1660,10 +1645,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;
+ }
+
+ /**
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
+index 01b960b152743d..ead4317a21680b 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
+@@ -212,13 +212,17 @@ static void pqm_clean_queue_resource(struct process_queue_manager *pqm,
+ void pqm_uninit(struct process_queue_manager *pqm)
+ {
+ struct process_queue_node *pqn, *next;
+- struct kfd_process_device *pdd;
+
+ list_for_each_entry_safe(pqn, next, &pqm->queues, process_queue_list) {
+ if (pqn->q) {
+- pdd = kfd_get_process_device_data(pqn->q->device, pqm->process);
+- kfd_queue_unref_bo_vas(pdd, &pqn->q->properties);
+- kfd_queue_release_buffers(pdd, &pqn->q->properties);
++ struct kfd_process_device *pdd = kfd_get_process_device_data(pqn->q->device,
++ pqm->process);
++ if (pdd) {
++ kfd_queue_unref_bo_vas(pdd, &pqn->q->properties);
++ kfd_queue_release_buffers(pdd, &pqn->q->properties);
++ } else {
++ WARN_ON(!pdd);
++ }
+ pqm_clean_queue_resource(pqm, pqn);
+ }
+
+diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
+index d0e6d051e9cf9f..1aedfafa507f7e 100644
+--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
+@@ -2717,4 +2717,5 @@ void smu_v13_0_7_set_ppt_funcs(struct smu_context *smu)
+ smu->workload_map = smu_v13_0_7_workload_map;
+ smu->smc_driver_if_version = SMU13_0_7_DRIVER_IF_VERSION;
+ smu_v13_0_set_smu_mailbox_registers(smu);
++ smu->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
+ }
+diff --git a/drivers/gpu/drm/drm_panic_qr.rs b/drivers/gpu/drm/drm_panic_qr.rs
+index 1ef56cb07dfbd2..447740d79d3d2e 100644
+--- a/drivers/gpu/drm/drm_panic_qr.rs
++++ b/drivers/gpu/drm/drm_panic_qr.rs
+@@ -929,7 +929,6 @@ fn draw_all(&mut self, data: impl Iterator<Item = u8>) {
+ /// * `tmp` must be valid for reading and writing for `tmp_size` bytes.
+ ///
+ /// They must remain valid for the duration of the function call.
+-
+ #[no_mangle]
+ pub unsafe extern "C" fn drm_panic_qr_generate(
+ url: *const i8,
+diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c
+index 5d701f48351b96..ec55cb651d4498 100644
+--- a/drivers/gpu/drm/i915/display/intel_color.c
++++ b/drivers/gpu/drm/i915/display/intel_color.c
+@@ -1333,19 +1333,29 @@ static void ilk_load_lut_8(const struct intel_crtc_state *crtc_state,
+ lut = blob->data;
+
+ /*
+- * DSB fails to correctly load the legacy LUT
+- * unless we either write each entry twice,
+- * or use non-posted writes
++ * DSB fails to correctly load the legacy LUT unless
++ * we either write each entry twice when using posted
++ * writes, or we use non-posted writes.
++ *
++ * If palette anti-collision is active during LUT
++ * register writes:
++ * - posted writes simply get dropped and thus the LUT
++ * contents may not be correctly updated
++ * - non-posted writes are blocked and thus the LUT
++ * contents are always correct, but simultaneous CPU
++ * MMIO access will start to fail
++ *
++ * Choose the lesser of two evils and use posted writes.
++ * Using posted writes is also faster, even when having
++ * to write each register twice.
+ */
+- if (crtc_state->dsb_color_vblank)
+- intel_dsb_nonpost_start(crtc_state->dsb_color_vblank);
+-
+- for (i = 0; i < 256; i++)
++ for (i = 0; i < 256; i++) {
+ ilk_lut_write(crtc_state, LGC_PALETTE(pipe, i),
+ i9xx_lut_8(&lut[i]));
+-
+- if (crtc_state->dsb_color_vblank)
+- intel_dsb_nonpost_end(crtc_state->dsb_color_vblank);
++ if (crtc_state->dsb_color_vblank)
++ ilk_lut_write(crtc_state, LGC_PALETTE(pipe, i),
++ i9xx_lut_8(&lut[i]));
++ }
+ }
+
+ static void ilk_load_lut_10(const struct intel_crtc_state *crtc_state,
+diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
+index 6469b9bcf2ec44..082ac72c757a9f 100644
+--- a/drivers/gpu/drm/i915/i915_gpu_error.c
++++ b/drivers/gpu/drm/i915/i915_gpu_error.c
+@@ -1652,9 +1652,21 @@ capture_engine(struct intel_engine_cs *engine,
+ return NULL;
+
+ intel_engine_get_hung_entity(engine, &ce, &rq);
+- if (rq && !i915_request_started(rq))
+- drm_info(&engine->gt->i915->drm, "Got hung context on %s with active request %lld:%lld [0x%04X] not yet started\n",
+- engine->name, rq->fence.context, rq->fence.seqno, ce->guc_id.id);
++ if (rq && !i915_request_started(rq)) {
++ /*
++ * We want to know also what is the guc_id of the context,
++ * but if we don't have the context reference, then skip
++ * printing it.
++ */
++ if (ce)
++ drm_info(&engine->gt->i915->drm,
++ "Got hung context on %s with active request %lld:%lld [0x%04X] not yet started\n",
++ engine->name, rq->fence.context, rq->fence.seqno, ce->guc_id.id);
++ else
++ drm_info(&engine->gt->i915->drm,
++ "Got hung context on %s with active request %lld:%lld not yet started\n",
++ engine->name, rq->fence.context, rq->fence.seqno);
++ }
+
+ if (rq) {
+ capture = intel_engine_coredump_add_request(ee, rq, ATOMIC_MAYFAIL);
+diff --git a/drivers/gpu/drm/i915/i915_scheduler.c b/drivers/gpu/drm/i915/i915_scheduler.c
+index 762127dd56c538..70a854557e6ec5 100644
+--- a/drivers/gpu/drm/i915/i915_scheduler.c
++++ b/drivers/gpu/drm/i915/i915_scheduler.c
+@@ -506,6 +506,6 @@ int __init i915_scheduler_module_init(void)
+ return 0;
+
+ err_priorities:
+- kmem_cache_destroy(slab_priorities);
++ kmem_cache_destroy(slab_dependencies);
+ return -ENOMEM;
+ }
+diff --git a/drivers/gpu/drm/xe/tests/xe_migrate.c b/drivers/gpu/drm/xe/tests/xe_migrate.c
+index 1a192a2a941b69..3bbdb362d6f0dc 100644
+--- a/drivers/gpu/drm/xe/tests/xe_migrate.c
++++ b/drivers/gpu/drm/xe/tests/xe_migrate.c
+@@ -224,8 +224,8 @@ static void xe_migrate_sanity_test(struct xe_migrate *m, struct kunit *test)
+ XE_BO_FLAG_VRAM_IF_DGFX(tile) |
+ XE_BO_FLAG_PINNED);
+ if (IS_ERR(tiny)) {
+- KUNIT_FAIL(test, "Failed to allocate fake pt: %li\n",
+- PTR_ERR(pt));
++ KUNIT_FAIL(test, "Failed to allocate tiny fake pt: %li\n",
++ PTR_ERR(tiny));
+ goto free_pt;
+ }
+
+diff --git a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c
+index 9d82ea30f4df23..7e385940df0863 100644
+--- a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c
++++ b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c
+@@ -65,6 +65,14 @@ invalidation_fence_signal(struct xe_device *xe, struct xe_gt_tlb_invalidation_fe
+ __invalidation_fence_signal(xe, fence);
+ }
+
++void xe_gt_tlb_invalidation_fence_signal(struct xe_gt_tlb_invalidation_fence *fence)
++{
++ if (WARN_ON_ONCE(!fence->gt))
++ return;
++
++ __invalidation_fence_signal(gt_to_xe(fence->gt), fence);
++}
++
+ static void xe_gt_tlb_fence_timeout(struct work_struct *work)
+ {
+ struct xe_gt *gt = container_of(work, struct xe_gt,
+diff --git a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h
+index f430d5797af701..00b1c6c01e8d95 100644
+--- a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h
++++ b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h
+@@ -28,6 +28,7 @@ int xe_guc_tlb_invalidation_done_handler(struct xe_guc *guc, u32 *msg, u32 len);
+ void xe_gt_tlb_invalidation_fence_init(struct xe_gt *gt,
+ struct xe_gt_tlb_invalidation_fence *fence,
+ bool stack);
++void xe_gt_tlb_invalidation_fence_signal(struct xe_gt_tlb_invalidation_fence *fence);
+
+ static inline void
+ xe_gt_tlb_invalidation_fence_wait(struct xe_gt_tlb_invalidation_fence *fence)
+diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
+index f27f579f4d85aa..797576690356f2 100644
+--- a/drivers/gpu/drm/xe/xe_pt.c
++++ b/drivers/gpu/drm/xe/xe_pt.c
+@@ -1333,8 +1333,7 @@ static void invalidation_fence_cb(struct dma_fence *fence,
+ queue_work(system_wq, &ifence->work);
+ } else {
+ ifence->base.base.error = ifence->fence->error;
+- dma_fence_signal(&ifence->base.base);
+- dma_fence_put(&ifence->base.base);
++ xe_gt_tlb_invalidation_fence_signal(&ifence->base);
+ }
+ dma_fence_put(ifence->fence);
+ }
+diff --git a/drivers/gpu/drm/xe/xe_reg_sr.c b/drivers/gpu/drm/xe/xe_reg_sr.c
+index 440ac572f6e5ef..52969c0909659d 100644
+--- a/drivers/gpu/drm/xe/xe_reg_sr.c
++++ b/drivers/gpu/drm/xe/xe_reg_sr.c
+@@ -26,46 +26,27 @@
+ #include "xe_reg_whitelist.h"
+ #include "xe_rtp_types.h"
+
+-#define XE_REG_SR_GROW_STEP_DEFAULT 16
+-
+ static void reg_sr_fini(struct drm_device *drm, void *arg)
+ {
+ struct xe_reg_sr *sr = arg;
++ struct xe_reg_sr_entry *entry;
++ unsigned long reg;
++
++ xa_for_each(&sr->xa, reg, entry)
++ kfree(entry);
+
+ xa_destroy(&sr->xa);
+- kfree(sr->pool.arr);
+- memset(&sr->pool, 0, sizeof(sr->pool));
+ }
+
+ int xe_reg_sr_init(struct xe_reg_sr *sr, const char *name, struct xe_device *xe)
+ {
+ xa_init(&sr->xa);
+- memset(&sr->pool, 0, sizeof(sr->pool));
+- sr->pool.grow_step = XE_REG_SR_GROW_STEP_DEFAULT;
+ sr->name = name;
+
+ return drmm_add_action_or_reset(&xe->drm, reg_sr_fini, sr);
+ }
+ EXPORT_SYMBOL_IF_KUNIT(xe_reg_sr_init);
+
+-static struct xe_reg_sr_entry *alloc_entry(struct xe_reg_sr *sr)
+-{
+- if (sr->pool.used == sr->pool.allocated) {
+- struct xe_reg_sr_entry *arr;
+-
+- arr = krealloc_array(sr->pool.arr,
+- ALIGN(sr->pool.allocated + 1, sr->pool.grow_step),
+- sizeof(*arr), GFP_KERNEL);
+- if (!arr)
+- return NULL;
+-
+- sr->pool.arr = arr;
+- sr->pool.allocated += sr->pool.grow_step;
+- }
+-
+- return &sr->pool.arr[sr->pool.used++];
+-}
+-
+ static bool compatible_entries(const struct xe_reg_sr_entry *e1,
+ const struct xe_reg_sr_entry *e2)
+ {
+@@ -111,7 +92,7 @@ int xe_reg_sr_add(struct xe_reg_sr *sr,
+ return 0;
+ }
+
+- pentry = alloc_entry(sr);
++ pentry = kmalloc(sizeof(*pentry), GFP_KERNEL);
+ if (!pentry) {
+ ret = -ENOMEM;
+ goto fail;
+diff --git a/drivers/gpu/drm/xe/xe_reg_sr_types.h b/drivers/gpu/drm/xe/xe_reg_sr_types.h
+index ad48a52b824a18..ebe11f237fa26d 100644
+--- a/drivers/gpu/drm/xe/xe_reg_sr_types.h
++++ b/drivers/gpu/drm/xe/xe_reg_sr_types.h
+@@ -20,12 +20,6 @@ struct xe_reg_sr_entry {
+ };
+
+ struct xe_reg_sr {
+- struct {
+- struct xe_reg_sr_entry *arr;
+- unsigned int used;
+- unsigned int allocated;
+- unsigned int grow_step;
+- } pool;
+ struct xarray xa;
+ const char *name;
+
+diff --git a/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c b/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c
+index c8ec74f089f3d6..6e41ddaa24d636 100644
+--- a/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c
++++ b/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c
+@@ -339,7 +339,7 @@ tegra241_cmdqv_get_cmdq(struct arm_smmu_device *smmu,
+ * one CPU at a time can enter the process, while the others
+ * will be spinning at the same lock.
+ */
+- lidx = smp_processor_id() % cmdqv->num_lvcmdqs_per_vintf;
++ lidx = raw_smp_processor_id() % cmdqv->num_lvcmdqs_per_vintf;
+ vcmdq = vintf->lvcmdqs[lidx];
+ if (!vcmdq || !READ_ONCE(vcmdq->enabled))
+ return NULL;
+diff --git a/drivers/iommu/intel/cache.c b/drivers/iommu/intel/cache.c
+index e5b89f728ad3b2..09694cca8752df 100644
+--- a/drivers/iommu/intel/cache.c
++++ b/drivers/iommu/intel/cache.c
+@@ -105,12 +105,35 @@ static void cache_tag_unassign(struct dmar_domain *domain, u16 did,
+ spin_unlock_irqrestore(&domain->cache_lock, flags);
+ }
+
++/* domain->qi_batch will be freed in iommu_free_domain() path. */
++static int domain_qi_batch_alloc(struct dmar_domain *domain)
++{
++ unsigned long flags;
++ int ret = 0;
++
++ spin_lock_irqsave(&domain->cache_lock, flags);
++ if (domain->qi_batch)
++ goto out_unlock;
++
++ domain->qi_batch = kzalloc(sizeof(*domain->qi_batch), GFP_ATOMIC);
++ if (!domain->qi_batch)
++ ret = -ENOMEM;
++out_unlock:
++ spin_unlock_irqrestore(&domain->cache_lock, flags);
++
++ return ret;
++}
++
+ static int __cache_tag_assign_domain(struct dmar_domain *domain, u16 did,
+ struct device *dev, ioasid_t pasid)
+ {
+ struct device_domain_info *info = dev_iommu_priv_get(dev);
+ int ret;
+
++ ret = domain_qi_batch_alloc(domain);
++ if (ret)
++ return ret;
++
+ ret = cache_tag_assign(domain, did, dev, pasid, CACHE_TAG_IOTLB);
+ if (ret || !info->ats_enabled)
+ return ret;
+@@ -139,6 +162,10 @@ static int __cache_tag_assign_parent_domain(struct dmar_domain *domain, u16 did,
+ struct device_domain_info *info = dev_iommu_priv_get(dev);
+ int ret;
+
++ ret = domain_qi_batch_alloc(domain);
++ if (ret)
++ return ret;
++
+ ret = cache_tag_assign(domain, did, dev, pasid, CACHE_TAG_NESTING_IOTLB);
+ if (ret || !info->ats_enabled)
+ return ret;
+@@ -190,13 +217,6 @@ int cache_tag_assign_domain(struct dmar_domain *domain,
+ u16 did = domain_get_id_for_dev(domain, dev);
+ int ret;
+
+- /* domain->qi_bach will be freed in iommu_free_domain() path. */
+- if (!domain->qi_batch) {
+- domain->qi_batch = kzalloc(sizeof(*domain->qi_batch), GFP_KERNEL);
+- if (!domain->qi_batch)
+- return -ENOMEM;
+- }
+-
+ ret = __cache_tag_assign_domain(domain, did, dev, pasid);
+ if (ret || domain->domain.type != IOMMU_DOMAIN_NESTED)
+ return ret;
+diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
+index a167d59101ae2e..cc23cfcdeb2d59 100644
+--- a/drivers/iommu/intel/iommu.c
++++ b/drivers/iommu/intel/iommu.c
+@@ -3372,6 +3372,9 @@ void device_block_translation(struct device *dev)
+ struct intel_iommu *iommu = info->iommu;
+ unsigned long flags;
+
++ if (info->domain)
++ cache_tag_unassign_domain(info->domain, dev, IOMMU_NO_PASID);
++
+ iommu_disable_pci_caps(info);
+ if (!dev_is_real_dma_subdevice(dev)) {
+ if (sm_supported(iommu))
+@@ -3388,7 +3391,6 @@ void device_block_translation(struct device *dev)
+ list_del(&info->link);
+ spin_unlock_irqrestore(&info->domain->lock, flags);
+
+- cache_tag_unassign_domain(info->domain, dev, IOMMU_NO_PASID);
+ domain_detach_iommu(info->domain, iommu);
+ info->domain = NULL;
+ }
+diff --git a/drivers/md/dm-zoned-reclaim.c b/drivers/md/dm-zoned-reclaim.c
+index d58db9a27e6cfd..76e2c686854871 100644
+--- a/drivers/md/dm-zoned-reclaim.c
++++ b/drivers/md/dm-zoned-reclaim.c
+@@ -76,9 +76,9 @@ static int dmz_reclaim_align_wp(struct dmz_reclaim *zrc, struct dm_zone *zone,
+ * pointer and the requested position.
+ */
+ nr_blocks = block - wp_block;
+- ret = blkdev_issue_zeroout(dev->bdev,
+- dmz_start_sect(zmd, zone) + dmz_blk2sect(wp_block),
+- dmz_blk2sect(nr_blocks), GFP_NOIO, 0);
++ ret = blk_zone_issue_zeroout(dev->bdev,
++ dmz_start_sect(zmd, zone) + dmz_blk2sect(wp_block),
++ dmz_blk2sect(nr_blocks), GFP_NOIO);
+ if (ret) {
+ dmz_dev_err(dev,
+ "Align zone %u wp %llu to %llu (wp+%u) blocks failed %d",
+diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
+index 15e0f14d0d49de..4d73abae503d1e 100644
+--- a/drivers/net/bonding/bond_main.c
++++ b/drivers/net/bonding/bond_main.c
+@@ -1520,9 +1520,7 @@ static netdev_features_t bond_fix_features(struct net_device *dev,
+ struct slave *slave;
+
+ mask = features;
+-
+- features &= ~NETIF_F_ONE_FOR_ALL;
+- features |= NETIF_F_ALL_FOR_ALL;
++ features = netdev_base_features(features);
+
+ bond_for_each_slave(bond, slave, iter) {
+ features = netdev_increment_features(features,
+@@ -1536,6 +1534,7 @@ static netdev_features_t bond_fix_features(struct net_device *dev,
+
+ #define BOND_VLAN_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | \
+ NETIF_F_FRAGLIST | NETIF_F_GSO_SOFTWARE | \
++ NETIF_F_GSO_ENCAP_ALL | \
+ NETIF_F_HIGHDMA | NETIF_F_LRO)
+
+ #define BOND_ENC_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | \
+@@ -1564,8 +1563,9 @@ static void bond_compute_features(struct bonding *bond)
+
+ if (!bond_has_slaves(bond))
+ goto done;
+- vlan_features &= NETIF_F_ALL_FOR_ALL;
+- mpls_features &= NETIF_F_ALL_FOR_ALL;
++
++ vlan_features = netdev_base_features(vlan_features);
++ mpls_features = netdev_base_features(mpls_features);
+
+ bond_for_each_slave(bond, slave, iter) {
+ vlan_features = netdev_increment_features(vlan_features,
+diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
+index 5290f5ad98f392..bf26cd0abf6dd9 100644
+--- a/drivers/net/dsa/microchip/ksz_common.c
++++ b/drivers/net/dsa/microchip/ksz_common.c
+@@ -1098,10 +1098,9 @@ static const struct regmap_range ksz9896_valid_regs[] = {
+ regmap_reg_range(0x1030, 0x1030),
+ regmap_reg_range(0x1100, 0x1115),
+ regmap_reg_range(0x111a, 0x111f),
+- regmap_reg_range(0x1122, 0x1127),
+- regmap_reg_range(0x112a, 0x112b),
+- regmap_reg_range(0x1136, 0x1139),
+- regmap_reg_range(0x113e, 0x113f),
++ regmap_reg_range(0x1120, 0x112b),
++ regmap_reg_range(0x1134, 0x113b),
++ regmap_reg_range(0x113c, 0x113f),
+ regmap_reg_range(0x1400, 0x1401),
+ regmap_reg_range(0x1403, 0x1403),
+ regmap_reg_range(0x1410, 0x1417),
+@@ -1128,10 +1127,9 @@ static const struct regmap_range ksz9896_valid_regs[] = {
+ regmap_reg_range(0x2030, 0x2030),
+ regmap_reg_range(0x2100, 0x2115),
+ regmap_reg_range(0x211a, 0x211f),
+- regmap_reg_range(0x2122, 0x2127),
+- regmap_reg_range(0x212a, 0x212b),
+- regmap_reg_range(0x2136, 0x2139),
+- regmap_reg_range(0x213e, 0x213f),
++ regmap_reg_range(0x2120, 0x212b),
++ regmap_reg_range(0x2134, 0x213b),
++ regmap_reg_range(0x213c, 0x213f),
+ regmap_reg_range(0x2400, 0x2401),
+ regmap_reg_range(0x2403, 0x2403),
+ regmap_reg_range(0x2410, 0x2417),
+@@ -1158,10 +1156,9 @@ static const struct regmap_range ksz9896_valid_regs[] = {
+ regmap_reg_range(0x3030, 0x3030),
+ regmap_reg_range(0x3100, 0x3115),
+ regmap_reg_range(0x311a, 0x311f),
+- regmap_reg_range(0x3122, 0x3127),
+- regmap_reg_range(0x312a, 0x312b),
+- regmap_reg_range(0x3136, 0x3139),
+- regmap_reg_range(0x313e, 0x313f),
++ regmap_reg_range(0x3120, 0x312b),
++ regmap_reg_range(0x3134, 0x313b),
++ regmap_reg_range(0x313c, 0x313f),
+ regmap_reg_range(0x3400, 0x3401),
+ regmap_reg_range(0x3403, 0x3403),
+ regmap_reg_range(0x3410, 0x3417),
+@@ -1188,10 +1185,9 @@ static const struct regmap_range ksz9896_valid_regs[] = {
+ regmap_reg_range(0x4030, 0x4030),
+ regmap_reg_range(0x4100, 0x4115),
+ regmap_reg_range(0x411a, 0x411f),
+- regmap_reg_range(0x4122, 0x4127),
+- regmap_reg_range(0x412a, 0x412b),
+- regmap_reg_range(0x4136, 0x4139),
+- regmap_reg_range(0x413e, 0x413f),
++ regmap_reg_range(0x4120, 0x412b),
++ regmap_reg_range(0x4134, 0x413b),
++ regmap_reg_range(0x413c, 0x413f),
+ regmap_reg_range(0x4400, 0x4401),
+ regmap_reg_range(0x4403, 0x4403),
+ regmap_reg_range(0x4410, 0x4417),
+@@ -1218,10 +1214,9 @@ static const struct regmap_range ksz9896_valid_regs[] = {
+ regmap_reg_range(0x5030, 0x5030),
+ regmap_reg_range(0x5100, 0x5115),
+ regmap_reg_range(0x511a, 0x511f),
+- regmap_reg_range(0x5122, 0x5127),
+- regmap_reg_range(0x512a, 0x512b),
+- regmap_reg_range(0x5136, 0x5139),
+- regmap_reg_range(0x513e, 0x513f),
++ regmap_reg_range(0x5120, 0x512b),
++ regmap_reg_range(0x5134, 0x513b),
++ regmap_reg_range(0x513c, 0x513f),
+ regmap_reg_range(0x5400, 0x5401),
+ regmap_reg_range(0x5403, 0x5403),
+ regmap_reg_range(0x5410, 0x5417),
+@@ -1248,10 +1243,9 @@ static const struct regmap_range ksz9896_valid_regs[] = {
+ regmap_reg_range(0x6030, 0x6030),
+ regmap_reg_range(0x6100, 0x6115),
+ regmap_reg_range(0x611a, 0x611f),
+- regmap_reg_range(0x6122, 0x6127),
+- regmap_reg_range(0x612a, 0x612b),
+- regmap_reg_range(0x6136, 0x6139),
+- regmap_reg_range(0x613e, 0x613f),
++ regmap_reg_range(0x6120, 0x612b),
++ regmap_reg_range(0x6134, 0x613b),
++ regmap_reg_range(0x613c, 0x613f),
+ regmap_reg_range(0x6300, 0x6301),
+ regmap_reg_range(0x6400, 0x6401),
+ regmap_reg_range(0x6403, 0x6403),
+diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c
+index 0102a82e88cc61..940f1b71226d64 100644
+--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
++++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
+@@ -24,7 +24,7 @@
+ #define VSC9959_NUM_PORTS 6
+
+ #define VSC9959_TAS_GCL_ENTRY_MAX 63
+-#define VSC9959_TAS_MIN_GATE_LEN_NS 33
++#define VSC9959_TAS_MIN_GATE_LEN_NS 35
+ #define VSC9959_VCAP_POLICER_BASE 63
+ #define VSC9959_VCAP_POLICER_MAX 383
+ #define VSC9959_SWITCH_PCI_BAR 4
+@@ -1056,11 +1056,15 @@ static void vsc9959_mdio_bus_free(struct ocelot *ocelot)
+ mdiobus_free(felix->imdio);
+ }
+
+-/* The switch considers any frame (regardless of size) as eligible for
+- * transmission if the traffic class gate is open for at least 33 ns.
++/* The switch considers any frame (regardless of size) as eligible
++ * for transmission if the traffic class gate is open for at least
++ * VSC9959_TAS_MIN_GATE_LEN_NS.
++ *
+ * Overruns are prevented by cropping an interval at the end of the gate time
+- * slot for which egress scheduling is blocked, but we need to still keep 33 ns
+- * available for one packet to be transmitted, otherwise the port tc will hang.
++ * slot for which egress scheduling is blocked, but we need to still keep
++ * VSC9959_TAS_MIN_GATE_LEN_NS available for one packet to be transmitted,
++ * otherwise the port tc will hang.
++ *
+ * This function returns the size of a gate interval that remains available for
+ * setting the guard band, after reserving the space for one egress frame.
+ */
+@@ -1303,7 +1307,8 @@ static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port)
+ * per-tc static guard band lengths, so it reduces the
+ * useful gate interval length. Therefore, be careful
+ * to calculate a guard band (and therefore max_sdu)
+- * that still leaves 33 ns available in the time slot.
++ * that still leaves VSC9959_TAS_MIN_GATE_LEN_NS
++ * available in the time slot.
+ */
+ max_sdu = div_u64(remaining_gate_len_ps, picos_per_byte);
+ /* A TC gate may be completely closed, which is a
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index 3d9ee91e1f8be0..dafc5a4039cd2c 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -1518,7 +1518,7 @@ static void bnxt_tpa_start(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
+ if (TPA_START_IS_IPV6(tpa_start1))
+ tpa_info->gso_type = SKB_GSO_TCPV6;
+ /* RSS profiles 1 and 3 with extract code 0 for inner 4-tuple */
+- else if (cmp_type == CMP_TYPE_RX_L2_TPA_START_CMP &&
++ else if (!BNXT_CHIP_P4_PLUS(bp) &&
+ TPA_START_HASH_TYPE(tpa_start) == 3)
+ tpa_info->gso_type = SKB_GSO_TCPV6;
+ tpa_info->rss_hash =
+@@ -2212,15 +2212,13 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
+ if (cmp_type == CMP_TYPE_RX_L2_V3_CMP) {
+ type = bnxt_rss_ext_op(bp, rxcmp);
+ } else {
+- u32 hash_type = RX_CMP_HASH_TYPE(rxcmp);
++ u32 itypes = RX_CMP_ITYPES(rxcmp);
+
+- /* RSS profiles 1 and 3 with extract code 0 for inner
+- * 4-tuple
+- */
+- if (hash_type != 1 && hash_type != 3)
+- type = PKT_HASH_TYPE_L3;
+- else
++ if (itypes == RX_CMP_FLAGS_ITYPE_TCP ||
++ itypes == RX_CMP_FLAGS_ITYPE_UDP)
+ type = PKT_HASH_TYPE_L4;
++ else
++ type = PKT_HASH_TYPE_L3;
+ }
+ skb_set_hash(skb, le32_to_cpu(rxcmp->rx_cmp_rss_hash), type);
+ }
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+index 69231e85140b2e..9e05704d94450e 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+@@ -267,6 +267,9 @@ struct rx_cmp {
+ (((le32_to_cpu((rxcmp)->rx_cmp_misc_v1) & RX_CMP_RSS_HASH_TYPE) >>\
+ RX_CMP_RSS_HASH_TYPE_SHIFT) & RSS_PROFILE_ID_MASK)
+
++#define RX_CMP_ITYPES(rxcmp) \
++ (le32_to_cpu((rxcmp)->rx_cmp_len_flags_type) & RX_CMP_FLAGS_ITYPES_MASK)
++
+ #define RX_CMP_V3_HASH_TYPE_LEGACY(rxcmp) \
+ ((le32_to_cpu((rxcmp)->rx_cmp_misc_v1) & RX_CMP_V3_RSS_EXT_OP_LEGACY) >>\
+ RX_CMP_V3_RSS_EXT_OP_LEGACY_SHIFT)
+@@ -378,7 +381,7 @@ struct rx_agg_cmp {
+ u32 rx_agg_cmp_opaque;
+ __le32 rx_agg_cmp_v;
+ #define RX_AGG_CMP_V (1 << 0)
+- #define RX_AGG_CMP_AGG_ID (0xffff << 16)
++ #define RX_AGG_CMP_AGG_ID (0x0fff << 16)
+ #define RX_AGG_CMP_AGG_ID_SHIFT 16
+ __le32 rx_agg_cmp_unused;
+ };
+@@ -416,7 +419,7 @@ struct rx_tpa_start_cmp {
+ #define RX_TPA_START_CMP_V3_RSS_HASH_TYPE_SHIFT 7
+ #define RX_TPA_START_CMP_AGG_ID (0x7f << 25)
+ #define RX_TPA_START_CMP_AGG_ID_SHIFT 25
+- #define RX_TPA_START_CMP_AGG_ID_P5 (0xffff << 16)
++ #define RX_TPA_START_CMP_AGG_ID_P5 (0x0fff << 16)
+ #define RX_TPA_START_CMP_AGG_ID_SHIFT_P5 16
+ #define RX_TPA_START_CMP_METADATA1 (0xf << 28)
+ #define RX_TPA_START_CMP_METADATA1_SHIFT 28
+@@ -540,7 +543,7 @@ struct rx_tpa_end_cmp {
+ #define RX_TPA_END_CMP_PAYLOAD_OFFSET_SHIFT 16
+ #define RX_TPA_END_CMP_AGG_ID (0x7f << 25)
+ #define RX_TPA_END_CMP_AGG_ID_SHIFT 25
+- #define RX_TPA_END_CMP_AGG_ID_P5 (0xffff << 16)
++ #define RX_TPA_END_CMP_AGG_ID_P5 (0x0fff << 16)
+ #define RX_TPA_END_CMP_AGG_ID_SHIFT_P5 16
+
+ __le32 rx_tpa_end_cmp_tsdelta;
+diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+index bbf7641a0fc799..7e13cd69f68a1f 100644
+--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
++++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+@@ -2077,7 +2077,7 @@ void t4_idma_monitor(struct adapter *adapter,
+ struct sge_idma_monitor_state *idma,
+ int hz, int ticks);
+ int t4_set_vf_mac_acl(struct adapter *adapter, unsigned int vf,
+- unsigned int naddr, u8 *addr);
++ u8 start, unsigned int naddr, u8 *addr);
+ void t4_tp_pio_read(struct adapter *adap, u32 *buff, u32 nregs,
+ u32 start_index, bool sleep_ok);
+ void t4_tp_tm_pio_read(struct adapter *adap, u32 *buff, u32 nregs,
+diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+index 2418645c882373..fb3933fbb8425e 100644
+--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
++++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+@@ -3246,7 +3246,7 @@ static int cxgb4_mgmt_set_vf_mac(struct net_device *dev, int vf, u8 *mac)
+
+ dev_info(pi->adapter->pdev_dev,
+ "Setting MAC %pM on VF %d\n", mac, vf);
+- ret = t4_set_vf_mac_acl(adap, vf + 1, 1, mac);
++ ret = t4_set_vf_mac_acl(adap, vf + 1, pi->lport, 1, mac);
+ if (!ret)
+ ether_addr_copy(adap->vfinfo[vf].vf_mac_addr, mac);
+ return ret;
+diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+index 76de55306c4d01..175bf9b1305888 100644
+--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
++++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+@@ -10215,11 +10215,12 @@ int t4_load_cfg(struct adapter *adap, const u8 *cfg_data, unsigned int size)
+ * t4_set_vf_mac_acl - Set MAC address for the specified VF
+ * @adapter: The adapter
+ * @vf: one of the VFs instantiated by the specified PF
++ * @start: The start port id associated with specified VF
+ * @naddr: the number of MAC addresses
+ * @addr: the MAC address(es) to be set to the specified VF
+ */
+ int t4_set_vf_mac_acl(struct adapter *adapter, unsigned int vf,
+- unsigned int naddr, u8 *addr)
++ u8 start, unsigned int naddr, u8 *addr)
+ {
+ struct fw_acl_mac_cmd cmd;
+
+@@ -10234,7 +10235,7 @@ int t4_set_vf_mac_acl(struct adapter *adapter, unsigned int vf,
+ cmd.en_to_len16 = cpu_to_be32((unsigned int)FW_LEN16(cmd));
+ cmd.nmac = naddr;
+
+- switch (adapter->pf) {
++ switch (start) {
+ case 3:
+ memcpy(cmd.macaddr3, addr, sizeof(cmd.macaddr3));
+ break;
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c
+index 3d74109f82300e..49f22cad92bfd0 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c
+@@ -297,7 +297,9 @@ dr_domain_add_vport_cap(struct mlx5dr_domain *dmn, u16 vport)
+ if (ret) {
+ mlx5dr_dbg(dmn, "Couldn't insert new vport into xarray (%d)\n", ret);
+ kvfree(vport_caps);
+- return ERR_PTR(ret);
++ if (ret == -EBUSY)
++ return ERR_PTR(-EBUSY);
++ return NULL;
+ }
+
+ return vport_caps;
+diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_main.c b/drivers/net/ethernet/microchip/sparx5/sparx5_main.c
+index b64c814eac11e8..0c4c75b3682faa 100644
+--- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.c
++++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.c
+@@ -693,12 +693,11 @@ static int sparx5_start(struct sparx5 *sparx5)
+ err = -ENXIO;
+ if (sparx5->fdma_irq >= 0) {
+ if (GCB_CHIP_ID_REV_ID_GET(sparx5->chip_id) > 0)
+- err = devm_request_threaded_irq(sparx5->dev,
+- sparx5->fdma_irq,
+- NULL,
+- sparx5_fdma_handler,
+- IRQF_ONESHOT,
+- "sparx5-fdma", sparx5);
++ err = devm_request_irq(sparx5->dev,
++ sparx5->fdma_irq,
++ sparx5_fdma_handler,
++ 0,
++ "sparx5-fdma", sparx5);
+ if (!err)
+ err = sparx5_fdma_start(sparx5);
+ if (err)
+diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_port.c b/drivers/net/ethernet/microchip/sparx5/sparx5_port.c
+index 062e486c002cf6..672508efce5c29 100644
+--- a/drivers/net/ethernet/microchip/sparx5/sparx5_port.c
++++ b/drivers/net/ethernet/microchip/sparx5/sparx5_port.c
+@@ -1119,7 +1119,7 @@ int sparx5_port_init(struct sparx5 *sparx5,
+ spx5_inst_rmw(DEV10G_MAC_MAXLEN_CFG_MAX_LEN_SET(ETH_MAXLEN),
+ DEV10G_MAC_MAXLEN_CFG_MAX_LEN,
+ devinst,
+- DEV10G_MAC_ENA_CFG(0));
++ DEV10G_MAC_MAXLEN_CFG(0));
+
+ /* Handle Signal Detect in 10G PCS */
+ spx5_inst_wr(PCS10G_BR_PCS_SD_CFG_SD_POL_SET(sd_pol) |
+diff --git a/drivers/net/ethernet/microsoft/mana/gdma_main.c b/drivers/net/ethernet/microsoft/mana/gdma_main.c
+index ca4ed58f1206dd..0c2ba2fa88c466 100644
+--- a/drivers/net/ethernet/microsoft/mana/gdma_main.c
++++ b/drivers/net/ethernet/microsoft/mana/gdma_main.c
+@@ -1315,7 +1315,7 @@ static int mana_gd_setup_irqs(struct pci_dev *pdev)
+ GFP_KERNEL);
+ if (!gc->irq_contexts) {
+ err = -ENOMEM;
+- goto free_irq_vector;
++ goto free_irq_array;
+ }
+
+ for (i = 0; i < nvec; i++) {
+@@ -1372,6 +1372,7 @@ static int mana_gd_setup_irqs(struct pci_dev *pdev)
+ gc->max_num_msix = nvec;
+ gc->num_msix_usable = nvec;
+ cpus_read_unlock();
++ kfree(irqs);
+ return 0;
+
+ free_irq:
+@@ -1384,8 +1385,9 @@ static int mana_gd_setup_irqs(struct pci_dev *pdev)
+ }
+
+ kfree(gc->irq_contexts);
+- kfree(irqs);
+ gc->irq_contexts = NULL;
++free_irq_array:
++ kfree(irqs);
+ free_irq_vector:
+ cpus_read_unlock();
+ pci_free_irq_vectors(pdev);
+diff --git a/drivers/net/ethernet/mscc/ocelot_ptp.c b/drivers/net/ethernet/mscc/ocelot_ptp.c
+index e172638b060102..808ce8e68d3937 100644
+--- a/drivers/net/ethernet/mscc/ocelot_ptp.c
++++ b/drivers/net/ethernet/mscc/ocelot_ptp.c
+@@ -14,6 +14,8 @@
+ #include <soc/mscc/ocelot.h>
+ #include "ocelot.h"
+
++#define OCELOT_PTP_TX_TSTAMP_TIMEOUT (5 * HZ)
++
+ int ocelot_ptp_gettime64(struct ptp_clock_info *ptp, struct timespec64 *ts)
+ {
+ struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
+@@ -495,6 +497,28 @@ static int ocelot_traps_to_ptp_rx_filter(unsigned int proto)
+ return HWTSTAMP_FILTER_NONE;
+ }
+
++static int ocelot_ptp_tx_type_to_cmd(int tx_type, int *ptp_cmd)
++{
++ switch (tx_type) {
++ case HWTSTAMP_TX_ON:
++ *ptp_cmd = IFH_REW_OP_TWO_STEP_PTP;
++ break;
++ case HWTSTAMP_TX_ONESTEP_SYNC:
++ /* IFH_REW_OP_ONE_STEP_PTP updates the correctionField,
++ * what we need to update is the originTimestamp.
++ */
++ *ptp_cmd = IFH_REW_OP_ORIGIN_PTP;
++ break;
++ case HWTSTAMP_TX_OFF:
++ *ptp_cmd = 0;
++ break;
++ default:
++ return -ERANGE;
++ }
++
++ return 0;
++}
++
+ int ocelot_hwstamp_get(struct ocelot *ocelot, int port, struct ifreq *ifr)
+ {
+ struct ocelot_port *ocelot_port = ocelot->ports[port];
+@@ -521,30 +545,19 @@ EXPORT_SYMBOL(ocelot_hwstamp_get);
+ int ocelot_hwstamp_set(struct ocelot *ocelot, int port, struct ifreq *ifr)
+ {
+ struct ocelot_port *ocelot_port = ocelot->ports[port];
++ int ptp_cmd, old_ptp_cmd = ocelot_port->ptp_cmd;
+ bool l2 = false, l4 = false;
+ struct hwtstamp_config cfg;
++ bool old_l2, old_l4;
+ int err;
+
+ if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
+ return -EFAULT;
+
+ /* Tx type sanity check */
+- switch (cfg.tx_type) {
+- case HWTSTAMP_TX_ON:
+- ocelot_port->ptp_cmd = IFH_REW_OP_TWO_STEP_PTP;
+- break;
+- case HWTSTAMP_TX_ONESTEP_SYNC:
+- /* IFH_REW_OP_ONE_STEP_PTP updates the correctional field, we
+- * need to update the origin time.
+- */
+- ocelot_port->ptp_cmd = IFH_REW_OP_ORIGIN_PTP;
+- break;
+- case HWTSTAMP_TX_OFF:
+- ocelot_port->ptp_cmd = 0;
+- break;
+- default:
+- return -ERANGE;
+- }
++ err = ocelot_ptp_tx_type_to_cmd(cfg.tx_type, &ptp_cmd);
++ if (err)
++ return err;
+
+ switch (cfg.rx_filter) {
+ case HWTSTAMP_FILTER_NONE:
+@@ -569,13 +582,27 @@ int ocelot_hwstamp_set(struct ocelot *ocelot, int port, struct ifreq *ifr)
+ return -ERANGE;
+ }
+
++ old_l2 = ocelot_port->trap_proto & OCELOT_PROTO_PTP_L2;
++ old_l4 = ocelot_port->trap_proto & OCELOT_PROTO_PTP_L4;
++
+ err = ocelot_setup_ptp_traps(ocelot, port, l2, l4);
+ if (err)
+ return err;
+
++ ocelot_port->ptp_cmd = ptp_cmd;
++
+ cfg.rx_filter = ocelot_traps_to_ptp_rx_filter(ocelot_port->trap_proto);
+
+- return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
++ if (copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg))) {
++ err = -EFAULT;
++ goto out_restore_ptp_traps;
++ }
++
++ return 0;
++out_restore_ptp_traps:
++ ocelot_setup_ptp_traps(ocelot, port, old_l2, old_l4);
++ ocelot_port->ptp_cmd = old_ptp_cmd;
++ return err;
+ }
+ EXPORT_SYMBOL(ocelot_hwstamp_set);
+
+@@ -603,34 +630,87 @@ int ocelot_get_ts_info(struct ocelot *ocelot, int port,
+ }
+ EXPORT_SYMBOL(ocelot_get_ts_info);
+
+-static int ocelot_port_add_txtstamp_skb(struct ocelot *ocelot, int port,
+- struct sk_buff *clone)
++static struct sk_buff *ocelot_port_dequeue_ptp_tx_skb(struct ocelot *ocelot,
++ int port, u8 ts_id,
++ u32 seqid)
+ {
+ struct ocelot_port *ocelot_port = ocelot->ports[port];
+- unsigned long flags;
++ struct sk_buff *skb, *skb_tmp, *skb_match = NULL;
++ struct ptp_header *hdr;
+
+- spin_lock_irqsave(&ocelot->ts_id_lock, flags);
++ spin_lock(&ocelot->ts_id_lock);
+
+- if (ocelot_port->ptp_skbs_in_flight == OCELOT_MAX_PTP_ID ||
+- ocelot->ptp_skbs_in_flight == OCELOT_PTP_FIFO_SIZE) {
+- spin_unlock_irqrestore(&ocelot->ts_id_lock, flags);
+- return -EBUSY;
++ skb_queue_walk_safe(&ocelot_port->tx_skbs, skb, skb_tmp) {
++ if (OCELOT_SKB_CB(skb)->ts_id != ts_id)
++ continue;
++
++ /* Check that the timestamp ID is for the expected PTP
++ * sequenceId. We don't have to test ptp_parse_header() against
++ * NULL, because we've pre-validated the packet's ptp_class.
++ */
++ hdr = ptp_parse_header(skb, OCELOT_SKB_CB(skb)->ptp_class);
++ if (seqid != ntohs(hdr->sequence_id))
++ continue;
++
++ __skb_unlink(skb, &ocelot_port->tx_skbs);
++ ocelot->ptp_skbs_in_flight--;
++ skb_match = skb;
++ break;
+ }
+
+- skb_shinfo(clone)->tx_flags |= SKBTX_IN_PROGRESS;
+- /* Store timestamp ID in OCELOT_SKB_CB(clone)->ts_id */
+- OCELOT_SKB_CB(clone)->ts_id = ocelot_port->ts_id;
++ spin_unlock(&ocelot->ts_id_lock);
+
+- ocelot_port->ts_id++;
+- if (ocelot_port->ts_id == OCELOT_MAX_PTP_ID)
+- ocelot_port->ts_id = 0;
++ return skb_match;
++}
++
++static int ocelot_port_queue_ptp_tx_skb(struct ocelot *ocelot, int port,
++ struct sk_buff *clone)
++{
++ struct ocelot_port *ocelot_port = ocelot->ports[port];
++ DECLARE_BITMAP(ts_id_in_flight, OCELOT_MAX_PTP_ID);
++ struct sk_buff *skb, *skb_tmp;
++ unsigned long n;
++
++ spin_lock(&ocelot->ts_id_lock);
++
++ /* To get a better chance of acquiring a timestamp ID, first flush the
++ * stale packets still waiting in the TX timestamping queue. They are
++ * probably lost.
++ */
++ skb_queue_walk_safe(&ocelot_port->tx_skbs, skb, skb_tmp) {
++ if (time_before(OCELOT_SKB_CB(skb)->ptp_tx_time +
++ OCELOT_PTP_TX_TSTAMP_TIMEOUT, jiffies)) {
++ dev_warn_ratelimited(ocelot->dev,
++ "port %d invalidating stale timestamp ID %u which seems lost\n",
++ port, OCELOT_SKB_CB(skb)->ts_id);
++ __skb_unlink(skb, &ocelot_port->tx_skbs);
++ kfree_skb(skb);
++ ocelot->ptp_skbs_in_flight--;
++ } else {
++ __set_bit(OCELOT_SKB_CB(skb)->ts_id, ts_id_in_flight);
++ }
++ }
++
++ if (ocelot->ptp_skbs_in_flight == OCELOT_PTP_FIFO_SIZE) {
++ spin_unlock(&ocelot->ts_id_lock);
++ return -EBUSY;
++ }
++
++ n = find_first_zero_bit(ts_id_in_flight, OCELOT_MAX_PTP_ID);
++ if (n == OCELOT_MAX_PTP_ID) {
++ spin_unlock(&ocelot->ts_id_lock);
++ return -EBUSY;
++ }
+
+- ocelot_port->ptp_skbs_in_flight++;
++ /* Found an available timestamp ID, use it */
++ OCELOT_SKB_CB(clone)->ts_id = n;
++ OCELOT_SKB_CB(clone)->ptp_tx_time = jiffies;
+ ocelot->ptp_skbs_in_flight++;
++ __skb_queue_tail(&ocelot_port->tx_skbs, clone);
+
+- skb_queue_tail(&ocelot_port->tx_skbs, clone);
++ spin_unlock(&ocelot->ts_id_lock);
+
+- spin_unlock_irqrestore(&ocelot->ts_id_lock, flags);
++ dev_dbg_ratelimited(ocelot->dev, "port %d timestamp id %lu\n", port, n);
+
+ return 0;
+ }
+@@ -687,10 +767,14 @@ int ocelot_port_txtstamp_request(struct ocelot *ocelot, int port,
+ if (!(*clone))
+ return -ENOMEM;
+
+- err = ocelot_port_add_txtstamp_skb(ocelot, port, *clone);
+- if (err)
++ /* Store timestamp ID in OCELOT_SKB_CB(clone)->ts_id */
++ err = ocelot_port_queue_ptp_tx_skb(ocelot, port, *clone);
++ if (err) {
++ kfree_skb(*clone);
+ return err;
++ }
+
++ skb_shinfo(*clone)->tx_flags |= SKBTX_IN_PROGRESS;
+ OCELOT_SKB_CB(skb)->ptp_cmd = ptp_cmd;
+ OCELOT_SKB_CB(*clone)->ptp_class = ptp_class;
+ }
+@@ -726,28 +810,15 @@ static void ocelot_get_hwtimestamp(struct ocelot *ocelot,
+ spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
+ }
+
+-static bool ocelot_validate_ptp_skb(struct sk_buff *clone, u16 seqid)
+-{
+- struct ptp_header *hdr;
+-
+- hdr = ptp_parse_header(clone, OCELOT_SKB_CB(clone)->ptp_class);
+- if (WARN_ON(!hdr))
+- return false;
+-
+- return seqid == ntohs(hdr->sequence_id);
+-}
+-
+ void ocelot_get_txtstamp(struct ocelot *ocelot)
+ {
+ int budget = OCELOT_PTP_QUEUE_SZ;
+
+ while (budget--) {
+- struct sk_buff *skb, *skb_tmp, *skb_match = NULL;
+ struct skb_shared_hwtstamps shhwtstamps;
+ u32 val, id, seqid, txport;
+- struct ocelot_port *port;
++ struct sk_buff *skb_match;
+ struct timespec64 ts;
+- unsigned long flags;
+
+ val = ocelot_read(ocelot, SYS_PTP_STATUS);
+
+@@ -762,36 +833,14 @@ void ocelot_get_txtstamp(struct ocelot *ocelot)
+ txport = SYS_PTP_STATUS_PTP_MESS_TXPORT_X(val);
+ seqid = SYS_PTP_STATUS_PTP_MESS_SEQ_ID(val);
+
+- port = ocelot->ports[txport];
+-
+- spin_lock(&ocelot->ts_id_lock);
+- port->ptp_skbs_in_flight--;
+- ocelot->ptp_skbs_in_flight--;
+- spin_unlock(&ocelot->ts_id_lock);
+-
+ /* Retrieve its associated skb */
+-try_again:
+- spin_lock_irqsave(&port->tx_skbs.lock, flags);
+-
+- skb_queue_walk_safe(&port->tx_skbs, skb, skb_tmp) {
+- if (OCELOT_SKB_CB(skb)->ts_id != id)
+- continue;
+- __skb_unlink(skb, &port->tx_skbs);
+- skb_match = skb;
+- break;
+- }
+-
+- spin_unlock_irqrestore(&port->tx_skbs.lock, flags);
+-
+- if (WARN_ON(!skb_match))
+- continue;
+-
+- if (!ocelot_validate_ptp_skb(skb_match, seqid)) {
+- dev_err_ratelimited(ocelot->dev,
+- "port %d received stale TX timestamp for seqid %d, discarding\n",
+- txport, seqid);
+- dev_kfree_skb_any(skb);
+- goto try_again;
++ skb_match = ocelot_port_dequeue_ptp_tx_skb(ocelot, txport, id,
++ seqid);
++ if (!skb_match) {
++ dev_warn_ratelimited(ocelot->dev,
++ "port %d received TX timestamp (seqid %d, ts id %u) for packet previously declared stale\n",
++ txport, seqid, id);
++ goto next_ts;
+ }
+
+ /* Get the h/w timestamp */
+@@ -802,7 +851,7 @@ void ocelot_get_txtstamp(struct ocelot *ocelot)
+ shhwtstamps.hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec);
+ skb_complete_tx_timestamp(skb_match, &shhwtstamps);
+
+- /* Next ts */
++next_ts:
+ ocelot_write(ocelot, SYS_PTP_NXT_PTP_NXT, SYS_PTP_NXT);
+ }
+ }
+diff --git a/drivers/net/ethernet/qualcomm/qca_spi.c b/drivers/net/ethernet/qualcomm/qca_spi.c
+index 8f7ce6b51a1c9b..6b4b40c6e1fe00 100644
+--- a/drivers/net/ethernet/qualcomm/qca_spi.c
++++ b/drivers/net/ethernet/qualcomm/qca_spi.c
+@@ -53,7 +53,7 @@ MODULE_PARM_DESC(qcaspi_burst_len, "Number of data bytes per burst. Use 1-5000."
+
+ #define QCASPI_PLUGGABLE_MIN 0
+ #define QCASPI_PLUGGABLE_MAX 1
+-static int qcaspi_pluggable = QCASPI_PLUGGABLE_MIN;
++static int qcaspi_pluggable = QCASPI_PLUGGABLE_MAX;
+ module_param(qcaspi_pluggable, int, 0);
+ MODULE_PARM_DESC(qcaspi_pluggable, "Pluggable SPI connection (yes/no).");
+
+@@ -812,7 +812,6 @@ qcaspi_netdev_init(struct net_device *dev)
+
+ dev->mtu = QCAFRM_MAX_MTU;
+ dev->type = ARPHRD_ETHER;
+- qca->clkspeed = qcaspi_clkspeed;
+ qca->burst_len = qcaspi_burst_len;
+ qca->spi_thread = NULL;
+ qca->buffer_size = (QCAFRM_MAX_MTU + VLAN_ETH_HLEN + QCAFRM_HEADER_LEN +
+@@ -903,17 +902,15 @@ qca_spi_probe(struct spi_device *spi)
+ legacy_mode = of_property_read_bool(spi->dev.of_node,
+ "qca,legacy-mode");
+
+- if (qcaspi_clkspeed == 0) {
+- if (spi->max_speed_hz)
+- qcaspi_clkspeed = spi->max_speed_hz;
+- else
+- qcaspi_clkspeed = QCASPI_CLK_SPEED;
+- }
++ if (qcaspi_clkspeed)
++ spi->max_speed_hz = qcaspi_clkspeed;
++ else if (!spi->max_speed_hz)
++ spi->max_speed_hz = QCASPI_CLK_SPEED;
+
+- if ((qcaspi_clkspeed < QCASPI_CLK_SPEED_MIN) ||
+- (qcaspi_clkspeed > QCASPI_CLK_SPEED_MAX)) {
+- dev_err(&spi->dev, "Invalid clkspeed: %d\n",
+- qcaspi_clkspeed);
++ if (spi->max_speed_hz < QCASPI_CLK_SPEED_MIN ||
++ spi->max_speed_hz > QCASPI_CLK_SPEED_MAX) {
++ dev_err(&spi->dev, "Invalid clkspeed: %u\n",
++ spi->max_speed_hz);
+ return -EINVAL;
+ }
+
+@@ -938,14 +935,13 @@ qca_spi_probe(struct spi_device *spi)
+ return -EINVAL;
+ }
+
+- dev_info(&spi->dev, "ver=%s, clkspeed=%d, burst_len=%d, pluggable=%d\n",
++ dev_info(&spi->dev, "ver=%s, clkspeed=%u, burst_len=%d, pluggable=%d\n",
+ QCASPI_DRV_VERSION,
+- qcaspi_clkspeed,
++ spi->max_speed_hz,
+ qcaspi_burst_len,
+ qcaspi_pluggable);
+
+ spi->mode = SPI_MODE_3;
+- spi->max_speed_hz = qcaspi_clkspeed;
+ if (spi_setup(spi) < 0) {
+ dev_err(&spi->dev, "Unable to setup SPI device\n");
+ return -EFAULT;
+diff --git a/drivers/net/ethernet/qualcomm/qca_spi.h b/drivers/net/ethernet/qualcomm/qca_spi.h
+index 8f4808695e8206..0831cefc58b898 100644
+--- a/drivers/net/ethernet/qualcomm/qca_spi.h
++++ b/drivers/net/ethernet/qualcomm/qca_spi.h
+@@ -89,7 +89,6 @@ struct qcaspi {
+ #endif
+
+ /* user configurable options */
+- u32 clkspeed;
+ u8 legacy_mode;
+ u16 burst_len;
+ };
+diff --git a/drivers/net/ethernet/renesas/rswitch.c b/drivers/net/ethernet/renesas/rswitch.c
+index b80aa27a7214d4..09117110e3dd2a 100644
+--- a/drivers/net/ethernet/renesas/rswitch.c
++++ b/drivers/net/ethernet/renesas/rswitch.c
+@@ -862,13 +862,10 @@ static void rswitch_tx_free(struct net_device *ndev)
+ struct rswitch_ext_desc *desc;
+ struct sk_buff *skb;
+
+- for (; rswitch_get_num_cur_queues(gq) > 0;
+- gq->dirty = rswitch_next_queue_index(gq, false, 1)) {
+- desc = &gq->tx_ring[gq->dirty];
+- if ((desc->desc.die_dt & DT_MASK) != DT_FEMPTY)
+- break;
+-
++ desc = &gq->tx_ring[gq->dirty];
++ while ((desc->desc.die_dt & DT_MASK) == DT_FEMPTY) {
+ dma_rmb();
++
+ skb = gq->skbs[gq->dirty];
+ if (skb) {
+ rdev->ndev->stats.tx_packets++;
+@@ -879,7 +876,10 @@ static void rswitch_tx_free(struct net_device *ndev)
+ dev_kfree_skb_any(gq->skbs[gq->dirty]);
+ gq->skbs[gq->dirty] = NULL;
+ }
++
+ desc->desc.die_dt = DT_EEMPTY;
++ gq->dirty = rswitch_next_queue_index(gq, false, 1);
++ desc = &gq->tx_ring[gq->dirty];
+ }
+ }
+
+@@ -908,8 +908,10 @@ static int rswitch_poll(struct napi_struct *napi, int budget)
+
+ if (napi_complete_done(napi, budget - quota)) {
+ spin_lock_irqsave(&priv->lock, flags);
+- rswitch_enadis_data_irq(priv, rdev->tx_queue->index, true);
+- rswitch_enadis_data_irq(priv, rdev->rx_queue->index, true);
++ if (test_bit(rdev->port, priv->opened_ports)) {
++ rswitch_enadis_data_irq(priv, rdev->tx_queue->index, true);
++ rswitch_enadis_data_irq(priv, rdev->rx_queue->index, true);
++ }
+ spin_unlock_irqrestore(&priv->lock, flags);
+ }
+
+@@ -1114,25 +1116,40 @@ static int rswitch_etha_wait_link_verification(struct rswitch_etha *etha)
+
+ static void rswitch_rmac_setting(struct rswitch_etha *etha, const u8 *mac)
+ {
+- u32 val;
++ u32 pis, lsc;
+
+ rswitch_etha_write_mac_address(etha, mac);
+
++ switch (etha->phy_interface) {
++ case PHY_INTERFACE_MODE_SGMII:
++ pis = MPIC_PIS_GMII;
++ break;
++ case PHY_INTERFACE_MODE_USXGMII:
++ case PHY_INTERFACE_MODE_5GBASER:
++ pis = MPIC_PIS_XGMII;
++ break;
++ default:
++ pis = FIELD_GET(MPIC_PIS, ioread32(etha->addr + MPIC));
++ break;
++ }
++
+ switch (etha->speed) {
+ case 100:
+- val = MPIC_LSC_100M;
++ lsc = MPIC_LSC_100M;
+ break;
+ case 1000:
+- val = MPIC_LSC_1G;
++ lsc = MPIC_LSC_1G;
+ break;
+ case 2500:
+- val = MPIC_LSC_2_5G;
++ lsc = MPIC_LSC_2_5G;
+ break;
+ default:
+- return;
++ lsc = FIELD_GET(MPIC_LSC, ioread32(etha->addr + MPIC));
++ break;
+ }
+
+- iowrite32(MPIC_PIS_GMII | val, etha->addr + MPIC);
++ rswitch_modify(etha->addr, MPIC, MPIC_PIS | MPIC_LSC,
++ FIELD_PREP(MPIC_PIS, pis) | FIELD_PREP(MPIC_LSC, lsc));
+ }
+
+ static void rswitch_etha_enable_mii(struct rswitch_etha *etha)
+@@ -1538,20 +1555,20 @@ static int rswitch_open(struct net_device *ndev)
+ struct rswitch_device *rdev = netdev_priv(ndev);
+ unsigned long flags;
+
+- phy_start(ndev->phydev);
++ if (bitmap_empty(rdev->priv->opened_ports, RSWITCH_NUM_PORTS))
++ iowrite32(GWCA_TS_IRQ_BIT, rdev->priv->addr + GWTSDIE);
+
+ napi_enable(&rdev->napi);
+- netif_start_queue(ndev);
+
+ spin_lock_irqsave(&rdev->priv->lock, flags);
++ bitmap_set(rdev->priv->opened_ports, rdev->port, 1);
+ rswitch_enadis_data_irq(rdev->priv, rdev->tx_queue->index, true);
+ rswitch_enadis_data_irq(rdev->priv, rdev->rx_queue->index, true);
+ spin_unlock_irqrestore(&rdev->priv->lock, flags);
+
+- if (bitmap_empty(rdev->priv->opened_ports, RSWITCH_NUM_PORTS))
+- iowrite32(GWCA_TS_IRQ_BIT, rdev->priv->addr + GWTSDIE);
++ phy_start(ndev->phydev);
+
+- bitmap_set(rdev->priv->opened_ports, rdev->port, 1);
++ netif_start_queue(ndev);
+
+ return 0;
+ };
+@@ -1563,7 +1580,16 @@ static int rswitch_stop(struct net_device *ndev)
+ unsigned long flags;
+
+ netif_tx_stop_all_queues(ndev);
++
++ phy_stop(ndev->phydev);
++
++ spin_lock_irqsave(&rdev->priv->lock, flags);
++ rswitch_enadis_data_irq(rdev->priv, rdev->tx_queue->index, false);
++ rswitch_enadis_data_irq(rdev->priv, rdev->rx_queue->index, false);
+ bitmap_clear(rdev->priv->opened_ports, rdev->port, 1);
++ spin_unlock_irqrestore(&rdev->priv->lock, flags);
++
++ napi_disable(&rdev->napi);
+
+ if (bitmap_empty(rdev->priv->opened_ports, RSWITCH_NUM_PORTS))
+ iowrite32(GWCA_TS_IRQ_BIT, rdev->priv->addr + GWTSDID);
+@@ -1576,14 +1602,6 @@ static int rswitch_stop(struct net_device *ndev)
+ kfree(ts_info);
+ }
+
+- spin_lock_irqsave(&rdev->priv->lock, flags);
+- rswitch_enadis_data_irq(rdev->priv, rdev->tx_queue->index, false);
+- rswitch_enadis_data_irq(rdev->priv, rdev->rx_queue->index, false);
+- spin_unlock_irqrestore(&rdev->priv->lock, flags);
+-
+- phy_stop(ndev->phydev);
+- napi_disable(&rdev->napi);
+-
+ return 0;
+ };
+
+@@ -1681,8 +1699,11 @@ 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();
+
+ /* DT_FSTART should be set at last. So, this is reverse order. */
+ for (i = nr_desc; i-- > 0; ) {
+@@ -1694,14 +1715,13 @@ static netdev_tx_t rswitch_start_xmit(struct sk_buff *skb, struct net_device *nd
+ goto err_unmap;
+ }
+
+- wmb(); /* gq->cur must be incremented after die_dt was set */
+-
+ gq->cur = rswitch_next_queue_index(gq, true, nr_desc);
+ rswitch_modify(rdev->addr, GWTRC(gq->index), 0, BIT(gq->index % 32));
+
+ return ret;
+
+ err_unmap:
++ gq->skbs[(gq->cur + nr_desc - 1) % gq->ring_size] = NULL;
+ dma_unmap_single(ndev->dev.parent, dma_addr_orig, skb->len, DMA_TO_DEVICE);
+
+ err_kfree:
+@@ -1889,7 +1909,6 @@ static int rswitch_device_alloc(struct rswitch_private *priv, unsigned int index
+ rdev->np_port = rswitch_get_port_node(rdev);
+ rdev->disabled = !rdev->np_port;
+ err = of_get_ethdev_address(rdev->np_port, ndev);
+- of_node_put(rdev->np_port);
+ if (err) {
+ if (is_valid_ether_addr(rdev->etha->mac_addr))
+ eth_hw_addr_set(ndev, rdev->etha->mac_addr);
+@@ -1919,6 +1938,7 @@ static int rswitch_device_alloc(struct rswitch_private *priv, unsigned int index
+
+ out_rxdmac:
+ out_get_params:
++ of_node_put(rdev->np_port);
+ netif_napi_del(&rdev->napi);
+ free_netdev(ndev);
+
+@@ -1932,6 +1952,7 @@ static void rswitch_device_free(struct rswitch_private *priv, unsigned int index
+
+ rswitch_txdmac_free(ndev);
+ rswitch_rxdmac_free(ndev);
++ of_node_put(rdev->np_port);
+ netif_napi_del(&rdev->napi);
+ free_netdev(ndev);
+ }
+diff --git a/drivers/net/ethernet/renesas/rswitch.h b/drivers/net/ethernet/renesas/rswitch.h
+index 72e3ff596d3183..e020800dcc570e 100644
+--- a/drivers/net/ethernet/renesas/rswitch.h
++++ b/drivers/net/ethernet/renesas/rswitch.h
+@@ -724,13 +724,13 @@ enum rswitch_etha_mode {
+
+ #define EAVCC_VEM_SC_TAG (0x3 << 16)
+
+-#define MPIC_PIS_MII 0x00
+-#define MPIC_PIS_GMII 0x02
+-#define MPIC_PIS_XGMII 0x04
+-#define MPIC_LSC_SHIFT 3
+-#define MPIC_LSC_100M (1 << MPIC_LSC_SHIFT)
+-#define MPIC_LSC_1G (2 << MPIC_LSC_SHIFT)
+-#define MPIC_LSC_2_5G (3 << MPIC_LSC_SHIFT)
++#define MPIC_PIS GENMASK(2, 0)
++#define MPIC_PIS_GMII 2
++#define MPIC_PIS_XGMII 4
++#define MPIC_LSC GENMASK(5, 3)
++#define MPIC_LSC_100M 1
++#define MPIC_LSC_1G 2
++#define MPIC_LSC_2_5G 3
+
+ #define MDIO_READ_C45 0x03
+ #define MDIO_WRITE_C45 0x01
+diff --git a/drivers/net/team/team_core.c b/drivers/net/team/team_core.c
+index 18191d5a8bd4d3..6ace5a74cddb57 100644
+--- a/drivers/net/team/team_core.c
++++ b/drivers/net/team/team_core.c
+@@ -983,7 +983,8 @@ static void team_port_disable(struct team *team,
+
+ #define TEAM_VLAN_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | \
+ NETIF_F_FRAGLIST | NETIF_F_GSO_SOFTWARE | \
+- NETIF_F_HIGHDMA | NETIF_F_LRO)
++ NETIF_F_HIGHDMA | NETIF_F_LRO | \
++ NETIF_F_GSO_ENCAP_ALL)
+
+ #define TEAM_ENC_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | \
+ NETIF_F_RXCSUM | NETIF_F_GSO_SOFTWARE)
+@@ -991,13 +992,14 @@ static void team_port_disable(struct team *team,
+ static void __team_compute_features(struct team *team)
+ {
+ struct team_port *port;
+- netdev_features_t vlan_features = TEAM_VLAN_FEATURES &
+- NETIF_F_ALL_FOR_ALL;
++ netdev_features_t vlan_features = TEAM_VLAN_FEATURES;
+ netdev_features_t enc_features = TEAM_ENC_FEATURES;
+ unsigned short max_hard_header_len = ETH_HLEN;
+ unsigned int dst_release_flag = IFF_XMIT_DST_RELEASE |
+ IFF_XMIT_DST_RELEASE_PERM;
+
++ vlan_features = netdev_base_features(vlan_features);
++
+ rcu_read_lock();
+ list_for_each_entry_rcu(port, &team->port_list, list) {
+ vlan_features = netdev_increment_features(vlan_features,
+@@ -2012,8 +2014,7 @@ static netdev_features_t team_fix_features(struct net_device *dev,
+ netdev_features_t mask;
+
+ mask = features;
+- features &= ~NETIF_F_ONE_FOR_ALL;
+- features |= NETIF_F_ALL_FOR_ALL;
++ features = netdev_base_features(features);
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(port, &team->port_list, list) {
+diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
+index c897afef0b414c..60027b439021b8 100644
+--- a/drivers/net/virtio_net.c
++++ b/drivers/net/virtio_net.c
+@@ -502,6 +502,7 @@ struct virtio_net_common_hdr {
+ };
+
+ static void virtnet_sq_free_unused_buf(struct virtqueue *vq, void *buf);
++static void virtnet_sq_free_unused_buf_done(struct virtqueue *vq);
+ static int virtnet_xdp_handler(struct bpf_prog *xdp_prog, struct xdp_buff *xdp,
+ struct net_device *dev,
+ unsigned int *xdp_xmit,
+@@ -2898,7 +2899,6 @@ static int virtnet_enable_queue_pair(struct virtnet_info *vi, int qp_index)
+ if (err < 0)
+ goto err_xdp_reg_mem_model;
+
+- netdev_tx_reset_queue(netdev_get_tx_queue(vi->dev, qp_index));
+ virtnet_napi_enable(vi->rq[qp_index].vq, &vi->rq[qp_index].napi);
+ virtnet_napi_tx_enable(vi, vi->sq[qp_index].vq, &vi->sq[qp_index].napi);
+
+@@ -3166,7 +3166,7 @@ static int virtnet_rx_resize(struct virtnet_info *vi,
+
+ virtnet_rx_pause(vi, rq);
+
+- err = virtqueue_resize(rq->vq, ring_num, virtnet_rq_unmap_free_buf);
++ err = virtqueue_resize(rq->vq, ring_num, virtnet_rq_unmap_free_buf, NULL);
+ if (err)
+ netdev_err(vi->dev, "resize rx fail: rx queue index: %d err: %d\n", qindex, err);
+
+@@ -3229,7 +3229,8 @@ static int virtnet_tx_resize(struct virtnet_info *vi, struct send_queue *sq,
+
+ virtnet_tx_pause(vi, sq);
+
+- err = virtqueue_resize(sq->vq, ring_num, virtnet_sq_free_unused_buf);
++ err = virtqueue_resize(sq->vq, ring_num, virtnet_sq_free_unused_buf,
++ virtnet_sq_free_unused_buf_done);
+ if (err)
+ netdev_err(vi->dev, "resize tx fail: tx queue index: %d err: %d\n", qindex, err);
+
+@@ -5997,6 +5998,14 @@ static void virtnet_sq_free_unused_buf(struct virtqueue *vq, void *buf)
+ xdp_return_frame(ptr_to_xdp(buf));
+ }
+
++static void virtnet_sq_free_unused_buf_done(struct virtqueue *vq)
++{
++ struct virtnet_info *vi = vq->vdev->priv;
++ int i = vq2txq(vq);
++
++ netdev_tx_reset_queue(netdev_get_tx_queue(vi->dev, i));
++}
++
+ static void free_unused_bufs(struct virtnet_info *vi)
+ {
+ void *buf;
+@@ -6728,11 +6737,20 @@ static int virtnet_probe(struct virtio_device *vdev)
+
+ static void remove_vq_common(struct virtnet_info *vi)
+ {
++ int i;
++
+ virtio_reset_device(vi->vdev);
+
+ /* Free unused buffers in both send and recv, if any. */
+ free_unused_bufs(vi);
+
++ /*
++ * Rule of thumb is netdev_tx_reset_queue() should follow any
++ * skb freeing not followed by netdev_tx_completed_queue()
++ */
++ for (i = 0; i < vi->max_queue_pairs; i++)
++ netdev_tx_reset_queue(netdev_get_tx_queue(vi->dev, i));
++
+ free_receive_bufs(vi);
+
+ free_receive_page_frags(vi);
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
+index a7a10e716e6517..e96ddaeeeeff52 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
+@@ -1967,7 +1967,7 @@ void iwl_mvm_channel_switch_error_notif(struct iwl_mvm *mvm,
+ if (csa_err_mask & (CS_ERR_COUNT_ERROR |
+ CS_ERR_LONG_DELAY_AFTER_CS |
+ CS_ERR_TX_BLOCK_TIMER_EXPIRED))
+- ieee80211_channel_switch_disconnect(vif, true);
++ ieee80211_channel_switch_disconnect(vif);
+ rcu_read_unlock();
+ }
+
+diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
+index 4265c1cd0ff716..63fe51d0e64db3 100644
+--- a/drivers/net/xen-netfront.c
++++ b/drivers/net/xen-netfront.c
+@@ -867,7 +867,7 @@ static netdev_tx_t xennet_start_xmit(struct sk_buff *skb, struct net_device *dev
+ static int xennet_close(struct net_device *dev)
+ {
+ struct netfront_info *np = netdev_priv(dev);
+- unsigned int num_queues = dev->real_num_tx_queues;
++ unsigned int num_queues = np->queues ? dev->real_num_tx_queues : 0;
+ unsigned int i;
+ struct netfront_queue *queue;
+ netif_tx_stop_all_queues(np->netdev);
+@@ -882,6 +882,9 @@ static void xennet_destroy_queues(struct netfront_info *info)
+ {
+ unsigned int i;
+
++ if (!info->queues)
++ return;
++
+ for (i = 0; i < info->netdev->real_num_tx_queues; i++) {
+ struct netfront_queue *queue = &info->queues[i];
+
+diff --git a/drivers/ptp/ptp_kvm_x86.c b/drivers/ptp/ptp_kvm_x86.c
+index 617c8d6706d3d0..6cea4fe39bcfe4 100644
+--- a/drivers/ptp/ptp_kvm_x86.c
++++ b/drivers/ptp/ptp_kvm_x86.c
+@@ -26,7 +26,7 @@ int kvm_arch_ptp_init(void)
+ long ret;
+
+ if (!kvm_para_available())
+- return -ENODEV;
++ return -EOPNOTSUPP;
+
+ if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) {
+ p = alloc_page(GFP_KERNEL | __GFP_ZERO);
+@@ -46,14 +46,14 @@ int kvm_arch_ptp_init(void)
+
+ clock_pair_gpa = slow_virt_to_phys(clock_pair);
+ if (!pvclock_get_pvti_cpu0_va()) {
+- ret = -ENODEV;
++ ret = -EOPNOTSUPP;
+ goto err;
+ }
+
+ ret = kvm_hypercall2(KVM_HC_CLOCK_PAIRING, clock_pair_gpa,
+ KVM_CLOCK_PAIRING_WALLCLOCK);
+ if (ret == -KVM_ENOSYS) {
+- ret = -ENODEV;
++ ret = -EOPNOTSUPP;
+ goto err;
+ }
+
+diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c
+index a8e91d9d028b89..945d2917b91bac 100644
+--- a/drivers/regulator/axp20x-regulator.c
++++ b/drivers/regulator/axp20x-regulator.c
+@@ -371,8 +371,8 @@
+ .ops = &axp20x_ops, \
+ }
+
+-#define AXP_DESC(_family, _id, _match, _supply, _min, _max, _step, _vreg, \
+- _vmask, _ereg, _emask) \
++#define AXP_DESC_DELAY(_family, _id, _match, _supply, _min, _max, _step, _vreg, \
++ _vmask, _ereg, _emask, _ramp_delay) \
+ [_family##_##_id] = { \
+ .name = (_match), \
+ .supply_name = (_supply), \
+@@ -388,9 +388,15 @@
+ .vsel_mask = (_vmask), \
+ .enable_reg = (_ereg), \
+ .enable_mask = (_emask), \
++ .ramp_delay = (_ramp_delay), \
+ .ops = &axp20x_ops, \
+ }
+
++#define AXP_DESC(_family, _id, _match, _supply, _min, _max, _step, _vreg, \
++ _vmask, _ereg, _emask) \
++ AXP_DESC_DELAY(_family, _id, _match, _supply, _min, _max, _step, _vreg, \
++ _vmask, _ereg, _emask, 0)
++
+ #define AXP_DESC_SW(_family, _id, _match, _supply, _ereg, _emask) \
+ [_family##_##_id] = { \
+ .name = (_match), \
+@@ -419,8 +425,8 @@
+ .ops = &axp20x_ops_fixed \
+ }
+
+-#define AXP_DESC_RANGES(_family, _id, _match, _supply, _ranges, _n_voltages, \
+- _vreg, _vmask, _ereg, _emask) \
++#define AXP_DESC_RANGES_DELAY(_family, _id, _match, _supply, _ranges, _n_voltages, \
++ _vreg, _vmask, _ereg, _emask, _ramp_delay) \
+ [_family##_##_id] = { \
+ .name = (_match), \
+ .supply_name = (_supply), \
+@@ -436,9 +442,15 @@
+ .enable_mask = (_emask), \
+ .linear_ranges = (_ranges), \
+ .n_linear_ranges = ARRAY_SIZE(_ranges), \
++ .ramp_delay = (_ramp_delay), \
+ .ops = &axp20x_ops_range, \
+ }
+
++#define AXP_DESC_RANGES(_family, _id, _match, _supply, _ranges, _n_voltages, \
++ _vreg, _vmask, _ereg, _emask) \
++ AXP_DESC_RANGES_DELAY(_family, _id, _match, _supply, _ranges, \
++ _n_voltages, _vreg, _vmask, _ereg, _emask, 0)
++
+ static const int axp209_dcdc2_ldo3_slew_rates[] = {
+ 1600,
+ 800,
+@@ -781,21 +793,21 @@ static const struct linear_range axp717_dcdc3_ranges[] = {
+ };
+
+ static const struct regulator_desc axp717_regulators[] = {
+- AXP_DESC_RANGES(AXP717, DCDC1, "dcdc1", "vin1",
++ AXP_DESC_RANGES_DELAY(AXP717, DCDC1, "dcdc1", "vin1",
+ axp717_dcdc1_ranges, AXP717_DCDC1_NUM_VOLTAGES,
+ AXP717_DCDC1_CONTROL, AXP717_DCDC_V_OUT_MASK,
+- AXP717_DCDC_OUTPUT_CONTROL, BIT(0)),
+- AXP_DESC_RANGES(AXP717, DCDC2, "dcdc2", "vin2",
++ AXP717_DCDC_OUTPUT_CONTROL, BIT(0), 640),
++ AXP_DESC_RANGES_DELAY(AXP717, DCDC2, "dcdc2", "vin2",
+ axp717_dcdc2_ranges, AXP717_DCDC2_NUM_VOLTAGES,
+ AXP717_DCDC2_CONTROL, AXP717_DCDC_V_OUT_MASK,
+- AXP717_DCDC_OUTPUT_CONTROL, BIT(1)),
+- AXP_DESC_RANGES(AXP717, DCDC3, "dcdc3", "vin3",
++ AXP717_DCDC_OUTPUT_CONTROL, BIT(1), 640),
++ AXP_DESC_RANGES_DELAY(AXP717, DCDC3, "dcdc3", "vin3",
+ axp717_dcdc3_ranges, AXP717_DCDC3_NUM_VOLTAGES,
+ AXP717_DCDC3_CONTROL, AXP717_DCDC_V_OUT_MASK,
+- AXP717_DCDC_OUTPUT_CONTROL, BIT(2)),
+- AXP_DESC(AXP717, DCDC4, "dcdc4", "vin4", 1000, 3700, 100,
++ AXP717_DCDC_OUTPUT_CONTROL, BIT(2), 640),
++ AXP_DESC_DELAY(AXP717, DCDC4, "dcdc4", "vin4", 1000, 3700, 100,
+ AXP717_DCDC4_CONTROL, AXP717_DCDC_V_OUT_MASK,
+- AXP717_DCDC_OUTPUT_CONTROL, BIT(3)),
++ AXP717_DCDC_OUTPUT_CONTROL, BIT(3), 6400),
+ AXP_DESC(AXP717, ALDO1, "aldo1", "aldoin", 500, 3500, 100,
+ AXP717_ALDO1_CONTROL, AXP717_LDO_V_OUT_MASK,
+ AXP717_LDO0_OUTPUT_CONTROL, BIT(0)),
+diff --git a/drivers/spi/spi-aspeed-smc.c b/drivers/spi/spi-aspeed-smc.c
+index bbd417c55e7f56..b0e3f307b28353 100644
+--- a/drivers/spi/spi-aspeed-smc.c
++++ b/drivers/spi/spi-aspeed-smc.c
+@@ -239,7 +239,7 @@ static ssize_t aspeed_spi_read_user(struct aspeed_spi_chip *chip,
+
+ ret = aspeed_spi_send_cmd_addr(chip, op->addr.nbytes, offset, op->cmd.opcode);
+ if (ret < 0)
+- return ret;
++ goto stop_user;
+
+ if (op->dummy.buswidth && op->dummy.nbytes) {
+ for (i = 0; i < op->dummy.nbytes / op->dummy.buswidth; i++)
+@@ -249,8 +249,9 @@ static ssize_t aspeed_spi_read_user(struct aspeed_spi_chip *chip,
+ aspeed_spi_set_io_mode(chip, io_mode);
+
+ aspeed_spi_read_from_ahb(buf, chip->ahb_base, len);
++stop_user:
+ aspeed_spi_stop_user(chip);
+- return 0;
++ return ret;
+ }
+
+ static ssize_t aspeed_spi_write_user(struct aspeed_spi_chip *chip,
+@@ -261,10 +262,11 @@ static ssize_t aspeed_spi_write_user(struct aspeed_spi_chip *chip,
+ aspeed_spi_start_user(chip);
+ ret = aspeed_spi_send_cmd_addr(chip, op->addr.nbytes, op->addr.val, op->cmd.opcode);
+ if (ret < 0)
+- return ret;
++ goto stop_user;
+ aspeed_spi_write_to_ahb(chip->ahb_base, op->data.buf.out, op->data.nbytes);
++stop_user:
+ aspeed_spi_stop_user(chip);
+- return 0;
++ return ret;
+ }
+
+ /* support for 1-1-1, 1-1-2 or 1-1-4 */
+diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
+index 0bb33c43b1b46e..40a64a598a7495 100644
+--- a/drivers/spi/spi-rockchip.c
++++ b/drivers/spi/spi-rockchip.c
+@@ -241,6 +241,20 @@ static void rockchip_spi_set_cs(struct spi_device *spi, bool enable)
+ struct spi_controller *ctlr = spi->controller;
+ struct rockchip_spi *rs = spi_controller_get_devdata(ctlr);
+ bool cs_asserted = spi->mode & SPI_CS_HIGH ? enable : !enable;
++ bool cs_actual;
++
++ /*
++ * SPI subsystem tries to avoid no-op calls that would break the PM
++ * refcount below. It can't however for the first time it is used.
++ * To detect this case we read it here and bail out early for no-ops.
++ */
++ if (spi_get_csgpiod(spi, 0))
++ cs_actual = !!(readl_relaxed(rs->regs + ROCKCHIP_SPI_SER) & 1);
++ else
++ cs_actual = !!(readl_relaxed(rs->regs + ROCKCHIP_SPI_SER) &
++ BIT(spi_get_chipselect(spi, 0)));
++ if (unlikely(cs_actual == cs_asserted))
++ return;
+
+ if (cs_asserted) {
+ /* Keep things powered as long as CS is asserted */
+diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
+index b80e9a528e17ff..bdf17eafd3598d 100644
+--- a/drivers/tty/serial/sh-sci.c
++++ b/drivers/tty/serial/sh-sci.c
+@@ -157,6 +157,7 @@ struct sci_port {
+
+ bool has_rtscts;
+ bool autorts;
++ bool tx_occurred;
+ };
+
+ #define SCI_NPORTS CONFIG_SERIAL_SH_SCI_NR_UARTS
+@@ -850,6 +851,7 @@ static void sci_transmit_chars(struct uart_port *port)
+ {
+ struct tty_port *tport = &port->state->port;
+ unsigned int stopped = uart_tx_stopped(port);
++ struct sci_port *s = to_sci_port(port);
+ unsigned short status;
+ unsigned short ctrl;
+ int count;
+@@ -885,6 +887,7 @@ static void sci_transmit_chars(struct uart_port *port)
+ }
+
+ sci_serial_out(port, SCxTDR, c);
++ s->tx_occurred = true;
+
+ port->icount.tx++;
+ } while (--count > 0);
+@@ -1241,6 +1244,8 @@ static void sci_dma_tx_complete(void *arg)
+ if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
+ uart_write_wakeup(port);
+
++ s->tx_occurred = true;
++
+ if (!kfifo_is_empty(&tport->xmit_fifo)) {
+ s->cookie_tx = 0;
+ schedule_work(&s->work_tx);
+@@ -1731,6 +1736,19 @@ static void sci_flush_buffer(struct uart_port *port)
+ s->cookie_tx = -EINVAL;
+ }
+ }
++
++static void sci_dma_check_tx_occurred(struct sci_port *s)
++{
++ struct dma_tx_state state;
++ enum dma_status status;
++
++ if (!s->chan_tx)
++ return;
++
++ status = dmaengine_tx_status(s->chan_tx, s->cookie_tx, &state);
++ if (status == DMA_COMPLETE || status == DMA_IN_PROGRESS)
++ s->tx_occurred = true;
++}
+ #else /* !CONFIG_SERIAL_SH_SCI_DMA */
+ static inline void sci_request_dma(struct uart_port *port)
+ {
+@@ -1740,6 +1758,10 @@ static inline void sci_free_dma(struct uart_port *port)
+ {
+ }
+
++static void sci_dma_check_tx_occurred(struct sci_port *s)
++{
++}
++
+ #define sci_flush_buffer NULL
+ #endif /* !CONFIG_SERIAL_SH_SCI_DMA */
+
+@@ -2076,6 +2098,12 @@ static unsigned int sci_tx_empty(struct uart_port *port)
+ {
+ unsigned short status = sci_serial_in(port, SCxSR);
+ unsigned short in_tx_fifo = sci_txfill(port);
++ struct sci_port *s = to_sci_port(port);
++
++ sci_dma_check_tx_occurred(s);
++
++ if (!s->tx_occurred)
++ return TIOCSER_TEMT;
+
+ return (status & SCxSR_TEND(port)) && !in_tx_fifo ? TIOCSER_TEMT : 0;
+ }
+@@ -2247,6 +2275,7 @@ static int sci_startup(struct uart_port *port)
+
+ dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
+
++ s->tx_occurred = false;
+ sci_request_dma(port);
+
+ ret = sci_request_irq(s);
+diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
+index cfebe4a1af9e84..bc13133efaa508 100644
+--- a/drivers/ufs/core/ufshcd.c
++++ b/drivers/ufs/core/ufshcd.c
+@@ -5566,6 +5566,7 @@ void ufshcd_compl_one_cqe(struct ufs_hba *hba, int task_tag,
+
+ lrbp = &hba->lrb[task_tag];
+ lrbp->compl_time_stamp = ktime_get();
++ lrbp->compl_time_stamp_local_clock = local_clock();
+ cmd = lrbp->cmd;
+ if (cmd) {
+ if (unlikely(ufshcd_should_inform_monitor(hba, lrbp)))
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 500dc35e64774d..0b2490347b9fe7 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -2794,8 +2794,14 @@ int usb_add_hcd(struct usb_hcd *hcd,
+ int retval;
+ struct usb_device *rhdev;
+ struct usb_hcd *shared_hcd;
++ int skip_phy_initialization;
+
+- if (!hcd->skip_phy_initialization) {
++ if (usb_hcd_is_primary_hcd(hcd))
++ skip_phy_initialization = hcd->skip_phy_initialization;
++ else
++ skip_phy_initialization = hcd->primary_hcd->skip_phy_initialization;
++
++ if (!skip_phy_initialization) {
+ if (usb_hcd_is_primary_hcd(hcd)) {
+ hcd->phy_roothub = usb_phy_roothub_alloc(hcd->self.sysdev);
+ if (IS_ERR(hcd->phy_roothub))
+diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
+index cb54390e7de488..8c3941ecaaf5d4 100644
+--- a/drivers/usb/dwc2/hcd.c
++++ b/drivers/usb/dwc2/hcd.c
+@@ -3546,11 +3546,9 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
+ port_status |= USB_PORT_STAT_C_OVERCURRENT << 16;
+ }
+
+- if (!hsotg->flags.b.port_connect_status) {
++ if (dwc2_is_device_mode(hsotg)) {
+ /*
+- * The port is disconnected, which means the core is
+- * either in device mode or it soon will be. Just
+- * return 0's for the remainder of the port status
++ * Just return 0's for the remainder of the port status
+ * since the port register can't be read if the core
+ * is in device mode.
+ */
+@@ -3620,13 +3618,11 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
+ if (wvalue != USB_PORT_FEAT_TEST && (!windex || windex > 1))
+ goto error;
+
+- if (!hsotg->flags.b.port_connect_status) {
++ if (dwc2_is_device_mode(hsotg)) {
+ /*
+- * The port is disconnected, which means the core is
+- * either in device mode or it soon will be. Just
+- * return without doing anything since the port
+- * register can't be written if the core is in device
+- * mode.
++ * Just return 0's for the remainder of the port status
++ * since the port register can't be read if the core
++ * is in device mode.
+ */
+ break;
+ }
+@@ -4349,7 +4345,7 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
+ if (hsotg->bus_suspended)
+ goto skip_power_saving;
+
+- if (hsotg->flags.b.port_connect_status == 0)
++ if (!(dwc2_read_hprt0(hsotg) & HPRT0_CONNSTS))
+ goto skip_power_saving;
+
+ switch (hsotg->params.power_down) {
+@@ -4431,6 +4427,7 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
+ * Power Down mode.
+ */
+ if (hprt0 & HPRT0_CONNSTS) {
++ set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+ hsotg->lx_state = DWC2_L0;
+ goto unlock;
+ }
+diff --git a/drivers/usb/dwc3/dwc3-imx8mp.c b/drivers/usb/dwc3/dwc3-imx8mp.c
+index 64c0cd1995aa06..e99faf014c78a6 100644
+--- a/drivers/usb/dwc3/dwc3-imx8mp.c
++++ b/drivers/usb/dwc3/dwc3-imx8mp.c
+@@ -129,6 +129,16 @@ static void dwc3_imx8mp_wakeup_disable(struct dwc3_imx8mp *dwc3_imx)
+ writel(val, dwc3_imx->hsio_blk_base + USB_WAKEUP_CTRL);
+ }
+
++static const struct property_entry dwc3_imx8mp_properties[] = {
++ PROPERTY_ENTRY_BOOL("xhci-missing-cas-quirk"),
++ PROPERTY_ENTRY_BOOL("xhci-skip-phy-init-quirk"),
++ {},
++};
++
++static const struct software_node dwc3_imx8mp_swnode = {
++ .properties = dwc3_imx8mp_properties,
++};
++
+ static irqreturn_t dwc3_imx8mp_interrupt(int irq, void *_dwc3_imx)
+ {
+ struct dwc3_imx8mp *dwc3_imx = _dwc3_imx;
+@@ -148,17 +158,6 @@ static irqreturn_t dwc3_imx8mp_interrupt(int irq, void *_dwc3_imx)
+ return IRQ_HANDLED;
+ }
+
+-static int dwc3_imx8mp_set_software_node(struct device *dev)
+-{
+- struct property_entry props[3] = { 0 };
+- int prop_idx = 0;
+-
+- props[prop_idx++] = PROPERTY_ENTRY_BOOL("xhci-missing-cas-quirk");
+- props[prop_idx++] = PROPERTY_ENTRY_BOOL("xhci-skip-phy-init-quirk");
+-
+- return device_create_managed_software_node(dev, props, NULL);
+-}
+-
+ static int dwc3_imx8mp_probe(struct platform_device *pdev)
+ {
+ struct device *dev = &pdev->dev;
+@@ -221,17 +220,17 @@ static int dwc3_imx8mp_probe(struct platform_device *pdev)
+ if (err < 0)
+ goto disable_rpm;
+
+- err = dwc3_imx8mp_set_software_node(dev);
++ err = device_add_software_node(dev, &dwc3_imx8mp_swnode);
+ if (err) {
+ err = -ENODEV;
+- dev_err(dev, "failed to create software node\n");
++ dev_err(dev, "failed to add software node\n");
+ goto disable_rpm;
+ }
+
+ err = of_platform_populate(node, NULL, NULL, dev);
+ if (err) {
+ dev_err(&pdev->dev, "failed to create dwc3 core\n");
+- goto disable_rpm;
++ goto remove_swnode;
+ }
+
+ dwc3_imx->dwc3 = of_find_device_by_node(dwc3_np);
+@@ -255,6 +254,8 @@ static int dwc3_imx8mp_probe(struct platform_device *pdev)
+
+ depopulate:
+ of_platform_depopulate(dev);
++remove_swnode:
++ device_remove_software_node(dev);
+ disable_rpm:
+ pm_runtime_disable(dev);
+ pm_runtime_put_noidle(dev);
+@@ -268,6 +269,7 @@ static void dwc3_imx8mp_remove(struct platform_device *pdev)
+
+ pm_runtime_get_sync(dev);
+ of_platform_depopulate(dev);
++ device_remove_software_node(dev);
+
+ pm_runtime_disable(dev);
+ pm_runtime_put_noidle(dev);
+diff --git a/drivers/usb/dwc3/dwc3-xilinx.c b/drivers/usb/dwc3/dwc3-xilinx.c
+index b5e5be424ce997..96c87dc4757f22 100644
+--- a/drivers/usb/dwc3/dwc3-xilinx.c
++++ b/drivers/usb/dwc3/dwc3-xilinx.c
+@@ -121,8 +121,11 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data)
+ * in use but the usb3-phy entry is missing from the device tree.
+ * Therefore, skip these operations in this case.
+ */
+- if (!priv_data->usb3_phy)
++ if (!priv_data->usb3_phy) {
++ /* Deselect the PIPE Clock Select bit in FPD PIPE Clock register */
++ writel(PIPE_CLK_DESELECT, priv_data->regs + XLNX_USB_FPD_PIPE_CLK);
+ goto skip_usb3_phy;
++ }
+
+ crst = devm_reset_control_get_exclusive(dev, "usb_crst");
+ if (IS_ERR(crst)) {
+diff --git a/drivers/usb/gadget/function/f_midi2.c b/drivers/usb/gadget/function/f_midi2.c
+index 8285df9ed6fd78..8c9d0074db588b 100644
+--- a/drivers/usb/gadget/function/f_midi2.c
++++ b/drivers/usb/gadget/function/f_midi2.c
+@@ -1593,7 +1593,11 @@ static int f_midi2_create_card(struct f_midi2 *midi2)
+ fb->info.midi_ci_version = b->midi_ci_version;
+ fb->info.ui_hint = reverse_dir(b->ui_hint);
+ fb->info.sysex8_streams = b->sysex8_streams;
+- fb->info.flags |= b->is_midi1;
++ if (b->is_midi1 < 2)
++ fb->info.flags |= b->is_midi1;
++ else
++ fb->info.flags |= SNDRV_UMP_BLOCK_IS_MIDI1 |
++ SNDRV_UMP_BLOCK_IS_LOWSPEED;
+ strscpy(fb->info.name, ump_fb_name(b),
+ sizeof(fb->info.name));
+ }
+diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c
+index 0a8c05b2746b4e..53d9fc41acc522 100644
+--- a/drivers/usb/gadget/function/u_serial.c
++++ b/drivers/usb/gadget/function/u_serial.c
+@@ -579,9 +579,12 @@ static int gs_start_io(struct gs_port *port)
+ * we didn't in gs_start_tx() */
+ tty_wakeup(port->port.tty);
+ } else {
+- gs_free_requests(ep, head, &port->read_allocated);
+- gs_free_requests(port->port_usb->in, &port->write_pool,
+- &port->write_allocated);
++ /* Free reqs only if we are still connected */
++ if (port->port_usb) {
++ gs_free_requests(ep, head, &port->read_allocated);
++ gs_free_requests(port->port_usb->in, &port->write_pool,
++ &port->write_allocated);
++ }
+ status = -EIO;
+ }
+
+diff --git a/drivers/usb/host/ehci-sh.c b/drivers/usb/host/ehci-sh.c
+index d31d9506e41ab0..7c2b2339e674dd 100644
+--- a/drivers/usb/host/ehci-sh.c
++++ b/drivers/usb/host/ehci-sh.c
+@@ -119,8 +119,12 @@ static int ehci_hcd_sh_probe(struct platform_device *pdev)
+ if (IS_ERR(priv->iclk))
+ priv->iclk = NULL;
+
+- clk_enable(priv->fclk);
+- clk_enable(priv->iclk);
++ ret = clk_enable(priv->fclk);
++ if (ret)
++ goto fail_request_resource;
++ ret = clk_enable(priv->iclk);
++ if (ret)
++ goto fail_iclk;
+
+ ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
+ if (ret != 0) {
+@@ -136,6 +140,7 @@ static int ehci_hcd_sh_probe(struct platform_device *pdev)
+
+ fail_add_hcd:
+ clk_disable(priv->iclk);
++fail_iclk:
+ clk_disable(priv->fclk);
+
+ fail_request_resource:
+diff --git a/drivers/usb/host/max3421-hcd.c b/drivers/usb/host/max3421-hcd.c
+index 9fe4f48b18980c..0881fdd1823e0b 100644
+--- a/drivers/usb/host/max3421-hcd.c
++++ b/drivers/usb/host/max3421-hcd.c
+@@ -779,11 +779,17 @@ max3421_check_unlink(struct usb_hcd *hcd)
+ retval = 1;
+ dev_dbg(&spi->dev, "%s: URB %p unlinked=%d",
+ __func__, urb, urb->unlinked);
+- usb_hcd_unlink_urb_from_ep(hcd, urb);
+- spin_unlock_irqrestore(&max3421_hcd->lock,
+- flags);
+- usb_hcd_giveback_urb(hcd, urb, 0);
+- spin_lock_irqsave(&max3421_hcd->lock, flags);
++ if (urb == max3421_hcd->curr_urb) {
++ max3421_hcd->urb_done = 1;
++ max3421_hcd->hien &= ~(BIT(MAX3421_HI_HXFRDN_BIT) |
++ BIT(MAX3421_HI_RCVDAV_BIT));
++ } else {
++ usb_hcd_unlink_urb_from_ep(hcd, urb);
++ spin_unlock_irqrestore(&max3421_hcd->lock,
++ flags);
++ usb_hcd_giveback_urb(hcd, urb, 0);
++ spin_lock_irqsave(&max3421_hcd->lock, flags);
++ }
+ }
+ }
+ }
+diff --git a/drivers/usb/misc/onboard_usb_dev.c b/drivers/usb/misc/onboard_usb_dev.c
+index 75dfdca04ff1c2..27b0a6e182678b 100644
+--- a/drivers/usb/misc/onboard_usb_dev.c
++++ b/drivers/usb/misc/onboard_usb_dev.c
+@@ -407,8 +407,10 @@ static int onboard_dev_probe(struct platform_device *pdev)
+ }
+
+ if (of_device_is_compatible(pdev->dev.of_node, "usb424,2744") ||
+- of_device_is_compatible(pdev->dev.of_node, "usb424,5744"))
++ of_device_is_compatible(pdev->dev.of_node, "usb424,5744")) {
+ err = onboard_dev_5744_i2c_init(client);
++ onboard_dev->always_powered_in_suspend = true;
++ }
+
+ put_device(&client->dev);
+ if (err < 0)
+diff --git a/drivers/usb/typec/anx7411.c b/drivers/usb/typec/anx7411.c
+index d1e7c487ddfbb5..0ae0a5ee3fae07 100644
+--- a/drivers/usb/typec/anx7411.c
++++ b/drivers/usb/typec/anx7411.c
+@@ -290,6 +290,8 @@ struct anx7411_data {
+ struct power_supply *psy;
+ struct power_supply_desc psy_desc;
+ struct device *dev;
++ struct fwnode_handle *switch_node;
++ struct fwnode_handle *mux_node;
+ };
+
+ static u8 snk_identity[] = {
+@@ -1021,6 +1023,16 @@ static void anx7411_port_unregister_altmodes(struct typec_altmode **adev)
+ }
+ }
+
++static void anx7411_port_unregister(struct typec_params *typecp)
++{
++ fwnode_handle_put(typecp->caps.fwnode);
++ anx7411_port_unregister_altmodes(typecp->port_amode);
++ if (typecp->port)
++ typec_unregister_port(typecp->port);
++ if (typecp->role_sw)
++ usb_role_switch_put(typecp->role_sw);
++}
++
+ static int anx7411_usb_mux_set(struct typec_mux_dev *mux,
+ struct typec_mux_state *state)
+ {
+@@ -1089,6 +1101,7 @@ static void anx7411_unregister_mux(struct anx7411_data *ctx)
+ if (ctx->typec.typec_mux) {
+ typec_mux_unregister(ctx->typec.typec_mux);
+ ctx->typec.typec_mux = NULL;
++ fwnode_handle_put(ctx->mux_node);
+ }
+ }
+
+@@ -1097,6 +1110,7 @@ static void anx7411_unregister_switch(struct anx7411_data *ctx)
+ if (ctx->typec.typec_switch) {
+ typec_switch_unregister(ctx->typec.typec_switch);
+ ctx->typec.typec_switch = NULL;
++ fwnode_handle_put(ctx->switch_node);
+ }
+ }
+
+@@ -1104,28 +1118,29 @@ static int anx7411_typec_switch_probe(struct anx7411_data *ctx,
+ struct device *dev)
+ {
+ int ret;
+- struct device_node *node;
+
+- node = of_get_child_by_name(dev->of_node, "orientation_switch");
+- if (!node)
++ ctx->switch_node = device_get_named_child_node(dev, "orientation_switch");
++ if (!ctx->switch_node)
+ return 0;
+
+- ret = anx7411_register_switch(ctx, dev, &node->fwnode);
++ ret = anx7411_register_switch(ctx, dev, ctx->switch_node);
+ if (ret) {
+ dev_err(dev, "failed register switch");
++ fwnode_handle_put(ctx->switch_node);
+ return ret;
+ }
+
+- node = of_get_child_by_name(dev->of_node, "mode_switch");
+- if (!node) {
++ ctx->mux_node = device_get_named_child_node(dev, "mode_switch");
++ if (!ctx->mux_node) {
+ dev_err(dev, "no typec mux exist");
+ ret = -ENODEV;
+ goto unregister_switch;
+ }
+
+- ret = anx7411_register_mux(ctx, dev, &node->fwnode);
++ ret = anx7411_register_mux(ctx, dev, ctx->mux_node);
+ if (ret) {
+ dev_err(dev, "failed register mode switch");
++ fwnode_handle_put(ctx->mux_node);
+ ret = -ENODEV;
+ goto unregister_switch;
+ }
+@@ -1154,34 +1169,34 @@ static int anx7411_typec_port_probe(struct anx7411_data *ctx,
+ ret = fwnode_property_read_string(fwnode, "power-role", &buf);
+ if (ret) {
+ dev_err(dev, "power-role not found: %d\n", ret);
+- return ret;
++ goto put_fwnode;
+ }
+
+ ret = typec_find_port_power_role(buf);
+ if (ret < 0)
+- return ret;
++ goto put_fwnode;
+ cap->type = ret;
+
+ ret = fwnode_property_read_string(fwnode, "data-role", &buf);
+ if (ret) {
+ dev_err(dev, "data-role not found: %d\n", ret);
+- return ret;
++ goto put_fwnode;
+ }
+
+ ret = typec_find_port_data_role(buf);
+ if (ret < 0)
+- return ret;
++ goto put_fwnode;
+ cap->data = ret;
+
+ ret = fwnode_property_read_string(fwnode, "try-power-role", &buf);
+ if (ret) {
+ dev_err(dev, "try-power-role not found: %d\n", ret);
+- return ret;
++ goto put_fwnode;
+ }
+
+ ret = typec_find_power_role(buf);
+ if (ret < 0)
+- return ret;
++ goto put_fwnode;
+ cap->prefer_role = ret;
+
+ /* Get source pdos */
+@@ -1193,7 +1208,7 @@ static int anx7411_typec_port_probe(struct anx7411_data *ctx,
+ typecp->src_pdo_nr);
+ if (ret < 0) {
+ dev_err(dev, "source cap validate failed: %d\n", ret);
+- return -EINVAL;
++ goto put_fwnode;
+ }
+
+ typecp->caps_flags |= HAS_SOURCE_CAP;
+@@ -1207,7 +1222,7 @@ static int anx7411_typec_port_probe(struct anx7411_data *ctx,
+ typecp->sink_pdo_nr);
+ if (ret < 0) {
+ dev_err(dev, "sink cap validate failed: %d\n", ret);
+- return -EINVAL;
++ goto put_fwnode;
+ }
+
+ for (i = 0; i < typecp->sink_pdo_nr; i++) {
+@@ -1251,13 +1266,21 @@ static int anx7411_typec_port_probe(struct anx7411_data *ctx,
+ ret = PTR_ERR(ctx->typec.port);
+ ctx->typec.port = NULL;
+ dev_err(dev, "Failed to register type c port %d\n", ret);
+- return ret;
++ goto put_usb_role_switch;
+ }
+
+ typec_port_register_altmodes(ctx->typec.port, NULL, ctx,
+ ctx->typec.port_amode,
+ MAX_ALTMODE);
+ return 0;
++
++put_usb_role_switch:
++ if (ctx->typec.role_sw)
++ usb_role_switch_put(ctx->typec.role_sw);
++put_fwnode:
++ fwnode_handle_put(fwnode);
++
++ return ret;
+ }
+
+ static int anx7411_typec_check_connection(struct anx7411_data *ctx)
+@@ -1523,8 +1546,7 @@ static int anx7411_i2c_probe(struct i2c_client *client)
+ destroy_workqueue(plat->workqueue);
+
+ free_typec_port:
+- typec_unregister_port(plat->typec.port);
+- anx7411_port_unregister_altmodes(plat->typec.port_amode);
++ anx7411_port_unregister(&plat->typec);
+
+ free_typec_switch:
+ anx7411_unregister_switch(plat);
+@@ -1548,17 +1570,11 @@ static void anx7411_i2c_remove(struct i2c_client *client)
+
+ i2c_unregister_device(plat->spi_client);
+
+- if (plat->typec.role_sw)
+- usb_role_switch_put(plat->typec.role_sw);
+-
+ anx7411_unregister_mux(plat);
+
+ anx7411_unregister_switch(plat);
+
+- if (plat->typec.port)
+- typec_unregister_port(plat->typec.port);
+-
+- anx7411_port_unregister_altmodes(plat->typec.port_amode);
++ anx7411_port_unregister(&plat->typec);
+ }
+
+ static const struct i2c_device_id anx7411_id[] = {
+diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
+index e0f3925e401b3d..7a3f0f5af38fdb 100644
+--- a/drivers/usb/typec/ucsi/ucsi.c
++++ b/drivers/usb/typec/ucsi/ucsi.c
+@@ -46,11 +46,11 @@ void ucsi_notify_common(struct ucsi *ucsi, u32 cci)
+ ucsi_connector_change(ucsi, UCSI_CCI_CONNECTOR(cci));
+
+ if (cci & UCSI_CCI_ACK_COMPLETE &&
+- test_bit(ACK_PENDING, &ucsi->flags))
++ test_and_clear_bit(ACK_PENDING, &ucsi->flags))
+ complete(&ucsi->complete);
+
+ if (cci & UCSI_CCI_COMMAND_COMPLETE &&
+- test_bit(COMMAND_PENDING, &ucsi->flags))
++ test_and_clear_bit(COMMAND_PENDING, &ucsi->flags))
+ complete(&ucsi->complete);
+ }
+ EXPORT_SYMBOL_GPL(ucsi_notify_common);
+@@ -65,6 +65,8 @@ int ucsi_sync_control_common(struct ucsi *ucsi, u64 command)
+ else
+ set_bit(COMMAND_PENDING, &ucsi->flags);
+
++ reinit_completion(&ucsi->complete);
++
+ ret = ucsi->ops->async_control(ucsi, command);
+ if (ret)
+ goto out_clear_bit;
+diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
+index 98374ed7c57723..0112742e4504b9 100644
+--- a/drivers/virtio/virtio_ring.c
++++ b/drivers/virtio/virtio_ring.c
+@@ -2716,6 +2716,7 @@ EXPORT_SYMBOL_GPL(vring_create_virtqueue_dma);
+ * @_vq: the struct virtqueue we're talking about.
+ * @num: new ring num
+ * @recycle: callback to recycle unused buffers
++ * @recycle_done: callback to be invoked when recycle for all unused buffers done
+ *
+ * When it is really necessary to create a new vring, it will set the current vq
+ * into the reset state. Then call the passed callback to recycle the buffer
+@@ -2736,7 +2737,8 @@ EXPORT_SYMBOL_GPL(vring_create_virtqueue_dma);
+ *
+ */
+ int virtqueue_resize(struct virtqueue *_vq, u32 num,
+- void (*recycle)(struct virtqueue *vq, void *buf))
++ void (*recycle)(struct virtqueue *vq, void *buf),
++ void (*recycle_done)(struct virtqueue *vq))
+ {
+ struct vring_virtqueue *vq = to_vvq(_vq);
+ int err;
+@@ -2753,6 +2755,8 @@ int virtqueue_resize(struct virtqueue *_vq, u32 num,
+ err = virtqueue_disable_and_recycle(_vq, recycle);
+ if (err)
+ return err;
++ if (recycle_done)
++ recycle_done(_vq);
+
+ if (vq->packed_ring)
+ err = virtqueue_resize_packed(_vq, num);
+diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c
+index b35fe1075503e1..fafc07e38663ca 100644
+--- a/fs/smb/client/inode.c
++++ b/fs/smb/client/inode.c
+@@ -1925,6 +1925,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
+ goto unlink_out;
+ }
+
++ netfs_wait_for_outstanding_io(inode);
+ cifs_close_deferred_file_under_dentry(tcon, full_path);
+ #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
+@@ -2442,8 +2443,10 @@ cifs_rename2(struct mnt_idmap *idmap, struct inode *source_dir,
+ }
+
+ cifs_close_deferred_file_under_dentry(tcon, from_name);
+- if (d_inode(target_dentry) != NULL)
++ if (d_inode(target_dentry) != NULL) {
++ netfs_wait_for_outstanding_io(d_inode(target_dentry));
+ cifs_close_deferred_file_under_dentry(tcon, to_name);
++ }
+
+ rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
+ to_name);
+diff --git a/fs/smb/server/auth.c b/fs/smb/server/auth.c
+index 611716bc8f27c1..8892177e500f19 100644
+--- a/fs/smb/server/auth.c
++++ b/fs/smb/server/auth.c
+@@ -1016,6 +1016,8 @@ static int ksmbd_get_encryption_key(struct ksmbd_work *work, __u64 ses_id,
+
+ ses_enc_key = enc ? sess->smb3encryptionkey :
+ sess->smb3decryptionkey;
++ if (enc)
++ ksmbd_user_session_get(sess);
+ memcpy(key, ses_enc_key, SMB3_ENC_DEC_KEY_SIZE);
+
+ return 0;
+diff --git a/fs/smb/server/mgmt/user_session.c b/fs/smb/server/mgmt/user_session.c
+index ad02fe555fda7e..d960ddcbba1657 100644
+--- a/fs/smb/server/mgmt/user_session.c
++++ b/fs/smb/server/mgmt/user_session.c
+@@ -263,8 +263,10 @@ struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn,
+
+ down_read(&conn->session_lock);
+ sess = xa_load(&conn->sessions, id);
+- if (sess)
++ if (sess) {
+ sess->last_active = jiffies;
++ ksmbd_user_session_get(sess);
++ }
+ up_read(&conn->session_lock);
+ return sess;
+ }
+@@ -275,6 +277,8 @@ struct ksmbd_session *ksmbd_session_lookup_slowpath(unsigned long long id)
+
+ down_read(&sessions_table_lock);
+ sess = __session_lookup(id);
++ if (sess)
++ ksmbd_user_session_get(sess);
+ up_read(&sessions_table_lock);
+
+ return sess;
+diff --git a/fs/smb/server/server.c b/fs/smb/server/server.c
+index c8cc6fa6fc3ebb..698af37e988d7b 100644
+--- a/fs/smb/server/server.c
++++ b/fs/smb/server/server.c
+@@ -241,14 +241,14 @@ static void __handle_ksmbd_work(struct ksmbd_work *work,
+ if (work->tcon)
+ ksmbd_tree_connect_put(work->tcon);
+ smb3_preauth_hash_rsp(work);
+- if (work->sess)
+- ksmbd_user_session_put(work->sess);
+ if (work->sess && work->sess->enc && work->encrypted &&
+ conn->ops->encrypt_resp) {
+ rc = conn->ops->encrypt_resp(work);
+ if (rc < 0)
+ conn->ops->set_rsp_status(work, STATUS_DATA_ERROR);
+ }
++ if (work->sess)
++ ksmbd_user_session_put(work->sess);
+
+ ksmbd_conn_write(work);
+ }
+diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
+index d0836d710f1814..7d01dd313351f7 100644
+--- a/fs/smb/server/smb2pdu.c
++++ b/fs/smb/server/smb2pdu.c
+@@ -67,8 +67,10 @@ static inline bool check_session_id(struct ksmbd_conn *conn, u64 id)
+ return false;
+
+ sess = ksmbd_session_lookup_all(conn, id);
+- if (sess)
++ if (sess) {
++ ksmbd_user_session_put(sess);
+ return true;
++ }
+ pr_err("Invalid user session id: %llu\n", id);
+ return false;
+ }
+@@ -605,10 +607,8 @@ int smb2_check_user_session(struct ksmbd_work *work)
+
+ /* Check for validity of user session */
+ work->sess = ksmbd_session_lookup_all(conn, sess_id);
+- if (work->sess) {
+- ksmbd_user_session_get(work->sess);
++ if (work->sess)
+ return 1;
+- }
+ ksmbd_debug(SMB, "Invalid user session, Uid %llu\n", sess_id);
+ return -ENOENT;
+ }
+@@ -1701,29 +1701,35 @@ int smb2_sess_setup(struct ksmbd_work *work)
+
+ if (conn->dialect != sess->dialect) {
+ rc = -EINVAL;
++ ksmbd_user_session_put(sess);
+ goto out_err;
+ }
+
+ if (!(req->hdr.Flags & SMB2_FLAGS_SIGNED)) {
+ rc = -EINVAL;
++ ksmbd_user_session_put(sess);
+ goto out_err;
+ }
+
+ if (strncmp(conn->ClientGUID, sess->ClientGUID,
+ SMB2_CLIENT_GUID_SIZE)) {
+ rc = -ENOENT;
++ ksmbd_user_session_put(sess);
+ goto out_err;
+ }
+
+ if (sess->state == SMB2_SESSION_IN_PROGRESS) {
+ rc = -EACCES;
++ ksmbd_user_session_put(sess);
+ goto out_err;
+ }
+
+ if (sess->state == SMB2_SESSION_EXPIRED) {
+ rc = -EFAULT;
++ ksmbd_user_session_put(sess);
+ goto out_err;
+ }
++ ksmbd_user_session_put(sess);
+
+ if (ksmbd_conn_need_reconnect(conn)) {
+ rc = -EFAULT;
+@@ -1731,7 +1737,8 @@ int smb2_sess_setup(struct ksmbd_work *work)
+ goto out_err;
+ }
+
+- if (ksmbd_session_lookup(conn, sess_id)) {
++ sess = ksmbd_session_lookup(conn, sess_id);
++ if (!sess) {
+ rc = -EACCES;
+ goto out_err;
+ }
+@@ -1742,7 +1749,6 @@ int smb2_sess_setup(struct ksmbd_work *work)
+ }
+
+ conn->binding = true;
+- ksmbd_user_session_get(sess);
+ } else if ((conn->dialect < SMB30_PROT_ID ||
+ server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL) &&
+ (req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) {
+@@ -1769,7 +1775,6 @@ int smb2_sess_setup(struct ksmbd_work *work)
+ }
+
+ conn->binding = false;
+- ksmbd_user_session_get(sess);
+ }
+ work->sess = sess;
+
+@@ -2195,9 +2200,9 @@ int smb2_tree_disconnect(struct ksmbd_work *work)
+ int smb2_session_logoff(struct ksmbd_work *work)
+ {
+ struct ksmbd_conn *conn = work->conn;
++ struct ksmbd_session *sess = work->sess;
+ struct smb2_logoff_req *req;
+ struct smb2_logoff_rsp *rsp;
+- struct ksmbd_session *sess;
+ u64 sess_id;
+ int err;
+
+@@ -2219,11 +2224,6 @@ int smb2_session_logoff(struct ksmbd_work *work)
+ ksmbd_close_session_fds(work);
+ ksmbd_conn_wait_idle(conn);
+
+- /*
+- * Re-lookup session to validate if session is deleted
+- * while waiting request complete
+- */
+- sess = ksmbd_session_lookup_all(conn, sess_id);
+ if (ksmbd_tree_conn_session_logoff(sess)) {
+ ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId);
+ rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED;
+@@ -8962,6 +8962,7 @@ int smb3_decrypt_req(struct ksmbd_work *work)
+ le64_to_cpu(tr_hdr->SessionId));
+ return -ECONNABORTED;
+ }
++ ksmbd_user_session_put(sess);
+
+ iov[0].iov_base = buf;
+ iov[0].iov_len = sizeof(struct smb2_transform_hdr) + 4;
+diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c
+index a5c4af148853f8..134d87b3489aa4 100644
+--- a/fs/xfs/libxfs/xfs_btree.c
++++ b/fs/xfs/libxfs/xfs_btree.c
+@@ -3569,14 +3569,31 @@ xfs_btree_insrec(
+ xfs_btree_log_block(cur, bp, XFS_BB_NUMRECS);
+
+ /*
+- * If we just inserted into a new tree block, we have to
+- * recalculate nkey here because nkey is out of date.
++ * Update btree keys to reflect the newly added record or keyptr.
++ * There are three cases here to be aware of. Normally, all we have to
++ * do is walk towards the root, updating keys as necessary.
+ *
+- * Otherwise we're just updating an existing block (having shoved
+- * some records into the new tree block), so use the regular key
+- * update mechanism.
++ * If the caller had us target a full block for the insertion, we dealt
++ * with that by calling the _make_block_unfull function. If the
++ * "make unfull" function splits the block, it'll hand us back the key
++ * and pointer of the new block. We haven't yet added the new block to
++ * the next level up, so if we decide to add the new record to the new
++ * block (bp->b_bn != old_bn), we have to update the caller's pointer
++ * so that the caller adds the new block with the correct key.
++ *
++ * However, there is a third possibility-- if the selected block is the
++ * root block of an inode-rooted btree and cannot be expanded further,
++ * the "make unfull" function moves the root block contents to a new
++ * block and updates the root block to point to the new block. In this
++ * case, no block pointer is passed back because the block has already
++ * been added to the btree. In this case, we need to use the regular
++ * key update function, just like the first case. This is critical for
++ * overlapping btrees, because the high key must be updated to reflect
++ * the entire tree, not just the subtree accessible through the first
++ * child of the root (which is now two levels down from the root).
+ */
+- if (bp && xfs_buf_daddr(bp) != old_bn) {
++ if (!xfs_btree_ptr_is_null(cur, &nptr) &&
++ bp && xfs_buf_daddr(bp) != old_bn) {
+ xfs_btree_get_keys(cur, block, lkey);
+ } else if (xfs_btree_needs_key_update(cur, optr)) {
+ error = xfs_btree_update_keys(cur, level);
+@@ -5156,7 +5173,7 @@ xfs_btree_count_blocks_helper(
+ int level,
+ void *data)
+ {
+- xfs_extlen_t *blocks = data;
++ xfs_filblks_t *blocks = data;
+ (*blocks)++;
+
+ return 0;
+@@ -5166,7 +5183,7 @@ xfs_btree_count_blocks_helper(
+ int
+ xfs_btree_count_blocks(
+ struct xfs_btree_cur *cur,
+- xfs_extlen_t *blocks)
++ xfs_filblks_t *blocks)
+ {
+ *blocks = 0;
+ return xfs_btree_visit_blocks(cur, xfs_btree_count_blocks_helper,
+diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h
+index 10b7ddc3b2b34e..91e0b6dac31ec6 100644
+--- a/fs/xfs/libxfs/xfs_btree.h
++++ b/fs/xfs/libxfs/xfs_btree.h
+@@ -485,7 +485,7 @@ typedef int (*xfs_btree_visit_blocks_fn)(struct xfs_btree_cur *cur, int level,
+ int xfs_btree_visit_blocks(struct xfs_btree_cur *cur,
+ xfs_btree_visit_blocks_fn fn, unsigned int flags, void *data);
+
+-int xfs_btree_count_blocks(struct xfs_btree_cur *cur, xfs_extlen_t *blocks);
++int xfs_btree_count_blocks(struct xfs_btree_cur *cur, xfs_filblks_t *blocks);
+
+ union xfs_btree_rec *xfs_btree_rec_addr(struct xfs_btree_cur *cur, int n,
+ struct xfs_btree_block *block);
+diff --git a/fs/xfs/libxfs/xfs_ialloc_btree.c b/fs/xfs/libxfs/xfs_ialloc_btree.c
+index 401b42d52af686..6aa43f3fc68e03 100644
+--- a/fs/xfs/libxfs/xfs_ialloc_btree.c
++++ b/fs/xfs/libxfs/xfs_ialloc_btree.c
+@@ -743,6 +743,7 @@ xfs_finobt_count_blocks(
+ {
+ struct xfs_buf *agbp = NULL;
+ struct xfs_btree_cur *cur;
++ xfs_filblks_t blocks;
+ int error;
+
+ error = xfs_ialloc_read_agi(pag, tp, 0, &agbp);
+@@ -750,9 +751,10 @@ xfs_finobt_count_blocks(
+ return error;
+
+ cur = xfs_finobt_init_cursor(pag, tp, agbp);
+- error = xfs_btree_count_blocks(cur, tree_blocks);
++ error = xfs_btree_count_blocks(cur, &blocks);
+ xfs_btree_del_cursor(cur, error);
+ xfs_trans_brelse(tp, agbp);
++ *tree_blocks = blocks;
+
+ return error;
+ }
+diff --git a/fs/xfs/libxfs/xfs_symlink_remote.c b/fs/xfs/libxfs/xfs_symlink_remote.c
+index f228127a88ff26..fb47a76ead18c2 100644
+--- a/fs/xfs/libxfs/xfs_symlink_remote.c
++++ b/fs/xfs/libxfs/xfs_symlink_remote.c
+@@ -92,8 +92,10 @@ xfs_symlink_verify(
+ struct xfs_mount *mp = bp->b_mount;
+ struct xfs_dsymlink_hdr *dsl = bp->b_addr;
+
++ /* no verification of non-crc buffers */
+ if (!xfs_has_crc(mp))
+- return __this_address;
++ return NULL;
++
+ if (!xfs_verify_magic(bp, dsl->sl_magic))
+ return __this_address;
+ if (!uuid_equal(&dsl->sl_uuid, &mp->m_sb.sb_meta_uuid))
+diff --git a/fs/xfs/scrub/agheader.c b/fs/xfs/scrub/agheader.c
+index f8e5b67128d25a..da30f926cbe66d 100644
+--- a/fs/xfs/scrub/agheader.c
++++ b/fs/xfs/scrub/agheader.c
+@@ -434,7 +434,7 @@ xchk_agf_xref_btreeblks(
+ {
+ struct xfs_agf *agf = sc->sa.agf_bp->b_addr;
+ struct xfs_mount *mp = sc->mp;
+- xfs_agblock_t blocks;
++ xfs_filblks_t blocks;
+ xfs_agblock_t btreeblks;
+ int error;
+
+@@ -483,7 +483,7 @@ xchk_agf_xref_refcblks(
+ struct xfs_scrub *sc)
+ {
+ struct xfs_agf *agf = sc->sa.agf_bp->b_addr;
+- xfs_agblock_t blocks;
++ xfs_filblks_t blocks;
+ int error;
+
+ if (!sc->sa.refc_cur)
+@@ -816,7 +816,7 @@ xchk_agi_xref_fiblocks(
+ struct xfs_scrub *sc)
+ {
+ struct xfs_agi *agi = sc->sa.agi_bp->b_addr;
+- xfs_agblock_t blocks;
++ xfs_filblks_t blocks;
+ int error = 0;
+
+ if (!xfs_has_inobtcounts(sc->mp))
+diff --git a/fs/xfs/scrub/agheader_repair.c b/fs/xfs/scrub/agheader_repair.c
+index 2f98d90d7fd66d..69b003259784fe 100644
+--- a/fs/xfs/scrub/agheader_repair.c
++++ b/fs/xfs/scrub/agheader_repair.c
+@@ -256,7 +256,7 @@ xrep_agf_calc_from_btrees(
+ struct xfs_agf *agf = agf_bp->b_addr;
+ struct xfs_mount *mp = sc->mp;
+ xfs_agblock_t btreeblks;
+- xfs_agblock_t blocks;
++ xfs_filblks_t blocks;
+ int error;
+
+ /* Update the AGF counters from the bnobt. */
+@@ -946,7 +946,7 @@ xrep_agi_calc_from_btrees(
+ if (error)
+ goto err;
+ if (xfs_has_inobtcounts(mp)) {
+- xfs_agblock_t blocks;
++ xfs_filblks_t blocks;
+
+ error = xfs_btree_count_blocks(cur, &blocks);
+ if (error)
+@@ -959,7 +959,7 @@ xrep_agi_calc_from_btrees(
+ agi->agi_freecount = cpu_to_be32(freecount);
+
+ if (xfs_has_finobt(mp) && xfs_has_inobtcounts(mp)) {
+- xfs_agblock_t blocks;
++ xfs_filblks_t blocks;
+
+ cur = xfs_finobt_init_cursor(sc->sa.pag, sc->tp, agi_bp);
+ error = xfs_btree_count_blocks(cur, &blocks);
+diff --git a/fs/xfs/scrub/fscounters.c b/fs/xfs/scrub/fscounters.c
+index 1d3e98346933e1..454f17595c9c9e 100644
+--- a/fs/xfs/scrub/fscounters.c
++++ b/fs/xfs/scrub/fscounters.c
+@@ -261,7 +261,7 @@ xchk_fscount_btreeblks(
+ struct xchk_fscounters *fsc,
+ xfs_agnumber_t agno)
+ {
+- xfs_extlen_t blocks;
++ xfs_filblks_t blocks;
+ int error;
+
+ error = xchk_ag_init_existing(sc, agno, &sc->sa);
+diff --git a/fs/xfs/scrub/ialloc.c b/fs/xfs/scrub/ialloc.c
+index 750d7b0cd25a78..a59c44e5903a45 100644
+--- a/fs/xfs/scrub/ialloc.c
++++ b/fs/xfs/scrub/ialloc.c
+@@ -652,8 +652,8 @@ xchk_iallocbt_xref_rmap_btreeblks(
+ struct xfs_scrub *sc)
+ {
+ xfs_filblks_t blocks;
+- xfs_extlen_t inobt_blocks = 0;
+- xfs_extlen_t finobt_blocks = 0;
++ xfs_filblks_t inobt_blocks = 0;
++ xfs_filblks_t finobt_blocks = 0;
+ int error;
+
+ if (!sc->sa.ino_cur || !sc->sa.rmap_cur ||
+diff --git a/fs/xfs/scrub/refcount.c b/fs/xfs/scrub/refcount.c
+index d0c7d4a29c0feb..cccf39d917a09c 100644
+--- a/fs/xfs/scrub/refcount.c
++++ b/fs/xfs/scrub/refcount.c
+@@ -490,7 +490,7 @@ xchk_refcount_xref_rmap(
+ struct xfs_scrub *sc,
+ xfs_filblks_t cow_blocks)
+ {
+- xfs_extlen_t refcbt_blocks = 0;
++ xfs_filblks_t refcbt_blocks = 0;
+ xfs_filblks_t blocks;
+ int error;
+
+diff --git a/fs/xfs/scrub/symlink_repair.c b/fs/xfs/scrub/symlink_repair.c
+index d015a86ef460fb..953ce7be78dc2f 100644
+--- a/fs/xfs/scrub/symlink_repair.c
++++ b/fs/xfs/scrub/symlink_repair.c
+@@ -36,6 +36,7 @@
+ #include "scrub/tempfile.h"
+ #include "scrub/tempexch.h"
+ #include "scrub/reap.h"
++#include "scrub/health.h"
+
+ /*
+ * Symbolic Link Repair
+@@ -233,7 +234,7 @@ xrep_symlink_salvage(
+ * target zapped flag.
+ */
+ if (buflen == 0) {
+- sc->sick_mask |= XFS_SICK_INO_SYMLINK_ZAPPED;
++ xchk_mark_healthy_if_clean(sc, XFS_SICK_INO_SYMLINK_ZAPPED);
+ sprintf(target_buf, DUMMY_TARGET);
+ }
+
+diff --git a/fs/xfs/scrub/trace.h b/fs/xfs/scrub/trace.h
+index c886d5d0eb021a..da773fee8638af 100644
+--- a/fs/xfs/scrub/trace.h
++++ b/fs/xfs/scrub/trace.h
+@@ -601,7 +601,7 @@ TRACE_EVENT(xchk_ifork_btree_op_error,
+ TP_fast_assign(
+ xfs_fsblock_t fsbno = xchk_btree_cur_fsbno(cur, level);
+ __entry->dev = sc->mp->m_super->s_dev;
+- __entry->ino = sc->ip->i_ino;
++ __entry->ino = cur->bc_ino.ip->i_ino;
+ __entry->whichfork = cur->bc_ino.whichfork;
+ __entry->type = sc->sm->sm_type;
+ __assign_str(name);
+diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
+index edaf193dbd5ccc..95f8a09f96ae20 100644
+--- a/fs/xfs/xfs_bmap_util.c
++++ b/fs/xfs/xfs_bmap_util.c
+@@ -111,7 +111,7 @@ xfs_bmap_count_blocks(
+ struct xfs_mount *mp = ip->i_mount;
+ struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork);
+ struct xfs_btree_cur *cur;
+- xfs_extlen_t btblocks = 0;
++ xfs_filblks_t btblocks = 0;
+ int error;
+
+ *nextents = 0;
+diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
+index b19916b11fd563..aba54e3c583661 100644
+--- a/fs/xfs/xfs_file.c
++++ b/fs/xfs/xfs_file.c
+@@ -1228,6 +1228,14 @@ xfs_file_remap_range(
+ xfs_iunlock2_remapping(src, dest);
+ if (ret)
+ trace_xfs_reflink_remap_range_error(dest, ret, _RET_IP_);
++ /*
++ * If the caller did not set CAN_SHORTEN, then it is not prepared to
++ * handle partial results -- either the whole remap succeeds, or we
++ * must say why it did not. In this case, any error should be returned
++ * to the caller.
++ */
++ if (ret && remapped < len && !(remap_flags & REMAP_FILE_CAN_SHORTEN))
++ return ret;
+ return remapped > 0 ? remapped : ret;
+ }
+
+diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
+index 3a2005a1e673dc..8caa55b8167467 100644
+--- a/fs/xfs/xfs_rtalloc.c
++++ b/fs/xfs/xfs_rtalloc.c
+@@ -1295,7 +1295,7 @@ xfs_rtallocate(
+ * For an allocation to an empty file at offset 0, pick an extent that
+ * will space things out in the rt area.
+ */
+- if (bno_hint)
++ if (bno_hint != NULLFSBLOCK)
+ start = xfs_rtb_to_rtx(args.mp, bno_hint);
+ else if (initial_user_data)
+ start = xfs_rtpick_extent(args.mp, tp, maxlen);
+diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
+index bdf3704dc30118..30e03342287a94 100644
+--- a/fs/xfs/xfs_trans.c
++++ b/fs/xfs/xfs_trans.c
+@@ -834,13 +834,6 @@ __xfs_trans_commit(
+
+ trace_xfs_trans_commit(tp, _RET_IP_);
+
+- error = xfs_trans_run_precommits(tp);
+- if (error) {
+- if (tp->t_flags & XFS_TRANS_PERM_LOG_RES)
+- xfs_defer_cancel(tp);
+- goto out_unreserve;
+- }
+-
+ /*
+ * Finish deferred items on final commit. Only permanent transactions
+ * should ever have deferred ops.
+@@ -851,13 +844,12 @@ __xfs_trans_commit(
+ error = xfs_defer_finish_noroll(&tp);
+ if (error)
+ goto out_unreserve;
+-
+- /* Run precommits from final tx in defer chain. */
+- error = xfs_trans_run_precommits(tp);
+- if (error)
+- goto out_unreserve;
+ }
+
++ error = xfs_trans_run_precommits(tp);
++ if (error)
++ goto out_unreserve;
++
+ /*
+ * If there is nothing to be logged by the transaction,
+ * then unlock all of the items associated with the
+@@ -1382,5 +1374,8 @@ xfs_trans_alloc_dir(
+
+ out_cancel:
+ xfs_trans_cancel(tp);
++ xfs_iunlock(dp, XFS_ILOCK_EXCL);
++ if (dp != ip)
++ xfs_iunlock(ip, XFS_ILOCK_EXCL);
+ return error;
+ }
+diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
+index 6b4bc85f4999ba..b7f327ce797e5b 100644
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -200,8 +200,6 @@ struct gendisk {
+ spinlock_t zone_wplugs_lock;
+ struct mempool_s *zone_wplugs_pool;
+ struct hlist_head *zone_wplugs_hash;
+- struct list_head zone_wplugs_err_list;
+- struct work_struct zone_wplugs_work;
+ struct workqueue_struct *zone_wplugs_wq;
+ #endif /* CONFIG_BLK_DEV_ZONED */
+
+@@ -1386,6 +1384,9 @@ static inline bool bdev_is_zone_start(struct block_device *bdev,
+ return bdev_offset_from_zone_start(bdev, sector) == 0;
+ }
+
++int blk_zone_issue_zeroout(struct block_device *bdev, sector_t sector,
++ sector_t nr_sects, gfp_t gfp_mask);
++
+ static inline int queue_dma_alignment(const struct request_queue *q)
+ {
+ return q->limits.dma_alignment;
+diff --git a/include/linux/bpf.h b/include/linux/bpf.h
+index cbe2350912460b..a7af13f550e0d4 100644
+--- a/include/linux/bpf.h
++++ b/include/linux/bpf.h
+@@ -2157,26 +2157,25 @@ bpf_prog_run_array(const struct bpf_prog_array *array,
+ * rcu-protected dynamically sized maps.
+ */
+ static __always_inline u32
+-bpf_prog_run_array_uprobe(const struct bpf_prog_array __rcu *array_rcu,
++bpf_prog_run_array_uprobe(const struct bpf_prog_array *array,
+ const void *ctx, bpf_prog_run_fn run_prog)
+ {
+ const struct bpf_prog_array_item *item;
+ const struct bpf_prog *prog;
+- const struct bpf_prog_array *array;
+ struct bpf_run_ctx *old_run_ctx;
+ struct bpf_trace_run_ctx run_ctx;
+ u32 ret = 1;
+
+ might_fault();
++ RCU_LOCKDEP_WARN(!rcu_read_lock_trace_held(), "no rcu lock held");
++
++ if (unlikely(!array))
++ return ret;
+
+- rcu_read_lock_trace();
+ migrate_disable();
+
+ run_ctx.is_uprobe = true;
+
+- array = rcu_dereference_check(array_rcu, rcu_read_lock_trace_held());
+- if (unlikely(!array))
+- goto out;
+ old_run_ctx = bpf_set_run_ctx(&run_ctx.run_ctx);
+ item = &array->items[0];
+ while ((prog = READ_ONCE(item->prog))) {
+@@ -2191,9 +2190,7 @@ bpf_prog_run_array_uprobe(const struct bpf_prog_array __rcu *array_rcu,
+ rcu_read_unlock();
+ }
+ bpf_reset_run_ctx(old_run_ctx);
+-out:
+ migrate_enable();
+- rcu_read_unlock_trace();
+ return ret;
+ }
+
+@@ -3471,10 +3468,4 @@ static inline bool bpf_is_subprog(const struct bpf_prog *prog)
+ return prog->aux->func_idx != 0;
+ }
+
+-static inline bool bpf_prog_is_raw_tp(const struct bpf_prog *prog)
+-{
+- return prog->type == BPF_PROG_TYPE_TRACING &&
+- prog->expected_attach_type == BPF_TRACE_RAW_TP;
+-}
+-
+ #endif /* _LINUX_BPF_H */
+diff --git a/include/linux/compiler.h b/include/linux/compiler.h
+index 4d4e23b6e3e761..2d962dade9faee 100644
+--- a/include/linux/compiler.h
++++ b/include/linux/compiler.h
+@@ -216,28 +216,43 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
+
+ #endif /* __KERNEL__ */
+
++/**
++ * offset_to_ptr - convert a relative memory offset to an absolute pointer
++ * @off: the address of the 32-bit offset value
++ */
++static inline void *offset_to_ptr(const int *off)
++{
++ return (void *)((unsigned long)off + *off);
++}
++
++#endif /* __ASSEMBLY__ */
++
++#ifdef CONFIG_64BIT
++#define ARCH_SEL(a,b) a
++#else
++#define ARCH_SEL(a,b) b
++#endif
++
+ /*
+ * Force the compiler to emit 'sym' as a symbol, so that we can reference
+ * it from inline assembler. Necessary in case 'sym' could be inlined
+ * otherwise, or eliminated entirely due to lack of references that are
+ * visible to the compiler.
+ */
+-#define ___ADDRESSABLE(sym, __attrs) \
+- static void * __used __attrs \
++#define ___ADDRESSABLE(sym, __attrs) \
++ static void * __used __attrs \
+ __UNIQUE_ID(__PASTE(__addressable_,sym)) = (void *)(uintptr_t)&sym;
++
+ #define __ADDRESSABLE(sym) \
+ ___ADDRESSABLE(sym, __section(".discard.addressable"))
+
+-/**
+- * offset_to_ptr - convert a relative memory offset to an absolute pointer
+- * @off: the address of the 32-bit offset value
+- */
+-static inline void *offset_to_ptr(const int *off)
+-{
+- return (void *)((unsigned long)off + *off);
+-}
++#define __ADDRESSABLE_ASM(sym) \
++ .pushsection .discard.addressable,"aw"; \
++ .align ARCH_SEL(8,4); \
++ ARCH_SEL(.quad, .long) __stringify(sym); \
++ .popsection;
+
+-#endif /* __ASSEMBLY__ */
++#define __ADDRESSABLE_ASM_STR(sym) __stringify(__ADDRESSABLE_ASM(sym))
+
+ /* &a[0] degrades to a pointer: a different type from an array */
+ #define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
+diff --git a/include/linux/dsa/ocelot.h b/include/linux/dsa/ocelot.h
+index 6fbfbde68a37c3..620a3260fc0802 100644
+--- a/include/linux/dsa/ocelot.h
++++ b/include/linux/dsa/ocelot.h
+@@ -15,6 +15,7 @@
+ struct ocelot_skb_cb {
+ struct sk_buff *clone;
+ unsigned int ptp_class; /* valid only for clones */
++ unsigned long ptp_tx_time; /* valid only for clones */
+ u32 tstamp_lo;
+ u8 ptp_cmd;
+ u8 ts_id;
+diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h
+index 66e7d26b70a4fe..11be70a7929f28 100644
+--- a/include/linux/netdev_features.h
++++ b/include/linux/netdev_features.h
+@@ -253,4 +253,11 @@ static inline int find_next_netdev_feature(u64 feature, unsigned long start)
+ NETIF_F_GSO_UDP_TUNNEL | \
+ NETIF_F_GSO_UDP_TUNNEL_CSUM)
+
++static inline netdev_features_t netdev_base_features(netdev_features_t features)
++{
++ features &= ~NETIF_F_ONE_FOR_ALL;
++ features |= NETIF_F_ALL_FOR_ALL;
++ return features;
++}
++
+ #endif /* _LINUX_NETDEV_FEATURES_H */
+diff --git a/include/linux/static_call.h b/include/linux/static_call.h
+index 141e6b176a1b30..78a77a4ae0ea87 100644
+--- a/include/linux/static_call.h
++++ b/include/linux/static_call.h
+@@ -160,6 +160,8 @@ extern void arch_static_call_transform(void *site, void *tramp, void *func, bool
+
+ #ifdef CONFIG_HAVE_STATIC_CALL_INLINE
+
++extern int static_call_initialized;
++
+ extern int __init static_call_init(void);
+
+ extern void static_call_force_reinit(void);
+@@ -225,6 +227,8 @@ extern long __static_call_return0(void);
+
+ #elif defined(CONFIG_HAVE_STATIC_CALL)
+
++#define static_call_initialized 0
++
+ static inline int static_call_init(void) { return 0; }
+
+ #define DEFINE_STATIC_CALL(name, _func) \
+@@ -281,6 +285,8 @@ extern long __static_call_return0(void);
+
+ #else /* Generic implementation */
+
++#define static_call_initialized 0
++
+ static inline int static_call_init(void) { return 0; }
+
+ static inline long __static_call_return0(void)
+diff --git a/include/linux/virtio.h b/include/linux/virtio.h
+index 306137a15d0753..73c8922e69e095 100644
+--- a/include/linux/virtio.h
++++ b/include/linux/virtio.h
+@@ -100,7 +100,8 @@ dma_addr_t virtqueue_get_avail_addr(const struct virtqueue *vq);
+ dma_addr_t virtqueue_get_used_addr(const struct virtqueue *vq);
+
+ int virtqueue_resize(struct virtqueue *vq, u32 num,
+- void (*recycle)(struct virtqueue *vq, void *buf));
++ void (*recycle)(struct virtqueue *vq, void *buf),
++ void (*recycle_done)(struct virtqueue *vq));
+ int virtqueue_reset(struct virtqueue *vq,
+ void (*recycle)(struct virtqueue *vq, void *buf));
+
+diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
+index f66bc85c6411dd..435250c72d5684 100644
+--- a/include/net/bluetooth/bluetooth.h
++++ b/include/net/bluetooth/bluetooth.h
+@@ -123,6 +123,7 @@ struct bt_voice {
+
+ #define BT_VOICE_TRANSPARENT 0x0003
+ #define BT_VOICE_CVSD_16BIT 0x0060
++#define BT_VOICE_TRANSPARENT_16BIT 0x0063
+
+ #define BT_SNDMTU 12
+ #define BT_RCVMTU 13
+@@ -590,15 +591,6 @@ static inline struct sk_buff *bt_skb_sendmmsg(struct sock *sk,
+ return skb;
+ }
+
+-static inline int bt_copy_from_sockptr(void *dst, size_t dst_size,
+- sockptr_t src, size_t src_size)
+-{
+- if (dst_size > src_size)
+- return -EINVAL;
+-
+- return copy_from_sockptr(dst, src, dst_size);
+-}
+-
+ int bt_to_errno(u16 code);
+ __u8 bt_status(int err);
+
+diff --git a/include/net/lapb.h b/include/net/lapb.h
+index 124ee122f2c8f8..6c07420644e45a 100644
+--- a/include/net/lapb.h
++++ b/include/net/lapb.h
+@@ -4,7 +4,7 @@
+ #include <linux/lapb.h>
+ #include <linux/refcount.h>
+
+-#define LAPB_HEADER_LEN 20 /* LAPB over Ethernet + a bit more */
++#define LAPB_HEADER_LEN MAX_HEADER /* LAPB over Ethernet + a bit more */
+
+ #define LAPB_ACK_PENDING_CONDITION 0x01
+ #define LAPB_REJECT_CONDITION 0x02
+diff --git a/include/net/mac80211.h b/include/net/mac80211.h
+index 333e0fae6796c8..5b712582f9a9ce 100644
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -6770,14 +6770,12 @@ void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success,
+ /**
+ * ieee80211_channel_switch_disconnect - disconnect due to channel switch error
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+- * @block_tx: if %true, do not send deauth frame.
+ *
+ * Instruct mac80211 to disconnect due to a channel switch error. The channel
+ * switch can request to block the tx and so, we need to make sure we do not send
+ * a deauth frame in this case.
+ */
+-void ieee80211_channel_switch_disconnect(struct ieee80211_vif *vif,
+- bool block_tx);
++void ieee80211_channel_switch_disconnect(struct ieee80211_vif *vif);
+
+ /**
+ * ieee80211_request_smps - request SM PS transition
+diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
+index e67b483cc8bbb8..9398c8f4995368 100644
+--- a/include/net/net_namespace.h
++++ b/include/net/net_namespace.h
+@@ -80,6 +80,7 @@ struct net {
+ * or to unregister pernet ops
+ * (pernet_ops_rwsem write locked).
+ */
++ struct llist_node defer_free_list;
+ struct llist_node cleanup_list; /* namespaces on death row */
+
+ #ifdef CONFIG_KEYS
+diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
+index 066a3ea33b12e9..91ae20cb76485b 100644
+--- a/include/net/netfilter/nf_tables.h
++++ b/include/net/netfilter/nf_tables.h
+@@ -1103,7 +1103,6 @@ struct nft_rule_blob {
+ * @name: name of the chain
+ * @udlen: user data length
+ * @udata: user data in the chain
+- * @rcu_head: rcu head for deferred release
+ * @blob_next: rule blob pointer to the next in the chain
+ */
+ struct nft_chain {
+@@ -1121,7 +1120,6 @@ struct nft_chain {
+ char *name;
+ u16 udlen;
+ u8 *udata;
+- struct rcu_head rcu_head;
+
+ /* Only used during control plane commit phase: */
+ struct nft_rule_blob *blob_next;
+@@ -1265,7 +1263,6 @@ static inline void nft_use_inc_restore(u32 *use)
+ * @sets: sets in the table
+ * @objects: stateful objects in the table
+ * @flowtables: flow tables in the table
+- * @net: netnamespace this table belongs to
+ * @hgenerator: handle generator state
+ * @handle: table handle
+ * @use: number of chain references to this table
+@@ -1285,7 +1282,6 @@ struct nft_table {
+ struct list_head sets;
+ struct list_head objects;
+ struct list_head flowtables;
+- possible_net_t net;
+ u64 hgenerator;
+ u64 handle;
+ u32 use;
+diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
+index 462c653e101746..2db9ae0575b609 100644
+--- a/include/soc/mscc/ocelot.h
++++ b/include/soc/mscc/ocelot.h
+@@ -778,7 +778,6 @@ struct ocelot_port {
+
+ phy_interface_t phy_mode;
+
+- unsigned int ptp_skbs_in_flight;
+ struct sk_buff_head tx_skbs;
+
+ unsigned int trap_proto;
+@@ -786,7 +785,6 @@ struct ocelot_port {
+ u16 mrp_ring_id;
+
+ u8 ptp_cmd;
+- u8 ts_id;
+
+ u8 index;
+
+diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
+index 346826e3c933da..41d20b7199c4af 100644
+--- a/kernel/bpf/btf.c
++++ b/kernel/bpf/btf.c
+@@ -6415,6 +6415,101 @@ int btf_ctx_arg_offset(const struct btf *btf, const struct btf_type *func_proto,
+ return off;
+ }
+
++struct bpf_raw_tp_null_args {
++ const char *func;
++ u64 mask;
++};
++
++static const struct bpf_raw_tp_null_args raw_tp_null_args[] = {
++ /* sched */
++ { "sched_pi_setprio", 0x10 },
++ /* ... from sched_numa_pair_template event class */
++ { "sched_stick_numa", 0x100 },
++ { "sched_swap_numa", 0x100 },
++ /* afs */
++ { "afs_make_fs_call", 0x10 },
++ { "afs_make_fs_calli", 0x10 },
++ { "afs_make_fs_call1", 0x10 },
++ { "afs_make_fs_call2", 0x10 },
++ { "afs_protocol_error", 0x1 },
++ { "afs_flock_ev", 0x10 },
++ /* cachefiles */
++ { "cachefiles_lookup", 0x1 | 0x200 },
++ { "cachefiles_unlink", 0x1 },
++ { "cachefiles_rename", 0x1 },
++ { "cachefiles_prep_read", 0x1 },
++ { "cachefiles_mark_active", 0x1 },
++ { "cachefiles_mark_failed", 0x1 },
++ { "cachefiles_mark_inactive", 0x1 },
++ { "cachefiles_vfs_error", 0x1 },
++ { "cachefiles_io_error", 0x1 },
++ { "cachefiles_ondemand_open", 0x1 },
++ { "cachefiles_ondemand_copen", 0x1 },
++ { "cachefiles_ondemand_close", 0x1 },
++ { "cachefiles_ondemand_read", 0x1 },
++ { "cachefiles_ondemand_cread", 0x1 },
++ { "cachefiles_ondemand_fd_write", 0x1 },
++ { "cachefiles_ondemand_fd_release", 0x1 },
++ /* ext4, from ext4__mballoc event class */
++ { "ext4_mballoc_discard", 0x10 },
++ { "ext4_mballoc_free", 0x10 },
++ /* fib */
++ { "fib_table_lookup", 0x100 },
++ /* filelock */
++ /* ... from filelock_lock event class */
++ { "posix_lock_inode", 0x10 },
++ { "fcntl_setlk", 0x10 },
++ { "locks_remove_posix", 0x10 },
++ { "flock_lock_inode", 0x10 },
++ /* ... from filelock_lease event class */
++ { "break_lease_noblock", 0x10 },
++ { "break_lease_block", 0x10 },
++ { "break_lease_unblock", 0x10 },
++ { "generic_delete_lease", 0x10 },
++ { "time_out_leases", 0x10 },
++ /* host1x */
++ { "host1x_cdma_push_gather", 0x10000 },
++ /* huge_memory */
++ { "mm_khugepaged_scan_pmd", 0x10 },
++ { "mm_collapse_huge_page_isolate", 0x1 },
++ { "mm_khugepaged_scan_file", 0x10 },
++ { "mm_khugepaged_collapse_file", 0x10 },
++ /* kmem */
++ { "mm_page_alloc", 0x1 },
++ { "mm_page_pcpu_drain", 0x1 },
++ /* .. from mm_page event class */
++ { "mm_page_alloc_zone_locked", 0x1 },
++ /* netfs */
++ { "netfs_failure", 0x10 },
++ /* power */
++ { "device_pm_callback_start", 0x10 },
++ /* qdisc */
++ { "qdisc_dequeue", 0x1000 },
++ /* rxrpc */
++ { "rxrpc_recvdata", 0x1 },
++ { "rxrpc_resend", 0x10 },
++ /* sunrpc */
++ { "xs_stream_read_data", 0x1 },
++ /* ... from xprt_cong_event event class */
++ { "xprt_reserve_cong", 0x10 },
++ { "xprt_release_cong", 0x10 },
++ { "xprt_get_cong", 0x10 },
++ { "xprt_put_cong", 0x10 },
++ /* tcp */
++ { "tcp_send_reset", 0x11 },
++ /* tegra_apb_dma */
++ { "tegra_dma_tx_status", 0x100 },
++ /* timer_migration */
++ { "tmigr_update_events", 0x1 },
++ /* writeback, from writeback_folio_template event class */
++ { "writeback_dirty_folio", 0x10 },
++ { "folio_wait_writeback", 0x10 },
++ /* rdma */
++ { "mr_integ_alloc", 0x2000 },
++ /* bpf_testmod */
++ { "bpf_testmod_test_read", 0x0 },
++};
++
+ bool btf_ctx_access(int off, int size, enum bpf_access_type type,
+ const struct bpf_prog *prog,
+ struct bpf_insn_access_aux *info)
+@@ -6425,6 +6520,7 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type,
+ const char *tname = prog->aux->attach_func_name;
+ struct bpf_verifier_log *log = info->log;
+ const struct btf_param *args;
++ bool ptr_err_raw_tp = false;
+ const char *tag_value;
+ u32 nr_args, arg;
+ int i, ret;
+@@ -6519,6 +6615,12 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type,
+ return false;
+ }
+
++ if (size != sizeof(u64)) {
++ bpf_log(log, "func '%s' size %d must be 8\n",
++ tname, size);
++ return false;
++ }
++
+ /* check for PTR_TO_RDONLY_BUF_OR_NULL or PTR_TO_RDWR_BUF_OR_NULL */
+ for (i = 0; i < prog->aux->ctx_arg_info_size; i++) {
+ const struct bpf_ctx_arg_aux *ctx_arg_info = &prog->aux->ctx_arg_info[i];
+@@ -6564,12 +6666,42 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type,
+ if (prog_args_trusted(prog))
+ info->reg_type |= PTR_TRUSTED;
+
+- /* Raw tracepoint arguments always get marked as maybe NULL */
+- if (bpf_prog_is_raw_tp(prog))
+- info->reg_type |= PTR_MAYBE_NULL;
+- else if (btf_param_match_suffix(btf, &args[arg], "__nullable"))
++ if (btf_param_match_suffix(btf, &args[arg], "__nullable"))
+ info->reg_type |= PTR_MAYBE_NULL;
+
++ if (prog->expected_attach_type == BPF_TRACE_RAW_TP) {
++ struct btf *btf = prog->aux->attach_btf;
++ const struct btf_type *t;
++ const char *tname;
++
++ /* BTF lookups cannot fail, return false on error */
++ t = btf_type_by_id(btf, prog->aux->attach_btf_id);
++ if (!t)
++ return false;
++ tname = btf_name_by_offset(btf, t->name_off);
++ if (!tname)
++ return false;
++ /* Checked by bpf_check_attach_target */
++ tname += sizeof("btf_trace_") - 1;
++ for (i = 0; i < ARRAY_SIZE(raw_tp_null_args); i++) {
++ /* Is this a func with potential NULL args? */
++ if (strcmp(tname, raw_tp_null_args[i].func))
++ continue;
++ if (raw_tp_null_args[i].mask & (0x1 << (arg * 4)))
++ info->reg_type |= PTR_MAYBE_NULL;
++ /* Is the current arg IS_ERR? */
++ if (raw_tp_null_args[i].mask & (0x2 << (arg * 4)))
++ ptr_err_raw_tp = true;
++ break;
++ }
++ /* If we don't know NULL-ness specification and the tracepoint
++ * is coming from a loadable module, be conservative and mark
++ * argument as PTR_MAYBE_NULL.
++ */
++ if (i == ARRAY_SIZE(raw_tp_null_args) && btf_is_module(btf))
++ info->reg_type |= PTR_MAYBE_NULL;
++ }
++
+ if (tgt_prog) {
+ enum bpf_prog_type tgt_type;
+
+@@ -6614,6 +6746,15 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type,
+ bpf_log(log, "func '%s' arg%d has btf_id %d type %s '%s'\n",
+ tname, arg, info->btf_id, btf_type_str(t),
+ __btf_name_by_offset(btf, t->name_off));
++
++ /* Perform all checks on the validity of type for this argument, but if
++ * we know it can be IS_ERR at runtime, scrub pointer type and mark as
++ * scalar.
++ */
++ if (ptr_err_raw_tp) {
++ bpf_log(log, "marking pointer arg%d as scalar as it may encode error", arg);
++ info->reg_type = SCALAR_VALUE;
++ }
+ return true;
+ }
+ EXPORT_SYMBOL_GPL(btf_ctx_access);
+diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
+index b2008076df9c26..4c486a0bfcc4d8 100644
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -418,25 +418,6 @@ static struct btf_record *reg_btf_record(const struct bpf_reg_state *reg)
+ return rec;
+ }
+
+-static bool mask_raw_tp_reg_cond(const struct bpf_verifier_env *env, struct bpf_reg_state *reg) {
+- return reg->type == (PTR_TO_BTF_ID | PTR_TRUSTED | PTR_MAYBE_NULL) &&
+- bpf_prog_is_raw_tp(env->prog) && !reg->ref_obj_id;
+-}
+-
+-static bool mask_raw_tp_reg(const struct bpf_verifier_env *env, struct bpf_reg_state *reg)
+-{
+- if (!mask_raw_tp_reg_cond(env, reg))
+- return false;
+- reg->type &= ~PTR_MAYBE_NULL;
+- return true;
+-}
+-
+-static void unmask_raw_tp_reg(struct bpf_reg_state *reg, bool result)
+-{
+- if (result)
+- reg->type |= PTR_MAYBE_NULL;
+-}
+-
+ static bool subprog_is_global(const struct bpf_verifier_env *env, int subprog)
+ {
+ struct bpf_func_info_aux *aux = env->prog->aux->func_info_aux;
+@@ -6618,7 +6599,6 @@ static int check_ptr_to_btf_access(struct bpf_verifier_env *env,
+ const char *field_name = NULL;
+ enum bpf_type_flag flag = 0;
+ u32 btf_id = 0;
+- bool mask;
+ int ret;
+
+ if (!env->allow_ptr_leaks) {
+@@ -6690,21 +6670,7 @@ static int check_ptr_to_btf_access(struct bpf_verifier_env *env,
+
+ if (ret < 0)
+ return ret;
+- /* For raw_tp progs, we allow dereference of PTR_MAYBE_NULL
+- * trusted PTR_TO_BTF_ID, these are the ones that are possibly
+- * arguments to the raw_tp. Since internal checks in for trusted
+- * reg in check_ptr_to_btf_access would consider PTR_MAYBE_NULL
+- * modifier as problematic, mask it out temporarily for the
+- * check. Don't apply this to pointers with ref_obj_id > 0, as
+- * those won't be raw_tp args.
+- *
+- * We may end up applying this relaxation to other trusted
+- * PTR_TO_BTF_ID with maybe null flag, since we cannot
+- * distinguish PTR_MAYBE_NULL tagged for arguments vs normal
+- * tagging, but that should expand allowed behavior, and not
+- * cause regression for existing behavior.
+- */
+- mask = mask_raw_tp_reg(env, reg);
++
+ if (ret != PTR_TO_BTF_ID) {
+ /* just mark; */
+
+@@ -6765,13 +6731,8 @@ static int check_ptr_to_btf_access(struct bpf_verifier_env *env,
+ clear_trusted_flags(&flag);
+ }
+
+- if (atype == BPF_READ && value_regno >= 0) {
++ if (atype == BPF_READ && value_regno >= 0)
+ mark_btf_ld_reg(env, regs, value_regno, ret, reg->btf, btf_id, flag);
+- /* We've assigned a new type to regno, so don't undo masking. */
+- if (regno == value_regno)
+- mask = false;
+- }
+- unmask_raw_tp_reg(reg, mask);
+
+ return 0;
+ }
+@@ -7146,7 +7107,7 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn
+ if (!err && t == BPF_READ && value_regno >= 0)
+ mark_reg_unknown(env, regs, value_regno);
+ } else if (base_type(reg->type) == PTR_TO_BTF_ID &&
+- (mask_raw_tp_reg_cond(env, reg) || !type_may_be_null(reg->type))) {
++ !type_may_be_null(reg->type)) {
+ err = check_ptr_to_btf_access(env, regs, regno, off, size, t,
+ value_regno);
+ } else if (reg->type == CONST_PTR_TO_MAP) {
+@@ -8844,7 +8805,6 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
+ enum bpf_reg_type type = reg->type;
+ u32 *arg_btf_id = NULL;
+ int err = 0;
+- bool mask;
+
+ if (arg_type == ARG_DONTCARE)
+ return 0;
+@@ -8885,11 +8845,11 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
+ base_type(arg_type) == ARG_PTR_TO_SPIN_LOCK)
+ arg_btf_id = fn->arg_btf_id[arg];
+
+- mask = mask_raw_tp_reg(env, reg);
+ err = check_reg_type(env, regno, arg_type, arg_btf_id, meta);
++ if (err)
++ return err;
+
+- err = err ?: check_func_arg_reg_off(env, reg, regno, arg_type);
+- unmask_raw_tp_reg(reg, mask);
++ err = check_func_arg_reg_off(env, reg, regno, arg_type);
+ if (err)
+ return err;
+
+@@ -9684,17 +9644,14 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env, int subprog,
+ return ret;
+ } else if (base_type(arg->arg_type) == ARG_PTR_TO_BTF_ID) {
+ struct bpf_call_arg_meta meta;
+- bool mask;
+ int err;
+
+ if (register_is_null(reg) && type_may_be_null(arg->arg_type))
+ continue;
+
+ memset(&meta, 0, sizeof(meta)); /* leave func_id as zero */
+- mask = mask_raw_tp_reg(env, reg);
+ err = check_reg_type(env, regno, arg->arg_type, &arg->btf_id, &meta);
+ err = err ?: check_func_arg_reg_off(env, reg, regno, arg->arg_type);
+- unmask_raw_tp_reg(reg, mask);
+ if (err)
+ return err;
+ } else {
+@@ -12009,7 +11966,6 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_
+ enum bpf_arg_type arg_type = ARG_DONTCARE;
+ u32 regno = i + 1, ref_id, type_size;
+ bool is_ret_buf_sz = false;
+- bool mask = false;
+ int kf_arg_type;
+
+ t = btf_type_skip_modifiers(btf, args[i].type, NULL);
+@@ -12068,15 +12024,12 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_
+ return -EINVAL;
+ }
+
+- mask = mask_raw_tp_reg(env, reg);
+ if ((is_kfunc_trusted_args(meta) || is_kfunc_rcu(meta)) &&
+ (register_is_null(reg) || type_may_be_null(reg->type)) &&
+ !is_kfunc_arg_nullable(meta->btf, &args[i])) {
+ verbose(env, "Possibly NULL pointer passed to trusted arg%d\n", i);
+- unmask_raw_tp_reg(reg, mask);
+ return -EACCES;
+ }
+- unmask_raw_tp_reg(reg, mask);
+
+ if (reg->ref_obj_id) {
+ if (is_kfunc_release(meta) && meta->ref_obj_id) {
+@@ -12134,24 +12087,16 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_
+ if (!is_kfunc_trusted_args(meta) && !is_kfunc_rcu(meta))
+ break;
+
+- /* Allow passing maybe NULL raw_tp arguments to
+- * kfuncs for compatibility. Don't apply this to
+- * arguments with ref_obj_id > 0.
+- */
+- mask = mask_raw_tp_reg(env, reg);
+ if (!is_trusted_reg(reg)) {
+ if (!is_kfunc_rcu(meta)) {
+ verbose(env, "R%d must be referenced or trusted\n", regno);
+- unmask_raw_tp_reg(reg, mask);
+ return -EINVAL;
+ }
+ if (!is_rcu_reg(reg)) {
+ verbose(env, "R%d must be a rcu pointer\n", regno);
+- unmask_raw_tp_reg(reg, mask);
+ return -EINVAL;
+ }
+ }
+- unmask_raw_tp_reg(reg, mask);
+ fallthrough;
+ case KF_ARG_PTR_TO_CTX:
+ case KF_ARG_PTR_TO_DYNPTR:
+@@ -12174,9 +12119,7 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_
+
+ if (is_kfunc_release(meta) && reg->ref_obj_id)
+ arg_type |= OBJ_RELEASE;
+- mask = mask_raw_tp_reg(env, reg);
+ ret = check_func_arg_reg_off(env, reg, regno, arg_type);
+- unmask_raw_tp_reg(reg, mask);
+ if (ret < 0)
+ return ret;
+
+@@ -12353,7 +12296,6 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_
+ ref_tname = btf_name_by_offset(btf, ref_t->name_off);
+ fallthrough;
+ case KF_ARG_PTR_TO_BTF_ID:
+- mask = mask_raw_tp_reg(env, reg);
+ /* Only base_type is checked, further checks are done here */
+ if ((base_type(reg->type) != PTR_TO_BTF_ID ||
+ (bpf_type_has_unsafe_modifiers(reg->type) && !is_rcu_reg(reg))) &&
+@@ -12362,11 +12304,9 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_
+ verbose(env, "expected %s or socket\n",
+ reg_type_str(env, base_type(reg->type) |
+ (type_flag(reg->type) & BPF_REG_TRUSTED_MODIFIERS)));
+- unmask_raw_tp_reg(reg, mask);
+ return -EINVAL;
+ }
+ ret = process_kf_arg_ptr_to_btf_id(env, reg, ref_t, ref_tname, ref_id, meta, i);
+- unmask_raw_tp_reg(reg, mask);
+ if (ret < 0)
+ return ret;
+ break;
+@@ -13336,7 +13276,7 @@ static int sanitize_check_bounds(struct bpf_verifier_env *env,
+ */
+ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
+ struct bpf_insn *insn,
+- struct bpf_reg_state *ptr_reg,
++ const struct bpf_reg_state *ptr_reg,
+ const struct bpf_reg_state *off_reg)
+ {
+ struct bpf_verifier_state *vstate = env->cur_state;
+@@ -13350,7 +13290,6 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
+ struct bpf_sanitize_info info = {};
+ u8 opcode = BPF_OP(insn->code);
+ u32 dst = insn->dst_reg;
+- bool mask;
+ int ret;
+
+ dst_reg = ®s[dst];
+@@ -13377,14 +13316,11 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
+ return -EACCES;
+ }
+
+- mask = mask_raw_tp_reg(env, ptr_reg);
+ if (ptr_reg->type & PTR_MAYBE_NULL) {
+ verbose(env, "R%d pointer arithmetic on %s prohibited, null-check it first\n",
+ dst, reg_type_str(env, ptr_reg->type));
+- unmask_raw_tp_reg(ptr_reg, mask);
+ return -EACCES;
+ }
+- unmask_raw_tp_reg(ptr_reg, mask);
+
+ switch (base_type(ptr_reg->type)) {
+ case PTR_TO_CTX:
+@@ -19934,7 +19870,6 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
+ * for this case.
+ */
+ case PTR_TO_BTF_ID | MEM_ALLOC | PTR_UNTRUSTED:
+- case PTR_TO_BTF_ID | PTR_TRUSTED | PTR_MAYBE_NULL:
+ if (type == BPF_READ) {
+ if (BPF_MODE(insn->code) == BPF_MEM)
+ insn->code = BPF_LDX | BPF_PROBE_MEM |
+diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
+index 40a1ad4493b4d9..fc6f41ac33eb13 100644
+--- a/kernel/sched/deadline.c
++++ b/kernel/sched/deadline.c
+@@ -781,7 +781,7 @@ static inline void replenish_dl_new_period(struct sched_dl_entity *dl_se,
+ * If it is a deferred reservation, and the server
+ * is not handling an starvation case, defer it.
+ */
+- if (dl_se->dl_defer & !dl_se->dl_defer_running) {
++ if (dl_se->dl_defer && !dl_se->dl_defer_running) {
+ dl_se->dl_throttled = 1;
+ dl_se->dl_defer_armed = 1;
+ }
+diff --git a/kernel/static_call_inline.c b/kernel/static_call_inline.c
+index 5259cda486d058..bb7d066a7c3979 100644
+--- a/kernel/static_call_inline.c
++++ b/kernel/static_call_inline.c
+@@ -15,7 +15,7 @@ extern struct static_call_site __start_static_call_sites[],
+ extern struct static_call_tramp_key __start_static_call_tramp_key[],
+ __stop_static_call_tramp_key[];
+
+-static int static_call_initialized;
++int static_call_initialized;
+
+ /*
+ * Must be called before early_initcall() to be effective.
+diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
+index 792dc35414a3c3..50881898e758d8 100644
+--- a/kernel/trace/bpf_trace.c
++++ b/kernel/trace/bpf_trace.c
+@@ -2215,6 +2215,9 @@ void perf_event_detach_bpf_prog(struct perf_event *event)
+ goto unlock;
+
+ old_array = bpf_event_rcu_dereference(event->tp_event->prog_array);
++ if (!old_array)
++ goto put;
++
+ ret = bpf_prog_array_copy(old_array, event->prog, NULL, 0, &new_array);
+ if (ret < 0) {
+ bpf_prog_array_delete_safe(old_array, event->prog);
+@@ -2223,6 +2226,14 @@ void perf_event_detach_bpf_prog(struct perf_event *event)
+ bpf_prog_array_free_sleepable(old_array);
+ }
+
++put:
++ /*
++ * It could be that the bpf_prog is not sleepable (and will be freed
++ * via normal RCU), but is called from a point that supports sleepable
++ * programs and uses tasks-trace-RCU.
++ */
++ synchronize_rcu_tasks_trace();
++
+ bpf_prog_put(event->prog);
+ event->prog = NULL;
+
+diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c
+index b30fc8fcd0956a..b085a8a164ea03 100644
+--- a/kernel/trace/trace_uprobe.c
++++ b/kernel/trace/trace_uprobe.c
+@@ -1400,9 +1400,13 @@ static void __uprobe_perf_func(struct trace_uprobe *tu,
+
+ #ifdef CONFIG_BPF_EVENTS
+ if (bpf_prog_array_valid(call)) {
++ const struct bpf_prog_array *array;
+ u32 ret;
+
+- ret = bpf_prog_run_array_uprobe(call->prog_array, regs, bpf_prog_run);
++ rcu_read_lock_trace();
++ array = rcu_dereference_check(call->prog_array, rcu_read_lock_trace_held());
++ ret = bpf_prog_run_array_uprobe(array, regs, bpf_prog_run);
++ rcu_read_unlock_trace();
+ if (!ret)
+ return;
+ }
+diff --git a/mm/slub.c b/mm/slub.c
+index 15ba89fef89a1f..b9447a955f6112 100644
+--- a/mm/slub.c
++++ b/mm/slub.c
+@@ -2199,9 +2199,24 @@ bool memcg_slab_post_charge(void *p, gfp_t flags)
+
+ folio = virt_to_folio(p);
+ if (!folio_test_slab(folio)) {
+- return folio_memcg_kmem(folio) ||
+- (__memcg_kmem_charge_page(folio_page(folio, 0), flags,
+- folio_order(folio)) == 0);
++ int size;
++
++ if (folio_memcg_kmem(folio))
++ return true;
++
++ if (__memcg_kmem_charge_page(folio_page(folio, 0), flags,
++ folio_order(folio)))
++ return false;
++
++ /*
++ * This folio has already been accounted in the global stats but
++ * not in the memcg stats. So, subtract from the global and use
++ * the interface which adds to both global and memcg stats.
++ */
++ size = folio_size(folio);
++ node_stat_mod_folio(folio, NR_SLAB_UNRECLAIMABLE_B, -size);
++ lruvec_stat_mod_folio(folio, NR_SLAB_UNRECLAIMABLE_B, size);
++ return true;
+ }
+
+ slab = folio_slab(folio);
+diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
+index 2243cec18ecc86..53dea8ae96e477 100644
+--- a/net/batman-adv/translation-table.c
++++ b/net/batman-adv/translation-table.c
+@@ -990,16 +990,25 @@ static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
+ int tt_diff_len, tt_change_len = 0;
+ int tt_diff_entries_num = 0;
+ int tt_diff_entries_count = 0;
++ bool drop_changes = false;
++ size_t tt_extra_len = 0;
+ u16 tvlv_len;
+
+ tt_diff_entries_num = atomic_read(&bat_priv->tt.local_changes);
+ tt_diff_len = batadv_tt_len(tt_diff_entries_num);
+
+ /* if we have too many changes for one packet don't send any
+- * and wait for the tt table request which will be fragmented
++ * and wait for the tt table request so we can reply with the full
++ * (fragmented) table.
++ *
++ * The local change history should still be cleaned up so the next
++ * TT round can start again with a clean state.
+ */
+- if (tt_diff_len > bat_priv->soft_iface->mtu)
++ if (tt_diff_len > bat_priv->soft_iface->mtu) {
+ tt_diff_len = 0;
++ tt_diff_entries_num = 0;
++ drop_changes = true;
++ }
+
+ tvlv_len = batadv_tt_prepare_tvlv_local_data(bat_priv, &tt_data,
+ &tt_change, &tt_diff_len);
+@@ -1008,7 +1017,7 @@ static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
+
+ tt_data->flags = BATADV_TT_OGM_DIFF;
+
+- if (tt_diff_len == 0)
++ if (!drop_changes && tt_diff_len == 0)
+ goto container_register;
+
+ spin_lock_bh(&bat_priv->tt.changes_list_lock);
+@@ -1027,6 +1036,9 @@ static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
+ }
+ spin_unlock_bh(&bat_priv->tt.changes_list_lock);
+
++ tt_extra_len = batadv_tt_len(tt_diff_entries_num -
++ tt_diff_entries_count);
++
+ /* Keep the buffer for possible tt_request */
+ spin_lock_bh(&bat_priv->tt.last_changeset_lock);
+ kfree(bat_priv->tt.last_changeset);
+@@ -1035,6 +1047,7 @@ static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
+ tt_change_len = batadv_tt_len(tt_diff_entries_count);
+ /* check whether this new OGM has no changes due to size problems */
+ if (tt_diff_entries_count > 0) {
++ tt_diff_len -= tt_extra_len;
+ /* if kmalloc() fails we will reply with the full table
+ * instead of providing the diff
+ */
+@@ -1047,6 +1060,8 @@ static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
+ }
+ spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
+
++ /* Remove extra packet space for OGM */
++ tvlv_len -= tt_extra_len;
+ container_register:
+ batadv_tvlv_container_register(bat_priv, BATADV_TVLV_TT, 1, tt_data,
+ tvlv_len);
+@@ -2747,14 +2762,16 @@ static bool batadv_tt_global_valid(const void *entry_ptr,
+ *
+ * Fills the tvlv buff with the tt entries from the specified hash. If valid_cb
+ * is not provided then this becomes a no-op.
++ *
++ * Return: Remaining unused length in tvlv_buff.
+ */
+-static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
+- struct batadv_hashtable *hash,
+- void *tvlv_buff, u16 tt_len,
+- bool (*valid_cb)(const void *,
+- const void *,
+- u8 *flags),
+- void *cb_data)
++static u16 batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
++ struct batadv_hashtable *hash,
++ void *tvlv_buff, u16 tt_len,
++ bool (*valid_cb)(const void *,
++ const void *,
++ u8 *flags),
++ void *cb_data)
+ {
+ struct batadv_tt_common_entry *tt_common_entry;
+ struct batadv_tvlv_tt_change *tt_change;
+@@ -2768,7 +2785,7 @@ static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
+ tt_change = tvlv_buff;
+
+ if (!valid_cb)
+- return;
++ return tt_len;
+
+ rcu_read_lock();
+ for (i = 0; i < hash->size; i++) {
+@@ -2794,6 +2811,8 @@ static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
+ }
+ }
+ rcu_read_unlock();
++
++ return batadv_tt_len(tt_tot - tt_num_entries);
+ }
+
+ /**
+@@ -3069,10 +3088,11 @@ static bool batadv_send_other_tt_response(struct batadv_priv *bat_priv,
+ goto out;
+
+ /* fill the rest of the tvlv with the real TT entries */
+- batadv_tt_tvlv_generate(bat_priv, bat_priv->tt.global_hash,
+- tt_change, tt_len,
+- batadv_tt_global_valid,
+- req_dst_orig_node);
++ tvlv_len -= batadv_tt_tvlv_generate(bat_priv,
++ bat_priv->tt.global_hash,
++ tt_change, tt_len,
++ batadv_tt_global_valid,
++ req_dst_orig_node);
+ }
+
+ /* Don't send the response, if larger than fragmented packet. */
+@@ -3196,9 +3216,11 @@ static bool batadv_send_my_tt_response(struct batadv_priv *bat_priv,
+ goto out;
+
+ /* fill the rest of the tvlv with the real TT entries */
+- batadv_tt_tvlv_generate(bat_priv, bat_priv->tt.local_hash,
+- tt_change, tt_len,
+- batadv_tt_local_valid, NULL);
++ tvlv_len -= batadv_tt_tvlv_generate(bat_priv,
++ bat_priv->tt.local_hash,
++ tt_change, tt_len,
++ batadv_tt_local_valid,
++ NULL);
+ }
+
+ tvlv_tt_data->flags = BATADV_TT_RESPONSE;
+diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
+index 2b5ba8acd1d84a..388d46c6a043d4 100644
+--- a/net/bluetooth/hci_event.c
++++ b/net/bluetooth/hci_event.c
+@@ -6872,38 +6872,27 @@ static void hci_le_create_big_complete_evt(struct hci_dev *hdev, void *data,
+ return;
+
+ hci_dev_lock(hdev);
+- rcu_read_lock();
+
+ /* Connect all BISes that are bound to the BIG */
+- list_for_each_entry_rcu(conn, &hdev->conn_hash.list, list) {
+- if (bacmp(&conn->dst, BDADDR_ANY) ||
+- conn->type != ISO_LINK ||
+- conn->iso_qos.bcast.big != ev->handle)
++ while ((conn = hci_conn_hash_lookup_big_state(hdev, ev->handle,
++ BT_BOUND))) {
++ if (ev->status) {
++ hci_connect_cfm(conn, ev->status);
++ hci_conn_del(conn);
+ continue;
++ }
+
+ if (hci_conn_set_handle(conn,
+ __le16_to_cpu(ev->bis_handle[i++])))
+ continue;
+
+- if (!ev->status) {
+- conn->state = BT_CONNECTED;
+- set_bit(HCI_CONN_BIG_CREATED, &conn->flags);
+- rcu_read_unlock();
+- hci_debugfs_create_conn(conn);
+- hci_conn_add_sysfs(conn);
+- hci_iso_setup_path(conn);
+- rcu_read_lock();
+- continue;
+- }
+-
+- hci_connect_cfm(conn, ev->status);
+- rcu_read_unlock();
+- hci_conn_del(conn);
+- rcu_read_lock();
++ conn->state = BT_CONNECTED;
++ set_bit(HCI_CONN_BIG_CREATED, &conn->flags);
++ hci_debugfs_create_conn(conn);
++ hci_conn_add_sysfs(conn);
++ hci_iso_setup_path(conn);
+ }
+
+- rcu_read_unlock();
+-
+ if (!ev->status && !i)
+ /* If no BISes have been connected for the BIG,
+ * terminate. This is in case all bound connections
+diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
+index 2272e1849ebd89..022b86797acdc5 100644
+--- a/net/bluetooth/hci_sock.c
++++ b/net/bluetooth/hci_sock.c
+@@ -1926,7 +1926,7 @@ static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg,
+ }
+
+ static int hci_sock_setsockopt_old(struct socket *sock, int level, int optname,
+- sockptr_t optval, unsigned int len)
++ sockptr_t optval, unsigned int optlen)
+ {
+ struct hci_ufilter uf = { .opcode = 0 };
+ struct sock *sk = sock->sk;
+@@ -1943,7 +1943,7 @@ static int hci_sock_setsockopt_old(struct socket *sock, int level, int optname,
+
+ switch (optname) {
+ case HCI_DATA_DIR:
+- err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, len);
++ err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
+ if (err)
+ break;
+
+@@ -1954,7 +1954,7 @@ static int hci_sock_setsockopt_old(struct socket *sock, int level, int optname,
+ break;
+
+ case HCI_TIME_STAMP:
+- err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, len);
++ err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
+ if (err)
+ break;
+
+@@ -1974,7 +1974,7 @@ static int hci_sock_setsockopt_old(struct socket *sock, int level, int optname,
+ uf.event_mask[1] = *((u32 *) f->event_mask + 1);
+ }
+
+- err = bt_copy_from_sockptr(&uf, sizeof(uf), optval, len);
++ err = copy_safe_from_sockptr(&uf, sizeof(uf), optval, optlen);
+ if (err)
+ break;
+
+@@ -2005,7 +2005,7 @@ static int hci_sock_setsockopt_old(struct socket *sock, int level, int optname,
+ }
+
+ static int hci_sock_setsockopt(struct socket *sock, int level, int optname,
+- sockptr_t optval, unsigned int len)
++ sockptr_t optval, unsigned int optlen)
+ {
+ struct sock *sk = sock->sk;
+ int err = 0;
+@@ -2015,7 +2015,7 @@ static int hci_sock_setsockopt(struct socket *sock, int level, int optname,
+
+ if (level == SOL_HCI)
+ return hci_sock_setsockopt_old(sock, level, optname, optval,
+- len);
++ optlen);
+
+ if (level != SOL_BLUETOOTH)
+ return -ENOPROTOOPT;
+@@ -2035,7 +2035,7 @@ static int hci_sock_setsockopt(struct socket *sock, int level, int optname,
+ goto done;
+ }
+
+- err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, len);
++ err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
+ if (err)
+ break;
+
+diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
+index 5e2d9758bd3c1c..644b606743e212 100644
+--- a/net/bluetooth/iso.c
++++ b/net/bluetooth/iso.c
+@@ -1129,6 +1129,7 @@ static int iso_listen_bis(struct sock *sk)
+ return -EHOSTUNREACH;
+
+ hci_dev_lock(hdev);
++ lock_sock(sk);
+
+ /* Fail if user set invalid QoS */
+ if (iso_pi(sk)->qos_user_set && !check_bcast_qos(&iso_pi(sk)->qos)) {
+@@ -1158,10 +1159,10 @@ static int iso_listen_bis(struct sock *sk)
+ goto unlock;
+ }
+
+- hci_dev_put(hdev);
+-
+ unlock:
++ release_sock(sk);
+ hci_dev_unlock(hdev);
++ hci_dev_put(hdev);
+ return err;
+ }
+
+@@ -1188,6 +1189,7 @@ static int iso_sock_listen(struct socket *sock, int backlog)
+
+ BT_DBG("sk %p backlog %d", sk, backlog);
+
++ sock_hold(sk);
+ lock_sock(sk);
+
+ if (sk->sk_state != BT_BOUND) {
+@@ -1200,10 +1202,16 @@ static int iso_sock_listen(struct socket *sock, int backlog)
+ goto done;
+ }
+
+- if (!bacmp(&iso_pi(sk)->dst, BDADDR_ANY))
++ if (!bacmp(&iso_pi(sk)->dst, BDADDR_ANY)) {
+ err = iso_listen_cis(sk);
+- else
++ } else {
++ /* Drop sock lock to avoid potential
++ * deadlock with the hdev lock.
++ */
++ release_sock(sk);
+ err = iso_listen_bis(sk);
++ lock_sock(sk);
++ }
+
+ if (err)
+ goto done;
+@@ -1215,6 +1223,7 @@ static int iso_sock_listen(struct socket *sock, int backlog)
+
+ done:
+ release_sock(sk);
++ sock_put(sk);
+ return err;
+ }
+
+@@ -1226,7 +1235,11 @@ static int iso_sock_accept(struct socket *sock, struct socket *newsock,
+ long timeo;
+ int err = 0;
+
+- lock_sock(sk);
++ /* Use explicit nested locking to avoid lockdep warnings generated
++ * because the parent socket and the child socket are locked on the
++ * same thread.
++ */
++ lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
+
+ timeo = sock_rcvtimeo(sk, arg->flags & O_NONBLOCK);
+
+@@ -1257,7 +1270,7 @@ static int iso_sock_accept(struct socket *sock, struct socket *newsock,
+ release_sock(sk);
+
+ timeo = wait_woken(&wait, TASK_INTERRUPTIBLE, timeo);
+- lock_sock(sk);
++ lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
+ }
+ remove_wait_queue(sk_sleep(sk), &wait);
+
+@@ -1398,6 +1411,7 @@ static void iso_conn_big_sync(struct sock *sk)
+ * change.
+ */
+ hci_dev_lock(hdev);
++ lock_sock(sk);
+
+ if (!test_and_set_bit(BT_SK_BIG_SYNC, &iso_pi(sk)->flags)) {
+ err = hci_le_big_create_sync(hdev, iso_pi(sk)->conn->hcon,
+@@ -1410,6 +1424,7 @@ static void iso_conn_big_sync(struct sock *sk)
+ err);
+ }
+
++ release_sock(sk);
+ hci_dev_unlock(hdev);
+ }
+
+@@ -1418,39 +1433,57 @@ static int iso_sock_recvmsg(struct socket *sock, struct msghdr *msg,
+ {
+ struct sock *sk = sock->sk;
+ struct iso_pinfo *pi = iso_pi(sk);
++ bool early_ret = false;
++ int err = 0;
+
+ BT_DBG("sk %p", sk);
+
+ if (test_and_clear_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
++ sock_hold(sk);
+ lock_sock(sk);
++
+ switch (sk->sk_state) {
+ case BT_CONNECT2:
+ if (test_bit(BT_SK_PA_SYNC, &pi->flags)) {
++ release_sock(sk);
+ iso_conn_big_sync(sk);
++ lock_sock(sk);
++
+ sk->sk_state = BT_LISTEN;
+ } else {
+ iso_conn_defer_accept(pi->conn->hcon);
+ sk->sk_state = BT_CONFIG;
+ }
+- release_sock(sk);
+- return 0;
++
++ early_ret = true;
++ break;
+ case BT_CONNECTED:
+ if (test_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags)) {
++ release_sock(sk);
+ iso_conn_big_sync(sk);
++ lock_sock(sk);
++
+ sk->sk_state = BT_LISTEN;
+- release_sock(sk);
+- return 0;
++ early_ret = true;
+ }
+
+- release_sock(sk);
+ break;
+ case BT_CONNECT:
+ release_sock(sk);
+- return iso_connect_cis(sk);
++ err = iso_connect_cis(sk);
++ lock_sock(sk);
++
++ early_ret = true;
++ break;
+ default:
+- release_sock(sk);
+ break;
+ }
++
++ release_sock(sk);
++ sock_put(sk);
++
++ if (early_ret)
++ return err;
+ }
+
+ return bt_sock_recvmsg(sock, msg, len, flags);
+@@ -1566,7 +1599,7 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
+ break;
+ }
+
+- err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
++ err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
+ if (err)
+ break;
+
+@@ -1577,7 +1610,7 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
+ break;
+
+ case BT_PKT_STATUS:
+- err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
++ err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
+ if (err)
+ break;
+
+@@ -1596,7 +1629,7 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
+ break;
+ }
+
+- err = bt_copy_from_sockptr(&qos, sizeof(qos), optval, optlen);
++ err = copy_safe_from_sockptr(&qos, sizeof(qos), optval, optlen);
+ if (err)
+ break;
+
+@@ -1617,8 +1650,8 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
+ break;
+ }
+
+- err = bt_copy_from_sockptr(iso_pi(sk)->base, optlen, optval,
+- optlen);
++ err = copy_safe_from_sockptr(iso_pi(sk)->base, optlen, optval,
++ optlen);
+ if (err)
+ break;
+
+diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
+index 18e89e764f3b42..3d2553dcdb1b3c 100644
+--- a/net/bluetooth/l2cap_sock.c
++++ b/net/bluetooth/l2cap_sock.c
+@@ -755,7 +755,8 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,
+ opts.max_tx = chan->max_tx;
+ opts.txwin_size = chan->tx_win;
+
+- err = bt_copy_from_sockptr(&opts, sizeof(opts), optval, optlen);
++ err = copy_safe_from_sockptr(&opts, sizeof(opts), optval,
++ optlen);
+ if (err)
+ break;
+
+@@ -800,7 +801,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,
+ break;
+
+ case L2CAP_LM:
+- err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
++ err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
+ if (err)
+ break;
+
+@@ -909,7 +910,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
+
+ sec.level = BT_SECURITY_LOW;
+
+- err = bt_copy_from_sockptr(&sec, sizeof(sec), optval, optlen);
++ err = copy_safe_from_sockptr(&sec, sizeof(sec), optval, optlen);
+ if (err)
+ break;
+
+@@ -956,7 +957,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
+ break;
+ }
+
+- err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
++ err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
+ if (err)
+ break;
+
+@@ -970,7 +971,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
+ break;
+
+ case BT_FLUSHABLE:
+- err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
++ err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
+ if (err)
+ break;
+
+@@ -1004,7 +1005,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
+
+ pwr.force_active = BT_POWER_FORCE_ACTIVE_ON;
+
+- err = bt_copy_from_sockptr(&pwr, sizeof(pwr), optval, optlen);
++ err = copy_safe_from_sockptr(&pwr, sizeof(pwr), optval, optlen);
+ if (err)
+ break;
+
+@@ -1015,7 +1016,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
+ break;
+
+ case BT_CHANNEL_POLICY:
+- err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
++ err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
+ if (err)
+ break;
+
+@@ -1046,7 +1047,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
+ break;
+ }
+
+- err = bt_copy_from_sockptr(&mtu, sizeof(mtu), optval, optlen);
++ err = copy_safe_from_sockptr(&mtu, sizeof(mtu), optval, optlen);
+ if (err)
+ break;
+
+@@ -1076,7 +1077,8 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
+ break;
+ }
+
+- err = bt_copy_from_sockptr(&mode, sizeof(mode), optval, optlen);
++ err = copy_safe_from_sockptr(&mode, sizeof(mode), optval,
++ optlen);
+ if (err)
+ break;
+
+diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
+index 40766f8119ed9c..913402806fa0d4 100644
+--- a/net/bluetooth/rfcomm/sock.c
++++ b/net/bluetooth/rfcomm/sock.c
+@@ -629,10 +629,9 @@ static int rfcomm_sock_setsockopt_old(struct socket *sock, int optname,
+
+ switch (optname) {
+ case RFCOMM_LM:
+- if (bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen)) {
+- err = -EFAULT;
++ err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
++ if (err)
+ break;
+- }
+
+ if (opt & RFCOMM_LM_FIPS) {
+ err = -EINVAL;
+@@ -685,7 +684,7 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname,
+
+ sec.level = BT_SECURITY_LOW;
+
+- err = bt_copy_from_sockptr(&sec, sizeof(sec), optval, optlen);
++ err = copy_safe_from_sockptr(&sec, sizeof(sec), optval, optlen);
+ if (err)
+ break;
+
+@@ -703,7 +702,7 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname,
+ break;
+ }
+
+- err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
++ err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
+ if (err)
+ break;
+
+diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
+index 1c7252a3686694..b872a2ca3ff38b 100644
+--- a/net/bluetooth/sco.c
++++ b/net/bluetooth/sco.c
+@@ -267,10 +267,13 @@ static int sco_connect(struct sock *sk)
+ else
+ type = SCO_LINK;
+
+- if (sco_pi(sk)->setting == BT_VOICE_TRANSPARENT &&
+- (!lmp_transp_capable(hdev) || !lmp_esco_capable(hdev))) {
+- err = -EOPNOTSUPP;
+- goto unlock;
++ switch (sco_pi(sk)->setting & SCO_AIRMODE_MASK) {
++ case SCO_AIRMODE_TRANSP:
++ if (!lmp_transp_capable(hdev) || !lmp_esco_capable(hdev)) {
++ err = -EOPNOTSUPP;
++ goto unlock;
++ }
++ break;
+ }
+
+ hcon = hci_connect_sco(hdev, type, &sco_pi(sk)->dst,
+@@ -853,7 +856,7 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
+ break;
+ }
+
+- err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
++ err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
+ if (err)
+ break;
+
+@@ -872,18 +875,11 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
+
+ voice.setting = sco_pi(sk)->setting;
+
+- err = bt_copy_from_sockptr(&voice, sizeof(voice), optval,
+- optlen);
++ err = copy_safe_from_sockptr(&voice, sizeof(voice), optval,
++ optlen);
+ if (err)
+ break;
+
+- /* Explicitly check for these values */
+- if (voice.setting != BT_VOICE_TRANSPARENT &&
+- voice.setting != BT_VOICE_CVSD_16BIT) {
+- err = -EINVAL;
+- break;
+- }
+-
+ sco_pi(sk)->setting = voice.setting;
+ hdev = hci_get_route(&sco_pi(sk)->dst, &sco_pi(sk)->src,
+ BDADDR_BREDR);
+@@ -891,14 +887,19 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
+ err = -EBADFD;
+ break;
+ }
+- if (enhanced_sync_conn_capable(hdev) &&
+- voice.setting == BT_VOICE_TRANSPARENT)
+- sco_pi(sk)->codec.id = BT_CODEC_TRANSPARENT;
++
++ switch (sco_pi(sk)->setting & SCO_AIRMODE_MASK) {
++ case SCO_AIRMODE_TRANSP:
++ if (enhanced_sync_conn_capable(hdev))
++ sco_pi(sk)->codec.id = BT_CODEC_TRANSPARENT;
++ break;
++ }
++
+ hci_dev_put(hdev);
+ break;
+
+ case BT_PKT_STATUS:
+- err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
++ err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
+ if (err)
+ break;
+
+@@ -941,7 +942,8 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
+ break;
+ }
+
+- err = bt_copy_from_sockptr(buffer, optlen, optval, optlen);
++ err = copy_struct_from_sockptr(buffer, sizeof(buffer), optval,
++ optlen);
+ if (err) {
+ hci_dev_put(hdev);
+ break;
+diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
+index e39479f1c9a486..70fea7c1a4b0a4 100644
+--- a/net/core/net_namespace.c
++++ b/net/core/net_namespace.c
+@@ -443,6 +443,21 @@ static struct net *net_alloc(void)
+ goto out;
+ }
+
++static LLIST_HEAD(defer_free_list);
++
++static void net_complete_free(void)
++{
++ struct llist_node *kill_list;
++ struct net *net, *next;
++
++ /* Get the list of namespaces to free from last round. */
++ kill_list = llist_del_all(&defer_free_list);
++
++ llist_for_each_entry_safe(net, next, kill_list, defer_free_list)
++ kmem_cache_free(net_cachep, net);
++
++}
++
+ static void net_free(struct net *net)
+ {
+ if (refcount_dec_and_test(&net->passive)) {
+@@ -451,7 +466,8 @@ static void net_free(struct net *net)
+ /* There should not be any trackers left there. */
+ ref_tracker_dir_exit(&net->notrefcnt_tracker);
+
+- kmem_cache_free(net_cachep, net);
++ /* Wait for an extra rcu_barrier() before final free. */
++ llist_add(&net->defer_free_list, &defer_free_list);
+ }
+ }
+
+@@ -636,6 +652,8 @@ static void cleanup_net(struct work_struct *work)
+ */
+ rcu_barrier();
+
++ net_complete_free();
++
+ /* Finally it is safe to free my network namespace structure */
+ list_for_each_entry_safe(net, tmp, &net_exit_list, exit_list) {
+ list_del_init(&net->exit_list);
+diff --git a/net/core/sock_map.c b/net/core/sock_map.c
+index 78347d7d25ef31..f1b9b3958792cd 100644
+--- a/net/core/sock_map.c
++++ b/net/core/sock_map.c
+@@ -159,6 +159,7 @@ static void sock_map_del_link(struct sock *sk,
+ verdict_stop = true;
+ list_del(&link->list);
+ sk_psock_free_link(link);
++ break;
+ }
+ }
+ spin_unlock_bh(&psock->link_lock);
+@@ -411,12 +412,11 @@ static void *sock_map_lookup_sys(struct bpf_map *map, void *key)
+ static int __sock_map_delete(struct bpf_stab *stab, struct sock *sk_test,
+ struct sock **psk)
+ {
+- struct sock *sk;
++ struct sock *sk = NULL;
+ int err = 0;
+
+ spin_lock_bh(&stab->lock);
+- sk = *psk;
+- if (!sk_test || sk_test == sk)
++ if (!sk_test || sk_test == *psk)
+ sk = xchg(psk, NULL);
+
+ if (likely(sk))
+diff --git a/net/dsa/tag_ocelot_8021q.c b/net/dsa/tag_ocelot_8021q.c
+index 8e8b1bef6af69d..11ea8cfd62661c 100644
+--- a/net/dsa/tag_ocelot_8021q.c
++++ b/net/dsa/tag_ocelot_8021q.c
+@@ -79,7 +79,7 @@ static struct sk_buff *ocelot_xmit(struct sk_buff *skb,
+ static struct sk_buff *ocelot_rcv(struct sk_buff *skb,
+ struct net_device *netdev)
+ {
+- int src_port, switch_id;
++ int src_port = -1, switch_id = -1;
+
+ dsa_8021q_rcv(skb, &src_port, &switch_id, NULL, NULL);
+
+diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
+index 68804fd01dafc4..8efc58716ce969 100644
+--- a/net/ipv4/tcp_output.c
++++ b/net/ipv4/tcp_output.c
+@@ -883,8 +883,10 @@ static unsigned int tcp_syn_options(struct sock *sk, struct sk_buff *skb,
+ unsigned int size;
+
+ if (mptcp_syn_options(sk, skb, &size, &opts->mptcp)) {
+- opts->options |= OPTION_MPTCP;
+- remaining -= size;
++ if (remaining >= size) {
++ opts->options |= OPTION_MPTCP;
++ remaining -= size;
++ }
+ }
+ }
+
+diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
+index 6dfc61a9acd4a5..1b1bf044378d48 100644
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -1061,13 +1061,13 @@ ieee80211_copy_mbssid_beacon(u8 *pos, struct cfg80211_mbssid_elems *dst,
+ {
+ int i, offset = 0;
+
++ dst->cnt = src->cnt;
+ for (i = 0; i < src->cnt; i++) {
+ memcpy(pos + offset, src->elem[i].data, src->elem[i].len);
+ dst->elem[i].len = src->elem[i].len;
+ dst->elem[i].data = pos + offset;
+ offset += dst->elem[i].len;
+ }
+- dst->cnt = src->cnt;
+
+ return offset;
+ }
+@@ -1911,6 +1911,8 @@ static int sta_link_apply_parameters(struct ieee80211_local *local,
+ params->eht_capa_len,
+ link_sta);
+
++ ieee80211_sta_init_nss(link_sta);
++
+ if (params->opmode_notif_used) {
+ /* returned value is only needed for rc update, but the
+ * rc isn't initialized here yet, so ignore it
+@@ -1920,8 +1922,6 @@ static int sta_link_apply_parameters(struct ieee80211_local *local,
+ sband->band);
+ }
+
+- ieee80211_sta_init_nss(link_sta);
+-
+ return 0;
+ }
+
+@@ -3674,13 +3674,12 @@ void ieee80211_csa_finish(struct ieee80211_vif *vif, unsigned int link_id)
+ }
+ EXPORT_SYMBOL(ieee80211_csa_finish);
+
+-void ieee80211_channel_switch_disconnect(struct ieee80211_vif *vif, bool block_tx)
++void ieee80211_channel_switch_disconnect(struct ieee80211_vif *vif)
+ {
+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+ struct ieee80211_local *local = sdata->local;
+
+- sdata->csa_blocked_queues = block_tx;
+ sdata_info(sdata, "channel switch failed, disconnecting\n");
+ wiphy_work_queue(local->hw.wiphy, &ifmgd->csa_connection_drop_work);
+ }
+diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
+index 3d3c9139ff5e45..7a0242e937d364 100644
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -1106,8 +1106,6 @@ struct ieee80211_sub_if_data {
+
+ unsigned long state;
+
+- bool csa_blocked_queues;
+-
+ char name[IFNAMSIZ];
+
+ struct ieee80211_fragment_cache frags;
+@@ -2411,17 +2409,13 @@ void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata);
+ void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_hdr *hdr, bool ack, u16 tx_time);
+-
++unsigned int
++ieee80211_get_vif_queues(struct ieee80211_local *local,
++ struct ieee80211_sub_if_data *sdata);
+ void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
+ unsigned long queues,
+ enum queue_stop_reason reason,
+ bool refcounted);
+-void ieee80211_stop_vif_queues(struct ieee80211_local *local,
+- struct ieee80211_sub_if_data *sdata,
+- enum queue_stop_reason reason);
+-void ieee80211_wake_vif_queues(struct ieee80211_local *local,
+- struct ieee80211_sub_if_data *sdata,
+- enum queue_stop_reason reason);
+ void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
+ unsigned long queues,
+ enum queue_stop_reason reason,
+@@ -2432,6 +2426,43 @@ void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,
+ void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
+ enum queue_stop_reason reason,
+ bool refcounted);
++static inline void
++ieee80211_stop_vif_queues(struct ieee80211_local *local,
++ struct ieee80211_sub_if_data *sdata,
++ enum queue_stop_reason reason)
++{
++ ieee80211_stop_queues_by_reason(&local->hw,
++ ieee80211_get_vif_queues(local, sdata),
++ reason, true);
++}
++
++static inline void
++ieee80211_wake_vif_queues(struct ieee80211_local *local,
++ struct ieee80211_sub_if_data *sdata,
++ enum queue_stop_reason reason)
++{
++ ieee80211_wake_queues_by_reason(&local->hw,
++ ieee80211_get_vif_queues(local, sdata),
++ reason, true);
++}
++static inline void
++ieee80211_stop_vif_queues_norefcount(struct ieee80211_local *local,
++ struct ieee80211_sub_if_data *sdata,
++ enum queue_stop_reason reason)
++{
++ ieee80211_stop_queues_by_reason(&local->hw,
++ ieee80211_get_vif_queues(local, sdata),
++ reason, false);
++}
++static inline void
++ieee80211_wake_vif_queues_norefcount(struct ieee80211_local *local,
++ struct ieee80211_sub_if_data *sdata,
++ enum queue_stop_reason reason)
++{
++ ieee80211_wake_queues_by_reason(&local->hw,
++ ieee80211_get_vif_queues(local, sdata),
++ reason, false);
++}
+ void ieee80211_add_pending_skb(struct ieee80211_local *local,
+ struct sk_buff *skb);
+ void ieee80211_add_pending_skbs(struct ieee80211_local *local,
+diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
+index 6ef0990d3d296a..af9055252e6dfa 100644
+--- a/net/mac80211/iface.c
++++ b/net/mac80211/iface.c
+@@ -2364,18 +2364,14 @@ void ieee80211_vif_block_queues_csa(struct ieee80211_sub_if_data *sdata)
+ if (ieee80211_hw_check(&local->hw, HANDLES_QUIET_CSA))
+ return;
+
+- ieee80211_stop_vif_queues(local, sdata,
+- IEEE80211_QUEUE_STOP_REASON_CSA);
+- sdata->csa_blocked_queues = true;
++ ieee80211_stop_vif_queues_norefcount(local, sdata,
++ IEEE80211_QUEUE_STOP_REASON_CSA);
+ }
+
+ void ieee80211_vif_unblock_queues_csa(struct ieee80211_sub_if_data *sdata)
+ {
+ struct ieee80211_local *local = sdata->local;
+
+- if (sdata->csa_blocked_queues) {
+- ieee80211_wake_vif_queues(local, sdata,
+- IEEE80211_QUEUE_STOP_REASON_CSA);
+- sdata->csa_blocked_queues = false;
+- }
++ ieee80211_wake_vif_queues_norefcount(local, sdata,
++ IEEE80211_QUEUE_STOP_REASON_CSA);
+ }
+diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
+index 0303972c23e4cb..111066928b963c 100644
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -2636,8 +2636,6 @@ ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link,
+ */
+ link->conf->csa_active = true;
+ link->u.mgd.csa.blocked_tx = csa_ie.mode;
+- sdata->csa_blocked_queues =
+- csa_ie.mode && !ieee80211_hw_check(&local->hw, HANDLES_QUIET_CSA);
+
+ wiphy_work_queue(sdata->local->hw.wiphy,
+ &ifmgd->csa_connection_drop_work);
+diff --git a/net/mac80211/util.c b/net/mac80211/util.c
+index f94faa86ba8a35..b4814e97cf7422 100644
+--- a/net/mac80211/util.c
++++ b/net/mac80211/util.c
+@@ -657,7 +657,7 @@ void ieee80211_wake_queues(struct ieee80211_hw *hw)
+ }
+ EXPORT_SYMBOL(ieee80211_wake_queues);
+
+-static unsigned int
++unsigned int
+ ieee80211_get_vif_queues(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata)
+ {
+@@ -669,7 +669,8 @@ ieee80211_get_vif_queues(struct ieee80211_local *local,
+ queues = 0;
+
+ for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
+- queues |= BIT(sdata->vif.hw_queue[ac]);
++ if (sdata->vif.hw_queue[ac] != IEEE80211_INVAL_HW_QUEUE)
++ queues |= BIT(sdata->vif.hw_queue[ac]);
+ if (sdata->vif.cab_queue != IEEE80211_INVAL_HW_QUEUE)
+ queues |= BIT(sdata->vif.cab_queue);
+ } else {
+@@ -724,24 +725,6 @@ void ieee80211_flush_queues(struct ieee80211_local *local,
+ __ieee80211_flush_queues(local, sdata, 0, drop);
+ }
+
+-void ieee80211_stop_vif_queues(struct ieee80211_local *local,
+- struct ieee80211_sub_if_data *sdata,
+- enum queue_stop_reason reason)
+-{
+- ieee80211_stop_queues_by_reason(&local->hw,
+- ieee80211_get_vif_queues(local, sdata),
+- reason, true);
+-}
+-
+-void ieee80211_wake_vif_queues(struct ieee80211_local *local,
+- struct ieee80211_sub_if_data *sdata,
+- enum queue_stop_reason reason)
+-{
+- ieee80211_wake_queues_by_reason(&local->hw,
+- ieee80211_get_vif_queues(local, sdata),
+- reason, true);
+-}
+-
+ static void __iterate_interfaces(struct ieee80211_local *local,
+ u32 iter_flags,
+ void (*iterator)(void *data, u8 *mac,
+diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
+index 4a137afaf0b87e..0c5ff4afc37022 100644
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -1495,7 +1495,6 @@ static int nf_tables_newtable(struct sk_buff *skb, const struct nfnl_info *info,
+ INIT_LIST_HEAD(&table->sets);
+ INIT_LIST_HEAD(&table->objects);
+ INIT_LIST_HEAD(&table->flowtables);
+- write_pnet(&table->net, net);
+ table->family = family;
+ table->flags = flags;
+ table->handle = ++nft_net->table_handle;
+@@ -3884,8 +3883,11 @@ void nf_tables_rule_destroy(const struct nft_ctx *ctx, struct nft_rule *rule)
+ kfree(rule);
+ }
+
++/* can only be used if rule is no longer visible to dumps */
+ static void nf_tables_rule_release(const struct nft_ctx *ctx, struct nft_rule *rule)
+ {
++ lockdep_commit_lock_is_held(ctx->net);
++
+ nft_rule_expr_deactivate(ctx, rule, NFT_TRANS_RELEASE);
+ nf_tables_rule_destroy(ctx, rule);
+ }
+@@ -5650,6 +5652,8 @@ void nf_tables_deactivate_set(const struct nft_ctx *ctx, struct nft_set *set,
+ struct nft_set_binding *binding,
+ enum nft_trans_phase phase)
+ {
++ lockdep_commit_lock_is_held(ctx->net);
++
+ switch (phase) {
+ case NFT_TRANS_PREPARE_ERROR:
+ nft_set_trans_unbind(ctx, set);
+@@ -11456,19 +11460,6 @@ static void __nft_release_basechain_now(struct nft_ctx *ctx)
+ nf_tables_chain_destroy(ctx->chain);
+ }
+
+-static void nft_release_basechain_rcu(struct rcu_head *head)
+-{
+- struct nft_chain *chain = container_of(head, struct nft_chain, rcu_head);
+- struct nft_ctx ctx = {
+- .family = chain->table->family,
+- .chain = chain,
+- .net = read_pnet(&chain->table->net),
+- };
+-
+- __nft_release_basechain_now(&ctx);
+- put_net(ctx.net);
+-}
+-
+ int __nft_release_basechain(struct nft_ctx *ctx)
+ {
+ struct nft_rule *rule;
+@@ -11483,11 +11474,18 @@ int __nft_release_basechain(struct nft_ctx *ctx)
+ nft_chain_del(ctx->chain);
+ nft_use_dec(&ctx->table->use);
+
+- if (maybe_get_net(ctx->net))
+- call_rcu(&ctx->chain->rcu_head, nft_release_basechain_rcu);
+- else
++ if (!maybe_get_net(ctx->net)) {
+ __nft_release_basechain_now(ctx);
++ return 0;
++ }
++
++ /* wait for ruleset dumps to complete. Owning chain is no longer in
++ * lists, so new dumps can't find any of these rules anymore.
++ */
++ synchronize_rcu();
+
++ __nft_release_basechain_now(ctx);
++ put_net(ctx->net);
+ return 0;
+ }
+ EXPORT_SYMBOL_GPL(__nft_release_basechain);
+diff --git a/net/netfilter/xt_IDLETIMER.c b/net/netfilter/xt_IDLETIMER.c
+index f8b25b6f5da736..9869ef3c2ab378 100644
+--- a/net/netfilter/xt_IDLETIMER.c
++++ b/net/netfilter/xt_IDLETIMER.c
+@@ -409,21 +409,23 @@ static void idletimer_tg_destroy(const struct xt_tgdtor_param *par)
+
+ mutex_lock(&list_mutex);
+
+- if (--info->timer->refcnt == 0) {
+- pr_debug("deleting timer %s\n", info->label);
+-
+- list_del(&info->timer->entry);
+- timer_shutdown_sync(&info->timer->timer);
+- cancel_work_sync(&info->timer->work);
+- sysfs_remove_file(idletimer_tg_kobj, &info->timer->attr.attr);
+- kfree(info->timer->attr.attr.name);
+- kfree(info->timer);
+- } else {
++ if (--info->timer->refcnt > 0) {
+ pr_debug("decreased refcnt of timer %s to %u\n",
+ info->label, info->timer->refcnt);
++ mutex_unlock(&list_mutex);
++ return;
+ }
+
++ pr_debug("deleting timer %s\n", info->label);
++
++ list_del(&info->timer->entry);
+ mutex_unlock(&list_mutex);
++
++ timer_shutdown_sync(&info->timer->timer);
++ cancel_work_sync(&info->timer->work);
++ sysfs_remove_file(idletimer_tg_kobj, &info->timer->attr.attr);
++ kfree(info->timer->attr.attr.name);
++ kfree(info->timer);
+ }
+
+ static void idletimer_tg_destroy_v1(const struct xt_tgdtor_param *par)
+@@ -434,25 +436,27 @@ static void idletimer_tg_destroy_v1(const struct xt_tgdtor_param *par)
+
+ mutex_lock(&list_mutex);
+
+- if (--info->timer->refcnt == 0) {
+- pr_debug("deleting timer %s\n", info->label);
+-
+- list_del(&info->timer->entry);
+- if (info->timer->timer_type & XT_IDLETIMER_ALARM) {
+- alarm_cancel(&info->timer->alarm);
+- } else {
+- timer_shutdown_sync(&info->timer->timer);
+- }
+- cancel_work_sync(&info->timer->work);
+- sysfs_remove_file(idletimer_tg_kobj, &info->timer->attr.attr);
+- kfree(info->timer->attr.attr.name);
+- kfree(info->timer);
+- } else {
++ if (--info->timer->refcnt > 0) {
+ pr_debug("decreased refcnt of timer %s to %u\n",
+ info->label, info->timer->refcnt);
++ mutex_unlock(&list_mutex);
++ return;
+ }
+
++ pr_debug("deleting timer %s\n", info->label);
++
++ list_del(&info->timer->entry);
+ mutex_unlock(&list_mutex);
++
++ if (info->timer->timer_type & XT_IDLETIMER_ALARM) {
++ alarm_cancel(&info->timer->alarm);
++ } else {
++ timer_shutdown_sync(&info->timer->timer);
++ }
++ cancel_work_sync(&info->timer->work);
++ sysfs_remove_file(idletimer_tg_kobj, &info->timer->attr.attr);
++ kfree(info->timer->attr.attr.name);
++ kfree(info->timer);
+ }
+
+
+diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
+index 39382ee1e33108..3b519adc01259f 100644
+--- a/net/sched/sch_netem.c
++++ b/net/sched/sch_netem.c
+@@ -78,6 +78,8 @@ struct netem_sched_data {
+ struct sk_buff *t_head;
+ struct sk_buff *t_tail;
+
++ u32 t_len;
++
+ /* optional qdisc for classful handling (NULL at netem init) */
+ struct Qdisc *qdisc;
+
+@@ -382,6 +384,7 @@ static void tfifo_reset(struct Qdisc *sch)
+ rtnl_kfree_skbs(q->t_head, q->t_tail);
+ q->t_head = NULL;
+ q->t_tail = NULL;
++ q->t_len = 0;
+ }
+
+ static void tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch)
+@@ -411,6 +414,7 @@ static void tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch)
+ rb_link_node(&nskb->rbnode, parent, p);
+ rb_insert_color(&nskb->rbnode, &q->t_root);
+ }
++ q->t_len++;
+ sch->q.qlen++;
+ }
+
+@@ -517,7 +521,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+ 1<<get_random_u32_below(8);
+ }
+
+- if (unlikely(sch->q.qlen >= sch->limit)) {
++ if (unlikely(q->t_len >= sch->limit)) {
+ /* re-link segs, so that qdisc_drop_all() frees them all */
+ skb->next = segs;
+ qdisc_drop_all(skb, sch, to_free);
+@@ -701,8 +705,8 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch)
+ tfifo_dequeue:
+ skb = __qdisc_dequeue_head(&sch->q);
+ if (skb) {
+- qdisc_qstats_backlog_dec(sch, skb);
+ deliver:
++ qdisc_qstats_backlog_dec(sch, skb);
+ qdisc_bstats_update(sch, skb);
+ return skb;
+ }
+@@ -718,8 +722,7 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch)
+
+ if (time_to_send <= now && q->slot.slot_next <= now) {
+ netem_erase_head(q, skb);
+- sch->q.qlen--;
+- qdisc_qstats_backlog_dec(sch, skb);
++ q->t_len--;
+ skb->next = NULL;
+ skb->prev = NULL;
+ /* skb->dev shares skb->rbnode area,
+@@ -746,16 +749,21 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch)
+ if (net_xmit_drop_count(err))
+ qdisc_qstats_drop(sch);
+ qdisc_tree_reduce_backlog(sch, 1, pkt_len);
++ sch->qstats.backlog -= pkt_len;
++ sch->q.qlen--;
+ }
+ goto tfifo_dequeue;
+ }
++ sch->q.qlen--;
+ goto deliver;
+ }
+
+ if (q->qdisc) {
+ skb = q->qdisc->ops->dequeue(q->qdisc);
+- if (skb)
++ if (skb) {
++ sch->q.qlen--;
+ goto deliver;
++ }
+ }
+
+ qdisc_watchdog_schedule_ns(&q->watchdog,
+@@ -765,8 +773,10 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch)
+
+ if (q->qdisc) {
+ skb = q->qdisc->ops->dequeue(q->qdisc);
+- if (skb)
++ if (skb) {
++ sch->q.qlen--;
+ goto deliver;
++ }
+ }
+ return NULL;
+ }
+diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c
+index b7e25e7e9933b6..108a4cc2e00107 100644
+--- a/net/tipc/udp_media.c
++++ b/net/tipc/udp_media.c
+@@ -807,6 +807,7 @@ static void cleanup_bearer(struct work_struct *work)
+ {
+ struct udp_bearer *ub = container_of(work, struct udp_bearer, work);
+ struct udp_replicast *rcast, *tmp;
++ struct tipc_net *tn;
+
+ list_for_each_entry_safe(rcast, tmp, &ub->rcast.list, list) {
+ dst_cache_destroy(&rcast->dst_cache);
+@@ -814,10 +815,14 @@ static void cleanup_bearer(struct work_struct *work)
+ kfree_rcu(rcast, rcu);
+ }
+
++ tn = tipc_net(sock_net(ub->ubsock->sk));
++
+ dst_cache_destroy(&ub->rcast.dst_cache);
+ udp_tunnel_sock_release(ub->ubsock);
++
++ /* Note: could use a call_rcu() to avoid another synchronize_net() */
+ synchronize_net();
+- atomic_dec(&tipc_net(sock_net(ub->ubsock->sk))->wq_count);
++ atomic_dec(&tn->wq_count);
+ kfree(ub);
+ }
+
+diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
+index 001ccc55ef0f93..6b176230044397 100644
+--- a/net/unix/af_unix.c
++++ b/net/unix/af_unix.c
+@@ -2313,6 +2313,7 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
+ fds_sent = true;
+
+ if (unlikely(msg->msg_flags & MSG_SPLICE_PAGES)) {
++ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ err = skb_splice_from_iter(skb, &msg->msg_iter, size,
+ sk->sk_allocation);
+ if (err < 0) {
+diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
+index 9b1b9dc5a7eb2a..1e78f575fb5630 100644
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -814,7 +814,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
+ [NL80211_ATTR_MLO_LINKS] =
+ NLA_POLICY_NESTED_ARRAY(nl80211_policy),
+ [NL80211_ATTR_MLO_LINK_ID] =
+- NLA_POLICY_RANGE(NLA_U8, 0, IEEE80211_MLD_MAX_NUM_LINKS),
++ NLA_POLICY_RANGE(NLA_U8, 0, IEEE80211_MLD_MAX_NUM_LINKS - 1),
+ [NL80211_ATTR_MLD_ADDR] = NLA_POLICY_EXACT_LEN(ETH_ALEN),
+ [NL80211_ATTR_MLO_SUPPORT] = { .type = NLA_FLAG },
+ [NL80211_ATTR_MAX_NUM_AKM_SUITES] = { .type = NLA_REJECT },
+diff --git a/net/wireless/sme.c b/net/wireless/sme.c
+index 431da30817a6f6..26817160008766 100644
+--- a/net/wireless/sme.c
++++ b/net/wireless/sme.c
+@@ -83,6 +83,7 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
+ if (!request)
+ return -ENOMEM;
+
++ request->n_channels = n_channels;
+ if (wdev->conn->params.channel) {
+ enum nl80211_band band = wdev->conn->params.channel->band;
+ struct ieee80211_supported_band *sband =
+diff --git a/rust/Makefile b/rust/Makefile
+index b5e0a73b78f3e5..9f59baacaf7730 100644
+--- a/rust/Makefile
++++ b/rust/Makefile
+@@ -267,9 +267,22 @@ endif
+
+ bindgen_c_flags_final = $(bindgen_c_flags_lto) -D__BINDGEN__
+
++# Each `bindgen` release may upgrade the list of Rust target versions. By
++# default, the highest stable release in their list is used. Thus we need to set
++# a `--rust-target` to avoid future `bindgen` releases emitting code that
++# `rustc` may not understand. On top of that, `bindgen` does not support passing
++# an unknown Rust target version.
++#
++# Therefore, the Rust target for `bindgen` can be only as high as the minimum
++# Rust version the kernel supports and only as high as the greatest stable Rust
++# target supported by the minimum `bindgen` version the kernel supports (that
++# is, if we do not test the actual `rustc`/`bindgen` versions running).
++#
++# Starting with `bindgen` 0.71.0, we will be able to set any future Rust version
++# instead, i.e. we will be able to set here our minimum supported Rust version.
+ quiet_cmd_bindgen = BINDGEN $@
+ cmd_bindgen = \
+- $(BINDGEN) $< $(bindgen_target_flags) \
++ $(BINDGEN) $< $(bindgen_target_flags) --rust-target 1.68 \
+ --use-core --with-derive-default --ctypes-prefix core::ffi --no-layout-tests \
+ --no-debug '.*' --enable-function-attribute-detection \
+ -o $@ -- $(bindgen_c_flags_final) -DMODULE \
+diff --git a/sound/core/control_led.c b/sound/core/control_led.c
+index 65a1ebe877768f..e33dfcf863cf13 100644
+--- a/sound/core/control_led.c
++++ b/sound/core/control_led.c
+@@ -668,10 +668,16 @@ static void snd_ctl_led_sysfs_add(struct snd_card *card)
+ goto cerr;
+ led->cards[card->number] = led_card;
+ snprintf(link_name, sizeof(link_name), "led-%s", led->name);
+- WARN(sysfs_create_link(&card->ctl_dev->kobj, &led_card->dev.kobj, link_name),
+- "can't create symlink to controlC%i device\n", card->number);
+- WARN(sysfs_create_link(&led_card->dev.kobj, &card->card_dev.kobj, "card"),
+- "can't create symlink to card%i\n", card->number);
++ if (sysfs_create_link(&card->ctl_dev->kobj, &led_card->dev.kobj,
++ link_name))
++ dev_err(card->dev,
++ "%s: can't create symlink to controlC%i device\n",
++ __func__, card->number);
++ if (sysfs_create_link(&led_card->dev.kobj, &card->card_dev.kobj,
++ "card"))
++ dev_err(card->dev,
++ "%s: can't create symlink to card%i\n",
++ __func__, card->number);
+
+ continue;
+ cerr:
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index 973671e0cdb09d..192fc75b51e6db 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -10127,6 +10127,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x1025, 0x1430, "Acer TravelMate B311R-31", ALC256_FIXUP_ACER_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1025, 0x1466, "Acer Aspire A515-56", ALC255_FIXUP_ACER_HEADPHONE_AND_MIC),
+ SND_PCI_QUIRK(0x1025, 0x1534, "Acer Predator PH315-54", ALC255_FIXUP_ACER_MIC_NO_PRESENCE),
++ SND_PCI_QUIRK(0x1025, 0x159c, "Acer Nitro 5 AN515-58", ALC2XX_FIXUP_HEADSET_MIC),
+ SND_PCI_QUIRK(0x1025, 0x169a, "Acer Swift SFG16", ALC256_FIXUP_ACER_SFG16_MICMUTE_LED),
+ SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
+ SND_PCI_QUIRK(0x1028, 0x053c, "Dell Latitude E5430", ALC292_FIXUP_DELL_E7X),
+diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c
+index e38c5885dadfbc..ecf57a6cb7c37d 100644
+--- a/sound/soc/amd/yc/acp6x-mach.c
++++ b/sound/soc/amd/yc/acp6x-mach.c
+@@ -578,14 +578,19 @@ static int acp6x_probe(struct platform_device *pdev)
+
+ handle = ACPI_HANDLE(pdev->dev.parent);
+ ret = acpi_evaluate_integer(handle, "_WOV", NULL, &dmic_status);
+- if (!ACPI_FAILURE(ret))
++ if (!ACPI_FAILURE(ret)) {
+ wov_en = dmic_status;
++ if (!wov_en)
++ return -ENODEV;
++ } else {
++ /* Incase of ACPI method read failure then jump to check_dmi_entry */
++ goto check_dmi_entry;
++ }
+
+- if (is_dmic_enable && wov_en)
++ if (is_dmic_enable)
+ platform_set_drvdata(pdev, &acp6x_card);
+- else
+- return 0;
+
++check_dmi_entry:
+ /* check for any DMI overrides */
+ dmi_id = dmi_first_match(yc_acp_quirk_table);
+ if (dmi_id)
+diff --git a/sound/soc/codecs/tas2781-i2c.c b/sound/soc/codecs/tas2781-i2c.c
+index 12d093437ba9b6..1b2f55030c3961 100644
+--- a/sound/soc/codecs/tas2781-i2c.c
++++ b/sound/soc/codecs/tas2781-i2c.c
+@@ -370,7 +370,7 @@ static void sngl_calib_start(struct tasdevice_priv *tas_priv, int i,
+ tasdevice_dev_read(tas_priv, i, p[j].reg,
+ (int *)&p[j].val[0]);
+ } else {
+- switch (p[j].reg) {
++ switch (tas2781_cali_start_reg[j].reg) {
+ case 0: {
+ if (!reg[0])
+ continue;
+diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c
+index b6ff04f7138a2c..ee946e0d3f4969 100644
+--- a/sound/soc/fsl/fsl_spdif.c
++++ b/sound/soc/fsl/fsl_spdif.c
+@@ -1204,7 +1204,7 @@ static struct snd_kcontrol_new fsl_spdif_ctrls[] = {
+ },
+ /* DPLL lock info get controller */
+ {
+- .iface = SNDRV_CTL_ELEM_IFACE_PCM,
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = RX_SAMPLE_RATE_KCONTROL,
+ .access = SNDRV_CTL_ELEM_ACCESS_READ |
+ SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+diff --git a/sound/soc/fsl/fsl_xcvr.c b/sound/soc/fsl/fsl_xcvr.c
+index beede7344efd63..4341269eb97780 100644
+--- a/sound/soc/fsl/fsl_xcvr.c
++++ b/sound/soc/fsl/fsl_xcvr.c
+@@ -169,7 +169,7 @@ static int fsl_xcvr_capds_put(struct snd_kcontrol *kcontrol,
+ }
+
+ static struct snd_kcontrol_new fsl_xcvr_earc_capds_kctl = {
+- .iface = SNDRV_CTL_ELEM_IFACE_PCM,
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Capabilities Data Structure",
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .info = fsl_xcvr_type_capds_bytes_info,
+diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c
+index a58842a8c8a641..db57292c00ca1e 100644
+--- a/sound/soc/intel/boards/sof_sdw.c
++++ b/sound/soc/intel/boards/sof_sdw.c
+@@ -1003,8 +1003,12 @@ static int sof_card_dai_links_create(struct snd_soc_card *card)
+ return ret;
+ }
+
+- /* One per DAI link, worst case is a DAI link for every endpoint */
+- sof_dais = kcalloc(num_ends, sizeof(*sof_dais), GFP_KERNEL);
++ /*
++ * One per DAI link, worst case is a DAI link for every endpoint, also
++ * add one additional to act as a terminator such that code can iterate
++ * until it hits an uninitialised DAI.
++ */
++ sof_dais = kcalloc(num_ends + 1, sizeof(*sof_dais), GFP_KERNEL);
+ if (!sof_dais)
+ return -ENOMEM;
+
+diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
+index 00101875d9a8d5..a0767de7f1b7ed 100644
+--- a/sound/usb/quirks.c
++++ b/sound/usb/quirks.c
+@@ -2179,6 +2179,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
+ QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_MIC_RES_384),
+ DEVICE_FLG(0x046d, 0x09a4, /* Logitech QuickCam E 3500 */
+ QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_IGNORE_CTL_ERROR),
++ DEVICE_FLG(0x0499, 0x1506, /* Yamaha THR5 */
++ QUIRK_FLAG_GENERIC_IMPLICIT_FB),
+ DEVICE_FLG(0x0499, 0x1509, /* Steinberg UR22 */
+ QUIRK_FLAG_GENERIC_IMPLICIT_FB),
+ DEVICE_FLG(0x0499, 0x3108, /* Yamaha YIT-W12TX */
+diff --git a/tools/lib/perf/evlist.c b/tools/lib/perf/evlist.c
+index c6d67fc9e57ef0..83c43dc13313cc 100644
+--- a/tools/lib/perf/evlist.c
++++ b/tools/lib/perf/evlist.c
+@@ -47,6 +47,20 @@ static void __perf_evlist__propagate_maps(struct perf_evlist *evlist,
+ */
+ perf_cpu_map__put(evsel->cpus);
+ evsel->cpus = perf_cpu_map__intersect(evlist->user_requested_cpus, evsel->own_cpus);
++
++ /*
++ * Empty cpu lists would eventually get opened as "any" so remove
++ * genuinely empty ones before they're opened in the wrong place.
++ */
++ if (perf_cpu_map__is_empty(evsel->cpus)) {
++ struct perf_evsel *next = perf_evlist__next(evlist, evsel);
++
++ perf_evlist__remove(evlist, evsel);
++ /* Keep idx contiguous */
++ if (next)
++ list_for_each_entry_from(next, &evlist->entries, node)
++ next->idx--;
++ }
+ } else if (!evsel->own_cpus || evlist->has_user_cpus ||
+ (!evsel->requires_cpu && perf_cpu_map__has_any_cpu(evlist->user_requested_cpus))) {
+ /*
+@@ -80,11 +94,11 @@ static void __perf_evlist__propagate_maps(struct perf_evlist *evlist,
+
+ static void perf_evlist__propagate_maps(struct perf_evlist *evlist)
+ {
+- struct perf_evsel *evsel;
++ struct perf_evsel *evsel, *n;
+
+ evlist->needs_map_propagation = true;
+
+- perf_evlist__for_each_evsel(evlist, evsel)
++ list_for_each_entry_safe(evsel, n, &evlist->entries, node)
+ __perf_evlist__propagate_maps(evlist, evsel);
+ }
+
+diff --git a/tools/objtool/check.c b/tools/objtool/check.c
+index 6604f5d038aadf..f0d8796b984a80 100644
+--- a/tools/objtool/check.c
++++ b/tools/objtool/check.c
+@@ -3820,9 +3820,12 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
+ break;
+
+ case INSN_CONTEXT_SWITCH:
+- if (func && (!next_insn || !next_insn->hint)) {
+- WARN_INSN(insn, "unsupported instruction in callable function");
+- return 1;
++ if (func) {
++ if (!next_insn || !next_insn->hint) {
++ WARN_INSN(insn, "unsupported instruction in callable function");
++ return 1;
++ }
++ break;
+ }
+ return 0;
+
+diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
+index 272d3c70810e7d..a56cf8b0a7d405 100644
+--- a/tools/perf/builtin-ftrace.c
++++ b/tools/perf/builtin-ftrace.c
+@@ -1151,8 +1151,9 @@ static int cmp_profile_data(const void *a, const void *b)
+
+ if (v1 > v2)
+ return -1;
+- else
++ if (v1 < v2)
+ return 1;
++ return 0;
+ }
+
+ static void print_profile_result(struct perf_ftrace *ftrace)
+diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
+index 8982f68e7230cd..e763e8d99a4367 100644
+--- a/tools/perf/util/build-id.c
++++ b/tools/perf/util/build-id.c
+@@ -277,7 +277,7 @@ static int write_buildid(const char *name, size_t name_len, struct build_id *bid
+ struct perf_record_header_build_id b;
+ size_t len;
+
+- len = sizeof(b) + name_len + 1;
++ len = name_len + 1;
+ len = PERF_ALIGN(len, sizeof(u64));
+
+ memset(&b, 0, sizeof(b));
+@@ -286,7 +286,7 @@ static int write_buildid(const char *name, size_t name_len, struct build_id *bid
+ misc |= PERF_RECORD_MISC_BUILD_ID_SIZE;
+ b.pid = pid;
+ b.header.misc = misc;
+- b.header.size = len;
++ b.header.size = sizeof(b) + len;
+
+ err = do_write(fd, &b, sizeof(b));
+ if (err < 0)
+diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
+index 4f0ac998b0ccfd..27d5345d2b307a 100644
+--- a/tools/perf/util/machine.c
++++ b/tools/perf/util/machine.c
+@@ -134,6 +134,8 @@ struct machine *machine__new_host(void)
+
+ if (machine__create_kernel_maps(machine) < 0)
+ goto out_delete;
++
++ machine->env = &perf_env;
+ }
+
+ return machine;
+diff --git a/tools/testing/selftests/arm64/abi/syscall-abi-asm.S b/tools/testing/selftests/arm64/abi/syscall-abi-asm.S
+index df3230fdac3958..66ab2e0bae5fd0 100644
+--- a/tools/testing/selftests/arm64/abi/syscall-abi-asm.S
++++ b/tools/testing/selftests/arm64/abi/syscall-abi-asm.S
+@@ -81,32 +81,31 @@ do_syscall:
+ stp x27, x28, [sp, #96]
+
+ // Set SVCR if we're doing SME
+- cbz x1, 1f
++ cbz x1, load_gpr
+ adrp x2, svcr_in
+ ldr x2, [x2, :lo12:svcr_in]
+ msr S3_3_C4_C2_2, x2
+-1:
+
+ // Load ZA and ZT0 if enabled - uses x12 as scratch due to SME LDR
+- tbz x2, #SVCR_ZA_SHIFT, 1f
++ tbz x2, #SVCR_ZA_SHIFT, load_gpr
+ mov w12, #0
+ ldr x2, =za_in
+-2: _ldr_za 12, 2
++1: _ldr_za 12, 2
+ add x2, x2, x1
+ add x12, x12, #1
+ cmp x1, x12
+- bne 2b
++ bne 1b
+
+ // ZT0
+ mrs x2, S3_0_C0_C4_5 // ID_AA64SMFR0_EL1
+ ubfx x2, x2, #ID_AA64SMFR0_EL1_SMEver_SHIFT, \
+ #ID_AA64SMFR0_EL1_SMEver_WIDTH
+- cbz x2, 1f
++ cbz x2, load_gpr
+ adrp x2, zt_in
+ add x2, x2, :lo12:zt_in
+ _ldr_zt 2
+-1:
+
++load_gpr:
+ // Load GPRs x8-x28, and save our SP/FP for later comparison
+ ldr x2, =gpr_in
+ add x2, x2, #64
+@@ -125,9 +124,9 @@ do_syscall:
+ str x30, [x2], #8 // LR
+
+ // Load FPRs if we're not doing neither SVE nor streaming SVE
+- cbnz x0, 1f
++ cbnz x0, check_sve_in
+ ldr x2, =svcr_in
+- tbnz x2, #SVCR_SM_SHIFT, 1f
++ tbnz x2, #SVCR_SM_SHIFT, check_sve_in
+
+ ldr x2, =fpr_in
+ ldp q0, q1, [x2]
+@@ -148,8 +147,8 @@ do_syscall:
+ ldp q30, q31, [x2, #16 * 30]
+
+ b 2f
+-1:
+
++check_sve_in:
+ // Load the SVE registers if we're doing SVE/SME
+
+ ldr x2, =z_in
+@@ -256,32 +255,31 @@ do_syscall:
+ stp q30, q31, [x2, #16 * 30]
+
+ // Save SVCR if we're doing SME
+- cbz x1, 1f
++ cbz x1, check_sve_out
+ mrs x2, S3_3_C4_C2_2
+ adrp x3, svcr_out
+ str x2, [x3, :lo12:svcr_out]
+-1:
+
+ // Save ZA if it's enabled - uses x12 as scratch due to SME STR
+- tbz x2, #SVCR_ZA_SHIFT, 1f
++ tbz x2, #SVCR_ZA_SHIFT, check_sve_out
+ mov w12, #0
+ ldr x2, =za_out
+-2: _str_za 12, 2
++1: _str_za 12, 2
+ add x2, x2, x1
+ add x12, x12, #1
+ cmp x1, x12
+- bne 2b
++ bne 1b
+
+ // ZT0
+ mrs x2, S3_0_C0_C4_5 // ID_AA64SMFR0_EL1
+ ubfx x2, x2, #ID_AA64SMFR0_EL1_SMEver_SHIFT, \
+ #ID_AA64SMFR0_EL1_SMEver_WIDTH
+- cbz x2, 1f
++ cbz x2, check_sve_out
+ adrp x2, zt_out
+ add x2, x2, :lo12:zt_out
+ _str_zt 2
+-1:
+
++check_sve_out:
+ // Save the SVE state if we have some
+ cbz x0, 1f
+
+diff --git a/tools/testing/selftests/bpf/progs/test_tp_btf_nullable.c b/tools/testing/selftests/bpf/progs/test_tp_btf_nullable.c
+index 5aaf2b065f86c2..bba3e37f749b86 100644
+--- a/tools/testing/selftests/bpf/progs/test_tp_btf_nullable.c
++++ b/tools/testing/selftests/bpf/progs/test_tp_btf_nullable.c
+@@ -7,11 +7,7 @@
+ #include "bpf_misc.h"
+
+ SEC("tp_btf/bpf_testmod_test_nullable_bare")
+-/* This used to be a failure test, but raw_tp nullable arguments can now
+- * directly be dereferenced, whether they have nullable annotation or not,
+- * and don't need to be explicitly checked.
+- */
+-__success
++__failure __msg("R1 invalid mem access 'trusted_ptr_or_null_'")
+ int BPF_PROG(handle_tp_btf_nullable_bare1, struct bpf_testmod_test_read_ctx *nullable_ctx)
+ {
+ return nullable_ctx->len;
+diff --git a/tools/testing/selftests/bpf/progs/verifier_btf_ctx_access.c b/tools/testing/selftests/bpf/progs/verifier_btf_ctx_access.c
+index a570e48b917acc..bfc3bf18fed4fe 100644
+--- a/tools/testing/selftests/bpf/progs/verifier_btf_ctx_access.c
++++ b/tools/testing/selftests/bpf/progs/verifier_btf_ctx_access.c
+@@ -11,7 +11,7 @@ __success __retval(0)
+ __naked void btf_ctx_access_accept(void)
+ {
+ asm volatile (" \
+- r2 = *(u32*)(r1 + 8); /* load 2nd argument value (int pointer) */\
++ r2 = *(u64 *)(r1 + 8); /* load 2nd argument value (int pointer) */\
+ r0 = 0; \
+ exit; \
+ " ::: __clobber_all);
+@@ -23,7 +23,7 @@ __success __retval(0)
+ __naked void ctx_access_u32_pointer_accept(void)
+ {
+ asm volatile (" \
+- r2 = *(u32*)(r1 + 0); /* load 1nd argument value (u32 pointer) */\
++ r2 = *(u64 *)(r1 + 0); /* load 1nd argument value (u32 pointer) */\
+ r0 = 0; \
+ exit; \
+ " ::: __clobber_all);
+diff --git a/tools/testing/selftests/bpf/progs/verifier_d_path.c b/tools/testing/selftests/bpf/progs/verifier_d_path.c
+index ec79cbcfde91ef..87e51a215558fd 100644
+--- a/tools/testing/selftests/bpf/progs/verifier_d_path.c
++++ b/tools/testing/selftests/bpf/progs/verifier_d_path.c
+@@ -11,7 +11,7 @@ __success __retval(0)
+ __naked void d_path_accept(void)
+ {
+ asm volatile (" \
+- r1 = *(u32*)(r1 + 0); \
++ r1 = *(u64 *)(r1 + 0); \
+ r2 = r10; \
+ r2 += -8; \
+ r6 = 0; \
+@@ -31,7 +31,7 @@ __failure __msg("helper call is not allowed in probe")
+ __naked void d_path_reject(void)
+ {
+ asm volatile (" \
+- r1 = *(u32*)(r1 + 0); \
++ r1 = *(u64 *)(r1 + 0); \
+ r2 = r10; \
+ r2 += -8; \
+ r6 = 0; \
+diff --git a/tools/testing/selftests/drivers/net/mlxsw/sharedbuffer.sh b/tools/testing/selftests/drivers/net/mlxsw/sharedbuffer.sh
+index 0c47faff9274b1..c068e6c2a580ea 100755
+--- a/tools/testing/selftests/drivers/net/mlxsw/sharedbuffer.sh
++++ b/tools/testing/selftests/drivers/net/mlxsw/sharedbuffer.sh
+@@ -22,20 +22,34 @@ SB_ITC=0
+ h1_create()
+ {
+ simple_if_init $h1 192.0.1.1/24
++ tc qdisc add dev $h1 clsact
++
++ # Add egress filter on $h1 that will guarantee that the packet sent,
++ # will be the only packet being passed to the device.
++ tc filter add dev $h1 egress pref 2 handle 102 matchall action drop
+ }
+
+ h1_destroy()
+ {
++ tc filter del dev $h1 egress pref 2 handle 102 matchall action drop
++ tc qdisc del dev $h1 clsact
+ simple_if_fini $h1 192.0.1.1/24
+ }
+
+ h2_create()
+ {
+ simple_if_init $h2 192.0.1.2/24
++ tc qdisc add dev $h2 clsact
++
++ # Add egress filter on $h2 that will guarantee that the packet sent,
++ # will be the only packet being passed to the device.
++ tc filter add dev $h2 egress pref 1 handle 101 matchall action drop
+ }
+
+ h2_destroy()
+ {
++ tc filter del dev $h2 egress pref 1 handle 101 matchall action drop
++ tc qdisc del dev $h2 clsact
+ simple_if_fini $h2 192.0.1.2/24
+ }
+
+@@ -101,6 +115,11 @@ port_pool_test()
+ local exp_max_occ=$(devlink_cell_size_get)
+ local max_occ
+
++ tc filter add dev $h1 egress protocol ip pref 1 handle 101 flower \
++ src_mac $h1mac dst_mac $h2mac \
++ src_ip 192.0.1.1 dst_ip 192.0.1.2 \
++ action pass
++
+ devlink sb occupancy clearmax $DEVLINK_DEV
+
+ $MZ $h1 -c 1 -p 10 -a $h1mac -b $h2mac -A 192.0.1.1 -B 192.0.1.2 \
+@@ -108,11 +127,6 @@ port_pool_test()
+
+ devlink sb occupancy snapshot $DEVLINK_DEV
+
+- RET=0
+- max_occ=$(sb_occ_pool_check $dl_port1 $SB_POOL_ING $exp_max_occ)
+- check_err $? "Expected iPool($SB_POOL_ING) max occupancy to be $exp_max_occ, but got $max_occ"
+- log_test "physical port's($h1) ingress pool"
+-
+ RET=0
+ max_occ=$(sb_occ_pool_check $dl_port2 $SB_POOL_ING $exp_max_occ)
+ check_err $? "Expected iPool($SB_POOL_ING) max occupancy to be $exp_max_occ, but got $max_occ"
+@@ -122,6 +136,11 @@ port_pool_test()
+ max_occ=$(sb_occ_pool_check $cpu_dl_port $SB_POOL_EGR_CPU $exp_max_occ)
+ check_err $? "Expected ePool($SB_POOL_EGR_CPU) max occupancy to be $exp_max_occ, but got $max_occ"
+ log_test "CPU port's egress pool"
++
++ tc filter del dev $h1 egress protocol ip pref 1 handle 101 flower \
++ src_mac $h1mac dst_mac $h2mac \
++ src_ip 192.0.1.1 dst_ip 192.0.1.2 \
++ action pass
+ }
+
+ port_tc_ip_test()
+@@ -129,6 +148,11 @@ port_tc_ip_test()
+ local exp_max_occ=$(devlink_cell_size_get)
+ local max_occ
+
++ tc filter add dev $h1 egress protocol ip pref 1 handle 101 flower \
++ src_mac $h1mac dst_mac $h2mac \
++ src_ip 192.0.1.1 dst_ip 192.0.1.2 \
++ action pass
++
+ devlink sb occupancy clearmax $DEVLINK_DEV
+
+ $MZ $h1 -c 1 -p 10 -a $h1mac -b $h2mac -A 192.0.1.1 -B 192.0.1.2 \
+@@ -136,11 +160,6 @@ port_tc_ip_test()
+
+ devlink sb occupancy snapshot $DEVLINK_DEV
+
+- RET=0
+- max_occ=$(sb_occ_itc_check $dl_port2 $SB_ITC $exp_max_occ)
+- check_err $? "Expected ingress TC($SB_ITC) max occupancy to be $exp_max_occ, but got $max_occ"
+- log_test "physical port's($h1) ingress TC - IP packet"
+-
+ RET=0
+ max_occ=$(sb_occ_itc_check $dl_port2 $SB_ITC $exp_max_occ)
+ check_err $? "Expected ingress TC($SB_ITC) max occupancy to be $exp_max_occ, but got $max_occ"
+@@ -150,6 +169,11 @@ port_tc_ip_test()
+ max_occ=$(sb_occ_etc_check $cpu_dl_port $SB_ITC_CPU_IP $exp_max_occ)
+ check_err $? "Expected egress TC($SB_ITC_CPU_IP) max occupancy to be $exp_max_occ, but got $max_occ"
+ log_test "CPU port's egress TC - IP packet"
++
++ tc filter del dev $h1 egress protocol ip pref 1 handle 101 flower \
++ src_mac $h1mac dst_mac $h2mac \
++ src_ip 192.0.1.1 dst_ip 192.0.1.2 \
++ action pass
+ }
+
+ port_tc_arp_test()
+@@ -157,17 +181,15 @@ port_tc_arp_test()
+ local exp_max_occ=$(devlink_cell_size_get)
+ local max_occ
+
++ tc filter add dev $h1 egress protocol arp pref 1 handle 101 flower \
++ src_mac $h1mac action pass
++
+ devlink sb occupancy clearmax $DEVLINK_DEV
+
+ $MZ $h1 -c 1 -p 10 -a $h1mac -A 192.0.1.1 -t arp -q
+
+ devlink sb occupancy snapshot $DEVLINK_DEV
+
+- RET=0
+- max_occ=$(sb_occ_itc_check $dl_port2 $SB_ITC $exp_max_occ)
+- check_err $? "Expected ingress TC($SB_ITC) max occupancy to be $exp_max_occ, but got $max_occ"
+- log_test "physical port's($h1) ingress TC - ARP packet"
+-
+ RET=0
+ max_occ=$(sb_occ_itc_check $dl_port2 $SB_ITC $exp_max_occ)
+ check_err $? "Expected ingress TC($SB_ITC) max occupancy to be $exp_max_occ, but got $max_occ"
+@@ -177,6 +199,9 @@ port_tc_arp_test()
+ max_occ=$(sb_occ_etc_check $cpu_dl_port $SB_ITC_CPU_ARP $exp_max_occ)
+ check_err $? "Expected egress TC($SB_ITC_IP2ME) max occupancy to be $exp_max_occ, but got $max_occ"
+ log_test "CPU port's egress TC - ARP packet"
++
++ tc filter del dev $h1 egress protocol arp pref 1 handle 101 flower \
++ src_mac $h1mac action pass
+ }
+
+ setup_prepare()
+diff --git a/tools/testing/selftests/net/netfilter/rpath.sh b/tools/testing/selftests/net/netfilter/rpath.sh
+index 4485fd7675ed7e..86ec4e68594dc3 100755
+--- a/tools/testing/selftests/net/netfilter/rpath.sh
++++ b/tools/testing/selftests/net/netfilter/rpath.sh
+@@ -61,9 +61,20 @@ ip -net "$ns2" a a 192.168.42.1/24 dev d0
+ ip -net "$ns1" a a fec0:42::2/64 dev v0 nodad
+ ip -net "$ns2" a a fec0:42::1/64 dev d0 nodad
+
++# avoid neighbor lookups and enable martian IPv6 pings
++ns2_hwaddr=$(ip -net "$ns2" link show dev v0 | \
++ sed -n 's, *link/ether \([^ ]*\) .*,\1,p')
++ns1_hwaddr=$(ip -net "$ns1" link show dev v0 | \
++ sed -n 's, *link/ether \([^ ]*\) .*,\1,p')
++ip -net "$ns1" neigh add fec0:42::1 lladdr "$ns2_hwaddr" nud permanent dev v0
++ip -net "$ns1" neigh add fec0:23::1 lladdr "$ns2_hwaddr" nud permanent dev v0
++ip -net "$ns2" neigh add fec0:42::2 lladdr "$ns1_hwaddr" nud permanent dev d0
++ip -net "$ns2" neigh add fec0:23::2 lladdr "$ns1_hwaddr" nud permanent dev v0
++
+ # firewall matches to test
+ [ -n "$iptables" ] && {
+ common='-t raw -A PREROUTING -s 192.168.0.0/16'
++ common+=' -p icmp --icmp-type echo-request'
+ if ! ip netns exec "$ns2" "$iptables" $common -m rpfilter;then
+ echo "Cannot add rpfilter rule"
+ exit $ksft_skip
+@@ -72,6 +83,7 @@ ip -net "$ns2" a a fec0:42::1/64 dev d0 nodad
+ }
+ [ -n "$ip6tables" ] && {
+ common='-t raw -A PREROUTING -s fec0::/16'
++ common+=' -p icmpv6 --icmpv6-type echo-request'
+ if ! ip netns exec "$ns2" "$ip6tables" $common -m rpfilter;then
+ echo "Cannot add rpfilter rule"
+ exit $ksft_skip
+@@ -82,8 +94,10 @@ ip -net "$ns2" a a fec0:42::1/64 dev d0 nodad
+ table inet t {
+ chain c {
+ type filter hook prerouting priority raw;
+- ip saddr 192.168.0.0/16 fib saddr . iif oif exists counter
+- ip6 saddr fec0::/16 fib saddr . iif oif exists counter
++ ip saddr 192.168.0.0/16 icmp type echo-request \
++ fib saddr . iif oif exists counter
++ ip6 saddr fec0::/16 icmpv6 type echo-request \
++ fib saddr . iif oif exists counter
+ }
+ }
+ EOF
next reply other threads:[~2024-12-19 18:07 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-12-19 18:07 Mike Pagano [this message]
-- strict thread matches above, loose matches on Subject: below --
2025-03-07 18:22 [gentoo-commits] proj/linux-patches:6.12 commit in: / Mike Pagano
2025-02-27 13:22 Mike Pagano
2025-02-21 13:31 Mike Pagano
2025-02-18 11:26 Mike Pagano
2025-02-17 15:44 Mike Pagano
2025-02-17 11:25 Mike Pagano
2025-02-17 11:16 Mike Pagano
2025-02-16 21:48 Mike Pagano
2025-02-08 11:26 Mike Pagano
2025-02-01 23:07 Mike Pagano
2025-01-30 12:47 Mike Pagano
2025-01-23 17:02 Mike Pagano
2025-01-17 13:18 Mike Pagano
2025-01-17 13:18 Mike Pagano
2025-01-09 13:51 Mike Pagano
2025-01-02 12:31 Mike Pagano
2024-12-27 14:08 Mike Pagano
2024-12-15 0:02 Mike Pagano
2024-12-14 23:59 Mike Pagano
2024-12-14 23:47 Mike Pagano
2024-12-11 21:01 Mike Pagano
2024-12-09 23:13 Mike Pagano
2024-12-09 11:35 Mike Pagano
2024-12-06 12:44 Mike Pagano
2024-12-05 20:05 Mike Pagano
2024-12-05 14:06 Mike Pagano
2024-12-02 17:15 Mike Pagano
2024-11-30 17:33 Mike Pagano
2024-11-22 17:45 Mike Pagano
2024-11-21 13:12 Mike Pagano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1734631630.1d0712601fc0cfb16d2abc9bf8d0e34c43b6afe4.mpagano@gentoo \
--to=mpagano@gentoo.org \
--cc=gentoo-commits@lists.gentoo.org \
--cc=gentoo-dev@lists.gentoo.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox