From: "Arisu Tachibana" <alicef@gentoo.org>
To: gentoo-commits@lists.gentoo.org
Subject: [gentoo-commits] proj/linux-patches:6.16 commit in: /
Date: Thu, 25 Sep 2025 12:02:17 +0000 (UTC) [thread overview]
Message-ID: <1758801724.fb4386cb8d3a0e3944fcbd135b1a7c53cd28d3ad.alicef@gentoo> (raw)
commit: fb4386cb8d3a0e3944fcbd135b1a7c53cd28d3ad
Author: Arisu Tachibana <alicef <AT> gentoo <DOT> org>
AuthorDate: Thu Sep 25 12:02:04 2025 +0000
Commit: Arisu Tachibana <alicef <AT> gentoo <DOT> org>
CommitDate: Thu Sep 25 12:02:04 2025 +0000
URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=fb4386cb
Linux patch 6.16.9
Signed-off-by: Arisu Tachibana <alicef <AT> gentoo.org>
0000_README | 4 +
1008_linux-6.16.9.patch | 6546 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 6550 insertions(+)
diff --git a/0000_README b/0000_README
index b72d6630..48b50ad0 100644
--- a/0000_README
+++ b/0000_README
@@ -75,6 +75,10 @@ Patch: 1007_linux-6.16.8.patch
From: https://www.kernel.org
Desc: Linux 6.16.8
+Patch: 1008_linux-6.16.9.patch
+From: https://www.kernel.org
+Desc: Linux 6.16.9
+
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/1008_linux-6.16.9.patch b/1008_linux-6.16.9.patch
new file mode 100644
index 00000000..3a65fc5a
--- /dev/null
+++ b/1008_linux-6.16.9.patch
@@ -0,0 +1,6546 @@
+diff --git a/Documentation/devicetree/bindings/serial/8250.yaml b/Documentation/devicetree/bindings/serial/8250.yaml
+index c6bc27709bf726..f59c0b37e8ebb2 100644
+--- a/Documentation/devicetree/bindings/serial/8250.yaml
++++ b/Documentation/devicetree/bindings/serial/8250.yaml
+@@ -48,6 +48,45 @@ allOf:
+ oneOf:
+ - required: [ clock-frequency ]
+ - required: [ clocks ]
++ - if:
++ properties:
++ compatible:
++ contains:
++ const: nxp,lpc1850-uart
++ then:
++ properties:
++ clock-names:
++ items:
++ - const: uartclk
++ - const: reg
++ else:
++ properties:
++ clock-names:
++ items:
++ - const: core
++ - const: bus
++ - if:
++ properties:
++ compatible:
++ contains:
++ enum:
++ - spacemit,k1-uart
++ - nxp,lpc1850-uart
++ then:
++ required:
++ - clocks
++ - clock-names
++ properties:
++ clocks:
++ minItems: 2
++ clock-names:
++ minItems: 2
++ else:
++ properties:
++ clocks:
++ maxItems: 1
++ clock-names:
++ maxItems: 1
+
+ properties:
+ compatible:
+@@ -142,9 +181,22 @@ properties:
+
+ clock-names:
+ minItems: 1
+- items:
+- - const: core
+- - const: bus
++ maxItems: 2
++ oneOf:
++ - items:
++ - const: core
++ - const: bus
++ - items:
++ - const: uartclk
++ - const: reg
++
++ dmas:
++ minItems: 1
++ maxItems: 4
++
++ dma-names:
++ minItems: 1
++ maxItems: 4
+
+ resets:
+ maxItems: 1
+@@ -233,25 +285,6 @@ required:
+ - reg
+ - interrupts
+
+-if:
+- properties:
+- compatible:
+- contains:
+- const: spacemit,k1-uart
+-then:
+- required: [clock-names]
+- properties:
+- clocks:
+- minItems: 2
+- clock-names:
+- minItems: 2
+-else:
+- properties:
+- clocks:
+- maxItems: 1
+- clock-names:
+- maxItems: 1
+-
+ unevaluatedProperties: false
+
+ examples:
+diff --git a/Documentation/netlink/specs/conntrack.yaml b/Documentation/netlink/specs/conntrack.yaml
+index 840dc4504216bc..1865ddf01fb0f6 100644
+--- a/Documentation/netlink/specs/conntrack.yaml
++++ b/Documentation/netlink/specs/conntrack.yaml
+@@ -575,8 +575,8 @@ operations:
+ - nat-dst
+ - timeout
+ - mark
+- - counter-orig
+- - counter-reply
++ - counters-orig
++ - counters-reply
+ - use
+ - id
+ - nat-dst
+@@ -591,7 +591,6 @@ operations:
+ request:
+ value: 0x101
+ attributes:
+- - nfgen-family
+ - mark
+ - filter
+ - status
+@@ -608,8 +607,8 @@ operations:
+ - nat-dst
+ - timeout
+ - mark
+- - counter-orig
+- - counter-reply
++ - counters-orig
++ - counters-reply
+ - use
+ - id
+ - nat-dst
+diff --git a/Documentation/netlink/specs/mptcp_pm.yaml b/Documentation/netlink/specs/mptcp_pm.yaml
+index ecfe5ee33de2d8..c77f32cfcae973 100644
+--- a/Documentation/netlink/specs/mptcp_pm.yaml
++++ b/Documentation/netlink/specs/mptcp_pm.yaml
+@@ -28,13 +28,13 @@ definitions:
+ traffic-patterns it can take a long time until the
+ MPTCP_EVENT_ESTABLISHED is sent.
+ Attributes: token, family, saddr4 | saddr6, daddr4 | daddr6, sport,
+- dport, server-side.
++ dport, server-side, [flags].
+ -
+ name: established
+ doc: >-
+ A MPTCP connection is established (can start new subflows).
+ Attributes: token, family, saddr4 | saddr6, daddr4 | daddr6, sport,
+- dport, server-side.
++ dport, server-side, [flags].
+ -
+ name: closed
+ doc: >-
+diff --git a/Makefile b/Makefile
+index 7594f35cbc2a5a..aef2cb6ea99d8b 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ VERSION = 6
+ PATCHLEVEL = 16
+-SUBLEVEL = 8
++SUBLEVEL = 9
+ EXTRAVERSION =
+ NAME = Baby Opossum Posse
+
+diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig
+index 4b19f93379a153..eb13fcf095a1d4 100644
+--- a/arch/loongarch/Kconfig
++++ b/arch/loongarch/Kconfig
+@@ -301,6 +301,10 @@ config AS_HAS_LVZ_EXTENSION
+ config CC_HAS_ANNOTATE_TABLEJUMP
+ def_bool $(cc-option,-mannotate-tablejump)
+
++config RUSTC_HAS_ANNOTATE_TABLEJUMP
++ depends on RUST
++ def_bool $(rustc-option,-Cllvm-args=--loongarch-annotate-tablejump)
++
+ menu "Kernel type and options"
+
+ source "kernel/Kconfig.hz"
+@@ -566,10 +570,14 @@ config ARCH_STRICT_ALIGN
+ -mstrict-align build parameter to prevent unaligned accesses.
+
+ CPUs with h/w unaligned access support:
+- Loongson-2K2000/2K3000/3A5000/3C5000/3D5000.
++ Loongson-2K2000/2K3000 and all of Loongson-3 series processors
++ based on LoongArch.
+
+ CPUs without h/w unaligned access support:
+- Loongson-2K500/2K1000.
++ Loongson-2K0300/2K0500/2K1000.
++
++ If you want to make sure whether to support unaligned memory access
++ on your hardware, please read the bit 20 (UAL) of CPUCFG1 register.
+
+ This option is enabled by default to make the kernel be able to run
+ on all LoongArch systems. But you can disable it manually if you want
+diff --git a/arch/loongarch/Makefile b/arch/loongarch/Makefile
+index a3a9759414f40f..ae419e32f22e2f 100644
+--- a/arch/loongarch/Makefile
++++ b/arch/loongarch/Makefile
+@@ -102,16 +102,21 @@ KBUILD_CFLAGS += $(call cc-option,-mthin-add-sub) $(call cc-option,-Wa$(comma)
+
+ ifdef CONFIG_OBJTOOL
+ ifdef CONFIG_CC_HAS_ANNOTATE_TABLEJUMP
++KBUILD_CFLAGS += -mannotate-tablejump
++else
++KBUILD_CFLAGS += -fno-jump-tables # keep compatibility with older compilers
++endif
++ifdef CONFIG_RUSTC_HAS_ANNOTATE_TABLEJUMP
++KBUILD_RUSTFLAGS += -Cllvm-args=--loongarch-annotate-tablejump
++else
++KBUILD_RUSTFLAGS += -Zno-jump-tables # keep compatibility with older compilers
++endif
++ifdef CONFIG_LTO_CLANG
+ # The annotate-tablejump option can not be passed to LLVM backend when LTO is enabled.
+ # Ensure it is aware of linker with LTO, '--loongarch-annotate-tablejump' also needs to
+ # be passed via '-mllvm' to ld.lld.
+-KBUILD_CFLAGS += -mannotate-tablejump
+-ifdef CONFIG_LTO_CLANG
+ KBUILD_LDFLAGS += -mllvm --loongarch-annotate-tablejump
+ endif
+-else
+-KBUILD_CFLAGS += -fno-jump-tables # keep compatibility with older compilers
+-endif
+ endif
+
+ KBUILD_RUSTFLAGS += --target=loongarch64-unknown-none-softfloat -Ccode-model=small
+diff --git a/arch/loongarch/include/asm/acenv.h b/arch/loongarch/include/asm/acenv.h
+index 52f298f7293bab..483c955f2ae50d 100644
+--- a/arch/loongarch/include/asm/acenv.h
++++ b/arch/loongarch/include/asm/acenv.h
+@@ -10,9 +10,8 @@
+ #ifndef _ASM_LOONGARCH_ACENV_H
+ #define _ASM_LOONGARCH_ACENV_H
+
+-/*
+- * This header is required by ACPI core, but we have nothing to fill in
+- * right now. Will be updated later when needed.
+- */
++#ifdef CONFIG_ARCH_STRICT_ALIGN
++#define ACPI_MISALIGNMENT_NOT_SUPPORTED
++#endif /* CONFIG_ARCH_STRICT_ALIGN */
+
+ #endif /* _ASM_LOONGARCH_ACENV_H */
+diff --git a/arch/loongarch/include/asm/kvm_mmu.h b/arch/loongarch/include/asm/kvm_mmu.h
+index 099bafc6f797c9..e36cc7e8ed200a 100644
+--- a/arch/loongarch/include/asm/kvm_mmu.h
++++ b/arch/loongarch/include/asm/kvm_mmu.h
+@@ -16,6 +16,13 @@
+ */
+ #define KVM_MMU_CACHE_MIN_PAGES (CONFIG_PGTABLE_LEVELS - 1)
+
++/*
++ * _PAGE_MODIFIED is a SW pte bit, it records page ever written on host
++ * kernel, on secondary MMU it records the page writeable attribute, in
++ * order for fast path handling.
++ */
++#define KVM_PAGE_WRITEABLE _PAGE_MODIFIED
++
+ #define _KVM_FLUSH_PGTABLE 0x1
+ #define _KVM_HAS_PGMASK 0x2
+ #define kvm_pfn_pte(pfn, prot) (((pfn) << PFN_PTE_SHIFT) | pgprot_val(prot))
+@@ -52,10 +59,10 @@ static inline void kvm_set_pte(kvm_pte_t *ptep, kvm_pte_t val)
+ WRITE_ONCE(*ptep, val);
+ }
+
+-static inline int kvm_pte_write(kvm_pte_t pte) { return pte & _PAGE_WRITE; }
+-static inline int kvm_pte_dirty(kvm_pte_t pte) { return pte & _PAGE_DIRTY; }
+ static inline int kvm_pte_young(kvm_pte_t pte) { return pte & _PAGE_ACCESSED; }
+ static inline int kvm_pte_huge(kvm_pte_t pte) { return pte & _PAGE_HUGE; }
++static inline int kvm_pte_dirty(kvm_pte_t pte) { return pte & __WRITEABLE; }
++static inline int kvm_pte_writeable(kvm_pte_t pte) { return pte & KVM_PAGE_WRITEABLE; }
+
+ static inline kvm_pte_t kvm_pte_mkyoung(kvm_pte_t pte)
+ {
+@@ -69,12 +76,12 @@ static inline kvm_pte_t kvm_pte_mkold(kvm_pte_t pte)
+
+ static inline kvm_pte_t kvm_pte_mkdirty(kvm_pte_t pte)
+ {
+- return pte | _PAGE_DIRTY;
++ return pte | __WRITEABLE;
+ }
+
+ static inline kvm_pte_t kvm_pte_mkclean(kvm_pte_t pte)
+ {
+- return pte & ~_PAGE_DIRTY;
++ return pte & ~__WRITEABLE;
+ }
+
+ static inline kvm_pte_t kvm_pte_mkhuge(kvm_pte_t pte)
+@@ -87,6 +94,11 @@ static inline kvm_pte_t kvm_pte_mksmall(kvm_pte_t pte)
+ return pte & ~_PAGE_HUGE;
+ }
+
++static inline kvm_pte_t kvm_pte_mkwriteable(kvm_pte_t pte)
++{
++ return pte | KVM_PAGE_WRITEABLE;
++}
++
+ static inline int kvm_need_flush(kvm_ptw_ctx *ctx)
+ {
+ return ctx->flag & _KVM_FLUSH_PGTABLE;
+diff --git a/arch/loongarch/kernel/env.c b/arch/loongarch/kernel/env.c
+index c0a5dc9aeae287..be309a71f20491 100644
+--- a/arch/loongarch/kernel/env.c
++++ b/arch/loongarch/kernel/env.c
+@@ -109,6 +109,8 @@ static int __init boardinfo_init(void)
+ struct kobject *loongson_kobj;
+
+ loongson_kobj = kobject_create_and_add("loongson", firmware_kobj);
++ if (!loongson_kobj)
++ return -ENOMEM;
+
+ return sysfs_create_file(loongson_kobj, &boardinfo_attr.attr);
+ }
+diff --git a/arch/loongarch/kernel/stacktrace.c b/arch/loongarch/kernel/stacktrace.c
+index 9a038d1070d73b..387dc4d3c4868f 100644
+--- a/arch/loongarch/kernel/stacktrace.c
++++ b/arch/loongarch/kernel/stacktrace.c
+@@ -51,12 +51,13 @@ int arch_stack_walk_reliable(stack_trace_consume_fn consume_entry,
+ if (task == current) {
+ regs->regs[3] = (unsigned long)__builtin_frame_address(0);
+ regs->csr_era = (unsigned long)__builtin_return_address(0);
++ regs->regs[22] = 0;
+ } else {
+ regs->regs[3] = thread_saved_fp(task);
+ regs->csr_era = thread_saved_ra(task);
++ regs->regs[22] = task->thread.reg22;
+ }
+ regs->regs[1] = 0;
+- regs->regs[22] = 0;
+
+ for (unwind_start(&state, task, regs);
+ !unwind_done(&state) && !unwind_error(&state); unwind_next_frame(&state)) {
+diff --git a/arch/loongarch/kernel/vdso.c b/arch/loongarch/kernel/vdso.c
+index 7b888d9085a014..dee1a15d7f4c77 100644
+--- a/arch/loongarch/kernel/vdso.c
++++ b/arch/loongarch/kernel/vdso.c
+@@ -54,6 +54,9 @@ static int __init init_vdso(void)
+ vdso_info.code_mapping.pages =
+ kcalloc(vdso_info.size / PAGE_SIZE, sizeof(struct page *), GFP_KERNEL);
+
++ if (!vdso_info.code_mapping.pages)
++ return -ENOMEM;
++
+ pfn = __phys_to_pfn(__pa_symbol(vdso_info.vdso));
+ for (i = 0; i < vdso_info.size / PAGE_SIZE; i++)
+ vdso_info.code_mapping.pages[i] = pfn_to_page(pfn + i);
+diff --git a/arch/loongarch/kvm/intc/eiointc.c b/arch/loongarch/kvm/intc/eiointc.c
+index 0207cfe1dbd6c7..8e10393d276dc4 100644
+--- a/arch/loongarch/kvm/intc/eiointc.c
++++ b/arch/loongarch/kvm/intc/eiointc.c
+@@ -810,21 +810,26 @@ static int kvm_eiointc_ctrl_access(struct kvm_device *dev,
+ struct loongarch_eiointc *s = dev->kvm->arch.eiointc;
+
+ data = (void __user *)attr->addr;
+- spin_lock_irqsave(&s->lock, flags);
+ switch (type) {
+ case KVM_DEV_LOONGARCH_EXTIOI_CTRL_INIT_NUM_CPU:
++ case KVM_DEV_LOONGARCH_EXTIOI_CTRL_INIT_FEATURE:
+ if (copy_from_user(&val, data, 4))
+- ret = -EFAULT;
+- else {
+- if (val >= EIOINTC_ROUTE_MAX_VCPUS)
+- ret = -EINVAL;
+- else
+- s->num_cpu = val;
+- }
++ return -EFAULT;
++ break;
++ default:
++ break;
++ }
++
++ spin_lock_irqsave(&s->lock, flags);
++ switch (type) {
++ case KVM_DEV_LOONGARCH_EXTIOI_CTRL_INIT_NUM_CPU:
++ if (val >= EIOINTC_ROUTE_MAX_VCPUS)
++ ret = -EINVAL;
++ else
++ s->num_cpu = val;
+ break;
+ case KVM_DEV_LOONGARCH_EXTIOI_CTRL_INIT_FEATURE:
+- if (copy_from_user(&s->features, data, 4))
+- ret = -EFAULT;
++ s->features = val;
+ if (!(s->features & BIT(EIOINTC_HAS_VIRT_EXTENSION)))
+ s->status |= BIT(EIOINTC_ENABLE);
+ break;
+@@ -846,19 +851,17 @@ static int kvm_eiointc_ctrl_access(struct kvm_device *dev,
+
+ static int kvm_eiointc_regs_access(struct kvm_device *dev,
+ struct kvm_device_attr *attr,
+- bool is_write)
++ bool is_write, int *data)
+ {
+ int addr, cpu, offset, ret = 0;
+ unsigned long flags;
+ void *p = NULL;
+- void __user *data;
+ struct loongarch_eiointc *s;
+
+ s = dev->kvm->arch.eiointc;
+ addr = attr->attr;
+ cpu = addr >> 16;
+ addr &= 0xffff;
+- data = (void __user *)attr->addr;
+ switch (addr) {
+ case EIOINTC_NODETYPE_START ... EIOINTC_NODETYPE_END:
+ offset = (addr - EIOINTC_NODETYPE_START) / 4;
+@@ -897,13 +900,10 @@ static int kvm_eiointc_regs_access(struct kvm_device *dev,
+ }
+
+ spin_lock_irqsave(&s->lock, flags);
+- if (is_write) {
+- if (copy_from_user(p, data, 4))
+- ret = -EFAULT;
+- } else {
+- if (copy_to_user(data, p, 4))
+- ret = -EFAULT;
+- }
++ if (is_write)
++ memcpy(p, data, 4);
++ else
++ memcpy(data, p, 4);
+ spin_unlock_irqrestore(&s->lock, flags);
+
+ return ret;
+@@ -911,19 +911,17 @@ static int kvm_eiointc_regs_access(struct kvm_device *dev,
+
+ static int kvm_eiointc_sw_status_access(struct kvm_device *dev,
+ struct kvm_device_attr *attr,
+- bool is_write)
++ bool is_write, int *data)
+ {
+ int addr, ret = 0;
+ unsigned long flags;
+ void *p = NULL;
+- void __user *data;
+ struct loongarch_eiointc *s;
+
+ s = dev->kvm->arch.eiointc;
+ addr = attr->attr;
+ addr &= 0xffff;
+
+- data = (void __user *)attr->addr;
+ switch (addr) {
+ case KVM_DEV_LOONGARCH_EXTIOI_SW_STATUS_NUM_CPU:
+ if (is_write)
+@@ -945,13 +943,10 @@ static int kvm_eiointc_sw_status_access(struct kvm_device *dev,
+ return -EINVAL;
+ }
+ spin_lock_irqsave(&s->lock, flags);
+- if (is_write) {
+- if (copy_from_user(p, data, 4))
+- ret = -EFAULT;
+- } else {
+- if (copy_to_user(data, p, 4))
+- ret = -EFAULT;
+- }
++ if (is_write)
++ memcpy(p, data, 4);
++ else
++ memcpy(data, p, 4);
+ spin_unlock_irqrestore(&s->lock, flags);
+
+ return ret;
+@@ -960,11 +955,27 @@ static int kvm_eiointc_sw_status_access(struct kvm_device *dev,
+ static int kvm_eiointc_get_attr(struct kvm_device *dev,
+ struct kvm_device_attr *attr)
+ {
++ int ret, data;
++
+ switch (attr->group) {
+ case KVM_DEV_LOONGARCH_EXTIOI_GRP_REGS:
+- return kvm_eiointc_regs_access(dev, attr, false);
++ ret = kvm_eiointc_regs_access(dev, attr, false, &data);
++ if (ret)
++ return ret;
++
++ if (copy_to_user((void __user *)attr->addr, &data, 4))
++ ret = -EFAULT;
++
++ return ret;
+ case KVM_DEV_LOONGARCH_EXTIOI_GRP_SW_STATUS:
+- return kvm_eiointc_sw_status_access(dev, attr, false);
++ ret = kvm_eiointc_sw_status_access(dev, attr, false, &data);
++ if (ret)
++ return ret;
++
++ if (copy_to_user((void __user *)attr->addr, &data, 4))
++ ret = -EFAULT;
++
++ return ret;
+ default:
+ return -EINVAL;
+ }
+@@ -973,13 +984,21 @@ static int kvm_eiointc_get_attr(struct kvm_device *dev,
+ static int kvm_eiointc_set_attr(struct kvm_device *dev,
+ struct kvm_device_attr *attr)
+ {
++ int data;
++
+ switch (attr->group) {
+ case KVM_DEV_LOONGARCH_EXTIOI_GRP_CTRL:
+ return kvm_eiointc_ctrl_access(dev, attr);
+ case KVM_DEV_LOONGARCH_EXTIOI_GRP_REGS:
+- return kvm_eiointc_regs_access(dev, attr, true);
++ if (copy_from_user(&data, (void __user *)attr->addr, 4))
++ return -EFAULT;
++
++ return kvm_eiointc_regs_access(dev, attr, true, &data);
+ case KVM_DEV_LOONGARCH_EXTIOI_GRP_SW_STATUS:
+- return kvm_eiointc_sw_status_access(dev, attr, true);
++ if (copy_from_user(&data, (void __user *)attr->addr, 4))
++ return -EFAULT;
++
++ return kvm_eiointc_sw_status_access(dev, attr, true, &data);
+ default:
+ return -EINVAL;
+ }
+diff --git a/arch/loongarch/kvm/intc/pch_pic.c b/arch/loongarch/kvm/intc/pch_pic.c
+index ef5044796b7a6e..52f19dcf6b8814 100644
+--- a/arch/loongarch/kvm/intc/pch_pic.c
++++ b/arch/loongarch/kvm/intc/pch_pic.c
+@@ -348,6 +348,7 @@ static int kvm_pch_pic_regs_access(struct kvm_device *dev,
+ struct kvm_device_attr *attr,
+ bool is_write)
+ {
++ char buf[8];
+ int addr, offset, len = 8, ret = 0;
+ void __user *data;
+ void *p = NULL;
+@@ -397,17 +398,23 @@ static int kvm_pch_pic_regs_access(struct kvm_device *dev,
+ return -EINVAL;
+ }
+
+- spin_lock(&s->lock);
+- /* write or read value according to is_write */
+ if (is_write) {
+- if (copy_from_user(p, data, len))
+- ret = -EFAULT;
+- } else {
+- if (copy_to_user(data, p, len))
+- ret = -EFAULT;
++ if (copy_from_user(buf, data, len))
++ return -EFAULT;
+ }
++
++ spin_lock(&s->lock);
++ if (is_write)
++ memcpy(p, buf, len);
++ else
++ memcpy(buf, p, len);
+ spin_unlock(&s->lock);
+
++ if (!is_write) {
++ if (copy_to_user(data, buf, len))
++ return -EFAULT;
++ }
++
+ return ret;
+ }
+
+diff --git a/arch/loongarch/kvm/mmu.c b/arch/loongarch/kvm/mmu.c
+index ed956c5cf2cc04..7c8143e79c1279 100644
+--- a/arch/loongarch/kvm/mmu.c
++++ b/arch/loongarch/kvm/mmu.c
+@@ -569,7 +569,7 @@ static int kvm_map_page_fast(struct kvm_vcpu *vcpu, unsigned long gpa, bool writ
+ /* Track access to pages marked old */
+ new = kvm_pte_mkyoung(*ptep);
+ if (write && !kvm_pte_dirty(new)) {
+- if (!kvm_pte_write(new)) {
++ if (!kvm_pte_writeable(new)) {
+ ret = -EFAULT;
+ goto out;
+ }
+@@ -856,9 +856,9 @@ static int kvm_map_page(struct kvm_vcpu *vcpu, unsigned long gpa, bool write)
+ prot_bits |= _CACHE_SUC;
+
+ if (writeable) {
+- prot_bits |= _PAGE_WRITE;
++ prot_bits = kvm_pte_mkwriteable(prot_bits);
+ if (write)
+- prot_bits |= __WRITEABLE;
++ prot_bits = kvm_pte_mkdirty(prot_bits);
+ }
+
+ /* Disable dirty logging on HugePages */
+@@ -904,7 +904,7 @@ static int kvm_map_page(struct kvm_vcpu *vcpu, unsigned long gpa, bool write)
+ kvm_release_faultin_page(kvm, page, false, writeable);
+ spin_unlock(&kvm->mmu_lock);
+
+- if (prot_bits & _PAGE_DIRTY)
++ if (kvm_pte_dirty(prot_bits))
+ mark_page_dirty_in_slot(kvm, memslot, gfn);
+
+ out:
+diff --git a/arch/s390/include/asm/pci_insn.h b/arch/s390/include/asm/pci_insn.h
+index e5f57cfe1d4582..025c6dcbf89331 100644
+--- a/arch/s390/include/asm/pci_insn.h
++++ b/arch/s390/include/asm/pci_insn.h
+@@ -16,11 +16,11 @@
+ #define ZPCI_PCI_ST_FUNC_NOT_AVAIL 40
+ #define ZPCI_PCI_ST_ALREADY_IN_RQ_STATE 44
+
+-/* Load/Store return codes */
+-#define ZPCI_PCI_LS_OK 0
+-#define ZPCI_PCI_LS_ERR 1
+-#define ZPCI_PCI_LS_BUSY 2
+-#define ZPCI_PCI_LS_INVAL_HANDLE 3
++/* PCI instruction condition codes */
++#define ZPCI_CC_OK 0
++#define ZPCI_CC_ERR 1
++#define ZPCI_CC_BUSY 2
++#define ZPCI_CC_INVAL_HANDLE 3
+
+ /* Load/Store address space identifiers */
+ #define ZPCI_PCIAS_MEMIO_0 0
+diff --git a/arch/um/drivers/virtio_uml.c b/arch/um/drivers/virtio_uml.c
+index ad8d78fb1d9aaf..de7867ae220d0c 100644
+--- a/arch/um/drivers/virtio_uml.c
++++ b/arch/um/drivers/virtio_uml.c
+@@ -1250,10 +1250,12 @@ static int virtio_uml_probe(struct platform_device *pdev)
+ device_set_wakeup_capable(&vu_dev->vdev.dev, true);
+
+ rc = register_virtio_device(&vu_dev->vdev);
+- if (rc)
++ if (rc) {
+ put_device(&vu_dev->vdev.dev);
++ return rc;
++ }
+ vu_dev->registered = 1;
+- return rc;
++ return 0;
+
+ error_init:
+ os_close_file(vu_dev->sock);
+diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c
+index 617886d1fb1e91..21f0e50fb1df95 100644
+--- a/arch/um/os-Linux/file.c
++++ b/arch/um/os-Linux/file.c
+@@ -535,7 +535,7 @@ ssize_t os_rcv_fd_msg(int fd, int *fds, unsigned int n_fds,
+ cmsg->cmsg_type != SCM_RIGHTS)
+ return n;
+
+- memcpy(fds, CMSG_DATA(cmsg), cmsg->cmsg_len);
++ memcpy(fds, CMSG_DATA(cmsg), cmsg->cmsg_len - CMSG_LEN(0));
+ return n;
+ }
+
+diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
+index 14d7e0719dd5ee..8d0dfd20ac2823 100644
+--- a/arch/x86/include/asm/sev.h
++++ b/arch/x86/include/asm/sev.h
+@@ -564,6 +564,24 @@ enum es_result sev_es_ghcb_hv_call(struct ghcb *ghcb,
+
+ extern struct ghcb *boot_ghcb;
+
++static inline void sev_evict_cache(void *va, int npages)
++{
++ volatile u8 val __always_unused;
++ u8 *bytes = va;
++ int page_idx;
++
++ /*
++ * For SEV guests, a read from the first/last cache-lines of a 4K page
++ * using the guest key is sufficient to cause a flush of all cache-lines
++ * associated with that 4K page without incurring all the overhead of a
++ * full CLFLUSH sequence.
++ */
++ for (page_idx = 0; page_idx < npages; page_idx++) {
++ val = bytes[page_idx * PAGE_SIZE];
++ val = bytes[page_idx * PAGE_SIZE + PAGE_SIZE - 1];
++ }
++}
++
+ #else /* !CONFIG_AMD_MEM_ENCRYPT */
+
+ #define snp_vmpl 0
+@@ -607,6 +625,7 @@ static inline int snp_send_guest_request(struct snp_msg_desc *mdesc, struct snp_
+ static inline int snp_svsm_vtpm_send_command(u8 *buffer) { return -ENODEV; }
+ static inline void __init snp_secure_tsc_prepare(void) { }
+ static inline void __init snp_secure_tsc_init(void) { }
++static inline void sev_evict_cache(void *va, int npages) {}
+
+ #endif /* CONFIG_AMD_MEM_ENCRYPT */
+
+@@ -621,24 +640,6 @@ int rmp_make_shared(u64 pfn, enum pg_level level);
+ void snp_leak_pages(u64 pfn, unsigned int npages);
+ void kdump_sev_callback(void);
+ void snp_fixup_e820_tables(void);
+-
+-static inline void sev_evict_cache(void *va, int npages)
+-{
+- volatile u8 val __always_unused;
+- u8 *bytes = va;
+- int page_idx;
+-
+- /*
+- * For SEV guests, a read from the first/last cache-lines of a 4K page
+- * using the guest key is sufficient to cause a flush of all cache-lines
+- * associated with that 4K page without incurring all the overhead of a
+- * full CLFLUSH sequence.
+- */
+- for (page_idx = 0; page_idx < npages; page_idx++) {
+- val = bytes[page_idx * PAGE_SIZE];
+- val = bytes[page_idx * PAGE_SIZE + PAGE_SIZE - 1];
+- }
+-}
+ #else
+ static inline bool snp_probe_rmptable_info(void) { return false; }
+ static inline int snp_rmptable_init(void) { return -ENOSYS; }
+@@ -654,7 +655,6 @@ static inline int rmp_make_shared(u64 pfn, enum pg_level level) { return -ENODEV
+ static inline void snp_leak_pages(u64 pfn, unsigned int npages) {}
+ static inline void kdump_sev_callback(void) { }
+ static inline void snp_fixup_e820_tables(void) {}
+-static inline void sev_evict_cache(void *va, int npages) {}
+ #endif
+
+ #endif
+diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
+index be8c43049f4d39..268d62fa28b824 100644
+--- a/arch/x86/kvm/svm/svm.c
++++ b/arch/x86/kvm/svm/svm.c
+@@ -4204,8 +4204,7 @@ static inline void sync_lapic_to_cr8(struct kvm_vcpu *vcpu)
+ struct vcpu_svm *svm = to_svm(vcpu);
+ u64 cr8;
+
+- if (nested_svm_virtualize_tpr(vcpu) ||
+- kvm_vcpu_apicv_active(vcpu))
++ if (nested_svm_virtualize_tpr(vcpu))
+ return;
+
+ cr8 = kvm_get_cr8(vcpu);
+diff --git a/crypto/af_alg.c b/crypto/af_alg.c
+index 0da7c1ac778a0e..ca6fdcc6c54aca 100644
+--- a/crypto/af_alg.c
++++ b/crypto/af_alg.c
+@@ -970,6 +970,12 @@ int af_alg_sendmsg(struct socket *sock, struct msghdr *msg, size_t size,
+ }
+
+ lock_sock(sk);
++ if (ctx->write) {
++ release_sock(sk);
++ return -EBUSY;
++ }
++ ctx->write = true;
++
+ if (ctx->init && !ctx->more) {
+ if (ctx->used) {
+ err = -EINVAL;
+@@ -1019,6 +1025,8 @@ int af_alg_sendmsg(struct socket *sock, struct msghdr *msg, size_t size,
+ continue;
+ }
+
++ ctx->merge = 0;
++
+ if (!af_alg_writable(sk)) {
+ err = af_alg_wait_for_wmem(sk, msg->msg_flags);
+ if (err)
+@@ -1058,7 +1066,6 @@ int af_alg_sendmsg(struct socket *sock, struct msghdr *msg, size_t size,
+ ctx->used += plen;
+ copied += plen;
+ size -= plen;
+- ctx->merge = 0;
+ } else {
+ do {
+ struct page *pg;
+@@ -1104,6 +1111,7 @@ int af_alg_sendmsg(struct socket *sock, struct msghdr *msg, size_t size,
+
+ unlock:
+ af_alg_data_wakeup(sk);
++ ctx->write = false;
+ release_sock(sk);
+
+ return copied ?: err;
+diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
+index 54c57103715f9b..0f7bcc86b6f724 100644
+--- a/drivers/block/zram/zram_drv.c
++++ b/drivers/block/zram/zram_drv.c
+@@ -1794,6 +1794,7 @@ static int write_same_filled_page(struct zram *zram, unsigned long fill,
+ u32 index)
+ {
+ zram_slot_lock(zram, index);
++ zram_free_page(zram, index);
+ zram_set_flag(zram, index, ZRAM_SAME);
+ zram_set_handle(zram, index, fill);
+ zram_slot_unlock(zram, index);
+@@ -1831,6 +1832,7 @@ static int write_incompressible_page(struct zram *zram, struct page *page,
+ kunmap_local(src);
+
+ zram_slot_lock(zram, index);
++ zram_free_page(zram, index);
+ zram_set_flag(zram, index, ZRAM_HUGE);
+ zram_set_handle(zram, index, handle);
+ zram_set_obj_size(zram, index, PAGE_SIZE);
+@@ -1854,11 +1856,6 @@ static int zram_write_page(struct zram *zram, struct page *page, u32 index)
+ unsigned long element;
+ bool same_filled;
+
+- /* First, free memory allocated to this slot (if any) */
+- zram_slot_lock(zram, index);
+- zram_free_page(zram, index);
+- zram_slot_unlock(zram, index);
+-
+ mem = kmap_local_page(page);
+ same_filled = page_same_filled(mem, &element);
+ kunmap_local(mem);
+@@ -1900,6 +1897,7 @@ static int zram_write_page(struct zram *zram, struct page *page, u32 index)
+ zcomp_stream_put(zstrm);
+
+ zram_slot_lock(zram, index);
++ zram_free_page(zram, index);
+ zram_set_handle(zram, index, handle);
+ zram_set_obj_size(zram, index, comp_len);
+ zram_slot_unlock(zram, index);
+diff --git a/drivers/clk/sunxi-ng/ccu_mp.c b/drivers/clk/sunxi-ng/ccu_mp.c
+index 354c981943b6f8..4221b1888b38da 100644
+--- a/drivers/clk/sunxi-ng/ccu_mp.c
++++ b/drivers/clk/sunxi-ng/ccu_mp.c
+@@ -185,7 +185,7 @@ static unsigned long ccu_mp_recalc_rate(struct clk_hw *hw,
+ p &= (1 << cmp->p.width) - 1;
+
+ if (cmp->common.features & CCU_FEATURE_DUAL_DIV)
+- rate = (parent_rate / p) / m;
++ rate = (parent_rate / (p + cmp->p.offset)) / m;
+ else
+ rate = (parent_rate >> p) / m;
+
+diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c
+index e058ba02779296..9f5ccc1720cbc1 100644
+--- a/drivers/crypto/ccp/sev-dev.c
++++ b/drivers/crypto/ccp/sev-dev.c
+@@ -2430,7 +2430,7 @@ static void __sev_firmware_shutdown(struct sev_device *sev, bool panic)
+ {
+ int error;
+
+- __sev_platform_shutdown_locked(NULL);
++ __sev_platform_shutdown_locked(&error);
+
+ if (sev_es_tmr) {
+ /*
+diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
+index c130f87147fa3f..815de752bcd384 100644
+--- a/drivers/dpll/dpll_netlink.c
++++ b/drivers/dpll/dpll_netlink.c
+@@ -173,8 +173,8 @@ static int
+ dpll_msg_add_clock_quality_level(struct sk_buff *msg, struct dpll_device *dpll,
+ struct netlink_ext_ack *extack)
+ {
++ DECLARE_BITMAP(qls, DPLL_CLOCK_QUALITY_LEVEL_MAX + 1) = { 0 };
+ const struct dpll_device_ops *ops = dpll_device_ops(dpll);
+- DECLARE_BITMAP(qls, DPLL_CLOCK_QUALITY_LEVEL_MAX) = { 0 };
+ enum dpll_clock_quality_level ql;
+ int ret;
+
+@@ -183,7 +183,7 @@ dpll_msg_add_clock_quality_level(struct sk_buff *msg, struct dpll_device *dpll,
+ ret = ops->clock_quality_level_get(dpll, dpll_priv(dpll), qls, extack);
+ if (ret)
+ return ret;
+- for_each_set_bit(ql, qls, DPLL_CLOCK_QUALITY_LEVEL_MAX)
++ for_each_set_bit(ql, qls, DPLL_CLOCK_QUALITY_LEVEL_MAX + 1)
+ if (nla_put_u32(msg, DPLL_A_CLOCK_QUALITY_LEVEL, ql))
+ return -EMSGSIZE;
+
+diff --git a/drivers/gpio/gpiolib-acpi-core.c b/drivers/gpio/gpiolib-acpi-core.c
+index 12b24a717e43f1..d11bcaf1ae8842 100644
+--- a/drivers/gpio/gpiolib-acpi-core.c
++++ b/drivers/gpio/gpiolib-acpi-core.c
+@@ -942,7 +942,7 @@ struct gpio_desc *acpi_find_gpio(struct fwnode_handle *fwnode,
+ {
+ struct acpi_device *adev = to_acpi_device_node(fwnode);
+ bool can_fallback = acpi_can_fallback_to_crs(adev, con_id);
+- struct acpi_gpio_info info;
++ struct acpi_gpio_info info = {};
+ struct gpio_desc *desc;
+
+ desc = __acpi_find_gpio(fwnode, con_id, idx, can_fallback, &info);
+@@ -992,7 +992,7 @@ int acpi_dev_gpio_irq_wake_get_by(struct acpi_device *adev, const char *con_id,
+ int ret;
+
+ for (i = 0, idx = 0; idx <= index; i++) {
+- struct acpi_gpio_info info;
++ struct acpi_gpio_info info = {};
+ struct gpio_desc *desc;
+
+ /* Ignore -EPROBE_DEFER, it only matters if idx matches */
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
+index fe282b85573414..31010040a12f04 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
+@@ -250,16 +250,24 @@ void amdgpu_amdkfd_interrupt(struct amdgpu_device *adev,
+
+ void amdgpu_amdkfd_suspend(struct amdgpu_device *adev, bool suspend_proc)
+ {
+- if (adev->kfd.dev)
+- kgd2kfd_suspend(adev->kfd.dev, suspend_proc);
++ if (adev->kfd.dev) {
++ if (adev->in_s0ix)
++ kgd2kfd_stop_sched_all_nodes(adev->kfd.dev);
++ else
++ kgd2kfd_suspend(adev->kfd.dev, suspend_proc);
++ }
+ }
+
+ int amdgpu_amdkfd_resume(struct amdgpu_device *adev, bool resume_proc)
+ {
+ int r = 0;
+
+- if (adev->kfd.dev)
+- r = kgd2kfd_resume(adev->kfd.dev, resume_proc);
++ if (adev->kfd.dev) {
++ if (adev->in_s0ix)
++ r = kgd2kfd_start_sched_all_nodes(adev->kfd.dev);
++ else
++ r = kgd2kfd_resume(adev->kfd.dev, resume_proc);
++ }
+
+ return r;
+ }
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
+index b7c3ec48340721..861697490ac2e3 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
+@@ -426,7 +426,9 @@ void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint64_t throttle_bitmask);
+ int kgd2kfd_check_and_lock_kfd(void);
+ void kgd2kfd_unlock_kfd(void);
+ int kgd2kfd_start_sched(struct kfd_dev *kfd, uint32_t node_id);
++int kgd2kfd_start_sched_all_nodes(struct kfd_dev *kfd);
+ int kgd2kfd_stop_sched(struct kfd_dev *kfd, uint32_t node_id);
++int kgd2kfd_stop_sched_all_nodes(struct kfd_dev *kfd);
+ bool kgd2kfd_compute_active(struct kfd_dev *kfd, uint32_t node_id);
+ bool kgd2kfd_vmfault_fast_path(struct amdgpu_device *adev, struct amdgpu_iv_entry *entry,
+ bool retry_fault);
+@@ -516,11 +518,21 @@ static inline int kgd2kfd_start_sched(struct kfd_dev *kfd, uint32_t node_id)
+ return 0;
+ }
+
++static inline int kgd2kfd_start_sched_all_nodes(struct kfd_dev *kfd)
++{
++ return 0;
++}
++
+ static inline int kgd2kfd_stop_sched(struct kfd_dev *kfd, uint32_t node_id)
+ {
+ return 0;
+ }
+
++static inline int kgd2kfd_stop_sched_all_nodes(struct kfd_dev *kfd)
++{
++ return 0;
++}
++
+ static inline bool kgd2kfd_compute_active(struct kfd_dev *kfd, uint32_t node_id)
+ {
+ return false;
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+index a57e8c5474bb00..a65591f70b15d8 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+@@ -5055,7 +5055,7 @@ int amdgpu_device_suspend(struct drm_device *dev, bool notify_clients)
+ adev->in_suspend = true;
+
+ if (amdgpu_sriov_vf(adev)) {
+- if (!adev->in_s0ix && !adev->in_runpm)
++ if (!adev->in_runpm)
+ amdgpu_amdkfd_suspend_process(adev);
+ amdgpu_virt_fini_data_exchange(adev);
+ r = amdgpu_virt_request_full_gpu(adev, false);
+@@ -5075,10 +5075,8 @@ int amdgpu_device_suspend(struct drm_device *dev, bool notify_clients)
+
+ amdgpu_device_ip_suspend_phase1(adev);
+
+- if (!adev->in_s0ix) {
+- amdgpu_amdkfd_suspend(adev, !amdgpu_sriov_vf(adev) && !adev->in_runpm);
+- amdgpu_userq_suspend(adev);
+- }
++ amdgpu_amdkfd_suspend(adev, !amdgpu_sriov_vf(adev) && !adev->in_runpm);
++ amdgpu_userq_suspend(adev);
+
+ r = amdgpu_device_evict_resources(adev);
+ if (r)
+@@ -5141,15 +5139,13 @@ int amdgpu_device_resume(struct drm_device *dev, bool notify_clients)
+ goto exit;
+ }
+
+- if (!adev->in_s0ix) {
+- r = amdgpu_amdkfd_resume(adev, !amdgpu_sriov_vf(adev) && !adev->in_runpm);
+- if (r)
+- goto exit;
++ r = amdgpu_amdkfd_resume(adev, !amdgpu_sriov_vf(adev) && !adev->in_runpm);
++ if (r)
++ goto exit;
+
+- r = amdgpu_userq_resume(adev);
+- if (r)
+- goto exit;
+- }
++ r = amdgpu_userq_resume(adev);
++ if (r)
++ goto exit;
+
+ r = amdgpu_device_ip_late_init(adev);
+ if (r)
+@@ -5162,7 +5158,7 @@ int amdgpu_device_resume(struct drm_device *dev, bool notify_clients)
+ amdgpu_virt_init_data_exchange(adev);
+ amdgpu_virt_release_full_gpu(adev, true);
+
+- if (!adev->in_s0ix && !r && !adev->in_runpm)
++ if (!r && !adev->in_runpm)
+ r = amdgpu_amdkfd_resume_process(adev);
+ }
+
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c
+index 097bf675378273..f512879cb71c65 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c
+@@ -1501,6 +1501,25 @@ int kgd2kfd_start_sched(struct kfd_dev *kfd, uint32_t node_id)
+ return ret;
+ }
+
++int kgd2kfd_start_sched_all_nodes(struct kfd_dev *kfd)
++{
++ struct kfd_node *node;
++ int i, r;
++
++ if (!kfd->init_complete)
++ return 0;
++
++ for (i = 0; i < kfd->num_nodes; i++) {
++ node = kfd->nodes[i];
++ r = node->dqm->ops.unhalt(node->dqm);
++ if (r) {
++ dev_err(kfd_device, "Error in starting scheduler\n");
++ return r;
++ }
++ }
++ return 0;
++}
++
+ int kgd2kfd_stop_sched(struct kfd_dev *kfd, uint32_t node_id)
+ {
+ struct kfd_node *node;
+@@ -1518,6 +1537,23 @@ int kgd2kfd_stop_sched(struct kfd_dev *kfd, uint32_t node_id)
+ return node->dqm->ops.halt(node->dqm);
+ }
+
++int kgd2kfd_stop_sched_all_nodes(struct kfd_dev *kfd)
++{
++ struct kfd_node *node;
++ int i, r;
++
++ if (!kfd->init_complete)
++ return 0;
++
++ for (i = 0; i < kfd->num_nodes; i++) {
++ node = kfd->nodes[i];
++ r = node->dqm->ops.halt(node->dqm);
++ if (r)
++ return r;
++ }
++ return 0;
++}
++
+ bool kgd2kfd_compute_active(struct kfd_dev *kfd, uint32_t node_id)
+ {
+ struct kfd_node *node;
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+index 312f6075e39d11..58ea351dd48b5d 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -8689,7 +8689,16 @@ static int amdgpu_dm_encoder_init(struct drm_device *dev,
+ static void manage_dm_interrupts(struct amdgpu_device *adev,
+ struct amdgpu_crtc *acrtc,
+ struct dm_crtc_state *acrtc_state)
+-{
++{ /*
++ * We cannot be sure that the frontend index maps to the same
++ * backend index - some even map to more than one.
++ * So we have to go through the CRTC to find the right IRQ.
++ */
++ int irq_type = amdgpu_display_crtc_idx_to_irq_type(
++ adev,
++ acrtc->crtc_id);
++ struct drm_device *dev = adev_to_drm(adev);
++
+ struct drm_vblank_crtc_config config = {0};
+ struct dc_crtc_timing *timing;
+ int offdelay;
+@@ -8742,7 +8751,35 @@ static void manage_dm_interrupts(struct amdgpu_device *adev,
+
+ drm_crtc_vblank_on_config(&acrtc->base,
+ &config);
++ /* Allow RX6xxx, RX7700, RX7800 GPUs to call amdgpu_irq_get.*/
++ switch (amdgpu_ip_version(adev, DCE_HWIP, 0)) {
++ case IP_VERSION(3, 0, 0):
++ case IP_VERSION(3, 0, 2):
++ case IP_VERSION(3, 0, 3):
++ case IP_VERSION(3, 2, 0):
++ if (amdgpu_irq_get(adev, &adev->pageflip_irq, irq_type))
++ drm_err(dev, "DM_IRQ: Cannot get pageflip irq!\n");
++#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
++ if (amdgpu_irq_get(adev, &adev->vline0_irq, irq_type))
++ drm_err(dev, "DM_IRQ: Cannot get vline0 irq!\n");
++#endif
++ }
++
+ } else {
++ /* Allow RX6xxx, RX7700, RX7800 GPUs to call amdgpu_irq_put.*/
++ switch (amdgpu_ip_version(adev, DCE_HWIP, 0)) {
++ case IP_VERSION(3, 0, 0):
++ case IP_VERSION(3, 0, 2):
++ case IP_VERSION(3, 0, 3):
++ case IP_VERSION(3, 2, 0):
++#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
++ if (amdgpu_irq_put(adev, &adev->vline0_irq, irq_type))
++ drm_err(dev, "DM_IRQ: Cannot put vline0 irq!\n");
++#endif
++ if (amdgpu_irq_put(adev, &adev->pageflip_irq, irq_type))
++ drm_err(dev, "DM_IRQ: Cannot put pageflip irq!\n");
++ }
++
+ drm_crtc_vblank_off(&acrtc->base);
+ }
+ }
+diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+index 26b8e232f85825..2278a123db23f9 100644
+--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+@@ -2185,7 +2185,7 @@ static int smu_resume(struct amdgpu_ip_block *ip_block)
+ return ret;
+ }
+
+- if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) {
++ if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL && smu->od_enabled) {
+ ret = smu_od_edit_dpm_table(smu, PP_OD_COMMIT_DPM_TABLE, NULL, 0);
+ if (ret)
+ return ret;
+diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
+index 8a9079c2ed5c22..8257132a8ee9d2 100644
+--- a/drivers/gpu/drm/bridge/analogix/anx7625.c
++++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
+@@ -2678,7 +2678,7 @@ static int anx7625_i2c_probe(struct i2c_client *client)
+ ret = devm_request_threaded_irq(dev, platform->pdata.intp_irq,
+ NULL, anx7625_intr_hpd_isr,
+ IRQF_TRIGGER_FALLING |
+- IRQF_ONESHOT,
++ IRQF_ONESHOT | IRQF_NO_AUTOEN,
+ "anx7625-intp", platform);
+ if (ret) {
+ DRM_DEV_ERROR(dev, "fail to request irq\n");
+@@ -2747,8 +2747,10 @@ static int anx7625_i2c_probe(struct i2c_client *client)
+ }
+
+ /* Add work function */
+- if (platform->pdata.intp_irq)
++ if (platform->pdata.intp_irq) {
++ enable_irq(platform->pdata.intp_irq);
+ queue_work(platform->workqueue, &platform->work);
++ }
+
+ if (platform->pdata.audio_en)
+ anx7625_register_audio(dev, platform);
+diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
+index b431e7efd1f0d7..dbef0ca1a22a38 100644
+--- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
++++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
+@@ -1984,8 +1984,10 @@ static void cdns_mhdp_atomic_enable(struct drm_bridge *bridge,
+ mhdp_state = to_cdns_mhdp_bridge_state(new_state);
+
+ mhdp_state->current_mode = drm_mode_duplicate(bridge->dev, mode);
+- if (!mhdp_state->current_mode)
+- return;
++ if (!mhdp_state->current_mode) {
++ ret = -EINVAL;
++ goto out;
++ }
+
+ drm_mode_set_name(mhdp_state->current_mode);
+
+diff --git a/drivers/gpu/drm/xe/abi/guc_actions_abi.h b/drivers/gpu/drm/xe/abi/guc_actions_abi.h
+index 448afb86e05c7d..4d9896e14649c0 100644
+--- a/drivers/gpu/drm/xe/abi/guc_actions_abi.h
++++ b/drivers/gpu/drm/xe/abi/guc_actions_abi.h
+@@ -117,6 +117,7 @@ enum xe_guc_action {
+ XE_GUC_ACTION_ENTER_S_STATE = 0x501,
+ XE_GUC_ACTION_EXIT_S_STATE = 0x502,
+ XE_GUC_ACTION_GLOBAL_SCHED_POLICY_CHANGE = 0x506,
++ XE_GUC_ACTION_UPDATE_SCHEDULING_POLICIES_KLV = 0x509,
+ XE_GUC_ACTION_SCHED_CONTEXT = 0x1000,
+ XE_GUC_ACTION_SCHED_CONTEXT_MODE_SET = 0x1001,
+ XE_GUC_ACTION_SCHED_CONTEXT_MODE_DONE = 0x1002,
+@@ -142,6 +143,7 @@ enum xe_guc_action {
+ XE_GUC_ACTION_SET_ENG_UTIL_BUFF = 0x550A,
+ XE_GUC_ACTION_SET_DEVICE_ENGINE_ACTIVITY_BUFFER = 0x550C,
+ XE_GUC_ACTION_SET_FUNCTION_ENGINE_ACTIVITY_BUFFER = 0x550D,
++ XE_GUC_ACTION_OPT_IN_FEATURE_KLV = 0x550E,
+ XE_GUC_ACTION_NOTIFY_MEMORY_CAT_ERROR = 0x6000,
+ XE_GUC_ACTION_REPORT_PAGE_FAULT_REQ_DESC = 0x6002,
+ XE_GUC_ACTION_PAGE_FAULT_RES_DESC = 0x6003,
+@@ -240,4 +242,7 @@ enum xe_guc_g2g_type {
+ #define XE_G2G_DEREGISTER_TILE REG_GENMASK(15, 12)
+ #define XE_G2G_DEREGISTER_TYPE REG_GENMASK(11, 8)
+
++/* invalid type for XE_GUC_ACTION_NOTIFY_MEMORY_CAT_ERROR */
++#define XE_GUC_CAT_ERR_TYPE_INVALID 0xdeadbeef
++
+ #endif
+diff --git a/drivers/gpu/drm/xe/abi/guc_klvs_abi.h b/drivers/gpu/drm/xe/abi/guc_klvs_abi.h
+index 7de8f827281fcd..89034bc97ec5a4 100644
+--- a/drivers/gpu/drm/xe/abi/guc_klvs_abi.h
++++ b/drivers/gpu/drm/xe/abi/guc_klvs_abi.h
+@@ -16,6 +16,8 @@
+ * +===+=======+==============================================================+
+ * | 0 | 31:16 | **KEY** - KLV key identifier |
+ * | | | - `GuC Self Config KLVs`_ |
++ * | | | - `GuC Opt In Feature KLVs`_ |
++ * | | | - `GuC Scheduling Policies KLVs`_ |
+ * | | | - `GuC VGT Policy KLVs`_ |
+ * | | | - `GuC VF Configuration KLVs`_ |
+ * | | | |
+@@ -124,6 +126,44 @@ enum {
+ GUC_CONTEXT_POLICIES_KLV_NUM_IDS = 5,
+ };
+
++/**
++ * DOC: GuC Opt In Feature KLVs
++ *
++ * `GuC KLV`_ keys available for use with OPT_IN_FEATURE_KLV
++ *
++ * _`GUC_KLV_OPT_IN_FEATURE_EXT_CAT_ERR_TYPE` : 0x4001
++ * Adds an extra dword to the XE_GUC_ACTION_NOTIFY_MEMORY_CAT_ERROR G2H
++ * containing the type of the CAT error. On HW that does not support
++ * reporting the CAT error type, the extra dword is set to 0xdeadbeef.
++ */
++
++#define GUC_KLV_OPT_IN_FEATURE_EXT_CAT_ERR_TYPE_KEY 0x4001
++#define GUC_KLV_OPT_IN_FEATURE_EXT_CAT_ERR_TYPE_LEN 0u
++
++/**
++ * DOC: GuC Scheduling Policies KLVs
++ *
++ * `GuC KLV`_ keys available for use with UPDATE_SCHEDULING_POLICIES_KLV.
++ *
++ * _`GUC_KLV_SCHEDULING_POLICIES_RENDER_COMPUTE_YIELD` : 0x1001
++ * Some platforms do not allow concurrent execution of RCS and CCS
++ * workloads from different address spaces. By default, the GuC prioritizes
++ * RCS submissions over CCS ones, which can lead to CCS workloads being
++ * significantly (or completely) starved of execution time. This KLV allows
++ * the driver to specify a quantum (in ms) and a ratio (percentage value
++ * between 0 and 100), and the GuC will prioritize the CCS for that
++ * percentage of each quantum. For example, specifying 100ms and 30% will
++ * make the GuC prioritize the CCS for 30ms of every 100ms.
++ * Note that this does not necessarly mean that RCS and CCS engines will
++ * only be active for their percentage of the quantum, as the restriction
++ * only kicks in if both classes are fully busy with non-compatible address
++ * spaces; i.e., if one engine is idle or running the same address space,
++ * a pending job on the other engine will still be submitted to the HW no
++ * matter what the ratio is
++ */
++#define GUC_KLV_SCHEDULING_POLICIES_RENDER_COMPUTE_YIELD_KEY 0x1001
++#define GUC_KLV_SCHEDULING_POLICIES_RENDER_COMPUTE_YIELD_LEN 2u
++
+ /**
+ * DOC: GuC VGT Policy KLVs
+ *
+diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c
+index fee22358cc09be..e5116975961461 100644
+--- a/drivers/gpu/drm/xe/xe_exec_queue.c
++++ b/drivers/gpu/drm/xe/xe_exec_queue.c
+@@ -151,6 +151,16 @@ static int __xe_exec_queue_init(struct xe_exec_queue *q)
+ return err;
+ }
+
++static void __xe_exec_queue_fini(struct xe_exec_queue *q)
++{
++ int i;
++
++ q->ops->fini(q);
++
++ for (i = 0; i < q->width; ++i)
++ xe_lrc_put(q->lrc[i]);
++}
++
+ struct xe_exec_queue *xe_exec_queue_create(struct xe_device *xe, struct xe_vm *vm,
+ u32 logical_mask, u16 width,
+ struct xe_hw_engine *hwe, u32 flags,
+@@ -181,11 +191,13 @@ struct xe_exec_queue *xe_exec_queue_create(struct xe_device *xe, struct xe_vm *v
+ if (xe_exec_queue_uses_pxp(q)) {
+ err = xe_pxp_exec_queue_add(xe->pxp, q);
+ if (err)
+- goto err_post_alloc;
++ goto err_post_init;
+ }
+
+ return q;
+
++err_post_init:
++ __xe_exec_queue_fini(q);
+ err_post_alloc:
+ __xe_exec_queue_free(q);
+ return ERR_PTR(err);
+@@ -283,13 +295,11 @@ void xe_exec_queue_destroy(struct kref *ref)
+ xe_exec_queue_put(eq);
+ }
+
+- q->ops->fini(q);
++ q->ops->destroy(q);
+ }
+
+ void xe_exec_queue_fini(struct xe_exec_queue *q)
+ {
+- int i;
+-
+ /*
+ * Before releasing our ref to lrc and xef, accumulate our run ticks
+ * and wakeup any waiters.
+@@ -298,9 +308,7 @@ void xe_exec_queue_fini(struct xe_exec_queue *q)
+ if (q->xef && atomic_dec_and_test(&q->xef->exec_queue.pending_removal))
+ wake_up_var(&q->xef->exec_queue.pending_removal);
+
+- for (i = 0; i < q->width; ++i)
+- xe_lrc_put(q->lrc[i]);
+-
++ __xe_exec_queue_fini(q);
+ __xe_exec_queue_free(q);
+ }
+
+diff --git a/drivers/gpu/drm/xe/xe_exec_queue_types.h b/drivers/gpu/drm/xe/xe_exec_queue_types.h
+index cc1cffb5c87f1d..1c9d03f2a3e5da 100644
+--- a/drivers/gpu/drm/xe/xe_exec_queue_types.h
++++ b/drivers/gpu/drm/xe/xe_exec_queue_types.h
+@@ -166,8 +166,14 @@ struct xe_exec_queue_ops {
+ int (*init)(struct xe_exec_queue *q);
+ /** @kill: Kill inflight submissions for backend */
+ void (*kill)(struct xe_exec_queue *q);
+- /** @fini: Fini exec queue for submission backend */
++ /** @fini: Undoes the init() for submission backend */
+ void (*fini)(struct xe_exec_queue *q);
++ /**
++ * @destroy: Destroy exec queue for submission backend. The backend
++ * function must call xe_exec_queue_fini() (which will in turn call the
++ * fini() backend function) to ensure the queue is properly cleaned up.
++ */
++ void (*destroy)(struct xe_exec_queue *q);
+ /** @set_priority: Set priority for exec queue */
+ int (*set_priority)(struct xe_exec_queue *q,
+ enum xe_exec_queue_priority priority);
+diff --git a/drivers/gpu/drm/xe/xe_execlist.c b/drivers/gpu/drm/xe/xe_execlist.c
+index 788f56b066b6ad..f83d421ac9d3d2 100644
+--- a/drivers/gpu/drm/xe/xe_execlist.c
++++ b/drivers/gpu/drm/xe/xe_execlist.c
+@@ -385,10 +385,20 @@ static int execlist_exec_queue_init(struct xe_exec_queue *q)
+ return err;
+ }
+
+-static void execlist_exec_queue_fini_async(struct work_struct *w)
++static void execlist_exec_queue_fini(struct xe_exec_queue *q)
++{
++ struct xe_execlist_exec_queue *exl = q->execlist;
++
++ drm_sched_entity_fini(&exl->entity);
++ drm_sched_fini(&exl->sched);
++
++ kfree(exl);
++}
++
++static void execlist_exec_queue_destroy_async(struct work_struct *w)
+ {
+ struct xe_execlist_exec_queue *ee =
+- container_of(w, struct xe_execlist_exec_queue, fini_async);
++ container_of(w, struct xe_execlist_exec_queue, destroy_async);
+ struct xe_exec_queue *q = ee->q;
+ struct xe_execlist_exec_queue *exl = q->execlist;
+ struct xe_device *xe = gt_to_xe(q->gt);
+@@ -401,10 +411,6 @@ static void execlist_exec_queue_fini_async(struct work_struct *w)
+ list_del(&exl->active_link);
+ spin_unlock_irqrestore(&exl->port->lock, flags);
+
+- drm_sched_entity_fini(&exl->entity);
+- drm_sched_fini(&exl->sched);
+- kfree(exl);
+-
+ xe_exec_queue_fini(q);
+ }
+
+@@ -413,10 +419,10 @@ static void execlist_exec_queue_kill(struct xe_exec_queue *q)
+ /* NIY */
+ }
+
+-static void execlist_exec_queue_fini(struct xe_exec_queue *q)
++static void execlist_exec_queue_destroy(struct xe_exec_queue *q)
+ {
+- INIT_WORK(&q->execlist->fini_async, execlist_exec_queue_fini_async);
+- queue_work(system_unbound_wq, &q->execlist->fini_async);
++ INIT_WORK(&q->execlist->destroy_async, execlist_exec_queue_destroy_async);
++ queue_work(system_unbound_wq, &q->execlist->destroy_async);
+ }
+
+ static int execlist_exec_queue_set_priority(struct xe_exec_queue *q,
+@@ -467,6 +473,7 @@ static const struct xe_exec_queue_ops execlist_exec_queue_ops = {
+ .init = execlist_exec_queue_init,
+ .kill = execlist_exec_queue_kill,
+ .fini = execlist_exec_queue_fini,
++ .destroy = execlist_exec_queue_destroy,
+ .set_priority = execlist_exec_queue_set_priority,
+ .set_timeslice = execlist_exec_queue_set_timeslice,
+ .set_preempt_timeout = execlist_exec_queue_set_preempt_timeout,
+diff --git a/drivers/gpu/drm/xe/xe_execlist_types.h b/drivers/gpu/drm/xe/xe_execlist_types.h
+index 415140936f11da..92c4ba52db0cb1 100644
+--- a/drivers/gpu/drm/xe/xe_execlist_types.h
++++ b/drivers/gpu/drm/xe/xe_execlist_types.h
+@@ -42,7 +42,7 @@ struct xe_execlist_exec_queue {
+
+ bool has_run;
+
+- struct work_struct fini_async;
++ struct work_struct destroy_async;
+
+ enum xe_exec_queue_priority active_priority;
+ struct list_head active_link;
+diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c
+index e3517ce2e18c14..eaf7569a7c1d1e 100644
+--- a/drivers/gpu/drm/xe/xe_gt.c
++++ b/drivers/gpu/drm/xe/xe_gt.c
+@@ -41,6 +41,7 @@
+ #include "xe_gt_topology.h"
+ #include "xe_guc_exec_queue_types.h"
+ #include "xe_guc_pc.h"
++#include "xe_guc_submit.h"
+ #include "xe_hw_fence.h"
+ #include "xe_hw_engine_class_sysfs.h"
+ #include "xe_irq.h"
+@@ -97,7 +98,7 @@ void xe_gt_sanitize(struct xe_gt *gt)
+ * FIXME: if xe_uc_sanitize is called here, on TGL driver will not
+ * reload
+ */
+- gt->uc.guc.submission_state.enabled = false;
++ xe_guc_submit_disable(>->uc.guc);
+ }
+
+ static void xe_gt_enable_host_l2_vram(struct xe_gt *gt)
+diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c
+index 53a44702c04afd..c15dc600dcae7a 100644
+--- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c
++++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c
+@@ -1600,7 +1600,6 @@ static u64 pf_estimate_fair_lmem(struct xe_gt *gt, unsigned int num_vfs)
+ u64 fair;
+
+ fair = div_u64(available, num_vfs);
+- fair = rounddown_pow_of_two(fair); /* XXX: ttm_vram_mgr & drm_buddy limitation */
+ fair = ALIGN_DOWN(fair, alignment);
+ #ifdef MAX_FAIR_LMEM
+ fair = min_t(u64, MAX_FAIR_LMEM, fair);
+diff --git a/drivers/gpu/drm/xe/xe_guc.c b/drivers/gpu/drm/xe/xe_guc.c
+index bac5471a1a7806..b9d21fdaad48ba 100644
+--- a/drivers/gpu/drm/xe/xe_guc.c
++++ b/drivers/gpu/drm/xe/xe_guc.c
+@@ -29,6 +29,7 @@
+ #include "xe_guc_db_mgr.h"
+ #include "xe_guc_engine_activity.h"
+ #include "xe_guc_hwconfig.h"
++#include "xe_guc_klv_helpers.h"
+ #include "xe_guc_log.h"
+ #include "xe_guc_pc.h"
+ #include "xe_guc_relay.h"
+@@ -570,6 +571,57 @@ static int guc_g2g_start(struct xe_guc *guc)
+ return err;
+ }
+
++static int __guc_opt_in_features_enable(struct xe_guc *guc, u64 addr, u32 num_dwords)
++{
++ u32 action[] = {
++ XE_GUC_ACTION_OPT_IN_FEATURE_KLV,
++ lower_32_bits(addr),
++ upper_32_bits(addr),
++ num_dwords
++ };
++
++ return xe_guc_ct_send_block(&guc->ct, action, ARRAY_SIZE(action));
++}
++
++#define OPT_IN_MAX_DWORDS 16
++int xe_guc_opt_in_features_enable(struct xe_guc *guc)
++{
++ struct xe_device *xe = guc_to_xe(guc);
++ CLASS(xe_guc_buf, buf)(&guc->buf, OPT_IN_MAX_DWORDS);
++ u32 count = 0;
++ u32 *klvs;
++ int ret;
++
++ if (!xe_guc_buf_is_valid(buf))
++ return -ENOBUFS;
++
++ klvs = xe_guc_buf_cpu_ptr(buf);
++
++ /*
++ * The extra CAT error type opt-in was added in GuC v70.17.0, which maps
++ * to compatibility version v1.7.0.
++ * Note that the GuC allows enabling this KLV even on platforms that do
++ * not support the extra type; in such case the returned type variable
++ * will be set to a known invalid value which we can check against.
++ */
++ if (GUC_SUBMIT_VER(guc) >= MAKE_GUC_VER(1, 7, 0))
++ klvs[count++] = PREP_GUC_KLV_TAG(OPT_IN_FEATURE_EXT_CAT_ERR_TYPE);
++
++ if (count) {
++ xe_assert(xe, count <= OPT_IN_MAX_DWORDS);
++
++ ret = __guc_opt_in_features_enable(guc, xe_guc_buf_flush(buf), count);
++ if (ret < 0) {
++ xe_gt_err(guc_to_gt(guc),
++ "failed to enable GuC opt-in features: %pe\n",
++ ERR_PTR(ret));
++ return ret;
++ }
++ }
++
++ return 0;
++}
++
+ static void guc_fini_hw(void *arg)
+ {
+ struct xe_guc *guc = arg;
+@@ -763,15 +815,17 @@ int xe_guc_post_load_init(struct xe_guc *guc)
+
+ xe_guc_ads_populate_post_load(&guc->ads);
+
++ ret = xe_guc_opt_in_features_enable(guc);
++ if (ret)
++ return ret;
++
+ if (xe_guc_g2g_wanted(guc_to_xe(guc))) {
+ ret = guc_g2g_start(guc);
+ if (ret)
+ return ret;
+ }
+
+- guc->submission_state.enabled = true;
+-
+- return 0;
++ return xe_guc_submit_enable(guc);
+ }
+
+ int xe_guc_reset(struct xe_guc *guc)
+@@ -1465,7 +1519,7 @@ void xe_guc_sanitize(struct xe_guc *guc)
+ {
+ xe_uc_fw_sanitize(&guc->fw);
+ xe_guc_ct_disable(&guc->ct);
+- guc->submission_state.enabled = false;
++ xe_guc_submit_disable(guc);
+ }
+
+ int xe_guc_reset_prepare(struct xe_guc *guc)
+diff --git a/drivers/gpu/drm/xe/xe_guc.h b/drivers/gpu/drm/xe/xe_guc.h
+index 58338be4455856..4a66575f017d2d 100644
+--- a/drivers/gpu/drm/xe/xe_guc.h
++++ b/drivers/gpu/drm/xe/xe_guc.h
+@@ -33,6 +33,7 @@ int xe_guc_reset(struct xe_guc *guc);
+ int xe_guc_upload(struct xe_guc *guc);
+ int xe_guc_min_load_for_hwconfig(struct xe_guc *guc);
+ int xe_guc_enable_communication(struct xe_guc *guc);
++int xe_guc_opt_in_features_enable(struct xe_guc *guc);
+ int xe_guc_suspend(struct xe_guc *guc);
+ void xe_guc_notify(struct xe_guc *guc);
+ int xe_guc_auth_huc(struct xe_guc *guc, u32 rsa_addr);
+diff --git a/drivers/gpu/drm/xe/xe_guc_exec_queue_types.h b/drivers/gpu/drm/xe/xe_guc_exec_queue_types.h
+index a3f421e2adc03b..c30c0e3ccbbb93 100644
+--- a/drivers/gpu/drm/xe/xe_guc_exec_queue_types.h
++++ b/drivers/gpu/drm/xe/xe_guc_exec_queue_types.h
+@@ -35,8 +35,8 @@ struct xe_guc_exec_queue {
+ struct xe_sched_msg static_msgs[MAX_STATIC_MSG_TYPE];
+ /** @lr_tdr: long running TDR worker */
+ struct work_struct lr_tdr;
+- /** @fini_async: do final fini async from this worker */
+- struct work_struct fini_async;
++ /** @destroy_async: do final destroy async from this worker */
++ struct work_struct destroy_async;
+ /** @resume_time: time of last resume */
+ u64 resume_time;
+ /** @state: GuC specific state for this xe_exec_queue */
+diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
+index ef3e9e1588f7c6..18ddbb7b98a15b 100644
+--- a/drivers/gpu/drm/xe/xe_guc_submit.c
++++ b/drivers/gpu/drm/xe/xe_guc_submit.c
+@@ -32,6 +32,7 @@
+ #include "xe_guc_ct.h"
+ #include "xe_guc_exec_queue_types.h"
+ #include "xe_guc_id_mgr.h"
++#include "xe_guc_klv_helpers.h"
+ #include "xe_guc_submit_types.h"
+ #include "xe_hw_engine.h"
+ #include "xe_hw_fence.h"
+@@ -316,6 +317,71 @@ int xe_guc_submit_init(struct xe_guc *guc, unsigned int num_ids)
+ return drmm_add_action_or_reset(&xe->drm, guc_submit_fini, guc);
+ }
+
++/*
++ * Given that we want to guarantee enough RCS throughput to avoid missing
++ * frames, we set the yield policy to 20% of each 80ms interval.
++ */
++#define RC_YIELD_DURATION 80 /* in ms */
++#define RC_YIELD_RATIO 20 /* in percent */
++static u32 *emit_render_compute_yield_klv(u32 *emit)
++{
++ *emit++ = PREP_GUC_KLV_TAG(SCHEDULING_POLICIES_RENDER_COMPUTE_YIELD);
++ *emit++ = RC_YIELD_DURATION;
++ *emit++ = RC_YIELD_RATIO;
++
++ return emit;
++}
++
++#define SCHEDULING_POLICY_MAX_DWORDS 16
++static int guc_init_global_schedule_policy(struct xe_guc *guc)
++{
++ u32 data[SCHEDULING_POLICY_MAX_DWORDS];
++ u32 *emit = data;
++ u32 count = 0;
++ int ret;
++
++ if (GUC_SUBMIT_VER(guc) < MAKE_GUC_VER(1, 1, 0))
++ return 0;
++
++ *emit++ = XE_GUC_ACTION_UPDATE_SCHEDULING_POLICIES_KLV;
++
++ if (CCS_MASK(guc_to_gt(guc)))
++ emit = emit_render_compute_yield_klv(emit);
++
++ count = emit - data;
++ if (count > 1) {
++ xe_assert(guc_to_xe(guc), count <= SCHEDULING_POLICY_MAX_DWORDS);
++
++ ret = xe_guc_ct_send_block(&guc->ct, data, count);
++ if (ret < 0) {
++ xe_gt_err(guc_to_gt(guc),
++ "failed to enable GuC sheduling policies: %pe\n",
++ ERR_PTR(ret));
++ return ret;
++ }
++ }
++
++ return 0;
++}
++
++int xe_guc_submit_enable(struct xe_guc *guc)
++{
++ int ret;
++
++ ret = guc_init_global_schedule_policy(guc);
++ if (ret)
++ return ret;
++
++ guc->submission_state.enabled = true;
++
++ return 0;
++}
++
++void xe_guc_submit_disable(struct xe_guc *guc)
++{
++ guc->submission_state.enabled = false;
++}
++
+ static void __release_guc_id(struct xe_guc *guc, struct xe_exec_queue *q, u32 xa_count)
+ {
+ int i;
+@@ -1269,48 +1335,57 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
+ return DRM_GPU_SCHED_STAT_NOMINAL;
+ }
+
+-static void __guc_exec_queue_fini_async(struct work_struct *w)
++static void guc_exec_queue_fini(struct xe_exec_queue *q)
++{
++ struct xe_guc_exec_queue *ge = q->guc;
++ struct xe_guc *guc = exec_queue_to_guc(q);
++
++ release_guc_id(guc, q);
++ xe_sched_entity_fini(&ge->entity);
++ xe_sched_fini(&ge->sched);
++
++ /*
++ * RCU free due sched being exported via DRM scheduler fences
++ * (timeline name).
++ */
++ kfree_rcu(ge, rcu);
++}
++
++static void __guc_exec_queue_destroy_async(struct work_struct *w)
+ {
+ struct xe_guc_exec_queue *ge =
+- container_of(w, struct xe_guc_exec_queue, fini_async);
++ container_of(w, struct xe_guc_exec_queue, destroy_async);
+ struct xe_exec_queue *q = ge->q;
+ struct xe_guc *guc = exec_queue_to_guc(q);
+
+ xe_pm_runtime_get(guc_to_xe(guc));
+ trace_xe_exec_queue_destroy(q);
+
+- release_guc_id(guc, q);
+ if (xe_exec_queue_is_lr(q))
+ cancel_work_sync(&ge->lr_tdr);
+ /* Confirm no work left behind accessing device structures */
+ cancel_delayed_work_sync(&ge->sched.base.work_tdr);
+- xe_sched_entity_fini(&ge->entity);
+- xe_sched_fini(&ge->sched);
+
+- /*
+- * RCU free due sched being exported via DRM scheduler fences
+- * (timeline name).
+- */
+- kfree_rcu(ge, rcu);
+ xe_exec_queue_fini(q);
++
+ xe_pm_runtime_put(guc_to_xe(guc));
+ }
+
+-static void guc_exec_queue_fini_async(struct xe_exec_queue *q)
++static void guc_exec_queue_destroy_async(struct xe_exec_queue *q)
+ {
+ struct xe_guc *guc = exec_queue_to_guc(q);
+ struct xe_device *xe = guc_to_xe(guc);
+
+- INIT_WORK(&q->guc->fini_async, __guc_exec_queue_fini_async);
++ INIT_WORK(&q->guc->destroy_async, __guc_exec_queue_destroy_async);
+
+ /* We must block on kernel engines so slabs are empty on driver unload */
+ if (q->flags & EXEC_QUEUE_FLAG_PERMANENT || exec_queue_wedged(q))
+- __guc_exec_queue_fini_async(&q->guc->fini_async);
++ __guc_exec_queue_destroy_async(&q->guc->destroy_async);
+ else
+- queue_work(xe->destroy_wq, &q->guc->fini_async);
++ queue_work(xe->destroy_wq, &q->guc->destroy_async);
+ }
+
+-static void __guc_exec_queue_fini(struct xe_guc *guc, struct xe_exec_queue *q)
++static void __guc_exec_queue_destroy(struct xe_guc *guc, struct xe_exec_queue *q)
+ {
+ /*
+ * Might be done from within the GPU scheduler, need to do async as we
+@@ -1319,7 +1394,7 @@ static void __guc_exec_queue_fini(struct xe_guc *guc, struct xe_exec_queue *q)
+ * this we and don't really care when everything is fini'd, just that it
+ * is.
+ */
+- guc_exec_queue_fini_async(q);
++ guc_exec_queue_destroy_async(q);
+ }
+
+ static void __guc_exec_queue_process_msg_cleanup(struct xe_sched_msg *msg)
+@@ -1333,7 +1408,7 @@ static void __guc_exec_queue_process_msg_cleanup(struct xe_sched_msg *msg)
+ if (exec_queue_registered(q))
+ disable_scheduling_deregister(guc, q);
+ else
+- __guc_exec_queue_fini(guc, q);
++ __guc_exec_queue_destroy(guc, q);
+ }
+
+ static bool guc_exec_queue_allowed_to_change_state(struct xe_exec_queue *q)
+@@ -1566,14 +1641,14 @@ static bool guc_exec_queue_try_add_msg(struct xe_exec_queue *q,
+ #define STATIC_MSG_CLEANUP 0
+ #define STATIC_MSG_SUSPEND 1
+ #define STATIC_MSG_RESUME 2
+-static void guc_exec_queue_fini(struct xe_exec_queue *q)
++static void guc_exec_queue_destroy(struct xe_exec_queue *q)
+ {
+ struct xe_sched_msg *msg = q->guc->static_msgs + STATIC_MSG_CLEANUP;
+
+ if (!(q->flags & EXEC_QUEUE_FLAG_PERMANENT) && !exec_queue_wedged(q))
+ guc_exec_queue_add_msg(q, msg, CLEANUP);
+ else
+- __guc_exec_queue_fini(exec_queue_to_guc(q), q);
++ __guc_exec_queue_destroy(exec_queue_to_guc(q), q);
+ }
+
+ static int guc_exec_queue_set_priority(struct xe_exec_queue *q,
+@@ -1703,6 +1778,7 @@ static const struct xe_exec_queue_ops guc_exec_queue_ops = {
+ .init = guc_exec_queue_init,
+ .kill = guc_exec_queue_kill,
+ .fini = guc_exec_queue_fini,
++ .destroy = guc_exec_queue_destroy,
+ .set_priority = guc_exec_queue_set_priority,
+ .set_timeslice = guc_exec_queue_set_timeslice,
+ .set_preempt_timeout = guc_exec_queue_set_preempt_timeout,
+@@ -1724,7 +1800,7 @@ static void guc_exec_queue_stop(struct xe_guc *guc, struct xe_exec_queue *q)
+ if (exec_queue_extra_ref(q) || xe_exec_queue_is_lr(q))
+ xe_exec_queue_put(q);
+ else if (exec_queue_destroyed(q))
+- __guc_exec_queue_fini(guc, q);
++ __guc_exec_queue_destroy(guc, q);
+ }
+ if (q->guc->suspend_pending) {
+ set_exec_queue_suspended(q);
+@@ -1981,7 +2057,7 @@ static void handle_deregister_done(struct xe_guc *guc, struct xe_exec_queue *q)
+ if (exec_queue_extra_ref(q) || xe_exec_queue_is_lr(q))
+ xe_exec_queue_put(q);
+ else
+- __guc_exec_queue_fini(guc, q);
++ __guc_exec_queue_destroy(guc, q);
+ }
+
+ int xe_guc_deregister_done_handler(struct xe_guc *guc, u32 *msg, u32 len)
+@@ -2078,12 +2154,16 @@ int xe_guc_exec_queue_memory_cat_error_handler(struct xe_guc *guc, u32 *msg,
+ struct xe_gt *gt = guc_to_gt(guc);
+ struct xe_exec_queue *q;
+ u32 guc_id;
++ u32 type = XE_GUC_CAT_ERR_TYPE_INVALID;
+
+- if (unlikely(len < 1))
++ if (unlikely(!len || len > 2))
+ return -EPROTO;
+
+ guc_id = msg[0];
+
++ if (len == 2)
++ type = msg[1];
++
+ if (guc_id == GUC_ID_UNKNOWN) {
+ /*
+ * GuC uses GUC_ID_UNKNOWN if it can not map the CAT fault to any PF/VF
+@@ -2097,8 +2177,19 @@ int xe_guc_exec_queue_memory_cat_error_handler(struct xe_guc *guc, u32 *msg,
+ if (unlikely(!q))
+ return -EPROTO;
+
+- xe_gt_dbg(gt, "Engine memory cat error: engine_class=%s, logical_mask: 0x%x, guc_id=%d",
+- xe_hw_engine_class_to_str(q->class), q->logical_mask, guc_id);
++ /*
++ * The type is HW-defined and changes based on platform, so we don't
++ * decode it in the kernel and only check if it is valid.
++ * See bspec 54047 and 72187 for details.
++ */
++ if (type != XE_GUC_CAT_ERR_TYPE_INVALID)
++ xe_gt_dbg(gt,
++ "Engine memory CAT error [%u]: class=%s, logical_mask: 0x%x, guc_id=%d",
++ type, xe_hw_engine_class_to_str(q->class), q->logical_mask, guc_id);
++ else
++ xe_gt_dbg(gt,
++ "Engine memory CAT error: class=%s, logical_mask: 0x%x, guc_id=%d",
++ xe_hw_engine_class_to_str(q->class), q->logical_mask, guc_id);
+
+ trace_xe_exec_queue_memory_cat_error(q);
+
+diff --git a/drivers/gpu/drm/xe/xe_guc_submit.h b/drivers/gpu/drm/xe/xe_guc_submit.h
+index 9b71a986c6ca69..0d126b807c1041 100644
+--- a/drivers/gpu/drm/xe/xe_guc_submit.h
++++ b/drivers/gpu/drm/xe/xe_guc_submit.h
+@@ -13,6 +13,8 @@ struct xe_exec_queue;
+ struct xe_guc;
+
+ int xe_guc_submit_init(struct xe_guc *guc, unsigned int num_ids);
++int xe_guc_submit_enable(struct xe_guc *guc);
++void xe_guc_submit_disable(struct xe_guc *guc);
+
+ int xe_guc_submit_reset_prepare(struct xe_guc *guc);
+ void xe_guc_submit_reset_wait(struct xe_guc *guc);
+diff --git a/drivers/gpu/drm/xe/xe_tile_sysfs.c b/drivers/gpu/drm/xe/xe_tile_sysfs.c
+index b804234a655160..9e1236a9ec6734 100644
+--- a/drivers/gpu/drm/xe/xe_tile_sysfs.c
++++ b/drivers/gpu/drm/xe/xe_tile_sysfs.c
+@@ -44,16 +44,18 @@ int xe_tile_sysfs_init(struct xe_tile *tile)
+ kt->tile = tile;
+
+ err = kobject_add(&kt->base, &dev->kobj, "tile%d", tile->id);
+- if (err) {
+- kobject_put(&kt->base);
+- return err;
+- }
++ if (err)
++ goto err_object;
+
+ tile->sysfs = &kt->base;
+
+ err = xe_vram_freq_sysfs_init(tile);
+ if (err)
+- return err;
++ goto err_object;
+
+ return devm_add_action_or_reset(xe->drm.dev, tile_sysfs_fini, tile);
++
++err_object:
++ kobject_put(&kt->base);
++ return err;
+ }
+diff --git a/drivers/gpu/drm/xe/xe_uc.c b/drivers/gpu/drm/xe/xe_uc.c
+index 3a8751a8b92dde..5c45b0f072a4c2 100644
+--- a/drivers/gpu/drm/xe/xe_uc.c
++++ b/drivers/gpu/drm/xe/xe_uc.c
+@@ -165,6 +165,10 @@ static int vf_uc_init_hw(struct xe_uc *uc)
+
+ uc->guc.submission_state.enabled = true;
+
++ err = xe_guc_opt_in_features_enable(&uc->guc);
++ if (err)
++ return err;
++
+ err = xe_gt_record_default_lrcs(uc_to_gt(uc));
+ if (err)
+ return err;
+diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
+index 84052b98002d14..92ce7374a79ce9 100644
+--- a/drivers/gpu/drm/xe/xe_vm.c
++++ b/drivers/gpu/drm/xe/xe_vm.c
+@@ -240,8 +240,8 @@ int xe_vm_add_compute_exec_queue(struct xe_vm *vm, struct xe_exec_queue *q)
+
+ pfence = xe_preempt_fence_create(q, q->lr.context,
+ ++q->lr.seqno);
+- if (!pfence) {
+- err = -ENOMEM;
++ if (IS_ERR(pfence)) {
++ err = PTR_ERR(pfence);
+ goto out_fini;
+ }
+
+diff --git a/drivers/iommu/amd/amd_iommu_types.h b/drivers/iommu/amd/amd_iommu_types.h
+index ccbab3a4811adf..a1086b6d1f11f8 100644
+--- a/drivers/iommu/amd/amd_iommu_types.h
++++ b/drivers/iommu/amd/amd_iommu_types.h
+@@ -551,6 +551,7 @@ struct gcr3_tbl_info {
+ };
+
+ struct amd_io_pgtable {
++ seqcount_t seqcount; /* Protects root/mode update */
+ struct io_pgtable pgtbl;
+ int mode;
+ u64 *root;
+diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
+index 7add9bcf45dc8b..eef55aa4143c1f 100644
+--- a/drivers/iommu/amd/init.c
++++ b/drivers/iommu/amd/init.c
+@@ -1450,12 +1450,12 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu,
+ PCI_FUNC(e->devid));
+
+ devid = e->devid;
+- for (dev_i = devid_start; dev_i <= devid; ++dev_i) {
+- if (alias)
++ if (alias) {
++ for (dev_i = devid_start; dev_i <= devid; ++dev_i)
+ pci_seg->alias_table[dev_i] = devid_to;
++ set_dev_entry_from_acpi(iommu, devid_to, flags, ext_flags);
+ }
+ set_dev_entry_from_acpi_range(iommu, devid_start, devid, flags, ext_flags);
+- set_dev_entry_from_acpi(iommu, devid_to, flags, ext_flags);
+ break;
+ case IVHD_DEV_SPECIAL: {
+ u8 handle, type;
+@@ -3048,7 +3048,8 @@ static int __init early_amd_iommu_init(void)
+
+ if (!boot_cpu_has(X86_FEATURE_CX16)) {
+ pr_err("Failed to initialize. The CMPXCHG16B feature is required.\n");
+- return -EINVAL;
++ ret = -EINVAL;
++ goto out;
+ }
+
+ /*
+diff --git a/drivers/iommu/amd/io_pgtable.c b/drivers/iommu/amd/io_pgtable.c
+index 4d308c07113495..5c6fdf38636a0c 100644
+--- a/drivers/iommu/amd/io_pgtable.c
++++ b/drivers/iommu/amd/io_pgtable.c
+@@ -17,6 +17,7 @@
+ #include <linux/slab.h>
+ #include <linux/types.h>
+ #include <linux/dma-mapping.h>
++#include <linux/seqlock.h>
+
+ #include <asm/barrier.h>
+
+@@ -130,8 +131,11 @@ static bool increase_address_space(struct amd_io_pgtable *pgtable,
+
+ *pte = PM_LEVEL_PDE(pgtable->mode, iommu_virt_to_phys(pgtable->root));
+
++ write_seqcount_begin(&pgtable->seqcount);
+ pgtable->root = pte;
+ pgtable->mode += 1;
++ write_seqcount_end(&pgtable->seqcount);
++
+ amd_iommu_update_and_flush_device_table(domain);
+
+ pte = NULL;
+@@ -153,6 +157,7 @@ static u64 *alloc_pte(struct amd_io_pgtable *pgtable,
+ {
+ unsigned long last_addr = address + (page_size - 1);
+ struct io_pgtable_cfg *cfg = &pgtable->pgtbl.cfg;
++ unsigned int seqcount;
+ int level, end_lvl;
+ u64 *pte, *page;
+
+@@ -170,8 +175,14 @@ static u64 *alloc_pte(struct amd_io_pgtable *pgtable,
+ }
+
+
+- level = pgtable->mode - 1;
+- pte = &pgtable->root[PM_LEVEL_INDEX(level, address)];
++ do {
++ seqcount = read_seqcount_begin(&pgtable->seqcount);
++
++ level = pgtable->mode - 1;
++ pte = &pgtable->root[PM_LEVEL_INDEX(level, address)];
++ } while (read_seqcount_retry(&pgtable->seqcount, seqcount));
++
++
+ address = PAGE_SIZE_ALIGN(address, page_size);
+ end_lvl = PAGE_SIZE_LEVEL(page_size);
+
+@@ -249,6 +260,7 @@ static u64 *fetch_pte(struct amd_io_pgtable *pgtable,
+ unsigned long *page_size)
+ {
+ int level;
++ unsigned int seqcount;
+ u64 *pte;
+
+ *page_size = 0;
+@@ -256,8 +268,12 @@ static u64 *fetch_pte(struct amd_io_pgtable *pgtable,
+ if (address > PM_LEVEL_SIZE(pgtable->mode))
+ return NULL;
+
+- level = pgtable->mode - 1;
+- pte = &pgtable->root[PM_LEVEL_INDEX(level, address)];
++ do {
++ seqcount = read_seqcount_begin(&pgtable->seqcount);
++ level = pgtable->mode - 1;
++ pte = &pgtable->root[PM_LEVEL_INDEX(level, address)];
++ } while (read_seqcount_retry(&pgtable->seqcount, seqcount));
++
+ *page_size = PTE_LEVEL_PAGE_SIZE(level);
+
+ while (level > 0) {
+@@ -541,6 +557,7 @@ static struct io_pgtable *v1_alloc_pgtable(struct io_pgtable_cfg *cfg, void *coo
+ if (!pgtable->root)
+ return NULL;
+ pgtable->mode = PAGE_MODE_3_LEVEL;
++ seqcount_init(&pgtable->seqcount);
+
+ cfg->pgsize_bitmap = amd_iommu_pgsize_bitmap;
+ cfg->ias = IOMMU_IN_ADDR_BIT_SIZE;
+diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
+index 34dd175a331dc7..3dd4d73fcb5dc6 100644
+--- a/drivers/iommu/intel/iommu.c
++++ b/drivers/iommu/intel/iommu.c
+@@ -1592,6 +1592,10 @@ static void switch_to_super_page(struct dmar_domain *domain,
+ unsigned long lvl_pages = lvl_to_nr_pages(level);
+ struct dma_pte *pte = NULL;
+
++ if (WARN_ON(!IS_ALIGNED(start_pfn, lvl_pages) ||
++ !IS_ALIGNED(end_pfn + 1, lvl_pages)))
++ return;
++
+ while (start_pfn <= end_pfn) {
+ if (!pte)
+ pte = pfn_to_dma_pte(domain, start_pfn, &level,
+@@ -1667,7 +1671,8 @@ __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
+ unsigned long pages_to_remove;
+
+ pteval |= DMA_PTE_LARGE_PAGE;
+- pages_to_remove = min_t(unsigned long, nr_pages,
++ pages_to_remove = min_t(unsigned long,
++ round_down(nr_pages, lvl_pages),
+ nr_pte_to_next_page(pte) * lvl_pages);
+ end_pfn = iov_pfn + pages_to_remove - 1;
+ switch_to_super_page(domain, iov_pfn, end_pfn, largepage_lvl);
+diff --git a/drivers/iommu/s390-iommu.c b/drivers/iommu/s390-iommu.c
+index 433b59f435302b..cc9ec636a7a21e 100644
+--- a/drivers/iommu/s390-iommu.c
++++ b/drivers/iommu/s390-iommu.c
+@@ -611,6 +611,23 @@ static u64 get_iota_region_flag(struct s390_domain *domain)
+ }
+ }
+
++static bool reg_ioat_propagate_error(int cc, u8 status)
++{
++ /*
++ * If the device is in the error state the reset routine
++ * will register the IOAT of the newly set domain on re-enable
++ */
++ if (cc == ZPCI_CC_ERR && status == ZPCI_PCI_ST_FUNC_NOT_AVAIL)
++ return false;
++ /*
++ * If the device was removed treat registration as success
++ * and let the subsequent error event trigger tear down.
++ */
++ if (cc == ZPCI_CC_INVAL_HANDLE)
++ return false;
++ return cc != ZPCI_CC_OK;
++}
++
+ static int s390_iommu_domain_reg_ioat(struct zpci_dev *zdev,
+ struct iommu_domain *domain, u8 *status)
+ {
+@@ -695,7 +712,7 @@ static int s390_iommu_attach_device(struct iommu_domain *domain,
+
+ /* If we fail now DMA remains blocked via blocking domain */
+ cc = s390_iommu_domain_reg_ioat(zdev, domain, &status);
+- if (cc && status != ZPCI_PCI_ST_FUNC_NOT_AVAIL)
++ if (reg_ioat_propagate_error(cc, status))
+ return -EIO;
+ zdev->dma_table = s390_domain->dma_table;
+ zdev_s390_domain_update(zdev, domain);
+@@ -1031,7 +1048,8 @@ struct zpci_iommu_ctrs *zpci_get_iommu_ctrs(struct zpci_dev *zdev)
+
+ lockdep_assert_held(&zdev->dom_lock);
+
+- if (zdev->s390_domain->type == IOMMU_DOMAIN_BLOCKED)
++ if (zdev->s390_domain->type == IOMMU_DOMAIN_BLOCKED ||
++ zdev->s390_domain->type == IOMMU_DOMAIN_IDENTITY)
+ return NULL;
+
+ s390_domain = to_s390_domain(zdev->s390_domain);
+@@ -1122,12 +1140,7 @@ static int s390_attach_dev_identity(struct iommu_domain *domain,
+
+ /* If we fail now DMA remains blocked via blocking domain */
+ cc = s390_iommu_domain_reg_ioat(zdev, domain, &status);
+-
+- /*
+- * If the device is undergoing error recovery the reset code
+- * will re-establish the new domain.
+- */
+- if (cc && status != ZPCI_PCI_ST_FUNC_NOT_AVAIL)
++ if (reg_ioat_propagate_error(cc, status))
+ return -EIO;
+
+ zdev_s390_domain_update(zdev, domain);
+diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
+index 9835f2fe26e99f..1e09b4860a4543 100644
+--- a/drivers/md/dm-raid.c
++++ b/drivers/md/dm-raid.c
+@@ -3810,8 +3810,10 @@ static void raid_io_hints(struct dm_target *ti, struct queue_limits *limits)
+ struct raid_set *rs = ti->private;
+ unsigned int chunk_size_bytes = to_bytes(rs->md.chunk_sectors);
+
+- limits->io_min = chunk_size_bytes;
+- limits->io_opt = chunk_size_bytes * mddev_data_stripes(rs);
++ if (chunk_size_bytes) {
++ limits->io_min = chunk_size_bytes;
++ limits->io_opt = chunk_size_bytes * mddev_data_stripes(rs);
++ }
+ }
+
+ static void raid_presuspend(struct dm_target *ti)
+diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
+index 5bbbdf8fc1bdef..2313dbaf642422 100644
+--- a/drivers/md/dm-stripe.c
++++ b/drivers/md/dm-stripe.c
+@@ -456,11 +456,15 @@ static void stripe_io_hints(struct dm_target *ti,
+ struct queue_limits *limits)
+ {
+ struct stripe_c *sc = ti->private;
+- unsigned int chunk_size = sc->chunk_size << SECTOR_SHIFT;
++ unsigned int io_min, io_opt;
+
+ limits->chunk_sectors = sc->chunk_size;
+- limits->io_min = chunk_size;
+- limits->io_opt = chunk_size * sc->stripes;
++
++ if (!check_shl_overflow(sc->chunk_size, SECTOR_SHIFT, &io_min) &&
++ !check_mul_overflow(io_min, sc->stripes, &io_opt)) {
++ limits->io_min = io_min;
++ limits->io_opt = io_opt;
++ }
+ }
+
+ static struct target_type stripe_target = {
+diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c
+index 101f36de7b63bd..8165fa4d0d937a 100644
+--- a/drivers/mmc/host/mvsdio.c
++++ b/drivers/mmc/host/mvsdio.c
+@@ -292,7 +292,7 @@ static u32 mvsd_finish_data(struct mvsd_host *host, struct mmc_data *data,
+ host->pio_ptr = NULL;
+ host->pio_size = 0;
+ } else {
+- dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->sg_frags,
++ dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
+ mmc_get_dma_dir(data));
+ }
+
+diff --git a/drivers/mmc/host/sdhci-pci-gli.c b/drivers/mmc/host/sdhci-pci-gli.c
+index 3a1de477e9af8d..b0f91cc9e40e43 100644
+--- a/drivers/mmc/host/sdhci-pci-gli.c
++++ b/drivers/mmc/host/sdhci-pci-gli.c
+@@ -283,6 +283,8 @@
+ #define PCIE_GLI_9767_UHS2_CTL2_ZC_VALUE 0xb
+ #define PCIE_GLI_9767_UHS2_CTL2_ZC_CTL BIT(6)
+ #define PCIE_GLI_9767_UHS2_CTL2_ZC_CTL_VALUE 0x1
++#define PCIE_GLI_9767_UHS2_CTL2_FORCE_PHY_RESETN BIT(13)
++#define PCIE_GLI_9767_UHS2_CTL2_FORCE_RESETN_VALUE BIT(14)
+
+ #define GLI_MAX_TUNING_LOOP 40
+
+@@ -1179,6 +1181,65 @@ static void gl9767_set_low_power_negotiation(struct pci_dev *pdev, bool enable)
+ gl9767_vhs_read(pdev);
+ }
+
++static void sdhci_gl9767_uhs2_phy_reset(struct sdhci_host *host, bool assert)
++{
++ struct sdhci_pci_slot *slot = sdhci_priv(host);
++ struct pci_dev *pdev = slot->chip->pdev;
++ u32 value, set, clr;
++
++ if (assert) {
++ /* Assert reset, set RESETN and clean RESETN_VALUE */
++ set = PCIE_GLI_9767_UHS2_CTL2_FORCE_PHY_RESETN;
++ clr = PCIE_GLI_9767_UHS2_CTL2_FORCE_RESETN_VALUE;
++ } else {
++ /* De-assert reset, clean RESETN and set RESETN_VALUE */
++ set = PCIE_GLI_9767_UHS2_CTL2_FORCE_RESETN_VALUE;
++ clr = PCIE_GLI_9767_UHS2_CTL2_FORCE_PHY_RESETN;
++ }
++
++ gl9767_vhs_write(pdev);
++ pci_read_config_dword(pdev, PCIE_GLI_9767_UHS2_CTL2, &value);
++ value |= set;
++ pci_write_config_dword(pdev, PCIE_GLI_9767_UHS2_CTL2, value);
++ value &= ~clr;
++ pci_write_config_dword(pdev, PCIE_GLI_9767_UHS2_CTL2, value);
++ gl9767_vhs_read(pdev);
++}
++
++static void __gl9767_uhs2_set_power(struct sdhci_host *host, unsigned char mode, unsigned short vdd)
++{
++ u8 pwr = 0;
++
++ if (mode != MMC_POWER_OFF) {
++ pwr = sdhci_get_vdd_value(vdd);
++ if (!pwr)
++ WARN(1, "%s: Invalid vdd %#x\n",
++ mmc_hostname(host->mmc), vdd);
++ pwr |= SDHCI_VDD2_POWER_180;
++ }
++
++ if (host->pwr == pwr)
++ return;
++
++ host->pwr = pwr;
++
++ if (pwr == 0) {
++ sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
++ } else {
++ sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
++
++ pwr |= SDHCI_POWER_ON;
++ sdhci_writeb(host, pwr & 0xf, SDHCI_POWER_CONTROL);
++ usleep_range(5000, 6250);
++
++ /* Assert reset */
++ sdhci_gl9767_uhs2_phy_reset(host, true);
++ pwr |= SDHCI_VDD2_POWER_ON;
++ sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
++ usleep_range(5000, 6250);
++ }
++}
++
+ static void sdhci_gl9767_set_clock(struct sdhci_host *host, unsigned int clock)
+ {
+ struct sdhci_pci_slot *slot = sdhci_priv(host);
+@@ -1205,6 +1266,11 @@ static void sdhci_gl9767_set_clock(struct sdhci_host *host, unsigned int clock)
+ }
+
+ sdhci_enable_clk(host, clk);
++
++ if (mmc_card_uhs2(host->mmc))
++ /* De-assert reset */
++ sdhci_gl9767_uhs2_phy_reset(host, false);
++
+ gl9767_set_low_power_negotiation(pdev, true);
+ }
+
+@@ -1476,7 +1542,7 @@ static void sdhci_gl9767_set_power(struct sdhci_host *host, unsigned char mode,
+ gl9767_vhs_read(pdev);
+
+ sdhci_gli_overcurrent_event_enable(host, false);
+- sdhci_uhs2_set_power(host, mode, vdd);
++ __gl9767_uhs2_set_power(host, mode, vdd);
+ sdhci_gli_overcurrent_event_enable(host, true);
+ } else {
+ gl9767_vhs_write(pdev);
+diff --git a/drivers/mmc/host/sdhci-uhs2.c b/drivers/mmc/host/sdhci-uhs2.c
+index 0efeb9d0c3765a..c459a08d01da52 100644
+--- a/drivers/mmc/host/sdhci-uhs2.c
++++ b/drivers/mmc/host/sdhci-uhs2.c
+@@ -295,7 +295,8 @@ static void __sdhci_uhs2_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+ else
+ sdhci_uhs2_set_power(host, ios->power_mode, ios->vdd);
+
+- sdhci_set_clock(host, host->clock);
++ host->ops->set_clock(host, ios->clock);
++ host->clock = ios->clock;
+ }
+
+ static int sdhci_uhs2_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
+index e116f2db34d52b..be701eb25fec42 100644
+--- a/drivers/mmc/host/sdhci.c
++++ b/drivers/mmc/host/sdhci.c
+@@ -2367,23 +2367,6 @@ void sdhci_set_ios_common(struct mmc_host *mmc, struct mmc_ios *ios)
+ (ios->power_mode == MMC_POWER_UP) &&
+ !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN))
+ sdhci_enable_preset_value(host, false);
+-
+- if (!ios->clock || ios->clock != host->clock) {
+- host->ops->set_clock(host, ios->clock);
+- host->clock = ios->clock;
+-
+- if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK &&
+- host->clock) {
+- host->timeout_clk = mmc->actual_clock ?
+- mmc->actual_clock / 1000 :
+- host->clock / 1000;
+- mmc->max_busy_timeout =
+- host->ops->get_max_timeout_count ?
+- host->ops->get_max_timeout_count(host) :
+- 1 << 27;
+- mmc->max_busy_timeout /= host->timeout_clk;
+- }
+- }
+ }
+ EXPORT_SYMBOL_GPL(sdhci_set_ios_common);
+
+@@ -2410,6 +2393,23 @@ void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+
+ sdhci_set_ios_common(mmc, ios);
+
++ if (!ios->clock || ios->clock != host->clock) {
++ host->ops->set_clock(host, ios->clock);
++ host->clock = ios->clock;
++
++ if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK &&
++ host->clock) {
++ host->timeout_clk = mmc->actual_clock ?
++ mmc->actual_clock / 1000 :
++ host->clock / 1000;
++ mmc->max_busy_timeout =
++ host->ops->get_max_timeout_count ?
++ host->ops->get_max_timeout_count(host) :
++ 1 << 27;
++ mmc->max_busy_timeout /= host->timeout_clk;
++ }
++ }
++
+ if (host->ops->set_power)
+ host->ops->set_power(host, ios->power_mode, ios->vdd);
+ else
+diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
+index c4d53e8e7c152d..e23195dd747769 100644
+--- a/drivers/net/bonding/bond_main.c
++++ b/drivers/net/bonding/bond_main.c
+@@ -2115,6 +2115,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
+ memcpy(ss.__data, bond_dev->dev_addr, bond_dev->addr_len);
+ } else if (bond->params.fail_over_mac == BOND_FOM_FOLLOW &&
+ BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP &&
++ bond_has_slaves(bond) &&
+ memcmp(slave_dev->dev_addr, bond_dev->dev_addr, bond_dev->addr_len) == 0) {
+ /* Set slave to random address to avoid duplicate mac
+ * address in later fail over.
+@@ -3338,7 +3339,6 @@ static void bond_ns_send_all(struct bonding *bond, struct slave *slave)
+ /* Find out through which dev should the packet go */
+ memset(&fl6, 0, sizeof(struct flowi6));
+ fl6.daddr = targets[i];
+- fl6.flowi6_oif = bond->dev->ifindex;
+
+ dst = ip6_route_output(dev_net(bond->dev), NULL, &fl6);
+ if (dst->error) {
+diff --git a/drivers/net/ethernet/broadcom/cnic.c b/drivers/net/ethernet/broadcom/cnic.c
+index a9040c42d2ff97..6e97a5a7daaf9c 100644
+--- a/drivers/net/ethernet/broadcom/cnic.c
++++ b/drivers/net/ethernet/broadcom/cnic.c
+@@ -4230,8 +4230,7 @@ static void cnic_cm_stop_bnx2x_hw(struct cnic_dev *dev)
+
+ cnic_bnx2x_delete_wait(dev, 0);
+
+- cancel_delayed_work(&cp->delete_task);
+- flush_workqueue(cnic_wq);
++ cancel_delayed_work_sync(&cp->delete_task);
+
+ if (atomic_read(&cp->iscsi_conn) != 0)
+ netdev_warn(dev->netdev, "%d iSCSI connections not destroyed\n",
+diff --git a/drivers/net/ethernet/cavium/liquidio/request_manager.c b/drivers/net/ethernet/cavium/liquidio/request_manager.c
+index de8a6ce86ad7e2..12105ffb5dac6d 100644
+--- a/drivers/net/ethernet/cavium/liquidio/request_manager.c
++++ b/drivers/net/ethernet/cavium/liquidio/request_manager.c
+@@ -126,7 +126,7 @@ int octeon_init_instr_queue(struct octeon_device *oct,
+ oct->io_qmask.iq |= BIT_ULL(iq_no);
+
+ /* Set the 32B/64B mode for each input queue */
+- oct->io_qmask.iq64B |= ((conf->instr_type == 64) << iq_no);
++ oct->io_qmask.iq64B |= ((u64)(conf->instr_type == 64) << iq_no);
+ iq->iqcmd_64B = (conf->instr_type == 64);
+
+ oct->fn_list.setup_iq_regs(oct, iq_no);
+diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
+index 4643a338061820..b1e1ad9e4b48e6 100644
+--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
++++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
+@@ -2736,7 +2736,7 @@ static int dpaa2_switch_setup_dpbp(struct ethsw_core *ethsw)
+ dev_err(dev, "dpsw_ctrl_if_set_pools() failed\n");
+ goto err_get_attr;
+ }
+- ethsw->bpid = dpbp_attrs.id;
++ ethsw->bpid = dpbp_attrs.bpid;
+
+ return 0;
+
+diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+index c006f716a3bdbe..ca7517a68a2c32 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
++++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+@@ -947,9 +947,6 @@ static bool i40e_clean_tx_irq(struct i40e_vsi *vsi,
+ if (!eop_desc)
+ break;
+
+- /* prevent any other reads prior to eop_desc */
+- smp_rmb();
+-
+ i40e_trace(clean_tx_irq, tx_ring, tx_desc, tx_buf);
+ /* we have caught up to head, no work left to do */
+ if (tx_head == tx_desc)
+diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c
+index c50cf3ad190e9a..4766597ac55509 100644
+--- a/drivers/net/ethernet/intel/ice/ice_txrx.c
++++ b/drivers/net/ethernet/intel/ice/ice_txrx.c
+@@ -865,10 +865,6 @@ ice_add_xdp_frag(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp,
+ __skb_fill_page_desc_noacc(sinfo, sinfo->nr_frags++, rx_buf->page,
+ rx_buf->page_offset, size);
+ sinfo->xdp_frags_size += size;
+- /* remember frag count before XDP prog execution; bpf_xdp_adjust_tail()
+- * can pop off frags but driver has to handle it on its own
+- */
+- rx_ring->nr_frags = sinfo->nr_frags;
+
+ if (page_is_pfmemalloc(rx_buf->page))
+ xdp_buff_set_frag_pfmemalloc(xdp);
+@@ -939,20 +935,20 @@ ice_get_rx_buf(struct ice_rx_ring *rx_ring, const unsigned int size,
+ /**
+ * ice_get_pgcnts - grab page_count() for gathered fragments
+ * @rx_ring: Rx descriptor ring to store the page counts on
++ * @ntc: the next to clean element (not included in this frame!)
+ *
+ * This function is intended to be called right before running XDP
+ * program so that the page recycling mechanism will be able to take
+ * a correct decision regarding underlying pages; this is done in such
+ * way as XDP program can change the refcount of page
+ */
+-static void ice_get_pgcnts(struct ice_rx_ring *rx_ring)
++static void ice_get_pgcnts(struct ice_rx_ring *rx_ring, unsigned int ntc)
+ {
+- u32 nr_frags = rx_ring->nr_frags + 1;
+ u32 idx = rx_ring->first_desc;
+ struct ice_rx_buf *rx_buf;
+ u32 cnt = rx_ring->count;
+
+- for (int i = 0; i < nr_frags; i++) {
++ while (idx != ntc) {
+ rx_buf = &rx_ring->rx_buf[idx];
+ rx_buf->pgcnt = page_count(rx_buf->page);
+
+@@ -1125,62 +1121,51 @@ ice_put_rx_buf(struct ice_rx_ring *rx_ring, struct ice_rx_buf *rx_buf)
+ }
+
+ /**
+- * ice_put_rx_mbuf - ice_put_rx_buf() caller, for all frame frags
++ * ice_put_rx_mbuf - ice_put_rx_buf() caller, for all buffers in frame
+ * @rx_ring: Rx ring with all the auxiliary data
+ * @xdp: XDP buffer carrying linear + frags part
+- * @xdp_xmit: XDP_TX/XDP_REDIRECT verdict storage
+- * @ntc: a current next_to_clean value to be stored at rx_ring
++ * @ntc: the next to clean element (not included in this frame!)
+ * @verdict: return code from XDP program execution
+ *
+- * Walk through gathered fragments and satisfy internal page
+- * recycle mechanism; we take here an action related to verdict
+- * returned by XDP program;
++ * Called after XDP program is completed, or on error with verdict set to
++ * ICE_XDP_CONSUMED.
++ *
++ * Walk through buffers from first_desc to the end of the frame, releasing
++ * buffers and satisfying internal page recycle mechanism. The action depends
++ * on verdict from XDP program.
+ */
+ static void ice_put_rx_mbuf(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp,
+- u32 *xdp_xmit, u32 ntc, u32 verdict)
++ u32 ntc, u32 verdict)
+ {
+- u32 nr_frags = rx_ring->nr_frags + 1;
+ u32 idx = rx_ring->first_desc;
+ u32 cnt = rx_ring->count;
+- u32 post_xdp_frags = 1;
+ struct ice_rx_buf *buf;
+- int i;
++ u32 xdp_frags = 0;
++ int i = 0;
+
+ if (unlikely(xdp_buff_has_frags(xdp)))
+- post_xdp_frags += xdp_get_shared_info_from_buff(xdp)->nr_frags;
++ xdp_frags = xdp_get_shared_info_from_buff(xdp)->nr_frags;
+
+- for (i = 0; i < post_xdp_frags; i++) {
++ while (idx != ntc) {
+ buf = &rx_ring->rx_buf[idx];
++ if (++idx == cnt)
++ idx = 0;
+
+- if (verdict & (ICE_XDP_TX | ICE_XDP_REDIR)) {
++ /* An XDP program could release fragments from the end of the
++ * buffer. For these, we need to keep the pagecnt_bias as-is.
++ * To do this, only adjust pagecnt_bias for fragments up to
++ * the total remaining after the XDP program has run.
++ */
++ if (verdict != ICE_XDP_CONSUMED)
+ ice_rx_buf_adjust_pg_offset(buf, xdp->frame_sz);
+- *xdp_xmit |= verdict;
+- } else if (verdict & ICE_XDP_CONSUMED) {
++ else if (i++ <= xdp_frags)
+ buf->pagecnt_bias++;
+- } else if (verdict == ICE_XDP_PASS) {
+- ice_rx_buf_adjust_pg_offset(buf, xdp->frame_sz);
+- }
+
+ ice_put_rx_buf(rx_ring, buf);
+-
+- if (++idx == cnt)
+- idx = 0;
+- }
+- /* handle buffers that represented frags released by XDP prog;
+- * for these we keep pagecnt_bias as-is; refcount from struct page
+- * has been decremented within XDP prog and we do not have to increase
+- * the biased refcnt
+- */
+- for (; i < nr_frags; i++) {
+- buf = &rx_ring->rx_buf[idx];
+- ice_put_rx_buf(rx_ring, buf);
+- if (++idx == cnt)
+- idx = 0;
+ }
+
+ xdp->data = NULL;
+ rx_ring->first_desc = ntc;
+- rx_ring->nr_frags = 0;
+ }
+
+ /**
+@@ -1260,6 +1245,10 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)
+ /* retrieve a buffer from the ring */
+ rx_buf = ice_get_rx_buf(rx_ring, size, ntc);
+
++ /* Increment ntc before calls to ice_put_rx_mbuf() */
++ if (++ntc == cnt)
++ ntc = 0;
++
+ if (!xdp->data) {
+ void *hard_start;
+
+@@ -1268,24 +1257,23 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)
+ xdp_prepare_buff(xdp, hard_start, offset, size, !!offset);
+ xdp_buff_clear_frags_flag(xdp);
+ } else if (ice_add_xdp_frag(rx_ring, xdp, rx_buf, size)) {
+- ice_put_rx_mbuf(rx_ring, xdp, NULL, ntc, ICE_XDP_CONSUMED);
++ ice_put_rx_mbuf(rx_ring, xdp, ntc, ICE_XDP_CONSUMED);
+ break;
+ }
+- if (++ntc == cnt)
+- ntc = 0;
+
+ /* skip if it is NOP desc */
+ if (ice_is_non_eop(rx_ring, rx_desc))
+ continue;
+
+- ice_get_pgcnts(rx_ring);
++ ice_get_pgcnts(rx_ring, ntc);
+ xdp_verdict = ice_run_xdp(rx_ring, xdp, xdp_prog, xdp_ring, rx_desc);
+ if (xdp_verdict == ICE_XDP_PASS)
+ goto construct_skb;
+ total_rx_bytes += xdp_get_buff_len(xdp);
+ total_rx_pkts++;
+
+- ice_put_rx_mbuf(rx_ring, xdp, &xdp_xmit, ntc, xdp_verdict);
++ ice_put_rx_mbuf(rx_ring, xdp, ntc, xdp_verdict);
++ xdp_xmit |= xdp_verdict & (ICE_XDP_TX | ICE_XDP_REDIR);
+
+ continue;
+ construct_skb:
+@@ -1298,7 +1286,7 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)
+ rx_ring->ring_stats->rx_stats.alloc_buf_failed++;
+ xdp_verdict = ICE_XDP_CONSUMED;
+ }
+- ice_put_rx_mbuf(rx_ring, xdp, &xdp_xmit, ntc, xdp_verdict);
++ ice_put_rx_mbuf(rx_ring, xdp, ntc, xdp_verdict);
+
+ if (!skb)
+ break;
+diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.h b/drivers/net/ethernet/intel/ice/ice_txrx.h
+index a4b1e95146327d..07155e615f75ab 100644
+--- a/drivers/net/ethernet/intel/ice/ice_txrx.h
++++ b/drivers/net/ethernet/intel/ice/ice_txrx.h
+@@ -358,7 +358,6 @@ struct ice_rx_ring {
+ struct ice_tx_ring *xdp_ring;
+ struct ice_rx_ring *next; /* pointer to next ring in q_vector */
+ struct xsk_buff_pool *xsk_pool;
+- u32 nr_frags;
+ u16 max_frame;
+ u16 rx_buf_len;
+ dma_addr_t dma; /* physical address of ring */
+diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h
+index 859a15e4ccbab5..1bbe7f72757c06 100644
+--- a/drivers/net/ethernet/intel/igc/igc.h
++++ b/drivers/net/ethernet/intel/igc/igc.h
+@@ -343,6 +343,7 @@ struct igc_adapter {
+ /* LEDs */
+ struct mutex led_mutex;
+ struct igc_led_classdev *leds;
++ bool leds_available;
+ };
+
+ void igc_up(struct igc_adapter *adapter);
+diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
+index 1b4465d6b2b726..5b8f9b51214897 100644
+--- a/drivers/net/ethernet/intel/igc/igc_main.c
++++ b/drivers/net/ethernet/intel/igc/igc_main.c
+@@ -7301,8 +7301,14 @@ static int igc_probe(struct pci_dev *pdev,
+
+ if (IS_ENABLED(CONFIG_IGC_LEDS)) {
+ err = igc_led_setup(adapter);
+- if (err)
+- goto err_register;
++ if (err) {
++ netdev_warn_once(netdev,
++ "LED init failed (%d); continuing without LED support\n",
++ err);
++ adapter->leds_available = false;
++ } else {
++ adapter->leds_available = true;
++ }
+ }
+
+ return 0;
+@@ -7358,7 +7364,7 @@ static void igc_remove(struct pci_dev *pdev)
+ cancel_work_sync(&adapter->watchdog_task);
+ hrtimer_cancel(&adapter->hrtimer);
+
+- if (IS_ENABLED(CONFIG_IGC_LEDS))
++ if (IS_ENABLED(CONFIG_IGC_LEDS) && adapter->leds_available)
+ igc_led_free(adapter);
+
+ /* Release control of h/w to f/w. If f/w is AMT enabled, this
+diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+index cba860f0e1f154..d5c421451f3191 100644
+--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+@@ -6801,6 +6801,13 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter,
+ break;
+ }
+
++ /* Make sure the SWFW semaphore is in a valid state */
++ if (hw->mac.ops.init_swfw_sync)
++ hw->mac.ops.init_swfw_sync(hw);
++
++ if (hw->mac.type == ixgbe_mac_e610)
++ mutex_init(&hw->aci.lock);
++
+ #ifdef IXGBE_FCOE
+ /* FCoE support exists, always init the FCoE lock */
+ spin_lock_init(&adapter->fcoe.lock);
+@@ -11474,10 +11481,6 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ if (err)
+ goto err_sw_init;
+
+- /* Make sure the SWFW semaphore is in a valid state */
+- if (hw->mac.ops.init_swfw_sync)
+- hw->mac.ops.init_swfw_sync(hw);
+-
+ if (ixgbe_check_fw_error(adapter))
+ return ixgbe_recovery_probe(adapter);
+
+@@ -11681,8 +11684,6 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ ether_addr_copy(hw->mac.addr, hw->mac.perm_addr);
+ ixgbe_mac_set_default_filter(adapter);
+
+- if (hw->mac.type == ixgbe_mac_e610)
+- mutex_init(&hw->aci.lock);
+ timer_setup(&adapter->service_timer, ixgbe_service_timer, 0);
+
+ if (ixgbe_removed(hw->hw_addr)) {
+@@ -11838,9 +11839,9 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ devl_unlock(adapter->devlink);
+ ixgbe_release_hw_control(adapter);
+ ixgbe_clear_interrupt_scheme(adapter);
++err_sw_init:
+ if (hw->mac.type == ixgbe_mac_e610)
+ mutex_destroy(&adapter->hw.aci.lock);
+-err_sw_init:
+ ixgbe_disable_sriov(adapter);
+ adapter->flags2 &= ~IXGBE_FLAG2_SEARCH_FOR_SFP;
+ iounmap(adapter->io_addr);
+@@ -11891,10 +11892,8 @@ static void ixgbe_remove(struct pci_dev *pdev)
+ set_bit(__IXGBE_REMOVING, &adapter->state);
+ cancel_work_sync(&adapter->service_task);
+
+- if (adapter->hw.mac.type == ixgbe_mac_e610) {
++ if (adapter->hw.mac.type == ixgbe_mac_e610)
+ ixgbe_disable_link_status_events(adapter);
+- mutex_destroy(&adapter->hw.aci.lock);
+- }
+
+ if (adapter->mii_bus)
+ mdiobus_unregister(adapter->mii_bus);
+@@ -11954,6 +11953,9 @@ static void ixgbe_remove(struct pci_dev *pdev)
+ disable_dev = !test_and_set_bit(__IXGBE_DISABLED, &adapter->state);
+ free_netdev(netdev);
+
++ if (adapter->hw.mac.type == ixgbe_mac_e610)
++ mutex_destroy(&adapter->hw.aci.lock);
++
+ if (disable_dev)
+ pci_disable_device(pdev);
+ }
+diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c b/drivers/net/ethernet/marvell/octeon_ep/octep_main.c
+index 24499bb36c0057..bcea3fc26a8c7d 100644
+--- a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c
++++ b/drivers/net/ethernet/marvell/octeon_ep/octep_main.c
+@@ -1124,11 +1124,24 @@ static int octep_set_features(struct net_device *dev, netdev_features_t features
+ return err;
+ }
+
++static bool octep_is_vf_valid(struct octep_device *oct, int vf)
++{
++ if (vf >= CFG_GET_ACTIVE_VFS(oct->conf)) {
++ netdev_err(oct->netdev, "Invalid VF ID %d\n", vf);
++ return false;
++ }
++
++ return true;
++}
++
+ static int octep_get_vf_config(struct net_device *dev, int vf,
+ struct ifla_vf_info *ivi)
+ {
+ struct octep_device *oct = netdev_priv(dev);
+
++ if (!octep_is_vf_valid(oct, vf))
++ return -EINVAL;
++
+ ivi->vf = vf;
+ ether_addr_copy(ivi->mac, oct->vf_info[vf].mac_addr);
+ ivi->spoofchk = true;
+@@ -1143,6 +1156,9 @@ static int octep_set_vf_mac(struct net_device *dev, int vf, u8 *mac)
+ struct octep_device *oct = netdev_priv(dev);
+ int err;
+
++ if (!octep_is_vf_valid(oct, vf))
++ return -EINVAL;
++
+ if (!is_valid_ether_addr(mac)) {
+ dev_err(&oct->pdev->dev, "Invalid MAC Address %pM\n", mac);
+ return -EADDRNOTAVAIL;
+diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c
+index ebecdd29f3bd05..0867fab61b1905 100644
+--- a/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c
++++ b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c
+@@ -196,6 +196,7 @@ static void octep_pfvf_get_mac_addr(struct octep_device *oct, u32 vf_id,
+ vf_id);
+ return;
+ }
++ ether_addr_copy(oct->vf_info[vf_id].mac_addr, rsp->s_set_mac.mac_addr);
+ rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
+ }
+
+@@ -205,6 +206,8 @@ static void octep_pfvf_dev_remove(struct octep_device *oct, u32 vf_id,
+ {
+ int err;
+
++ /* Reset VF-specific information maintained by the PF */
++ memset(&oct->vf_info[vf_id], 0, sizeof(struct octep_pfvf_info));
+ err = octep_ctrl_net_dev_remove(oct, vf_id);
+ if (err) {
+ rsp->s.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
+diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ptp.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ptp.c
+index 63130ba37e9df1..69b435ed8fbbe9 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ptp.c
++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ptp.c
+@@ -491,7 +491,7 @@ void otx2_ptp_destroy(struct otx2_nic *pfvf)
+ if (!ptp)
+ return;
+
+- cancel_delayed_work(&pfvf->ptp->synctstamp_work);
++ cancel_delayed_work_sync(&pfvf->ptp->synctstamp_work);
+
+ ptp_clock_unregister(ptp->ptp_clock);
+ kfree(ptp);
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/fs.h b/drivers/net/ethernet/mellanox/mlx5/core/en/fs.h
+index 9560fcba643f50..ac65e319148029 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en/fs.h
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/fs.h
+@@ -92,6 +92,7 @@ enum {
+ MLX5E_ACCEL_FS_ESP_FT_LEVEL = MLX5E_INNER_TTC_FT_LEVEL + 1,
+ MLX5E_ACCEL_FS_ESP_FT_ERR_LEVEL,
+ MLX5E_ACCEL_FS_POL_FT_LEVEL,
++ MLX5E_ACCEL_FS_POL_MISS_FT_LEVEL,
+ MLX5E_ACCEL_FS_ESP_FT_ROCE_LEVEL,
+ #endif
+ };
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h
+index ffcd0cdeb77544..23703f28386ad9 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h
+@@ -185,6 +185,7 @@ struct mlx5e_ipsec_rx_create_attr {
+ u32 family;
+ int prio;
+ int pol_level;
++ int pol_miss_level;
+ int sa_level;
+ int status_level;
+ enum mlx5_flow_namespace_type chains_ns;
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c
+index 98b6a3a623f995..65dc3529283b69 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c
+@@ -747,6 +747,7 @@ static void ipsec_rx_create_attr_set(struct mlx5e_ipsec *ipsec,
+ attr->family = family;
+ attr->prio = MLX5E_NIC_PRIO;
+ attr->pol_level = MLX5E_ACCEL_FS_POL_FT_LEVEL;
++ attr->pol_miss_level = MLX5E_ACCEL_FS_POL_MISS_FT_LEVEL;
+ attr->sa_level = MLX5E_ACCEL_FS_ESP_FT_LEVEL;
+ attr->status_level = MLX5E_ACCEL_FS_ESP_FT_ERR_LEVEL;
+ attr->chains_ns = MLX5_FLOW_NAMESPACE_KERNEL;
+@@ -833,7 +834,7 @@ static int ipsec_rx_chains_create_miss(struct mlx5e_ipsec *ipsec,
+
+ ft_attr.max_fte = 1;
+ ft_attr.autogroup.max_num_groups = 1;
+- ft_attr.level = attr->pol_level;
++ ft_attr.level = attr->pol_miss_level;
+ ft_attr.prio = attr->prio;
+
+ ft = mlx5_create_auto_grouped_flow_table(attr->ns, &ft_attr);
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+index e39c51cfc8e6c2..f0142d32b648f5 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+@@ -136,8 +136,6 @@ void mlx5e_update_carrier(struct mlx5e_priv *priv)
+ if (up) {
+ netdev_info(priv->netdev, "Link up\n");
+ netif_carrier_on(priv->netdev);
+- mlx5e_port_manual_buffer_config(priv, 0, priv->netdev->mtu,
+- NULL, NULL, NULL);
+ } else {
+ netdev_info(priv->netdev, "Link down\n");
+ netif_carrier_off(priv->netdev);
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+index 63a7a788fb0db5..cd0242eb008c29 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+@@ -1506,12 +1506,21 @@ static const struct mlx5e_profile mlx5e_uplink_rep_profile = {
+ static int
+ mlx5e_vport_uplink_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
+ {
+- struct mlx5e_priv *priv = netdev_priv(mlx5_uplink_netdev_get(dev));
+ struct mlx5e_rep_priv *rpriv = mlx5e_rep_to_rep_priv(rep);
++ struct net_device *netdev;
++ struct mlx5e_priv *priv;
++ int err;
++
++ netdev = mlx5_uplink_netdev_get(dev);
++ if (!netdev)
++ return 0;
+
++ priv = netdev_priv(netdev);
+ rpriv->netdev = priv->netdev;
+- return mlx5e_netdev_change_profile(priv, &mlx5e_uplink_rep_profile,
+- rpriv);
++ err = mlx5e_netdev_change_profile(priv, &mlx5e_uplink_rep_profile,
++ rpriv);
++ mlx5_uplink_netdev_put(dev, netdev);
++ return err;
+ }
+
+ static void
+@@ -1638,8 +1647,16 @@ mlx5e_vport_rep_unload(struct mlx5_eswitch_rep *rep)
+ {
+ struct mlx5e_rep_priv *rpriv = mlx5e_rep_to_rep_priv(rep);
+ struct net_device *netdev = rpriv->netdev;
+- struct mlx5e_priv *priv = netdev_priv(netdev);
+- void *ppriv = priv->ppriv;
++ struct mlx5e_priv *priv;
++ void *ppriv;
++
++ if (!netdev) {
++ ppriv = rpriv;
++ goto free_ppriv;
++ }
++
++ priv = netdev_priv(netdev);
++ ppriv = priv->ppriv;
+
+ if (rep->vport == MLX5_VPORT_UPLINK) {
+ mlx5e_vport_uplink_rep_unload(rpriv);
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c
+index ad9f6fca9b6a20..c6476e943e98d4 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c
+@@ -743,6 +743,7 @@ static u32 mlx5_esw_qos_lag_link_speed_get_locked(struct mlx5_core_dev *mdev)
+ speed = lksettings.base.speed;
+
+ out:
++ mlx5_uplink_netdev_put(mdev, slave);
+ return speed;
+ }
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
+index 29ce09af59aef0..3b57ef6b3de383 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
+@@ -114,9 +114,9 @@
+ #define ETHTOOL_NUM_PRIOS 11
+ #define ETHTOOL_MIN_LEVEL (KERNEL_MIN_LEVEL + ETHTOOL_NUM_PRIOS)
+ /* Vlan, mac, ttc, inner ttc, {UDP/ANY/aRFS/accel/{esp, esp_err}}, IPsec policy,
+- * {IPsec RoCE MPV,Alias table},IPsec RoCE policy
++ * IPsec policy miss, {IPsec RoCE MPV,Alias table},IPsec RoCE policy
+ */
+-#define KERNEL_NIC_PRIO_NUM_LEVELS 10
++#define KERNEL_NIC_PRIO_NUM_LEVELS 11
+ #define KERNEL_NIC_NUM_PRIOS 1
+ /* One more level for tc, and one more for promisc */
+ #define KERNEL_MIN_LEVEL (KERNEL_NIC_PRIO_NUM_LEVELS + 2)
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/mlx5.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/mlx5.h
+index 37d5f445598c7b..a7486e6d0d5eff 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/mlx5.h
++++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/mlx5.h
+@@ -52,7 +52,20 @@ static inline struct net *mlx5_core_net(struct mlx5_core_dev *dev)
+
+ static inline struct net_device *mlx5_uplink_netdev_get(struct mlx5_core_dev *mdev)
+ {
+- return mdev->mlx5e_res.uplink_netdev;
++ struct mlx5e_resources *mlx5e_res = &mdev->mlx5e_res;
++ struct net_device *netdev;
++
++ mutex_lock(&mlx5e_res->uplink_netdev_lock);
++ netdev = mlx5e_res->uplink_netdev;
++ netdev_hold(netdev, &mlx5e_res->tracker, GFP_KERNEL);
++ mutex_unlock(&mlx5e_res->uplink_netdev_lock);
++ return netdev;
++}
++
++static inline void mlx5_uplink_netdev_put(struct mlx5_core_dev *mdev,
++ struct net_device *netdev)
++{
++ netdev_put(netdev, &mdev->mlx5e_res.tracker);
+ }
+
+ struct mlx5_sd;
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c b/drivers/net/ethernet/mellanox/mlx5/core/port.c
+index 2d7adf7444ba29..aa9f2b0a77d36f 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/port.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c
+@@ -1170,7 +1170,11 @@ const struct mlx5_link_info *mlx5_port_ptys2info(struct mlx5_core_dev *mdev,
+ mlx5e_port_get_link_mode_info_arr(mdev, &table, &max_size,
+ force_legacy);
+ i = find_first_bit(&temp, max_size);
+- if (i < max_size)
++
++ /* mlx5e_link_info has holes. Check speed
++ * is not zero as indication of one.
++ */
++ if (i < max_size && table[i].speed)
+ return &table[i];
+
+ return NULL;
+diff --git a/drivers/net/ethernet/natsemi/ns83820.c b/drivers/net/ethernet/natsemi/ns83820.c
+index 56d5464222d97a..cdbf82affa7bea 100644
+--- a/drivers/net/ethernet/natsemi/ns83820.c
++++ b/drivers/net/ethernet/natsemi/ns83820.c
+@@ -820,7 +820,7 @@ static void rx_irq(struct net_device *ndev)
+ struct ns83820 *dev = PRIV(ndev);
+ struct rx_info *info = &dev->rx_info;
+ unsigned next_rx;
+- int rx_rc, len;
++ int len;
+ u32 cmdsts;
+ __le32 *desc;
+ unsigned long flags;
+@@ -881,8 +881,10 @@ static void rx_irq(struct net_device *ndev)
+ if (likely(CMDSTS_OK & cmdsts)) {
+ #endif
+ skb_put(skb, len);
+- if (unlikely(!skb))
++ if (unlikely(!skb)) {
++ ndev->stats.rx_dropped++;
+ goto netdev_mangle_me_harder_failed;
++ }
+ if (cmdsts & CMDSTS_DEST_MULTI)
+ ndev->stats.multicast++;
+ ndev->stats.rx_packets++;
+@@ -901,15 +903,12 @@ static void rx_irq(struct net_device *ndev)
+ __vlan_hwaccel_put_tag(skb, htons(ETH_P_IPV6), tag);
+ }
+ #endif
+- rx_rc = netif_rx(skb);
+- if (NET_RX_DROP == rx_rc) {
+-netdev_mangle_me_harder_failed:
+- ndev->stats.rx_dropped++;
+- }
++ netif_rx(skb);
+ } else {
+ dev_kfree_skb_irq(skb);
+ }
+
++netdev_mangle_me_harder_failed:
+ nr++;
+ next_rx = info->next_rx;
+ desc = info->descs + (DESC_SIZE * next_rx);
+diff --git a/drivers/net/ethernet/qlogic/qed/qed_debug.c b/drivers/net/ethernet/qlogic/qed/qed_debug.c
+index 9c3d3dd2f84753..1f0cea3cae92f5 100644
+--- a/drivers/net/ethernet/qlogic/qed/qed_debug.c
++++ b/drivers/net/ethernet/qlogic/qed/qed_debug.c
+@@ -4462,10 +4462,11 @@ static enum dbg_status qed_protection_override_dump(struct qed_hwfn *p_hwfn,
+ goto out;
+ }
+
+- /* Add override window info to buffer */
++ /* Add override window info to buffer, preventing buffer overflow */
+ override_window_dwords =
+- qed_rd(p_hwfn, p_ptt, GRC_REG_NUMBER_VALID_OVERRIDE_WINDOW) *
+- PROTECTION_OVERRIDE_ELEMENT_DWORDS;
++ min(qed_rd(p_hwfn, p_ptt, GRC_REG_NUMBER_VALID_OVERRIDE_WINDOW) *
++ PROTECTION_OVERRIDE_ELEMENT_DWORDS,
++ PROTECTION_OVERRIDE_DEPTH_DWORDS);
+ if (override_window_dwords) {
+ addr = BYTES_TO_DWORDS(GRC_REG_PROTECTION_OVERRIDE_WINDOW);
+ offset += qed_grc_dump_addr_range(p_hwfn,
+diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c
+index 8e6ce16ab5b88f..c9e2dca3083123 100644
+--- a/drivers/net/wireless/mediatek/mt76/mac80211.c
++++ b/drivers/net/wireless/mediatek/mt76/mac80211.c
+@@ -1731,7 +1731,7 @@ EXPORT_SYMBOL_GPL(mt76_wcid_cleanup);
+
+ void mt76_wcid_add_poll(struct mt76_dev *dev, struct mt76_wcid *wcid)
+ {
+- if (test_bit(MT76_MCU_RESET, &dev->phy.state))
++ if (test_bit(MT76_MCU_RESET, &dev->phy.state) || !wcid->sta)
+ return;
+
+ spin_lock_bh(&dev->sta_poll_lock);
+diff --git a/drivers/net/wireless/microchip/wilc1000/wlan_cfg.c b/drivers/net/wireless/microchip/wilc1000/wlan_cfg.c
+index 131388886acbfa..cfabd5aebb5400 100644
+--- a/drivers/net/wireless/microchip/wilc1000/wlan_cfg.c
++++ b/drivers/net/wireless/microchip/wilc1000/wlan_cfg.c
+@@ -41,10 +41,10 @@ static const struct wilc_cfg_word g_cfg_word[] = {
+ };
+
+ static const struct wilc_cfg_str g_cfg_str[] = {
+- {WID_FIRMWARE_VERSION, NULL},
+- {WID_MAC_ADDR, NULL},
+- {WID_ASSOC_RES_INFO, NULL},
+- {WID_NIL, NULL}
++ {WID_FIRMWARE_VERSION, 0, NULL},
++ {WID_MAC_ADDR, 0, NULL},
++ {WID_ASSOC_RES_INFO, 0, NULL},
++ {WID_NIL, 0, NULL}
+ };
+
+ #define WILC_RESP_MSG_TYPE_CONFIG_REPLY 'R'
+@@ -147,44 +147,58 @@ static void wilc_wlan_parse_response_frame(struct wilc *wl, u8 *info, int size)
+
+ switch (FIELD_GET(WILC_WID_TYPE, wid)) {
+ case WID_CHAR:
++ len = 3;
++ if (len + 2 > size)
++ return;
++
+ while (cfg->b[i].id != WID_NIL && cfg->b[i].id != wid)
+ i++;
+
+ if (cfg->b[i].id == wid)
+ cfg->b[i].val = info[4];
+
+- len = 3;
+ break;
+
+ case WID_SHORT:
++ len = 4;
++ if (len + 2 > size)
++ return;
++
+ while (cfg->hw[i].id != WID_NIL && cfg->hw[i].id != wid)
+ i++;
+
+ if (cfg->hw[i].id == wid)
+ cfg->hw[i].val = get_unaligned_le16(&info[4]);
+
+- len = 4;
+ break;
+
+ case WID_INT:
++ len = 6;
++ if (len + 2 > size)
++ return;
++
+ while (cfg->w[i].id != WID_NIL && cfg->w[i].id != wid)
+ i++;
+
+ if (cfg->w[i].id == wid)
+ cfg->w[i].val = get_unaligned_le32(&info[4]);
+
+- len = 6;
+ break;
+
+ case WID_STR:
++ len = 2 + get_unaligned_le16(&info[2]);
++
+ while (cfg->s[i].id != WID_NIL && cfg->s[i].id != wid)
+ i++;
+
+- if (cfg->s[i].id == wid)
++ if (cfg->s[i].id == wid) {
++ if (len > cfg->s[i].len || (len + 2 > size))
++ return;
++
+ memcpy(cfg->s[i].str, &info[2],
+- get_unaligned_le16(&info[2]) + 2);
++ len);
++ }
+
+- len = 2 + get_unaligned_le16(&info[2]);
+ break;
+
+ default:
+@@ -384,12 +398,15 @@ int wilc_wlan_cfg_init(struct wilc *wl)
+ /* store the string cfg parameters */
+ wl->cfg.s[i].id = WID_FIRMWARE_VERSION;
+ wl->cfg.s[i].str = str_vals->firmware_version;
++ wl->cfg.s[i].len = sizeof(str_vals->firmware_version);
+ i++;
+ wl->cfg.s[i].id = WID_MAC_ADDR;
+ wl->cfg.s[i].str = str_vals->mac_address;
++ wl->cfg.s[i].len = sizeof(str_vals->mac_address);
+ i++;
+ wl->cfg.s[i].id = WID_ASSOC_RES_INFO;
+ wl->cfg.s[i].str = str_vals->assoc_rsp;
++ wl->cfg.s[i].len = sizeof(str_vals->assoc_rsp);
+ i++;
+ wl->cfg.s[i].id = WID_NIL;
+ wl->cfg.s[i].str = NULL;
+diff --git a/drivers/net/wireless/microchip/wilc1000/wlan_cfg.h b/drivers/net/wireless/microchip/wilc1000/wlan_cfg.h
+index 7038b74f8e8ff6..5ae74bced7d748 100644
+--- a/drivers/net/wireless/microchip/wilc1000/wlan_cfg.h
++++ b/drivers/net/wireless/microchip/wilc1000/wlan_cfg.h
+@@ -24,12 +24,13 @@ struct wilc_cfg_word {
+
+ struct wilc_cfg_str {
+ u16 id;
++ u16 len;
+ u8 *str;
+ };
+
+ struct wilc_cfg_str_vals {
+- u8 mac_address[7];
+- u8 firmware_version[129];
++ u8 mac_address[8];
++ u8 firmware_version[130];
+ u8 assoc_rsp[WILC_MAX_ASSOC_RESP_FRAME_SIZE];
+ };
+
+diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
+index 895fb163d48e6a..5395623d2ba6aa 100644
+--- a/drivers/nvme/host/core.c
++++ b/drivers/nvme/host/core.c
+@@ -903,6 +903,15 @@ static void nvme_set_ref_tag(struct nvme_ns *ns, struct nvme_command *cmnd,
+ u32 upper, lower;
+ u64 ref48;
+
++ /* only type1 and type 2 PI formats have a reftag */
++ switch (ns->head->pi_type) {
++ case NVME_NS_DPS_PI_TYPE1:
++ case NVME_NS_DPS_PI_TYPE2:
++ break;
++ default:
++ return;
++ }
++
+ /* both rw and write zeroes share the same reftag format */
+ switch (ns->head->guard_type) {
+ case NVME_NVM_NS_16B_GUARD:
+@@ -942,13 +951,7 @@ static inline blk_status_t nvme_setup_write_zeroes(struct nvme_ns *ns,
+
+ if (nvme_ns_has_pi(ns->head)) {
+ cmnd->write_zeroes.control |= cpu_to_le16(NVME_RW_PRINFO_PRACT);
+-
+- switch (ns->head->pi_type) {
+- case NVME_NS_DPS_PI_TYPE1:
+- case NVME_NS_DPS_PI_TYPE2:
+- nvme_set_ref_tag(ns, cmnd, req);
+- break;
+- }
++ nvme_set_ref_tag(ns, cmnd, req);
+ }
+
+ return BLK_STS_OK;
+@@ -1039,6 +1042,7 @@ static inline blk_status_t nvme_setup_rw(struct nvme_ns *ns,
+ if (WARN_ON_ONCE(!nvme_ns_has_pi(ns->head)))
+ return BLK_STS_NOTSUPP;
+ control |= NVME_RW_PRINFO_PRACT;
++ nvme_set_ref_tag(ns, cmnd, req);
+ }
+
+ if (bio_integrity_flagged(req->bio, BIP_CHECK_GUARD))
+diff --git a/drivers/pcmcia/omap_cf.c b/drivers/pcmcia/omap_cf.c
+index 441cdf83f5a449..d6f24c7d156227 100644
+--- a/drivers/pcmcia/omap_cf.c
++++ b/drivers/pcmcia/omap_cf.c
+@@ -304,7 +304,13 @@ static void __exit omap_cf_remove(struct platform_device *pdev)
+ kfree(cf);
+ }
+
+-static struct platform_driver omap_cf_driver = {
++/*
++ * omap_cf_remove() lives in .exit.text. For drivers registered via
++ * platform_driver_probe() this is ok because they cannot get unbound at
++ * runtime. So mark the driver struct with __refdata to prevent modpost
++ * triggering a section mismatch warning.
++ */
++static struct platform_driver omap_cf_driver __refdata = {
+ .driver = {
+ .name = driver_name,
+ },
+diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c
+index e6726be5890e7f..ce177c37994140 100644
+--- a/drivers/platform/x86/asus-nb-wmi.c
++++ b/drivers/platform/x86/asus-nb-wmi.c
+@@ -147,7 +147,12 @@ static struct quirk_entry quirk_asus_ignore_fan = {
+ };
+
+ static struct quirk_entry quirk_asus_zenbook_duo_kbd = {
+- .ignore_key_wlan = true,
++ .key_wlan_event = ASUS_WMI_KEY_IGNORE,
++};
++
++static struct quirk_entry quirk_asus_z13 = {
++ .key_wlan_event = ASUS_WMI_KEY_ARMOURY,
++ .tablet_switch_mode = asus_wmi_kbd_dock_devid,
+ };
+
+ static int dmi_matched(const struct dmi_system_id *dmi)
+@@ -539,6 +544,15 @@ static const struct dmi_system_id asus_quirks[] = {
+ },
+ .driver_data = &quirk_asus_zenbook_duo_kbd,
+ },
++ {
++ .callback = dmi_matched,
++ .ident = "ASUS ROG Z13",
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
++ DMI_MATCH(DMI_PRODUCT_NAME, "ROG Flow Z13"),
++ },
++ .driver_data = &quirk_asus_z13,
++ },
+ {},
+ };
+
+@@ -636,6 +650,7 @@ static const struct key_entry asus_nb_wmi_keymap[] = {
+ { KE_IGNORE, 0xCF, }, /* AC mode */
+ { KE_KEY, 0xFA, { KEY_PROG2 } }, /* Lid flip action */
+ { KE_KEY, 0xBD, { KEY_PROG2 } }, /* Lid flip action on ROG xflow laptops */
++ { KE_KEY, ASUS_WMI_KEY_ARMOURY, { KEY_PROG3 } },
+ { KE_END, 0},
+ };
+
+@@ -655,9 +670,11 @@ static void asus_nb_wmi_key_filter(struct asus_wmi_driver *asus_wmi, int *code,
+ if (atkbd_reports_vol_keys)
+ *code = ASUS_WMI_KEY_IGNORE;
+ break;
+- case 0x5F: /* Wireless console Disable */
+- if (quirks->ignore_key_wlan)
+- *code = ASUS_WMI_KEY_IGNORE;
++ case 0x5D: /* Wireless console Toggle */
++ case 0x5E: /* Wireless console Enable / Keyboard Attach, Detach */
++ case 0x5F: /* Wireless console Disable / Special Key */
++ if (quirks->key_wlan_event)
++ *code = quirks->key_wlan_event;
+ break;
+ }
+ }
+diff --git a/drivers/platform/x86/asus-wmi.h b/drivers/platform/x86/asus-wmi.h
+index 018dfde4025e79..5cd4392b964eb8 100644
+--- a/drivers/platform/x86/asus-wmi.h
++++ b/drivers/platform/x86/asus-wmi.h
+@@ -18,6 +18,7 @@
+ #include <linux/i8042.h>
+
+ #define ASUS_WMI_KEY_IGNORE (-1)
++#define ASUS_WMI_KEY_ARMOURY 0xffff01
+ #define ASUS_WMI_BRN_DOWN 0x2e
+ #define ASUS_WMI_BRN_UP 0x2f
+
+@@ -40,7 +41,7 @@ struct quirk_entry {
+ bool wmi_force_als_set;
+ bool wmi_ignore_fan;
+ bool filter_i8042_e1_extended_codes;
+- bool ignore_key_wlan;
++ int key_wlan_event;
+ enum asus_wmi_tablet_switch_mode tablet_switch_mode;
+ int wapf;
+ /*
+diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c
+index 93dcebbe114175..ad2d9ecf32a5ae 100644
+--- a/drivers/power/supply/bq27xxx_battery.c
++++ b/drivers/power/supply/bq27xxx_battery.c
+@@ -1919,8 +1919,8 @@ static void bq27xxx_battery_update_unlocked(struct bq27xxx_device_info *di)
+ bool has_singe_flag = di->opts & BQ27XXX_O_ZERO;
+
+ cache.flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, has_singe_flag);
+- if ((cache.flags & 0xff) == 0xff)
+- cache.flags = -1; /* read error */
++ if (di->chip == BQ27000 && (cache.flags & 0xff) == 0xff)
++ cache.flags = -ENODEV; /* bq27000 hdq read error */
+ if (cache.flags >= 0) {
+ cache.capacity = bq27xxx_battery_read_soc(di);
+
+diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c
+index 8c597fa605233a..41e4b3d4f2b581 100644
+--- a/fs/btrfs/delayed-inode.c
++++ b/fs/btrfs/delayed-inode.c
+@@ -1843,7 +1843,6 @@ static void fill_stack_inode_item(struct btrfs_trans_handle *trans,
+
+ int btrfs_fill_inode(struct btrfs_inode *inode, u32 *rdev)
+ {
+- struct btrfs_fs_info *fs_info = inode->root->fs_info;
+ struct btrfs_delayed_node *delayed_node;
+ struct btrfs_inode_item *inode_item;
+ struct inode *vfs_inode = &inode->vfs_inode;
+@@ -1864,8 +1863,6 @@ int btrfs_fill_inode(struct btrfs_inode *inode, u32 *rdev)
+ i_uid_write(vfs_inode, btrfs_stack_inode_uid(inode_item));
+ i_gid_write(vfs_inode, btrfs_stack_inode_gid(inode_item));
+ btrfs_i_size_write(inode, btrfs_stack_inode_size(inode_item));
+- btrfs_inode_set_file_extent_range(inode, 0,
+- round_up(i_size_read(vfs_inode), fs_info->sectorsize));
+ vfs_inode->i_mode = btrfs_stack_inode_mode(inode_item);
+ set_nlink(vfs_inode, btrfs_stack_inode_nlink(inode_item));
+ inode_set_bytes(vfs_inode, btrfs_stack_inode_nbytes(inode_item));
+diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
+index e266a229484852..eb73025d4e4abb 100644
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -3881,10 +3881,6 @@ static int btrfs_read_locked_inode(struct btrfs_inode *inode, struct btrfs_path
+ bool filled = false;
+ int first_xattr_slot;
+
+- ret = btrfs_init_file_extent_tree(inode);
+- if (ret)
+- goto out;
+-
+ ret = btrfs_fill_inode(inode, &rdev);
+ if (!ret)
+ filled = true;
+@@ -3916,8 +3912,6 @@ static int btrfs_read_locked_inode(struct btrfs_inode *inode, struct btrfs_path
+ i_uid_write(vfs_inode, btrfs_inode_uid(leaf, inode_item));
+ i_gid_write(vfs_inode, btrfs_inode_gid(leaf, inode_item));
+ btrfs_i_size_write(inode, btrfs_inode_size(leaf, inode_item));
+- btrfs_inode_set_file_extent_range(inode, 0,
+- round_up(i_size_read(vfs_inode), fs_info->sectorsize));
+
+ inode_set_atime(vfs_inode, btrfs_timespec_sec(leaf, &inode_item->atime),
+ btrfs_timespec_nsec(leaf, &inode_item->atime));
+@@ -3948,6 +3942,11 @@ static int btrfs_read_locked_inode(struct btrfs_inode *inode, struct btrfs_path
+ btrfs_update_inode_mapping_flags(inode);
+
+ cache_index:
++ ret = btrfs_init_file_extent_tree(inode);
++ if (ret)
++ goto out;
++ btrfs_inode_set_file_extent_range(inode, 0,
++ round_up(i_size_read(vfs_inode), fs_info->sectorsize));
+ /*
+ * If we were modified in the current generation and evicted from memory
+ * and then re-read we need to do a full sync since we don't have any
+diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c
+index 8f4703b488b71d..b59d01b976ff1d 100644
+--- a/fs/btrfs/tree-checker.c
++++ b/fs/btrfs/tree-checker.c
+@@ -1756,10 +1756,10 @@ static int check_inode_ref(struct extent_buffer *leaf,
+ while (ptr < end) {
+ u16 namelen;
+
+- if (unlikely(ptr + sizeof(iref) > end)) {
++ if (unlikely(ptr + sizeof(*iref) > end)) {
+ inode_ref_err(leaf, slot,
+ "inode ref overflow, ptr %lu end %lu inode_ref_size %zu",
+- ptr, end, sizeof(iref));
++ ptr, end, sizeof(*iref));
+ return -EUCLEAN;
+ }
+
+diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
+index 56d30ec0f52fca..5466a93a28f58f 100644
+--- a/fs/btrfs/tree-log.c
++++ b/fs/btrfs/tree-log.c
+@@ -1933,7 +1933,7 @@ static noinline int replay_one_name(struct btrfs_trans_handle *trans,
+
+ search_key.objectid = log_key.objectid;
+ search_key.type = BTRFS_INODE_EXTREF_KEY;
+- search_key.offset = key->objectid;
++ search_key.offset = btrfs_extref_hash(key->objectid, name.name, name.len);
+ ret = backref_in_log(root->log_root, &search_key, key->objectid, &name);
+ if (ret < 0) {
+ goto out;
+diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c
+index d7a1193332d941..60937127a0bc63 100644
+--- a/fs/btrfs/zoned.c
++++ b/fs/btrfs/zoned.c
+@@ -2577,9 +2577,9 @@ void btrfs_zoned_reserve_data_reloc_bg(struct btrfs_fs_info *fs_info)
+ spin_lock(&space_info->lock);
+ space_info->total_bytes -= bg->length;
+ space_info->disk_total -= bg->length * factor;
++ space_info->disk_total -= bg->zone_unusable;
+ /* There is no allocation ever happened. */
+ ASSERT(bg->used == 0);
+- ASSERT(bg->zone_unusable == 0);
+ /* No super block in a block group on the zoned setup. */
+ ASSERT(bg->bytes_super == 0);
+ spin_unlock(&space_info->lock);
+diff --git a/fs/nilfs2/sysfs.c b/fs/nilfs2/sysfs.c
+index 14868a3dd592ca..bc52afbfc5c739 100644
+--- a/fs/nilfs2/sysfs.c
++++ b/fs/nilfs2/sysfs.c
+@@ -1075,7 +1075,7 @@ void nilfs_sysfs_delete_device_group(struct the_nilfs *nilfs)
+ ************************************************************************/
+
+ static ssize_t nilfs_feature_revision_show(struct kobject *kobj,
+- struct attribute *attr, char *buf)
++ struct kobj_attribute *attr, char *buf)
+ {
+ return sysfs_emit(buf, "%d.%d\n",
+ NILFS_CURRENT_REV, NILFS_MINOR_REV);
+@@ -1087,7 +1087,7 @@ static const char features_readme_str[] =
+ "(1) revision\n\tshow current revision of NILFS file system driver.\n";
+
+ static ssize_t nilfs_feature_README_show(struct kobject *kobj,
+- struct attribute *attr,
++ struct kobj_attribute *attr,
+ char *buf)
+ {
+ return sysfs_emit(buf, features_readme_str);
+diff --git a/fs/nilfs2/sysfs.h b/fs/nilfs2/sysfs.h
+index 78a87a016928b7..d370cd5cce3f5d 100644
+--- a/fs/nilfs2/sysfs.h
++++ b/fs/nilfs2/sysfs.h
+@@ -50,16 +50,16 @@ struct nilfs_sysfs_dev_subgroups {
+ struct completion sg_segments_kobj_unregister;
+ };
+
+-#define NILFS_COMMON_ATTR_STRUCT(name) \
++#define NILFS_KOBJ_ATTR_STRUCT(name) \
+ struct nilfs_##name##_attr { \
+ struct attribute attr; \
+- ssize_t (*show)(struct kobject *, struct attribute *, \
++ ssize_t (*show)(struct kobject *, struct kobj_attribute *, \
+ char *); \
+- ssize_t (*store)(struct kobject *, struct attribute *, \
++ ssize_t (*store)(struct kobject *, struct kobj_attribute *, \
+ const char *, size_t); \
+ }
+
+-NILFS_COMMON_ATTR_STRUCT(feature);
++NILFS_KOBJ_ATTR_STRUCT(feature);
+
+ #define NILFS_DEV_ATTR_STRUCT(name) \
+ struct nilfs_##name##_attr { \
+diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h
+index 045227ed4efc96..0dcea9acca5442 100644
+--- a/fs/smb/client/cifsproto.h
++++ b/fs/smb/client/cifsproto.h
+@@ -297,8 +297,8 @@ extern void cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode);
+
+ extern void cifs_close_all_deferred_files(struct cifs_tcon *cifs_tcon);
+
+-extern void cifs_close_deferred_file_under_dentry(struct cifs_tcon *cifs_tcon,
+- const char *path);
++void cifs_close_deferred_file_under_dentry(struct cifs_tcon *cifs_tcon,
++ struct dentry *dentry);
+
+ extern void cifs_mark_open_handles_for_deleted_file(struct inode *inode,
+ const char *path);
+diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c
+index 11d442e8b3d622..0f0d2dae6283ad 100644
+--- a/fs/smb/client/inode.c
++++ b/fs/smb/client/inode.c
+@@ -1984,7 +1984,7 @@ static int __cifs_unlink(struct inode *dir, struct dentry *dentry, bool sillyren
+ }
+
+ netfs_wait_for_outstanding_io(inode);
+- cifs_close_deferred_file_under_dentry(tcon, full_path);
++ cifs_close_deferred_file_under_dentry(tcon, dentry);
+ #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
+ le64_to_cpu(tcon->fsUnixInfo.Capability))) {
+@@ -2003,8 +2003,21 @@ static int __cifs_unlink(struct inode *dir, struct dentry *dentry, bool sillyren
+ goto psx_del_no_retry;
+ }
+
+- if (sillyrename || (server->vals->protocol_id > SMB10_PROT_ID &&
+- d_is_positive(dentry) && d_count(dentry) > 2))
++ /* For SMB2+, if the file is open, we always perform a silly rename.
++ *
++ * We check for d_count() right after calling
++ * cifs_close_deferred_file_under_dentry() to make sure that the
++ * dentry's refcount gets dropped in case the file had any deferred
++ * close.
++ */
++ if (!sillyrename && server->vals->protocol_id > SMB10_PROT_ID) {
++ spin_lock(&dentry->d_lock);
++ if (d_count(dentry) > 1)
++ sillyrename = true;
++ spin_unlock(&dentry->d_lock);
++ }
++
++ if (sillyrename)
+ rc = -EBUSY;
+ else
+ rc = server->ops->unlink(xid, tcon, full_path, cifs_sb, dentry);
+@@ -2538,10 +2551,10 @@ cifs_rename2(struct mnt_idmap *idmap, struct inode *source_dir,
+ goto cifs_rename_exit;
+ }
+
+- cifs_close_deferred_file_under_dentry(tcon, from_name);
++ cifs_close_deferred_file_under_dentry(tcon, source_dentry);
+ if (d_inode(target_dentry) != NULL) {
+ netfs_wait_for_outstanding_io(d_inode(target_dentry));
+- cifs_close_deferred_file_under_dentry(tcon, to_name);
++ cifs_close_deferred_file_under_dentry(tcon, target_dentry);
+ }
+
+ rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
+diff --git a/fs/smb/client/misc.c b/fs/smb/client/misc.c
+index da23cc12a52caa..dda6dece802ad2 100644
+--- a/fs/smb/client/misc.c
++++ b/fs/smb/client/misc.c
+@@ -832,33 +832,28 @@ cifs_close_all_deferred_files(struct cifs_tcon *tcon)
+ kfree(tmp_list);
+ }
+ }
+-void
+-cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon, const char *path)
++
++void cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon,
++ struct dentry *dentry)
+ {
+- struct cifsFileInfo *cfile;
+ struct file_list *tmp_list, *tmp_next_list;
+- void *page;
+- const char *full_path;
++ struct cifsFileInfo *cfile;
+ LIST_HEAD(file_head);
+
+- page = alloc_dentry_path();
+ spin_lock(&tcon->open_file_lock);
+ list_for_each_entry(cfile, &tcon->openFileList, tlist) {
+- full_path = build_path_from_dentry(cfile->dentry, page);
+- if (strstr(full_path, path)) {
+- if (delayed_work_pending(&cfile->deferred)) {
+- if (cancel_delayed_work(&cfile->deferred)) {
+- spin_lock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
+- cifs_del_deferred_close(cfile);
+- spin_unlock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
+-
+- tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC);
+- if (tmp_list == NULL)
+- break;
+- tmp_list->cfile = cfile;
+- list_add_tail(&tmp_list->list, &file_head);
+- }
+- }
++ if ((cfile->dentry == dentry) &&
++ delayed_work_pending(&cfile->deferred) &&
++ cancel_delayed_work(&cfile->deferred)) {
++ spin_lock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
++ cifs_del_deferred_close(cfile);
++ spin_unlock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
++
++ tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC);
++ if (tmp_list == NULL)
++ break;
++ tmp_list->cfile = cfile;
++ list_add_tail(&tmp_list->list, &file_head);
+ }
+ }
+ spin_unlock(&tcon->open_file_lock);
+@@ -868,7 +863,6 @@ cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon, const char *path)
+ list_del(&tmp_list->list);
+ kfree(tmp_list);
+ }
+- free_dentry_path(page);
+ }
+
+ /*
+diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c
+index b9bb531717a651..6dd2a1c66df3db 100644
+--- a/fs/smb/client/smbdirect.c
++++ b/fs/smb/client/smbdirect.c
+@@ -13,23 +13,23 @@
+ #include "cifsproto.h"
+ #include "smb2proto.h"
+
+-static struct smbd_response *get_receive_buffer(
++static struct smbdirect_recv_io *get_receive_buffer(
+ struct smbd_connection *info);
+ static void put_receive_buffer(
+ struct smbd_connection *info,
+- struct smbd_response *response);
++ struct smbdirect_recv_io *response);
+ static int allocate_receive_buffers(struct smbd_connection *info, int num_buf);
+ static void destroy_receive_buffers(struct smbd_connection *info);
+
+ static void enqueue_reassembly(
+ struct smbd_connection *info,
+- struct smbd_response *response, int data_length);
+-static struct smbd_response *_get_first_reassembly(
++ struct smbdirect_recv_io *response, int data_length);
++static struct smbdirect_recv_io *_get_first_reassembly(
+ struct smbd_connection *info);
+
+ static int smbd_post_recv(
+ struct smbd_connection *info,
+- struct smbd_response *response);
++ struct smbdirect_recv_io *response);
+
+ static int smbd_post_send_empty(struct smbd_connection *info);
+
+@@ -260,7 +260,7 @@ static inline void *smbd_request_payload(struct smbd_request *request)
+ return (void *)request->packet;
+ }
+
+-static inline void *smbd_response_payload(struct smbd_response *response)
++static inline void *smbdirect_recv_io_payload(struct smbdirect_recv_io *response)
+ {
+ return (void *)response->packet;
+ }
+@@ -315,12 +315,13 @@ static void dump_smbdirect_negotiate_resp(struct smbdirect_negotiate_resp *resp)
+ * return value: true if negotiation is a success, false if failed
+ */
+ static bool process_negotiation_response(
+- struct smbd_response *response, int packet_length)
++ struct smbdirect_recv_io *response, int packet_length)
+ {
+- struct smbd_connection *info = response->info;
+- struct smbdirect_socket *sc = &info->socket;
++ struct smbdirect_socket *sc = response->socket;
++ struct smbd_connection *info =
++ container_of(sc, struct smbd_connection, socket);
+ struct smbdirect_socket_parameters *sp = &sc->parameters;
+- struct smbdirect_negotiate_resp *packet = smbd_response_payload(response);
++ struct smbdirect_negotiate_resp *packet = smbdirect_recv_io_payload(response);
+
+ if (packet_length < sizeof(struct smbdirect_negotiate_resp)) {
+ log_rdma_event(ERR,
+@@ -383,6 +384,7 @@ static bool process_negotiation_response(
+ info->max_frmr_depth * PAGE_SIZE);
+ info->max_frmr_depth = sp->max_read_write_size / PAGE_SIZE;
+
++ sc->recv_io.expected = SMBDIRECT_EXPECT_DATA_TRANSFER;
+ return true;
+ }
+
+@@ -390,7 +392,7 @@ static void smbd_post_send_credits(struct work_struct *work)
+ {
+ int ret = 0;
+ int rc;
+- struct smbd_response *response;
++ struct smbdirect_recv_io *response;
+ struct smbd_connection *info =
+ container_of(work, struct smbd_connection,
+ post_send_credits_work);
+@@ -408,7 +410,6 @@ static void smbd_post_send_credits(struct work_struct *work)
+ if (!response)
+ break;
+
+- response->type = SMBD_TRANSFER_DATA;
+ response->first_segment = false;
+ rc = smbd_post_recv(info, response);
+ if (rc) {
+@@ -442,13 +443,18 @@ static void smbd_post_send_credits(struct work_struct *work)
+ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
+ {
+ struct smbdirect_data_transfer *data_transfer;
+- struct smbd_response *response =
+- container_of(wc->wr_cqe, struct smbd_response, cqe);
+- struct smbd_connection *info = response->info;
+- int data_length = 0;
++ struct smbdirect_recv_io *response =
++ container_of(wc->wr_cqe, struct smbdirect_recv_io, cqe);
++ struct smbdirect_socket *sc = response->socket;
++ struct smbdirect_socket_parameters *sp = &sc->parameters;
++ struct smbd_connection *info =
++ container_of(sc, struct smbd_connection, socket);
++ u32 data_offset = 0;
++ u32 data_length = 0;
++ u32 remaining_data_length = 0;
+
+ log_rdma_recv(INFO, "response=0x%p type=%d wc status=%d wc opcode %d byte_len=%d pkey_index=%u\n",
+- response, response->type, wc->status, wc->opcode,
++ response, sc->recv_io.expected, wc->status, wc->opcode,
+ wc->byte_len, wc->pkey_index);
+
+ if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_RECV) {
+@@ -463,10 +469,10 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
+ response->sge.length,
+ DMA_FROM_DEVICE);
+
+- switch (response->type) {
++ switch (sc->recv_io.expected) {
+ /* SMBD negotiation response */
+- case SMBD_NEGOTIATE_RESP:
+- dump_smbdirect_negotiate_resp(smbd_response_payload(response));
++ case SMBDIRECT_EXPECT_NEGOTIATE_REP:
++ dump_smbdirect_negotiate_resp(smbdirect_recv_io_payload(response));
+ info->full_packet_received = true;
+ info->negotiate_done =
+ process_negotiation_response(response, wc->byte_len);
+@@ -475,9 +481,24 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
+ return;
+
+ /* SMBD data transfer packet */
+- case SMBD_TRANSFER_DATA:
+- data_transfer = smbd_response_payload(response);
++ case SMBDIRECT_EXPECT_DATA_TRANSFER:
++ data_transfer = smbdirect_recv_io_payload(response);
++
++ if (wc->byte_len <
++ offsetof(struct smbdirect_data_transfer, padding))
++ goto error;
++
++ remaining_data_length = le32_to_cpu(data_transfer->remaining_data_length);
++ data_offset = le32_to_cpu(data_transfer->data_offset);
+ data_length = le32_to_cpu(data_transfer->data_length);
++ if (wc->byte_len < data_offset ||
++ (u64)wc->byte_len < (u64)data_offset + data_length)
++ goto error;
++
++ if (remaining_data_length > sp->max_fragmented_recv_size ||
++ data_length > sp->max_fragmented_recv_size ||
++ (u64)remaining_data_length + (u64)data_length > (u64)sp->max_fragmented_recv_size)
++ goto error;
+
+ if (data_length) {
+ if (info->full_packet_received)
+@@ -526,13 +547,17 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
+ put_receive_buffer(info, response);
+
+ return;
++
++ case SMBDIRECT_EXPECT_NEGOTIATE_REQ:
++ /* Only server... */
++ break;
+ }
+
+ /*
+ * This is an internal error!
+ */
+- log_rdma_recv(ERR, "unexpected response type=%d\n", response->type);
+- WARN_ON_ONCE(response->type != SMBD_TRANSFER_DATA);
++ log_rdma_recv(ERR, "unexpected response type=%d\n", sc->recv_io.expected);
++ WARN_ON_ONCE(sc->recv_io.expected != SMBDIRECT_EXPECT_DATA_TRANSFER);
+ error:
+ put_receive_buffer(info, response);
+ smbd_disconnect_rdma_connection(info);
+@@ -1029,7 +1054,7 @@ static int smbd_post_send_full_iter(struct smbd_connection *info,
+ * The interaction is controlled by send/receive credit system
+ */
+ static int smbd_post_recv(
+- struct smbd_connection *info, struct smbd_response *response)
++ struct smbd_connection *info, struct smbdirect_recv_io *response)
+ {
+ struct smbdirect_socket *sc = &info->socket;
+ struct smbdirect_socket_parameters *sp = &sc->parameters;
+@@ -1067,16 +1092,19 @@ static int smbd_post_recv(
+ /* Perform SMBD negotiate according to [MS-SMBD] 3.1.5.2 */
+ static int smbd_negotiate(struct smbd_connection *info)
+ {
++ struct smbdirect_socket *sc = &info->socket;
+ int rc;
+- struct smbd_response *response = get_receive_buffer(info);
++ struct smbdirect_recv_io *response = get_receive_buffer(info);
+
+- response->type = SMBD_NEGOTIATE_RESP;
++ sc->recv_io.expected = SMBDIRECT_EXPECT_NEGOTIATE_REP;
+ rc = smbd_post_recv(info, response);
+ log_rdma_event(INFO, "smbd_post_recv rc=%d iov.addr=0x%llx iov.length=%u iov.lkey=0x%x\n",
+ rc, response->sge.addr,
+ response->sge.length, response->sge.lkey);
+- if (rc)
++ if (rc) {
++ put_receive_buffer(info, response);
+ return rc;
++ }
+
+ init_completion(&info->negotiate_completion);
+ info->negotiate_done = false;
+@@ -1113,7 +1141,7 @@ static int smbd_negotiate(struct smbd_connection *info)
+ */
+ static void enqueue_reassembly(
+ struct smbd_connection *info,
+- struct smbd_response *response,
++ struct smbdirect_recv_io *response,
+ int data_length)
+ {
+ spin_lock(&info->reassembly_queue_lock);
+@@ -1137,14 +1165,14 @@ static void enqueue_reassembly(
+ * Caller is responsible for locking
+ * return value: the first entry if any, NULL if queue is empty
+ */
+-static struct smbd_response *_get_first_reassembly(struct smbd_connection *info)
++static struct smbdirect_recv_io *_get_first_reassembly(struct smbd_connection *info)
+ {
+- struct smbd_response *ret = NULL;
++ struct smbdirect_recv_io *ret = NULL;
+
+ if (!list_empty(&info->reassembly_queue)) {
+ ret = list_first_entry(
+ &info->reassembly_queue,
+- struct smbd_response, list);
++ struct smbdirect_recv_io, list);
+ }
+ return ret;
+ }
+@@ -1155,16 +1183,16 @@ static struct smbd_response *_get_first_reassembly(struct smbd_connection *info)
+ * pre-allocated in advance.
+ * return value: the receive buffer, NULL if none is available
+ */
+-static struct smbd_response *get_receive_buffer(struct smbd_connection *info)
++static struct smbdirect_recv_io *get_receive_buffer(struct smbd_connection *info)
+ {
+- struct smbd_response *ret = NULL;
++ struct smbdirect_recv_io *ret = NULL;
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->receive_queue_lock, flags);
+ if (!list_empty(&info->receive_queue)) {
+ ret = list_first_entry(
+ &info->receive_queue,
+- struct smbd_response, list);
++ struct smbdirect_recv_io, list);
+ list_del(&ret->list);
+ info->count_receive_queue--;
+ info->count_get_receive_buffer++;
+@@ -1181,7 +1209,7 @@ static struct smbd_response *get_receive_buffer(struct smbd_connection *info)
+ * receive buffer is returned.
+ */
+ static void put_receive_buffer(
+- struct smbd_connection *info, struct smbd_response *response)
++ struct smbd_connection *info, struct smbdirect_recv_io *response)
+ {
+ struct smbdirect_socket *sc = &info->socket;
+ unsigned long flags;
+@@ -1206,8 +1234,9 @@ static void put_receive_buffer(
+ /* Preallocate all receive buffer on transport establishment */
+ static int allocate_receive_buffers(struct smbd_connection *info, int num_buf)
+ {
++ struct smbdirect_socket *sc = &info->socket;
++ struct smbdirect_recv_io *response;
+ int i;
+- struct smbd_response *response;
+
+ INIT_LIST_HEAD(&info->reassembly_queue);
+ spin_lock_init(&info->reassembly_queue_lock);
+@@ -1225,7 +1254,7 @@ static int allocate_receive_buffers(struct smbd_connection *info, int num_buf)
+ if (!response)
+ goto allocate_failed;
+
+- response->info = info;
++ response->socket = sc;
+ response->sge.length = 0;
+ list_add_tail(&response->list, &info->receive_queue);
+ info->count_receive_queue++;
+@@ -1237,7 +1266,7 @@ static int allocate_receive_buffers(struct smbd_connection *info, int num_buf)
+ while (!list_empty(&info->receive_queue)) {
+ response = list_first_entry(
+ &info->receive_queue,
+- struct smbd_response, list);
++ struct smbdirect_recv_io, list);
+ list_del(&response->list);
+ info->count_receive_queue--;
+
+@@ -1248,7 +1277,7 @@ static int allocate_receive_buffers(struct smbd_connection *info, int num_buf)
+
+ static void destroy_receive_buffers(struct smbd_connection *info)
+ {
+- struct smbd_response *response;
++ struct smbdirect_recv_io *response;
+
+ while ((response = get_receive_buffer(info)))
+ mempool_free(response, info->response_mempool);
+@@ -1289,7 +1318,7 @@ void smbd_destroy(struct TCP_Server_Info *server)
+ struct smbd_connection *info = server->smbd_conn;
+ struct smbdirect_socket *sc;
+ struct smbdirect_socket_parameters *sp;
+- struct smbd_response *response;
++ struct smbdirect_recv_io *response;
+ unsigned long flags;
+
+ if (!info) {
+@@ -1308,13 +1337,16 @@ void smbd_destroy(struct TCP_Server_Info *server)
+ sc->status == SMBDIRECT_SOCKET_DISCONNECTED);
+ }
+
++ log_rdma_event(INFO, "cancelling post_send_credits_work\n");
++ disable_work_sync(&info->post_send_credits_work);
++
+ log_rdma_event(INFO, "destroying qp\n");
+ ib_drain_qp(sc->ib.qp);
+ rdma_destroy_qp(sc->rdma.cm_id);
+ sc->ib.qp = NULL;
+
+ log_rdma_event(INFO, "cancelling idle timer\n");
+- cancel_delayed_work_sync(&info->idle_timer_work);
++ disable_delayed_work_sync(&info->idle_timer_work);
+
+ /* It's not possible for upper layer to get to reassembly */
+ log_rdma_event(INFO, "drain the reassembly queue\n");
+@@ -1446,17 +1478,17 @@ static int allocate_caches_and_workqueue(struct smbd_connection *info)
+ if (!info->request_mempool)
+ goto out1;
+
+- scnprintf(name, MAX_NAME_LEN, "smbd_response_%p", info);
++ scnprintf(name, MAX_NAME_LEN, "smbdirect_recv_io_%p", info);
+
+ struct kmem_cache_args response_args = {
+- .align = __alignof__(struct smbd_response),
+- .useroffset = (offsetof(struct smbd_response, packet) +
++ .align = __alignof__(struct smbdirect_recv_io),
++ .useroffset = (offsetof(struct smbdirect_recv_io, packet) +
+ sizeof(struct smbdirect_data_transfer)),
+ .usersize = sp->max_recv_size - sizeof(struct smbdirect_data_transfer),
+ };
+ info->response_cache =
+ kmem_cache_create(name,
+- sizeof(struct smbd_response) + sp->max_recv_size,
++ sizeof(struct smbdirect_recv_io) + sp->max_recv_size,
+ &response_args, SLAB_HWCACHE_ALIGN);
+ if (!info->response_cache)
+ goto out2;
+@@ -1686,7 +1718,7 @@ static struct smbd_connection *_smbd_get_connection(
+ return NULL;
+
+ negotiation_failed:
+- cancel_delayed_work_sync(&info->idle_timer_work);
++ disable_delayed_work_sync(&info->idle_timer_work);
+ destroy_caches_and_workqueue(info);
+ sc->status = SMBDIRECT_SOCKET_NEGOTIATE_FAILED;
+ rdma_disconnect(sc->rdma.cm_id);
+@@ -1747,7 +1779,7 @@ struct smbd_connection *smbd_get_connection(
+ int smbd_recv(struct smbd_connection *info, struct msghdr *msg)
+ {
+ struct smbdirect_socket *sc = &info->socket;
+- struct smbd_response *response;
++ struct smbdirect_recv_io *response;
+ struct smbdirect_data_transfer *data_transfer;
+ size_t size = iov_iter_count(&msg->msg_iter);
+ int to_copy, to_read, data_read, offset;
+@@ -1783,7 +1815,7 @@ int smbd_recv(struct smbd_connection *info, struct msghdr *msg)
+ offset = info->first_entry_offset;
+ while (data_read < size) {
+ response = _get_first_reassembly(info);
+- data_transfer = smbd_response_payload(response);
++ data_transfer = smbdirect_recv_io_payload(response);
+ data_length = le32_to_cpu(data_transfer->data_length);
+ remaining_data_length =
+ le32_to_cpu(
+@@ -2045,7 +2077,7 @@ static void destroy_mr_list(struct smbd_connection *info)
+ struct smbdirect_socket *sc = &info->socket;
+ struct smbd_mr *mr, *tmp;
+
+- cancel_work_sync(&info->mr_recovery_work);
++ disable_work_sync(&info->mr_recovery_work);
+ list_for_each_entry_safe(mr, tmp, &info->mr_list, list) {
+ if (mr->state == MR_INVALIDATED)
+ ib_dma_unmap_sg(sc->ib.dev, mr->sgt.sgl,
+diff --git a/fs/smb/client/smbdirect.h b/fs/smb/client/smbdirect.h
+index ea04ce8a9763a6..d60e445da22563 100644
+--- a/fs/smb/client/smbdirect.h
++++ b/fs/smb/client/smbdirect.h
+@@ -157,11 +157,6 @@ struct smbd_connection {
+ unsigned int count_send_empty;
+ };
+
+-enum smbd_message_type {
+- SMBD_NEGOTIATE_RESP,
+- SMBD_TRANSFER_DATA,
+-};
+-
+ /* Maximum number of SGEs used by smbdirect.c in any send work request */
+ #define SMBDIRECT_MAX_SEND_SGE 6
+
+@@ -181,24 +176,6 @@ struct smbd_request {
+ /* Maximum number of SGEs used by smbdirect.c in any receive work request */
+ #define SMBDIRECT_MAX_RECV_SGE 1
+
+-/* The context for a SMBD response */
+-struct smbd_response {
+- struct smbd_connection *info;
+- struct ib_cqe cqe;
+- struct ib_sge sge;
+-
+- enum smbd_message_type type;
+-
+- /* Link to receive queue or reassembly queue */
+- struct list_head list;
+-
+- /* Indicate if this is the 1st packet of a payload */
+- bool first_segment;
+-
+- /* SMBD packet header and payload follows this structure */
+- u8 packet[];
+-};
+-
+ /* Create a SMBDirect session */
+ struct smbd_connection *smbd_get_connection(
+ struct TCP_Server_Info *server, struct sockaddr *dstaddr);
+diff --git a/fs/smb/common/smbdirect/smbdirect_socket.h b/fs/smb/common/smbdirect/smbdirect_socket.h
+index e5b15cc44a7ba5..a7ad31c471a7b6 100644
+--- a/fs/smb/common/smbdirect/smbdirect_socket.h
++++ b/fs/smb/common/smbdirect/smbdirect_socket.h
+@@ -38,6 +38,35 @@ struct smbdirect_socket {
+ } ib;
+
+ struct smbdirect_socket_parameters parameters;
++
++ /*
++ * The state for posted receive buffers
++ */
++ struct {
++ /*
++ * The type of PDU we are expecting
++ */
++ enum {
++ SMBDIRECT_EXPECT_NEGOTIATE_REQ = 1,
++ SMBDIRECT_EXPECT_NEGOTIATE_REP = 2,
++ SMBDIRECT_EXPECT_DATA_TRANSFER = 3,
++ } expected;
++ } recv_io;
++};
++
++struct smbdirect_recv_io {
++ struct smbdirect_socket *socket;
++ struct ib_cqe cqe;
++ struct ib_sge sge;
++
++ /* Link to free or reassembly list */
++ struct list_head list;
++
++ /* Indicate if this is the 1st packet of a payload */
++ bool first_segment;
++
++ /* SMBD packet header and payload follows this structure */
++ u8 packet[];
+ };
+
+ #endif /* __FS_SMB_COMMON_SMBDIRECT_SMBDIRECT_SOCKET_H__ */
+diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
+index 5466aa8c39b1cd..6550bd9f002c27 100644
+--- a/fs/smb/server/transport_rdma.c
++++ b/fs/smb/server/transport_rdma.c
+@@ -554,7 +554,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
+ case SMB_DIRECT_MSG_DATA_TRANSFER: {
+ struct smb_direct_data_transfer *data_transfer =
+ (struct smb_direct_data_transfer *)recvmsg->packet;
+- unsigned int data_length;
++ u32 remaining_data_length, data_offset, data_length;
+ int avail_recvmsg_count, receive_credits;
+
+ if (wc->byte_len <
+@@ -564,15 +564,25 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
+ return;
+ }
+
++ remaining_data_length = le32_to_cpu(data_transfer->remaining_data_length);
+ data_length = le32_to_cpu(data_transfer->data_length);
+- if (data_length) {
+- if (wc->byte_len < sizeof(struct smb_direct_data_transfer) +
+- (u64)data_length) {
+- put_recvmsg(t, recvmsg);
+- smb_direct_disconnect_rdma_connection(t);
+- return;
+- }
++ data_offset = le32_to_cpu(data_transfer->data_offset);
++ if (wc->byte_len < data_offset ||
++ wc->byte_len < (u64)data_offset + data_length) {
++ put_recvmsg(t, recvmsg);
++ smb_direct_disconnect_rdma_connection(t);
++ return;
++ }
++ if (remaining_data_length > t->max_fragmented_recv_size ||
++ data_length > t->max_fragmented_recv_size ||
++ (u64)remaining_data_length + (u64)data_length >
++ (u64)t->max_fragmented_recv_size) {
++ put_recvmsg(t, recvmsg);
++ smb_direct_disconnect_rdma_connection(t);
++ return;
++ }
+
++ if (data_length) {
+ if (t->full_packet_received)
+ recvmsg->first_segment = true;
+
+@@ -1209,78 +1219,130 @@ static int smb_direct_writev(struct ksmbd_transport *t,
+ bool need_invalidate, unsigned int remote_key)
+ {
+ struct smb_direct_transport *st = smb_trans_direct_transfort(t);
+- int remaining_data_length;
+- int start, i, j;
+- int max_iov_size = st->max_send_size -
++ size_t remaining_data_length;
++ size_t iov_idx;
++ size_t iov_ofs;
++ size_t max_iov_size = st->max_send_size -
+ sizeof(struct smb_direct_data_transfer);
+ int ret;
+- struct kvec vec;
+ struct smb_direct_send_ctx send_ctx;
++ int error = 0;
+
+ if (st->status != SMB_DIRECT_CS_CONNECTED)
+ return -ENOTCONN;
+
+ //FIXME: skip RFC1002 header..
++ if (WARN_ON_ONCE(niovs <= 1 || iov[0].iov_len != 4))
++ return -EINVAL;
+ buflen -= 4;
++ iov_idx = 1;
++ iov_ofs = 0;
+
+ remaining_data_length = buflen;
+ ksmbd_debug(RDMA, "Sending smb (RDMA): smb_len=%u\n", buflen);
+
+ smb_direct_send_ctx_init(st, &send_ctx, need_invalidate, remote_key);
+- start = i = 1;
+- buflen = 0;
+- while (true) {
+- buflen += iov[i].iov_len;
+- if (buflen > max_iov_size) {
+- if (i > start) {
+- remaining_data_length -=
+- (buflen - iov[i].iov_len);
+- ret = smb_direct_post_send_data(st, &send_ctx,
+- &iov[start], i - start,
+- remaining_data_length);
+- if (ret)
++ while (remaining_data_length) {
++ struct kvec vecs[SMB_DIRECT_MAX_SEND_SGES - 1]; /* minus smbdirect hdr */
++ size_t possible_bytes = max_iov_size;
++ size_t possible_vecs;
++ size_t bytes = 0;
++ size_t nvecs = 0;
++
++ /*
++ * For the last message remaining_data_length should be
++ * have been 0 already!
++ */
++ if (WARN_ON_ONCE(iov_idx >= niovs)) {
++ error = -EINVAL;
++ goto done;
++ }
++
++ /*
++ * We have 2 factors which limit the arguments we pass
++ * to smb_direct_post_send_data():
++ *
++ * 1. The number of supported sges for the send,
++ * while one is reserved for the smbdirect header.
++ * And we currently need one SGE per page.
++ * 2. The number of negotiated payload bytes per send.
++ */
++ possible_vecs = min_t(size_t, ARRAY_SIZE(vecs), niovs - iov_idx);
++
++ while (iov_idx < niovs && possible_vecs && possible_bytes) {
++ struct kvec *v = &vecs[nvecs];
++ int page_count;
++
++ v->iov_base = ((u8 *)iov[iov_idx].iov_base) + iov_ofs;
++ v->iov_len = min_t(size_t,
++ iov[iov_idx].iov_len - iov_ofs,
++ possible_bytes);
++ page_count = get_buf_page_count(v->iov_base, v->iov_len);
++ if (page_count > possible_vecs) {
++ /*
++ * If the number of pages in the buffer
++ * is to much (because we currently require
++ * one SGE per page), we need to limit the
++ * length.
++ *
++ * We know possible_vecs is at least 1,
++ * so we always keep the first page.
++ *
++ * We need to calculate the number extra
++ * pages (epages) we can also keep.
++ *
++ * We calculate the number of bytes in the
++ * first page (fplen), this should never be
++ * larger than v->iov_len because page_count is
++ * at least 2, but adding a limitation feels
++ * better.
++ *
++ * Then we calculate the number of bytes (elen)
++ * we can keep for the extra pages.
++ */
++ size_t epages = possible_vecs - 1;
++ size_t fpofs = offset_in_page(v->iov_base);
++ size_t fplen = min_t(size_t, PAGE_SIZE - fpofs, v->iov_len);
++ size_t elen = min_t(size_t, v->iov_len - fplen, epages*PAGE_SIZE);
++
++ v->iov_len = fplen + elen;
++ page_count = get_buf_page_count(v->iov_base, v->iov_len);
++ if (WARN_ON_ONCE(page_count > possible_vecs)) {
++ /*
++ * Something went wrong in the above
++ * logic...
++ */
++ error = -EINVAL;
+ goto done;
+- } else {
+- /* iov[start] is too big, break it */
+- int nvec = (buflen + max_iov_size - 1) /
+- max_iov_size;
+-
+- for (j = 0; j < nvec; j++) {
+- vec.iov_base =
+- (char *)iov[start].iov_base +
+- j * max_iov_size;
+- vec.iov_len =
+- min_t(int, max_iov_size,
+- buflen - max_iov_size * j);
+- remaining_data_length -= vec.iov_len;
+- ret = smb_direct_post_send_data(st, &send_ctx, &vec, 1,
+- remaining_data_length);
+- if (ret)
+- goto done;
+ }
+- i++;
+- if (i == niovs)
+- break;
+ }
+- start = i;
+- buflen = 0;
+- } else {
+- i++;
+- if (i == niovs) {
+- /* send out all remaining vecs */
+- remaining_data_length -= buflen;
+- ret = smb_direct_post_send_data(st, &send_ctx,
+- &iov[start], i - start,
+- remaining_data_length);
+- if (ret)
+- goto done;
+- break;
++ possible_vecs -= page_count;
++ nvecs += 1;
++ possible_bytes -= v->iov_len;
++ bytes += v->iov_len;
++
++ iov_ofs += v->iov_len;
++ if (iov_ofs >= iov[iov_idx].iov_len) {
++ iov_idx += 1;
++ iov_ofs = 0;
+ }
+ }
++
++ remaining_data_length -= bytes;
++
++ ret = smb_direct_post_send_data(st, &send_ctx,
++ vecs, nvecs,
++ remaining_data_length);
++ if (unlikely(ret)) {
++ error = ret;
++ goto done;
++ }
+ }
+
+ done:
+ ret = smb_direct_flush_send_list(st, &send_ctx, true);
++ if (unlikely(!ret && error))
++ ret = error;
+
+ /*
+ * As an optimization, we don't wait for individual I/O to finish
+@@ -1744,6 +1806,11 @@ static int smb_direct_init_params(struct smb_direct_transport *t,
+ return -EINVAL;
+ }
+
++ if (device->attrs.max_send_sge < SMB_DIRECT_MAX_SEND_SGES) {
++ pr_err("warning: device max_send_sge = %d too small\n",
++ device->attrs.max_send_sge);
++ return -EINVAL;
++ }
+ if (device->attrs.max_recv_sge < SMB_DIRECT_MAX_RECV_SGES) {
+ pr_err("warning: device max_recv_sge = %d too small\n",
+ device->attrs.max_recv_sge);
+@@ -1767,7 +1834,7 @@ static int smb_direct_init_params(struct smb_direct_transport *t,
+
+ cap->max_send_wr = max_send_wrs;
+ cap->max_recv_wr = t->recv_credit_max;
+- cap->max_send_sge = max_sge_per_wr;
++ cap->max_send_sge = SMB_DIRECT_MAX_SEND_SGES;
+ cap->max_recv_sge = SMB_DIRECT_MAX_RECV_SGES;
+ cap->max_inline_data = 0;
+ cap->max_rdma_ctxs = t->max_rw_credits;
+diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h
+index f7b3b93f3a49a7..0c70f3a5557505 100644
+--- a/include/crypto/if_alg.h
++++ b/include/crypto/if_alg.h
+@@ -135,6 +135,7 @@ struct af_alg_async_req {
+ * SG?
+ * @enc: Cryptographic operation to be performed when
+ * recvmsg is invoked.
++ * @write: True if we are in the middle of a write.
+ * @init: True if metadata has been sent.
+ * @len: Length of memory allocated for this data structure.
+ * @inflight: Non-zero when AIO requests are in flight.
+@@ -151,10 +152,11 @@ struct af_alg_ctx {
+ size_t used;
+ atomic_t rcvused;
+
+- bool more;
+- bool merge;
+- bool enc;
+- bool init;
++ u32 more:1,
++ merge:1,
++ enc:1,
++ write:1,
++ init:1;
+
+ unsigned int len;
+
+diff --git a/include/linux/io_uring_types.h b/include/linux/io_uring_types.h
+index a7efcec2e3d081..215ff20affa33f 100644
+--- a/include/linux/io_uring_types.h
++++ b/include/linux/io_uring_types.h
+@@ -418,9 +418,6 @@ struct io_ring_ctx {
+ struct list_head defer_list;
+ unsigned nr_drained;
+
+- struct io_alloc_cache msg_cache;
+- spinlock_t msg_lock;
+-
+ #ifdef CONFIG_NET_RX_BUSY_POLL
+ struct list_head napi_list; /* track busy poll napi_id */
+ spinlock_t napi_lock; /* napi_list lock */
+diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
+index e6ba8f4f4bd1f4..27850ebb651b30 100644
+--- a/include/linux/mlx5/driver.h
++++ b/include/linux/mlx5/driver.h
+@@ -662,6 +662,7 @@ struct mlx5e_resources {
+ bool tisn_valid;
+ } hw_objs;
+ struct net_device *uplink_netdev;
++ netdevice_tracker tracker;
+ struct mutex uplink_netdev_lock;
+ struct mlx5_crypto_dek_priv *dek_priv;
+ };
+diff --git a/include/linux/swap.h b/include/linux/swap.h
+index bc0e1c275fc047..8b56b2bbaa4f07 100644
+--- a/include/linux/swap.h
++++ b/include/linux/swap.h
+@@ -384,6 +384,16 @@ void folio_add_lru_vma(struct folio *, struct vm_area_struct *);
+ void mark_page_accessed(struct page *);
+ void folio_mark_accessed(struct folio *);
+
++static inline bool folio_may_be_lru_cached(struct folio *folio)
++{
++ /*
++ * Holding PMD-sized folios in per-CPU LRU cache unbalances accounting.
++ * Holding small numbers of low-order mTHP folios in per-CPU LRU cache
++ * will be sensible, but nobody has implemented and tested that yet.
++ */
++ return !folio_test_large(folio);
++}
++
+ extern atomic_t lru_disable_count;
+
+ static inline bool lru_cache_disabled(void)
+diff --git a/include/net/dst_metadata.h b/include/net/dst_metadata.h
+index 4160731dcb6e3a..1fc2fb03ce3f9a 100644
+--- a/include/net/dst_metadata.h
++++ b/include/net/dst_metadata.h
+@@ -3,6 +3,7 @@
+ #define __NET_DST_METADATA_H 1
+
+ #include <linux/skbuff.h>
++#include <net/ip.h>
+ #include <net/ip_tunnels.h>
+ #include <net/macsec.h>
+ #include <net/dst.h>
+@@ -220,9 +221,15 @@ static inline struct metadata_dst *ip_tun_rx_dst(struct sk_buff *skb,
+ int md_size)
+ {
+ const struct iphdr *iph = ip_hdr(skb);
++ struct metadata_dst *tun_dst;
++
++ tun_dst = __ip_tun_set_dst(iph->saddr, iph->daddr, iph->tos, iph->ttl,
++ 0, flags, tunnel_id, md_size);
+
+- return __ip_tun_set_dst(iph->saddr, iph->daddr, iph->tos, iph->ttl,
+- 0, flags, tunnel_id, md_size);
++ if (tun_dst && (iph->frag_off & htons(IP_DF)))
++ __set_bit(IP_TUNNEL_DONT_FRAGMENT_BIT,
++ tun_dst->u.tun_info.key.tun_flags);
++ return tun_dst;
+ }
+
+ static inline struct metadata_dst *__ipv6_tun_set_dst(const struct in6_addr *saddr,
+diff --git a/include/net/sock.h b/include/net/sock.h
+index a348ae145eda43..6e9f4c126672d0 100644
+--- a/include/net/sock.h
++++ b/include/net/sock.h
+@@ -2061,6 +2061,9 @@ static inline void sk_set_socket(struct sock *sk, struct socket *sock)
+ if (sock) {
+ WRITE_ONCE(sk->sk_uid, SOCK_INODE(sock)->i_uid);
+ WRITE_ONCE(sk->sk_ino, SOCK_INODE(sock)->i_ino);
++ } else {
++ /* Note: sk_uid is unchanged. */
++ WRITE_ONCE(sk->sk_ino, 0);
+ }
+ }
+
+@@ -2082,8 +2085,6 @@ static inline void sock_orphan(struct sock *sk)
+ sock_set_flag(sk, SOCK_DEAD);
+ sk_set_socket(sk, NULL);
+ sk->sk_wq = NULL;
+- /* Note: sk_uid is unchanged. */
+- WRITE_ONCE(sk->sk_ino, 0);
+ write_unlock_bh(&sk->sk_callback_lock);
+ }
+
+diff --git a/include/sound/sdca.h b/include/sound/sdca.h
+index 5a5d6de78d7283..9c6a351c9d474f 100644
+--- a/include/sound/sdca.h
++++ b/include/sound/sdca.h
+@@ -46,6 +46,7 @@ struct sdca_device_data {
+
+ enum sdca_quirk {
+ SDCA_QUIRKS_RT712_VB,
++ SDCA_QUIRKS_SKIP_FUNC_TYPE_PATCHING,
+ };
+
+ #if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_SND_SOC_SDCA)
+diff --git a/include/uapi/linux/mptcp.h b/include/uapi/linux/mptcp.h
+index 67d015df8893cc..5fd5b4cf75ca1e 100644
+--- a/include/uapi/linux/mptcp.h
++++ b/include/uapi/linux/mptcp.h
+@@ -31,6 +31,8 @@
+ #define MPTCP_INFO_FLAG_FALLBACK _BITUL(0)
+ #define MPTCP_INFO_FLAG_REMOTE_KEY_RECEIVED _BITUL(1)
+
++#define MPTCP_PM_EV_FLAG_DENY_JOIN_ID0 _BITUL(0)
++
+ #define MPTCP_PM_ADDR_FLAG_SIGNAL (1 << 0)
+ #define MPTCP_PM_ADDR_FLAG_SUBFLOW (1 << 1)
+ #define MPTCP_PM_ADDR_FLAG_BACKUP (1 << 2)
+diff --git a/include/uapi/linux/mptcp_pm.h b/include/uapi/linux/mptcp_pm.h
+index 6ac84b2f636ca2..7359d34da446b9 100644
+--- a/include/uapi/linux/mptcp_pm.h
++++ b/include/uapi/linux/mptcp_pm.h
+@@ -16,10 +16,10 @@
+ * good time to allocate memory and send ADD_ADDR if needed. Depending on the
+ * traffic-patterns it can take a long time until the MPTCP_EVENT_ESTABLISHED
+ * is sent. Attributes: token, family, saddr4 | saddr6, daddr4 | daddr6,
+- * sport, dport, server-side.
++ * sport, dport, server-side, [flags].
+ * @MPTCP_EVENT_ESTABLISHED: A MPTCP connection is established (can start new
+ * subflows). Attributes: token, family, saddr4 | saddr6, daddr4 | daddr6,
+- * sport, dport, server-side.
++ * sport, dport, server-side, [flags].
+ * @MPTCP_EVENT_CLOSED: A MPTCP connection has stopped. Attribute: token.
+ * @MPTCP_EVENT_ANNOUNCED: A new address has been announced by the peer.
+ * Attributes: token, rem_id, family, daddr4 | daddr6 [, dport].
+diff --git a/io_uring/io-wq.c b/io_uring/io-wq.c
+index 17dfaa0395c46b..1d03b2fc4b2594 100644
+--- a/io_uring/io-wq.c
++++ b/io_uring/io-wq.c
+@@ -352,16 +352,16 @@ static void create_worker_cb(struct callback_head *cb)
+ struct io_wq *wq;
+
+ struct io_wq_acct *acct;
+- bool do_create = false;
++ bool activated_free_worker, do_create = false;
+
+ worker = container_of(cb, struct io_worker, create_work);
+ wq = worker->wq;
+ acct = worker->acct;
+
+ rcu_read_lock();
+- do_create = !io_acct_activate_free_worker(acct);
++ activated_free_worker = io_acct_activate_free_worker(acct);
+ rcu_read_unlock();
+- if (!do_create)
++ if (activated_free_worker)
+ goto no_need_create;
+
+ raw_spin_lock(&acct->workers_lock);
+diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
+index 5111ec040c5342..eaa5410e5a70a1 100644
+--- a/io_uring/io_uring.c
++++ b/io_uring/io_uring.c
+@@ -290,7 +290,6 @@ static void io_free_alloc_caches(struct io_ring_ctx *ctx)
+ io_alloc_cache_free(&ctx->netmsg_cache, io_netmsg_cache_free);
+ io_alloc_cache_free(&ctx->rw_cache, io_rw_cache_free);
+ io_alloc_cache_free(&ctx->cmd_cache, io_cmd_cache_free);
+- io_alloc_cache_free(&ctx->msg_cache, kfree);
+ io_futex_cache_free(ctx);
+ io_rsrc_cache_free(ctx);
+ }
+@@ -337,9 +336,6 @@ static __cold struct io_ring_ctx *io_ring_ctx_alloc(struct io_uring_params *p)
+ ret |= io_alloc_cache_init(&ctx->cmd_cache, IO_ALLOC_CACHE_MAX,
+ sizeof(struct io_async_cmd),
+ sizeof(struct io_async_cmd));
+- spin_lock_init(&ctx->msg_lock);
+- ret |= io_alloc_cache_init(&ctx->msg_cache, IO_ALLOC_CACHE_MAX,
+- sizeof(struct io_kiocb), 0);
+ ret |= io_futex_cache_init(ctx);
+ ret |= io_rsrc_cache_init(ctx);
+ if (ret)
+@@ -1371,8 +1367,10 @@ static void io_req_task_cancel(struct io_kiocb *req, io_tw_token_t tw)
+
+ void io_req_task_submit(struct io_kiocb *req, io_tw_token_t tw)
+ {
+- io_tw_lock(req->ctx, tw);
+- if (unlikely(io_should_terminate_tw()))
++ struct io_ring_ctx *ctx = req->ctx;
++
++ io_tw_lock(ctx, tw);
++ if (unlikely(io_should_terminate_tw(ctx)))
+ io_req_defer_failed(req, -EFAULT);
+ else if (req->flags & REQ_F_FORCE_ASYNC)
+ io_queue_iowq(req);
+diff --git a/io_uring/io_uring.h b/io_uring/io_uring.h
+index 66c1ca73f55ee5..336689752d9fe1 100644
+--- a/io_uring/io_uring.h
++++ b/io_uring/io_uring.h
+@@ -470,9 +470,9 @@ static inline bool io_allowed_run_tw(struct io_ring_ctx *ctx)
+ * 2) PF_KTHREAD is set, in which case the invoker of the task_work is
+ * our fallback task_work.
+ */
+-static inline bool io_should_terminate_tw(void)
++static inline bool io_should_terminate_tw(struct io_ring_ctx *ctx)
+ {
+- return current->flags & (PF_KTHREAD | PF_EXITING);
++ return (current->flags & (PF_KTHREAD | PF_EXITING)) || percpu_ref_is_dying(&ctx->refs);
+ }
+
+ static inline void io_req_queue_tw_complete(struct io_kiocb *req, s32 res)
+diff --git a/io_uring/msg_ring.c b/io_uring/msg_ring.c
+index 4c2578f2efcb0e..5e5b94236d7204 100644
+--- a/io_uring/msg_ring.c
++++ b/io_uring/msg_ring.c
+@@ -11,7 +11,6 @@
+ #include "io_uring.h"
+ #include "rsrc.h"
+ #include "filetable.h"
+-#include "alloc_cache.h"
+ #include "msg_ring.h"
+
+ /* All valid masks for MSG_RING */
+@@ -76,13 +75,7 @@ static void io_msg_tw_complete(struct io_kiocb *req, io_tw_token_t tw)
+ struct io_ring_ctx *ctx = req->ctx;
+
+ io_add_aux_cqe(ctx, req->cqe.user_data, req->cqe.res, req->cqe.flags);
+- if (spin_trylock(&ctx->msg_lock)) {
+- if (io_alloc_cache_put(&ctx->msg_cache, req))
+- req = NULL;
+- spin_unlock(&ctx->msg_lock);
+- }
+- if (req)
+- kfree_rcu(req, rcu_head);
++ kfree_rcu(req, rcu_head);
+ percpu_ref_put(&ctx->refs);
+ }
+
+@@ -104,26 +97,13 @@ static int io_msg_remote_post(struct io_ring_ctx *ctx, struct io_kiocb *req,
+ return 0;
+ }
+
+-static struct io_kiocb *io_msg_get_kiocb(struct io_ring_ctx *ctx)
+-{
+- struct io_kiocb *req = NULL;
+-
+- if (spin_trylock(&ctx->msg_lock)) {
+- req = io_alloc_cache_get(&ctx->msg_cache);
+- spin_unlock(&ctx->msg_lock);
+- if (req)
+- return req;
+- }
+- return kmem_cache_alloc(req_cachep, GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO);
+-}
+-
+ static int io_msg_data_remote(struct io_ring_ctx *target_ctx,
+ struct io_msg *msg)
+ {
+ struct io_kiocb *target;
+ u32 flags = 0;
+
+- target = io_msg_get_kiocb(target_ctx);
++ target = kmem_cache_alloc(req_cachep, GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO) ;
+ if (unlikely(!target))
+ return -ENOMEM;
+
+diff --git a/io_uring/notif.c b/io_uring/notif.c
+index 9a6f6e92d74242..ea9c0116cec2df 100644
+--- a/io_uring/notif.c
++++ b/io_uring/notif.c
+@@ -85,7 +85,7 @@ static int io_link_skb(struct sk_buff *skb, struct ubuf_info *uarg)
+ return -EEXIST;
+
+ prev_nd = container_of(prev_uarg, struct io_notif_data, uarg);
+- prev_notif = cmd_to_io_kiocb(nd);
++ prev_notif = cmd_to_io_kiocb(prev_nd);
+
+ /* make sure all noifications can be finished in the same task_work */
+ if (unlikely(notif->ctx != prev_notif->ctx ||
+diff --git a/io_uring/poll.c b/io_uring/poll.c
+index 20e9b46a4adfd5..1b79c268725d47 100644
+--- a/io_uring/poll.c
++++ b/io_uring/poll.c
+@@ -224,7 +224,7 @@ static int io_poll_check_events(struct io_kiocb *req, io_tw_token_t tw)
+ {
+ int v;
+
+- if (unlikely(io_should_terminate_tw()))
++ if (unlikely(io_should_terminate_tw(req->ctx)))
+ return -ECANCELED;
+
+ do {
+diff --git a/io_uring/timeout.c b/io_uring/timeout.c
+index 7f13bfa9f2b617..17e3aab0af3676 100644
+--- a/io_uring/timeout.c
++++ b/io_uring/timeout.c
+@@ -324,7 +324,7 @@ static void io_req_task_link_timeout(struct io_kiocb *req, io_tw_token_t tw)
+ int ret;
+
+ if (prev) {
+- if (!io_should_terminate_tw()) {
++ if (!io_should_terminate_tw(req->ctx)) {
+ struct io_cancel_data cd = {
+ .ctx = req->ctx,
+ .data = prev->cqe.user_data,
+diff --git a/io_uring/uring_cmd.c b/io_uring/uring_cmd.c
+index 929cad6ee32628..b2b4f62c90ce80 100644
+--- a/io_uring/uring_cmd.c
++++ b/io_uring/uring_cmd.c
+@@ -123,7 +123,7 @@ static void io_uring_cmd_work(struct io_kiocb *req, io_tw_token_t tw)
+ struct io_uring_cmd *ioucmd = io_kiocb_to_cmd(req, struct io_uring_cmd);
+ unsigned int flags = IO_URING_F_COMPLETE_DEFER;
+
+- if (io_should_terminate_tw())
++ if (io_should_terminate_tw(req->ctx))
+ flags |= IO_URING_F_TASK_DEAD;
+
+ /* task_work executor checks the deffered list completion */
+diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
+index a723b7dc6e4e28..20f76b21765016 100644
+--- a/kernel/cgroup/cgroup.c
++++ b/kernel/cgroup/cgroup.c
+@@ -126,8 +126,31 @@ DEFINE_PERCPU_RWSEM(cgroup_threadgroup_rwsem);
+ * of concurrent destructions. Use a separate workqueue so that cgroup
+ * destruction work items don't end up filling up max_active of system_wq
+ * which may lead to deadlock.
++ *
++ * A cgroup destruction should enqueue work sequentially to:
++ * cgroup_offline_wq: use for css offline work
++ * cgroup_release_wq: use for css release work
++ * cgroup_free_wq: use for free work
++ *
++ * Rationale for using separate workqueues:
++ * The cgroup root free work may depend on completion of other css offline
++ * operations. If all tasks were enqueued to a single workqueue, this could
++ * create a deadlock scenario where:
++ * - Free work waits for other css offline work to complete.
++ * - But other css offline work is queued after free work in the same queue.
++ *
++ * Example deadlock scenario with single workqueue (cgroup_destroy_wq):
++ * 1. umount net_prio
++ * 2. net_prio root destruction enqueues work to cgroup_destroy_wq (CPUx)
++ * 3. perf_event CSS A offline enqueues work to same cgroup_destroy_wq (CPUx)
++ * 4. net_prio cgroup_destroy_root->cgroup_lock_and_drain_offline.
++ * 5. net_prio root destruction blocks waiting for perf_event CSS A offline,
++ * which can never complete as it's behind in the same queue and
++ * workqueue's max_active is 1.
+ */
+-static struct workqueue_struct *cgroup_destroy_wq;
++static struct workqueue_struct *cgroup_offline_wq;
++static struct workqueue_struct *cgroup_release_wq;
++static struct workqueue_struct *cgroup_free_wq;
+
+ /* generate an array of cgroup subsystem pointers */
+ #define SUBSYS(_x) [_x ## _cgrp_id] = &_x ## _cgrp_subsys,
+@@ -5553,7 +5576,7 @@ static void css_release_work_fn(struct work_struct *work)
+ cgroup_unlock();
+
+ INIT_RCU_WORK(&css->destroy_rwork, css_free_rwork_fn);
+- queue_rcu_work(cgroup_destroy_wq, &css->destroy_rwork);
++ queue_rcu_work(cgroup_free_wq, &css->destroy_rwork);
+ }
+
+ static void css_release(struct percpu_ref *ref)
+@@ -5562,7 +5585,7 @@ static void css_release(struct percpu_ref *ref)
+ container_of(ref, struct cgroup_subsys_state, refcnt);
+
+ INIT_WORK(&css->destroy_work, css_release_work_fn);
+- queue_work(cgroup_destroy_wq, &css->destroy_work);
++ queue_work(cgroup_release_wq, &css->destroy_work);
+ }
+
+ static void init_and_link_css(struct cgroup_subsys_state *css,
+@@ -5696,7 +5719,7 @@ static struct cgroup_subsys_state *css_create(struct cgroup *cgrp,
+ list_del_rcu(&css->sibling);
+ err_free_css:
+ INIT_RCU_WORK(&css->destroy_rwork, css_free_rwork_fn);
+- queue_rcu_work(cgroup_destroy_wq, &css->destroy_rwork);
++ queue_rcu_work(cgroup_free_wq, &css->destroy_rwork);
+ return ERR_PTR(err);
+ }
+
+@@ -5934,7 +5957,7 @@ static void css_killed_ref_fn(struct percpu_ref *ref)
+
+ if (atomic_dec_and_test(&css->online_cnt)) {
+ INIT_WORK(&css->destroy_work, css_killed_work_fn);
+- queue_work(cgroup_destroy_wq, &css->destroy_work);
++ queue_work(cgroup_offline_wq, &css->destroy_work);
+ }
+ }
+
+@@ -6320,8 +6343,14 @@ static int __init cgroup_wq_init(void)
+ * We would prefer to do this in cgroup_init() above, but that
+ * is called before init_workqueues(): so leave this until after.
+ */
+- cgroup_destroy_wq = alloc_workqueue("cgroup_destroy", 0, 1);
+- BUG_ON(!cgroup_destroy_wq);
++ cgroup_offline_wq = alloc_workqueue("cgroup_offline", 0, 1);
++ BUG_ON(!cgroup_offline_wq);
++
++ cgroup_release_wq = alloc_workqueue("cgroup_release", 0, 1);
++ BUG_ON(!cgroup_release_wq);
++
++ cgroup_free_wq = alloc_workqueue("cgroup_free", 0, 1);
++ BUG_ON(!cgroup_free_wq);
+ return 0;
+ }
+ core_initcall(cgroup_wq_init);
+diff --git a/kernel/sched/ext.c b/kernel/sched/ext.c
+index 717e3d1d6a2fa2..f3a97005713db7 100644
+--- a/kernel/sched/ext.c
++++ b/kernel/sched/ext.c
+@@ -6794,12 +6794,8 @@ __bpf_kfunc u32 scx_bpf_reenqueue_local(void)
+ * CPUs disagree, they use %ENQUEUE_RESTORE which is bypassed to
+ * the current local DSQ for running tasks and thus are not
+ * visible to the BPF scheduler.
+- *
+- * Also skip re-enqueueing tasks that can only run on this
+- * CPU, as they would just be re-added to the same local
+- * DSQ without any benefit.
+ */
+- if (p->migration_pending || is_migration_disabled(p) || p->nr_cpus_allowed == 1)
++ if (p->migration_pending)
+ continue;
+
+ dispatch_dequeue(rq, p);
+diff --git a/mm/gup.c b/mm/gup.c
+index 3c39cbbeebef1f..10e46ff0904b05 100644
+--- a/mm/gup.c
++++ b/mm/gup.c
+@@ -2300,6 +2300,31 @@ static void pofs_unpin(struct pages_or_folios *pofs)
+ unpin_user_pages(pofs->pages, pofs->nr_entries);
+ }
+
++static struct folio *pofs_next_folio(struct folio *folio,
++ struct pages_or_folios *pofs, long *index_ptr)
++{
++ long i = *index_ptr + 1;
++
++ if (!pofs->has_folios && folio_test_large(folio)) {
++ const unsigned long start_pfn = folio_pfn(folio);
++ const unsigned long end_pfn = start_pfn + folio_nr_pages(folio);
++
++ for (; i < pofs->nr_entries; i++) {
++ unsigned long pfn = page_to_pfn(pofs->pages[i]);
++
++ /* Is this page part of this folio? */
++ if (pfn < start_pfn || pfn >= end_pfn)
++ break;
++ }
++ }
++
++ if (unlikely(i == pofs->nr_entries))
++ return NULL;
++ *index_ptr = i;
++
++ return pofs_get_folio(pofs, i);
++}
++
+ /*
+ * Returns the number of collected folios. Return value is always >= 0.
+ */
+@@ -2307,16 +2332,13 @@ static unsigned long collect_longterm_unpinnable_folios(
+ struct list_head *movable_folio_list,
+ struct pages_or_folios *pofs)
+ {
+- unsigned long i, collected = 0;
+- struct folio *prev_folio = NULL;
+- bool drain_allow = true;
+-
+- for (i = 0; i < pofs->nr_entries; i++) {
+- struct folio *folio = pofs_get_folio(pofs, i);
++ unsigned long collected = 0;
++ struct folio *folio;
++ int drained = 0;
++ long i = 0;
+
+- if (folio == prev_folio)
+- continue;
+- prev_folio = folio;
++ for (folio = pofs_get_folio(pofs, i); folio;
++ folio = pofs_next_folio(folio, pofs, &i)) {
+
+ if (folio_is_longterm_pinnable(folio))
+ continue;
+@@ -2331,9 +2353,17 @@ static unsigned long collect_longterm_unpinnable_folios(
+ continue;
+ }
+
+- if (!folio_test_lru(folio) && drain_allow) {
++ if (drained == 0 && folio_may_be_lru_cached(folio) &&
++ folio_ref_count(folio) !=
++ folio_expected_ref_count(folio) + 1) {
++ lru_add_drain();
++ drained = 1;
++ }
++ if (drained == 1 && folio_may_be_lru_cached(folio) &&
++ folio_ref_count(folio) !=
++ folio_expected_ref_count(folio) + 1) {
+ lru_add_drain_all();
+- drain_allow = false;
++ drained = 2;
+ }
+
+ if (!folio_isolate_lru(folio))
+diff --git a/mm/mlock.c b/mm/mlock.c
+index 3cb72b579ffd33..2f454ed6e51041 100644
+--- a/mm/mlock.c
++++ b/mm/mlock.c
+@@ -255,7 +255,7 @@ void mlock_folio(struct folio *folio)
+
+ folio_get(folio);
+ if (!folio_batch_add(fbatch, mlock_lru(folio)) ||
+- folio_test_large(folio) || lru_cache_disabled())
++ !folio_may_be_lru_cached(folio) || lru_cache_disabled())
+ mlock_folio_batch(fbatch);
+ local_unlock(&mlock_fbatch.lock);
+ }
+@@ -278,7 +278,7 @@ void mlock_new_folio(struct folio *folio)
+
+ folio_get(folio);
+ if (!folio_batch_add(fbatch, mlock_new(folio)) ||
+- folio_test_large(folio) || lru_cache_disabled())
++ !folio_may_be_lru_cached(folio) || lru_cache_disabled())
+ mlock_folio_batch(fbatch);
+ local_unlock(&mlock_fbatch.lock);
+ }
+@@ -299,7 +299,7 @@ void munlock_folio(struct folio *folio)
+ */
+ folio_get(folio);
+ if (!folio_batch_add(fbatch, folio) ||
+- folio_test_large(folio) || lru_cache_disabled())
++ !folio_may_be_lru_cached(folio) || lru_cache_disabled())
+ mlock_folio_batch(fbatch);
+ local_unlock(&mlock_fbatch.lock);
+ }
+diff --git a/mm/swap.c b/mm/swap.c
+index 4fc322f7111a98..a524736323c8b7 100644
+--- a/mm/swap.c
++++ b/mm/swap.c
+@@ -164,6 +164,10 @@ static void folio_batch_move_lru(struct folio_batch *fbatch, move_fn_t move_fn)
+ for (i = 0; i < folio_batch_count(fbatch); i++) {
+ struct folio *folio = fbatch->folios[i];
+
++ /* block memcg migration while the folio moves between lru */
++ if (move_fn != lru_add && !folio_test_clear_lru(folio))
++ continue;
++
+ folio_lruvec_relock_irqsave(folio, &lruvec, &flags);
+ move_fn(lruvec, folio);
+
+@@ -176,14 +180,10 @@ static void folio_batch_move_lru(struct folio_batch *fbatch, move_fn_t move_fn)
+ }
+
+ static void __folio_batch_add_and_move(struct folio_batch __percpu *fbatch,
+- struct folio *folio, move_fn_t move_fn,
+- bool on_lru, bool disable_irq)
++ struct folio *folio, move_fn_t move_fn, bool disable_irq)
+ {
+ unsigned long flags;
+
+- if (on_lru && !folio_test_clear_lru(folio))
+- return;
+-
+ folio_get(folio);
+
+ if (disable_irq)
+@@ -191,8 +191,8 @@ static void __folio_batch_add_and_move(struct folio_batch __percpu *fbatch,
+ else
+ local_lock(&cpu_fbatches.lock);
+
+- if (!folio_batch_add(this_cpu_ptr(fbatch), folio) || folio_test_large(folio) ||
+- lru_cache_disabled())
++ if (!folio_batch_add(this_cpu_ptr(fbatch), folio) ||
++ !folio_may_be_lru_cached(folio) || lru_cache_disabled())
+ folio_batch_move_lru(this_cpu_ptr(fbatch), move_fn);
+
+ if (disable_irq)
+@@ -201,13 +201,13 @@ static void __folio_batch_add_and_move(struct folio_batch __percpu *fbatch,
+ local_unlock(&cpu_fbatches.lock);
+ }
+
+-#define folio_batch_add_and_move(folio, op, on_lru) \
+- __folio_batch_add_and_move( \
+- &cpu_fbatches.op, \
+- folio, \
+- op, \
+- on_lru, \
+- offsetof(struct cpu_fbatches, op) >= offsetof(struct cpu_fbatches, lock_irq) \
++#define folio_batch_add_and_move(folio, op) \
++ __folio_batch_add_and_move( \
++ &cpu_fbatches.op, \
++ folio, \
++ op, \
++ offsetof(struct cpu_fbatches, op) >= \
++ offsetof(struct cpu_fbatches, lock_irq) \
+ )
+
+ static void lru_move_tail(struct lruvec *lruvec, struct folio *folio)
+@@ -231,10 +231,10 @@ static void lru_move_tail(struct lruvec *lruvec, struct folio *folio)
+ void folio_rotate_reclaimable(struct folio *folio)
+ {
+ if (folio_test_locked(folio) || folio_test_dirty(folio) ||
+- folio_test_unevictable(folio))
++ folio_test_unevictable(folio) || !folio_test_lru(folio))
+ return;
+
+- folio_batch_add_and_move(folio, lru_move_tail, true);
++ folio_batch_add_and_move(folio, lru_move_tail);
+ }
+
+ void lru_note_cost(struct lruvec *lruvec, bool file,
+@@ -323,10 +323,11 @@ static void folio_activate_drain(int cpu)
+
+ void folio_activate(struct folio *folio)
+ {
+- if (folio_test_active(folio) || folio_test_unevictable(folio))
++ if (folio_test_active(folio) || folio_test_unevictable(folio) ||
++ !folio_test_lru(folio))
+ return;
+
+- folio_batch_add_and_move(folio, lru_activate, true);
++ folio_batch_add_and_move(folio, lru_activate);
+ }
+
+ #else
+@@ -502,7 +503,7 @@ void folio_add_lru(struct folio *folio)
+ lru_gen_in_fault() && !(current->flags & PF_MEMALLOC))
+ folio_set_active(folio);
+
+- folio_batch_add_and_move(folio, lru_add, false);
++ folio_batch_add_and_move(folio, lru_add);
+ }
+ EXPORT_SYMBOL(folio_add_lru);
+
+@@ -680,13 +681,13 @@ void lru_add_drain_cpu(int cpu)
+ void deactivate_file_folio(struct folio *folio)
+ {
+ /* Deactivating an unevictable folio will not accelerate reclaim */
+- if (folio_test_unevictable(folio))
++ if (folio_test_unevictable(folio) || !folio_test_lru(folio))
+ return;
+
+ if (lru_gen_enabled() && lru_gen_clear_refs(folio))
+ return;
+
+- folio_batch_add_and_move(folio, lru_deactivate_file, true);
++ folio_batch_add_and_move(folio, lru_deactivate_file);
+ }
+
+ /*
+@@ -699,13 +700,13 @@ void deactivate_file_folio(struct folio *folio)
+ */
+ void folio_deactivate(struct folio *folio)
+ {
+- if (folio_test_unevictable(folio))
++ if (folio_test_unevictable(folio) || !folio_test_lru(folio))
+ return;
+
+ if (lru_gen_enabled() ? lru_gen_clear_refs(folio) : !folio_test_active(folio))
+ return;
+
+- folio_batch_add_and_move(folio, lru_deactivate, true);
++ folio_batch_add_and_move(folio, lru_deactivate);
+ }
+
+ /**
+@@ -718,10 +719,11 @@ void folio_deactivate(struct folio *folio)
+ void folio_mark_lazyfree(struct folio *folio)
+ {
+ if (!folio_test_anon(folio) || !folio_test_swapbacked(folio) ||
++ !folio_test_lru(folio) ||
+ folio_test_swapcache(folio) || folio_test_unevictable(folio))
+ return;
+
+- folio_batch_add_and_move(folio, lru_lazyfree, true);
++ folio_batch_add_and_move(folio, lru_lazyfree);
+ }
+
+ void lru_add_drain(void)
+diff --git a/mm/vmscan.c b/mm/vmscan.c
+index 424412680cfcc6..b7ed263e6dd701 100644
+--- a/mm/vmscan.c
++++ b/mm/vmscan.c
+@@ -4505,7 +4505,7 @@ static bool sort_folio(struct lruvec *lruvec, struct folio *folio, struct scan_c
+ }
+
+ /* ineligible */
+- if (!folio_test_lru(folio) || zone > sc->reclaim_idx) {
++ if (zone > sc->reclaim_idx) {
+ gen = folio_inc_gen(lruvec, folio, false);
+ list_move_tail(&folio->lru, &lrugen->folios[gen][type][zone]);
+ return true;
+diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
+index 461a9ab540af02..98da33e0c308b0 100644
+--- a/net/ipv4/tcp.c
++++ b/net/ipv4/tcp.c
+@@ -3330,6 +3330,7 @@ int tcp_disconnect(struct sock *sk, int flags)
+ struct inet_connection_sock *icsk = inet_csk(sk);
+ struct tcp_sock *tp = tcp_sk(sk);
+ int old_state = sk->sk_state;
++ struct request_sock *req;
+ u32 seq;
+
+ if (old_state != TCP_CLOSE)
+@@ -3445,6 +3446,10 @@ int tcp_disconnect(struct sock *sk, int flags)
+
+
+ /* Clean up fastopen related fields */
++ req = rcu_dereference_protected(tp->fastopen_rsk,
++ lockdep_sock_is_held(sk));
++ if (req)
++ reqsk_fastopen_remove(sk, req, false);
+ tcp_free_fastopen_req(tp);
+ inet_clear_bit(DEFER_CONNECT, sk);
+ tp->fastopen_client_fail = 0;
+diff --git a/net/ipv4/tcp_ao.c b/net/ipv4/tcp_ao.c
+index bbb8d5f0eae7d3..3338b6cc85c487 100644
+--- a/net/ipv4/tcp_ao.c
++++ b/net/ipv4/tcp_ao.c
+@@ -1178,7 +1178,9 @@ void tcp_ao_finish_connect(struct sock *sk, struct sk_buff *skb)
+ if (!ao)
+ return;
+
+- WRITE_ONCE(ao->risn, tcp_hdr(skb)->seq);
++ /* sk with TCP_REPAIR_ON does not have skb in tcp_finish_connect */
++ if (skb)
++ WRITE_ONCE(ao->risn, tcp_hdr(skb)->seq);
+ ao->rcv_sne = 0;
+
+ hlist_for_each_entry_rcu(key, &ao->head, node, lockdep_sock_is_held(sk))
+diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
+index 307587c8a0037b..7964a7c5f0b2b5 100644
+--- a/net/mac80211/driver-ops.h
++++ b/net/mac80211/driver-ops.h
+@@ -1389,7 +1389,7 @@ drv_get_ftm_responder_stats(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ struct cfg80211_ftm_responder_stats *ftm_stats)
+ {
+- u32 ret = -EOPNOTSUPP;
++ int ret = -EOPNOTSUPP;
+
+ might_sleep();
+ lockdep_assert_wiphy(local->hw.wiphy);
+diff --git a/net/mac80211/main.c b/net/mac80211/main.c
+index 1bad353d8a772b..35c6755b817a83 100644
+--- a/net/mac80211/main.c
++++ b/net/mac80211/main.c
+@@ -1136,7 +1136,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
+ int result, i;
+ enum nl80211_band band;
+ int channels, max_bitrates;
+- bool supp_ht, supp_vht, supp_he, supp_eht;
++ bool supp_ht, supp_vht, supp_he, supp_eht, supp_s1g;
+ struct cfg80211_chan_def dflt_chandef = {};
+
+ if (ieee80211_hw_check(hw, QUEUE_CONTROL) &&
+@@ -1252,6 +1252,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
+ supp_vht = false;
+ supp_he = false;
+ supp_eht = false;
++ supp_s1g = false;
+ for (band = 0; band < NUM_NL80211_BANDS; band++) {
+ const struct ieee80211_sband_iftype_data *iftd;
+ struct ieee80211_supported_band *sband;
+@@ -1299,6 +1300,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
+ max_bitrates = sband->n_bitrates;
+ supp_ht = supp_ht || sband->ht_cap.ht_supported;
+ supp_vht = supp_vht || sband->vht_cap.vht_supported;
++ supp_s1g = supp_s1g || sband->s1g_cap.s1g;
+
+ for_each_sband_iftype_data(sband, i, iftd) {
+ u8 he_40_mhz_cap;
+@@ -1432,6 +1434,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
+ local->scan_ies_len +=
+ 2 + sizeof(struct ieee80211_vht_cap);
+
++ if (supp_s1g)
++ local->scan_ies_len += 2 + sizeof(struct ieee80211_s1g_cap);
++
+ /*
+ * HE cap element is variable in size - set len to allow max size */
+ if (supp_he) {
+diff --git a/net/mptcp/options.c b/net/mptcp/options.c
+index c6983471dca552..bb4253aa675a61 100644
+--- a/net/mptcp/options.c
++++ b/net/mptcp/options.c
+@@ -984,13 +984,13 @@ static bool check_fully_established(struct mptcp_sock *msk, struct sock *ssk,
+ return false;
+ }
+
+- if (mp_opt->deny_join_id0)
+- WRITE_ONCE(msk->pm.remote_deny_join_id0, true);
+-
+ if (unlikely(!READ_ONCE(msk->pm.server_side)))
+ pr_warn_once("bogus mpc option on established client sk");
+
+ set_fully_established:
++ if (mp_opt->deny_join_id0)
++ WRITE_ONCE(msk->pm.remote_deny_join_id0, true);
++
+ mptcp_data_lock((struct sock *)msk);
+ __mptcp_subflow_fully_established(msk, subflow, mp_opt);
+ mptcp_data_unlock((struct sock *)msk);
+diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c
+index 50aaf259959aea..ce7d42d3bd007b 100644
+--- a/net/mptcp/pm_netlink.c
++++ b/net/mptcp/pm_netlink.c
+@@ -408,6 +408,7 @@ static int mptcp_event_created(struct sk_buff *skb,
+ const struct sock *ssk)
+ {
+ int err = nla_put_u32(skb, MPTCP_ATTR_TOKEN, READ_ONCE(msk->token));
++ u16 flags = 0;
+
+ if (err)
+ return err;
+@@ -415,6 +416,12 @@ static int mptcp_event_created(struct sk_buff *skb,
+ if (nla_put_u8(skb, MPTCP_ATTR_SERVER_SIDE, READ_ONCE(msk->pm.server_side)))
+ return -EMSGSIZE;
+
++ if (READ_ONCE(msk->pm.remote_deny_join_id0))
++ flags |= MPTCP_PM_EV_FLAG_DENY_JOIN_ID0;
++
++ if (flags && nla_put_u16(skb, MPTCP_ATTR_FLAGS, flags))
++ return -EMSGSIZE;
++
+ return mptcp_event_add_subflow(skb, ssk);
+ }
+
+diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
+index 1063c53850c057..b895e3ecdc9b7c 100644
+--- a/net/mptcp/protocol.c
++++ b/net/mptcp/protocol.c
+@@ -350,6 +350,20 @@ static void mptcp_close_wake_up(struct sock *sk)
+ sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN);
+ }
+
++static void mptcp_shutdown_subflows(struct mptcp_sock *msk)
++{
++ struct mptcp_subflow_context *subflow;
++
++ mptcp_for_each_subflow(msk, subflow) {
++ struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
++ bool slow;
++
++ slow = lock_sock_fast(ssk);
++ tcp_shutdown(ssk, SEND_SHUTDOWN);
++ unlock_sock_fast(ssk, slow);
++ }
++}
++
+ /* called under the msk socket lock */
+ static bool mptcp_pending_data_fin_ack(struct sock *sk)
+ {
+@@ -374,6 +388,7 @@ static void mptcp_check_data_fin_ack(struct sock *sk)
+ break;
+ case TCP_CLOSING:
+ case TCP_LAST_ACK:
++ mptcp_shutdown_subflows(msk);
+ mptcp_set_state(sk, TCP_CLOSE);
+ break;
+ }
+@@ -542,6 +557,7 @@ static bool mptcp_check_data_fin(struct sock *sk)
+ mptcp_set_state(sk, TCP_CLOSING);
+ break;
+ case TCP_FIN_WAIT2:
++ mptcp_shutdown_subflows(msk);
+ mptcp_set_state(sk, TCP_CLOSE);
+ break;
+ default:
+diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
+index 1802bc5435a1aa..d77a2e374a7ae8 100644
+--- a/net/mptcp/subflow.c
++++ b/net/mptcp/subflow.c
+@@ -882,6 +882,10 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
+
+ ctx->subflow_id = 1;
+ owner = mptcp_sk(ctx->conn);
++
++ if (mp_opt.deny_join_id0)
++ WRITE_ONCE(owner->pm.remote_deny_join_id0, true);
++
+ mptcp_pm_new_connection(owner, child, 1);
+
+ /* with OoO packets we can reach here without ingress
+diff --git a/net/rds/ib_frmr.c b/net/rds/ib_frmr.c
+index 28c1b00221780f..bd861191157b54 100644
+--- a/net/rds/ib_frmr.c
++++ b/net/rds/ib_frmr.c
+@@ -133,12 +133,15 @@ static int rds_ib_post_reg_frmr(struct rds_ib_mr *ibmr)
+
+ ret = ib_map_mr_sg_zbva(frmr->mr, ibmr->sg, ibmr->sg_dma_len,
+ &off, PAGE_SIZE);
+- if (unlikely(ret != ibmr->sg_dma_len))
+- return ret < 0 ? ret : -EINVAL;
++ if (unlikely(ret != ibmr->sg_dma_len)) {
++ ret = ret < 0 ? ret : -EINVAL;
++ goto out_inc;
++ }
+
+- if (cmpxchg(&frmr->fr_state,
+- FRMR_IS_FREE, FRMR_IS_INUSE) != FRMR_IS_FREE)
+- return -EBUSY;
++ if (cmpxchg(&frmr->fr_state, FRMR_IS_FREE, FRMR_IS_INUSE) != FRMR_IS_FREE) {
++ ret = -EBUSY;
++ goto out_inc;
++ }
+
+ atomic_inc(&ibmr->ic->i_fastreg_inuse_count);
+
+@@ -166,11 +169,10 @@ static int rds_ib_post_reg_frmr(struct rds_ib_mr *ibmr)
+ /* Failure here can be because of -ENOMEM as well */
+ rds_transition_frwr_state(ibmr, FRMR_IS_INUSE, FRMR_IS_STALE);
+
+- atomic_inc(&ibmr->ic->i_fastreg_wrs);
+ if (printk_ratelimit())
+ pr_warn("RDS/IB: %s returned error(%d)\n",
+ __func__, ret);
+- goto out;
++ goto out_inc;
+ }
+
+ /* Wait for the registration to complete in order to prevent an invalid
+@@ -179,8 +181,10 @@ static int rds_ib_post_reg_frmr(struct rds_ib_mr *ibmr)
+ */
+ wait_event(frmr->fr_reg_done, !frmr->fr_reg);
+
+-out:
++ return ret;
+
++out_inc:
++ atomic_inc(&ibmr->ic->i_fastreg_wrs);
+ return ret;
+ }
+
+diff --git a/net/rfkill/rfkill-gpio.c b/net/rfkill/rfkill-gpio.c
+index 41e657e977618a..cf2dcec6ce5afc 100644
+--- a/net/rfkill/rfkill-gpio.c
++++ b/net/rfkill/rfkill-gpio.c
+@@ -94,10 +94,10 @@ static const struct dmi_system_id rfkill_gpio_deny_table[] = {
+ static int rfkill_gpio_probe(struct platform_device *pdev)
+ {
+ struct rfkill_gpio_data *rfkill;
+- struct gpio_desc *gpio;
++ const char *type_name = NULL;
+ const char *name_property;
+ const char *type_property;
+- const char *type_name;
++ struct gpio_desc *gpio;
+ int ret;
+
+ if (dmi_check_system(rfkill_gpio_deny_table))
+diff --git a/net/rxrpc/rxgk.c b/net/rxrpc/rxgk.c
+index 1e19c605bcc829..dce5a3d8a964f8 100644
+--- a/net/rxrpc/rxgk.c
++++ b/net/rxrpc/rxgk.c
+@@ -475,7 +475,7 @@ static int rxgk_verify_packet_integrity(struct rxrpc_call *call,
+ struct krb5_buffer metadata;
+ unsigned int offset = sp->offset, len = sp->len;
+ size_t data_offset = 0, data_len = len;
+- u32 ac;
++ u32 ac = 0;
+ int ret = -ENOMEM;
+
+ _enter("");
+@@ -499,9 +499,10 @@ static int rxgk_verify_packet_integrity(struct rxrpc_call *call,
+ ret = rxgk_verify_mic_skb(gk->krb5, gk->rx_Kc, &metadata,
+ skb, &offset, &len, &ac);
+ kfree(hdr);
+- if (ret == -EPROTO) {
+- rxrpc_abort_eproto(call, skb, ac,
+- rxgk_abort_1_verify_mic_eproto);
++ if (ret < 0) {
++ if (ret != -ENOMEM)
++ rxrpc_abort_eproto(call, skb, ac,
++ rxgk_abort_1_verify_mic_eproto);
+ } else {
+ sp->offset = offset;
+ sp->len = len;
+@@ -524,15 +525,16 @@ static int rxgk_verify_packet_encrypted(struct rxrpc_call *call,
+ struct rxgk_header hdr;
+ unsigned int offset = sp->offset, len = sp->len;
+ int ret;
+- u32 ac;
++ u32 ac = 0;
+
+ _enter("");
+
+ ret = rxgk_decrypt_skb(gk->krb5, gk->rx_enc, skb, &offset, &len, &ac);
+- if (ret == -EPROTO)
+- rxrpc_abort_eproto(call, skb, ac, rxgk_abort_2_decrypt_eproto);
+- if (ret < 0)
++ if (ret < 0) {
++ if (ret != -ENOMEM)
++ rxrpc_abort_eproto(call, skb, ac, rxgk_abort_2_decrypt_eproto);
+ goto error;
++ }
+
+ if (len < sizeof(hdr)) {
+ ret = rxrpc_abort_eproto(call, skb, RXGK_PACKETSHORT,
+diff --git a/net/rxrpc/rxgk_app.c b/net/rxrpc/rxgk_app.c
+index b94b77a1c31780..30275cb5ba3e25 100644
+--- a/net/rxrpc/rxgk_app.c
++++ b/net/rxrpc/rxgk_app.c
+@@ -54,6 +54,10 @@ int rxgk_yfs_decode_ticket(struct rxrpc_connection *conn, struct sk_buff *skb,
+
+ _enter("");
+
++ if (ticket_len < 10 * sizeof(__be32))
++ return rxrpc_abort_conn(conn, skb, RXGK_INCONSISTENCY, -EPROTO,
++ rxgk_abort_resp_short_yfs_tkt);
++
+ /* Get the session key length */
+ ret = skb_copy_bits(skb, ticket_offset, tmp, sizeof(tmp));
+ if (ret < 0)
+@@ -187,7 +191,7 @@ int rxgk_extract_token(struct rxrpc_connection *conn, struct sk_buff *skb,
+ struct key *server_key;
+ unsigned int ticket_offset, ticket_len;
+ u32 kvno, enctype;
+- int ret, ec;
++ int ret, ec = 0;
+
+ struct {
+ __be32 kvno;
+@@ -195,22 +199,23 @@ int rxgk_extract_token(struct rxrpc_connection *conn, struct sk_buff *skb,
+ __be32 token_len;
+ } container;
+
++ if (token_len < sizeof(container))
++ goto short_packet;
++
+ /* Decode the RXGK_TokenContainer object. This tells us which server
+ * key we should be using. We can then fetch the key, get the secret
+ * and set up the crypto to extract the token.
+ */
+ if (skb_copy_bits(skb, token_offset, &container, sizeof(container)) < 0)
+- return rxrpc_abort_conn(conn, skb, RXGK_PACKETSHORT, -EPROTO,
+- rxgk_abort_resp_tok_short);
++ goto short_packet;
+
+ kvno = ntohl(container.kvno);
+ enctype = ntohl(container.enctype);
+ ticket_len = ntohl(container.token_len);
+ ticket_offset = token_offset + sizeof(container);
+
+- if (xdr_round_up(ticket_len) > token_len - 3 * 4)
+- return rxrpc_abort_conn(conn, skb, RXGK_PACKETSHORT, -EPROTO,
+- rxgk_abort_resp_tok_short);
++ if (xdr_round_up(ticket_len) > token_len - sizeof(container))
++ goto short_packet;
+
+ _debug("KVNO %u", kvno);
+ _debug("ENC %u", enctype);
+@@ -236,9 +241,11 @@ int rxgk_extract_token(struct rxrpc_connection *conn, struct sk_buff *skb,
+ &ticket_offset, &ticket_len, &ec);
+ crypto_free_aead(token_enc);
+ token_enc = NULL;
+- if (ret < 0)
+- return rxrpc_abort_conn(conn, skb, ec, ret,
+- rxgk_abort_resp_tok_dec);
++ if (ret < 0) {
++ if (ret != -ENOMEM)
++ return rxrpc_abort_conn(conn, skb, ec, ret,
++ rxgk_abort_resp_tok_dec);
++ }
+
+ ret = conn->security->default_decode_ticket(conn, skb, ticket_offset,
+ ticket_len, _key);
+@@ -283,4 +290,8 @@ int rxgk_extract_token(struct rxrpc_connection *conn, struct sk_buff *skb,
+ * also come out this way if the ticket decryption fails.
+ */
+ return ret;
++
++short_packet:
++ return rxrpc_abort_conn(conn, skb, RXGK_PACKETSHORT, -EPROTO,
++ rxgk_abort_resp_tok_short);
+ }
+diff --git a/net/rxrpc/rxgk_common.h b/net/rxrpc/rxgk_common.h
+index 7370a56559853f..80164d89e19c03 100644
+--- a/net/rxrpc/rxgk_common.h
++++ b/net/rxrpc/rxgk_common.h
+@@ -88,11 +88,16 @@ int rxgk_decrypt_skb(const struct krb5_enctype *krb5,
+ *_offset += offset;
+ *_len = len;
+ break;
++ case -EBADMSG: /* Checksum mismatch. */
+ case -EPROTO:
+- case -EBADMSG:
+ *_error_code = RXGK_SEALEDINCON;
+ break;
++ case -EMSGSIZE:
++ *_error_code = RXGK_PACKETSHORT;
++ break;
++ case -ENOPKG: /* Would prefer RXGK_BADETYPE, but not available for YFS. */
+ default:
++ *_error_code = RXGK_INCONSISTENCY;
+ break;
+ }
+
+@@ -127,11 +132,16 @@ int rxgk_verify_mic_skb(const struct krb5_enctype *krb5,
+ *_offset += offset;
+ *_len = len;
+ break;
++ case -EBADMSG: /* Checksum mismatch */
+ case -EPROTO:
+- case -EBADMSG:
+ *_error_code = RXGK_SEALEDINCON;
+ break;
++ case -EMSGSIZE:
++ *_error_code = RXGK_PACKETSHORT;
++ break;
++ case -ENOPKG: /* Would prefer RXGK_BADETYPE, but not available for YFS. */
+ default:
++ *_error_code = RXGK_INCONSISTENCY;
+ break;
+ }
+
+diff --git a/net/tls/tls.h b/net/tls/tls.h
+index 4e077068e6d98a..e4c42731ce39ae 100644
+--- a/net/tls/tls.h
++++ b/net/tls/tls.h
+@@ -141,6 +141,7 @@ void update_sk_prot(struct sock *sk, struct tls_context *ctx);
+
+ int wait_on_pending_writer(struct sock *sk, long *timeo);
+ void tls_err_abort(struct sock *sk, int err);
++void tls_strp_abort_strp(struct tls_strparser *strp, int err);
+
+ int init_prot_info(struct tls_prot_info *prot,
+ const struct tls_crypto_info *crypto_info,
+diff --git a/net/tls/tls_strp.c b/net/tls/tls_strp.c
+index d71643b494a1ae..98e12f0ff57e51 100644
+--- a/net/tls/tls_strp.c
++++ b/net/tls/tls_strp.c
+@@ -13,7 +13,7 @@
+
+ static struct workqueue_struct *tls_strp_wq;
+
+-static void tls_strp_abort_strp(struct tls_strparser *strp, int err)
++void tls_strp_abort_strp(struct tls_strparser *strp, int err)
+ {
+ if (strp->stopped)
+ return;
+@@ -211,11 +211,17 @@ static int tls_strp_copyin_frag(struct tls_strparser *strp, struct sk_buff *skb,
+ struct sk_buff *in_skb, unsigned int offset,
+ size_t in_len)
+ {
++ unsigned int nfrag = skb->len / PAGE_SIZE;
+ size_t len, chunk;
+ skb_frag_t *frag;
+ int sz;
+
+- frag = &skb_shinfo(skb)->frags[skb->len / PAGE_SIZE];
++ if (unlikely(nfrag >= skb_shinfo(skb)->nr_frags)) {
++ DEBUG_NET_WARN_ON_ONCE(1);
++ return -EMSGSIZE;
++ }
++
++ frag = &skb_shinfo(skb)->frags[nfrag];
+
+ len = in_len;
+ /* First make sure we got the header */
+@@ -520,10 +526,8 @@ static int tls_strp_read_sock(struct tls_strparser *strp)
+ tls_strp_load_anchor_with_queue(strp, inq);
+ if (!strp->stm.full_len) {
+ sz = tls_rx_msg_size(strp, strp->anchor);
+- if (sz < 0) {
+- tls_strp_abort_strp(strp, sz);
++ if (sz < 0)
+ return sz;
+- }
+
+ strp->stm.full_len = sz;
+
+diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
+index bac65d0d4e3e1e..daac9fd4be7eb5 100644
+--- a/net/tls/tls_sw.c
++++ b/net/tls/tls_sw.c
+@@ -2474,8 +2474,7 @@ int tls_rx_msg_size(struct tls_strparser *strp, struct sk_buff *skb)
+ return data_len + TLS_HEADER_SIZE;
+
+ read_failure:
+- tls_err_abort(strp->sk, ret);
+-
++ tls_strp_abort_strp(strp, ret);
+ return ret;
+ }
+
+diff --git a/samples/damon/mtier.c b/samples/damon/mtier.c
+index ed6bed8b3d4d99..88156145172f17 100644
+--- a/samples/damon/mtier.c
++++ b/samples/damon/mtier.c
+@@ -27,14 +27,14 @@ module_param(node1_end_addr, ulong, 0600);
+ static int damon_sample_mtier_enable_store(
+ const char *val, const struct kernel_param *kp);
+
+-static const struct kernel_param_ops enable_param_ops = {
++static const struct kernel_param_ops enabled_param_ops = {
+ .set = damon_sample_mtier_enable_store,
+ .get = param_get_bool,
+ };
+
+-static bool enable __read_mostly;
+-module_param_cb(enable, &enable_param_ops, &enable, 0600);
+-MODULE_PARM_DESC(enable, "Enable of disable DAMON_SAMPLE_MTIER");
++static bool enabled __read_mostly;
++module_param_cb(enabled, &enabled_param_ops, &enabled, 0600);
++MODULE_PARM_DESC(enabled, "Enable or disable DAMON_SAMPLE_MTIER");
+
+ static struct damon_ctx *ctxs[2];
+
+@@ -156,20 +156,23 @@ static bool init_called;
+ static int damon_sample_mtier_enable_store(
+ const char *val, const struct kernel_param *kp)
+ {
+- bool enabled = enable;
++ bool is_enabled = enabled;
+ int err;
+
+- err = kstrtobool(val, &enable);
++ err = kstrtobool(val, &enabled);
+ if (err)
+ return err;
+
+- if (enable == enabled)
++ if (enabled == is_enabled)
+ return 0;
+
+- if (enable) {
++ if (!init_called)
++ return 0;
++
++ if (enabled) {
+ err = damon_sample_mtier_start();
+ if (err)
+- enable = false;
++ enabled = false;
+ return err;
+ }
+ damon_sample_mtier_stop();
+@@ -181,10 +184,10 @@ static int __init damon_sample_mtier_init(void)
+ int err = 0;
+
+ init_called = true;
+- if (enable) {
++ if (enabled) {
+ err = damon_sample_mtier_start();
+ if (err)
+- enable = false;
++ enabled = false;
+ }
+ return 0;
+ }
+diff --git a/samples/damon/prcl.c b/samples/damon/prcl.c
+index 5597e6a08ab226..f971e61e6c5c00 100644
+--- a/samples/damon/prcl.c
++++ b/samples/damon/prcl.c
+@@ -17,14 +17,14 @@ module_param(target_pid, int, 0600);
+ static int damon_sample_prcl_enable_store(
+ const char *val, const struct kernel_param *kp);
+
+-static const struct kernel_param_ops enable_param_ops = {
++static const struct kernel_param_ops enabled_param_ops = {
+ .set = damon_sample_prcl_enable_store,
+ .get = param_get_bool,
+ };
+
+-static bool enable __read_mostly;
+-module_param_cb(enable, &enable_param_ops, &enable, 0600);
+-MODULE_PARM_DESC(enable, "Enable of disable DAMON_SAMPLE_WSSE");
++static bool enabled __read_mostly;
++module_param_cb(enabled, &enabled_param_ops, &enabled, 0600);
++MODULE_PARM_DESC(enabled, "Enable or disable DAMON_SAMPLE_PRCL");
+
+ static struct damon_ctx *ctx;
+ static struct pid *target_pidp;
+@@ -109,23 +109,28 @@ static void damon_sample_prcl_stop(void)
+ put_pid(target_pidp);
+ }
+
++static bool init_called;
++
+ static int damon_sample_prcl_enable_store(
+ const char *val, const struct kernel_param *kp)
+ {
+- bool enabled = enable;
++ bool is_enabled = enabled;
+ int err;
+
+- err = kstrtobool(val, &enable);
++ err = kstrtobool(val, &enabled);
+ if (err)
+ return err;
+
+- if (enable == enabled)
++ if (enabled == is_enabled)
++ return 0;
++
++ if (!init_called)
+ return 0;
+
+- if (enable) {
++ if (enabled) {
+ err = damon_sample_prcl_start();
+ if (err)
+- enable = false;
++ enabled = false;
+ return err;
+ }
+ damon_sample_prcl_stop();
+@@ -134,6 +139,14 @@ static int damon_sample_prcl_enable_store(
+
+ static int __init damon_sample_prcl_init(void)
+ {
++ int err = 0;
++
++ init_called = true;
++ if (enabled) {
++ err = damon_sample_prcl_start();
++ if (err)
++ enabled = false;
++ }
+ return 0;
+ }
+
+diff --git a/samples/damon/wsse.c b/samples/damon/wsse.c
+index e941958b103249..d50730ee65a7e7 100644
+--- a/samples/damon/wsse.c
++++ b/samples/damon/wsse.c
+@@ -18,14 +18,14 @@ module_param(target_pid, int, 0600);
+ static int damon_sample_wsse_enable_store(
+ const char *val, const struct kernel_param *kp);
+
+-static const struct kernel_param_ops enable_param_ops = {
++static const struct kernel_param_ops enabled_param_ops = {
+ .set = damon_sample_wsse_enable_store,
+ .get = param_get_bool,
+ };
+
+-static bool enable __read_mostly;
+-module_param_cb(enable, &enable_param_ops, &enable, 0600);
+-MODULE_PARM_DESC(enable, "Enable or disable DAMON_SAMPLE_WSSE");
++static bool enabled __read_mostly;
++module_param_cb(enabled, &enabled_param_ops, &enabled, 0600);
++MODULE_PARM_DESC(enabled, "Enable or disable DAMON_SAMPLE_WSSE");
+
+ static struct damon_ctx *ctx;
+ static struct pid *target_pidp;
+@@ -94,20 +94,20 @@ static bool init_called;
+ static int damon_sample_wsse_enable_store(
+ const char *val, const struct kernel_param *kp)
+ {
+- bool enabled = enable;
++ bool is_enabled = enabled;
+ int err;
+
+- err = kstrtobool(val, &enable);
++ err = kstrtobool(val, &enabled);
+ if (err)
+ return err;
+
+- if (enable == enabled)
++ if (enabled == is_enabled)
+ return 0;
+
+- if (enable) {
++ if (enabled) {
+ err = damon_sample_wsse_start();
+ if (err)
+- enable = false;
++ enabled = false;
+ return err;
+ }
+ damon_sample_wsse_stop();
+@@ -119,10 +119,10 @@ static int __init damon_sample_wsse_init(void)
+ int err = 0;
+
+ init_called = true;
+- if (enable) {
++ if (enabled) {
+ err = damon_sample_wsse_start();
+ if (err)
+- enable = false;
++ enabled = false;
+ }
+ return err;
+ }
+diff --git a/sound/firewire/motu/motu-hwdep.c b/sound/firewire/motu/motu-hwdep.c
+index 88d1f4b56e4be4..a220ac0c8eb831 100644
+--- a/sound/firewire/motu/motu-hwdep.c
++++ b/sound/firewire/motu/motu-hwdep.c
+@@ -111,7 +111,7 @@ static __poll_t hwdep_poll(struct snd_hwdep *hwdep, struct file *file,
+ events = 0;
+ spin_unlock_irq(&motu->lock);
+
+- return events | EPOLLOUT;
++ return events;
+ }
+
+ static int hwdep_get_info(struct snd_motu *motu, void __user *arg)
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index 8458ca4d8d9dab..4819bd332f0390 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -10752,6 +10752,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x103c, 0x8992, "HP EliteBook 845 G9", ALC287_FIXUP_CS35L41_I2C_2),
+ SND_PCI_QUIRK(0x103c, 0x8994, "HP EliteBook 855 G9", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x8995, "HP EliteBook 855 G9", ALC287_FIXUP_CS35L41_I2C_2),
++ SND_PCI_QUIRK(0x103c, 0x89a0, "HP Laptop 15-dw4xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
+ SND_PCI_QUIRK(0x103c, 0x89a4, "HP ProBook 440 G9", ALC236_FIXUP_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x89a6, "HP ProBook 450 G9", ALC236_FIXUP_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x89aa, "HP EliteBook 630 G9", ALC236_FIXUP_HP_GPIO_LED),
+diff --git a/sound/soc/amd/acp/acp-i2s.c b/sound/soc/amd/acp/acp-i2s.c
+index 70fa54d568ef68..4d9589b67099ef 100644
+--- a/sound/soc/amd/acp/acp-i2s.c
++++ b/sound/soc/amd/acp/acp-i2s.c
+@@ -72,7 +72,7 @@ static int acp_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
+ unsigned int fmt)
+ {
+ struct device *dev = cpu_dai->component->dev;
+- struct acp_chip_info *chip = dev_get_platdata(dev);
++ struct acp_chip_info *chip = dev_get_drvdata(dev->parent);
+ int mode;
+
+ mode = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
+@@ -196,7 +196,7 @@ static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_
+ u32 reg_val, fmt_reg, tdm_fmt;
+ u32 lrclk_div_val, bclk_div_val;
+
+- chip = dev_get_platdata(dev);
++ chip = dev_get_drvdata(dev->parent);
+ rsrc = chip->rsrc;
+
+ /* These values are as per Hardware Spec */
+@@ -383,7 +383,7 @@ static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct
+ {
+ struct acp_stream *stream = substream->runtime->private_data;
+ struct device *dev = dai->component->dev;
+- struct acp_chip_info *chip = dev_get_platdata(dev);
++ struct acp_chip_info *chip = dev_get_drvdata(dev->parent);
+ struct acp_resource *rsrc = chip->rsrc;
+ u32 val, period_bytes, reg_val, ier_val, water_val, buf_size, buf_reg;
+
+@@ -513,14 +513,13 @@ static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct
+ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
+ {
+ struct device *dev = dai->component->dev;
+- struct acp_chip_info *chip = dev_get_platdata(dev);
++ struct acp_chip_info *chip = dev_get_drvdata(dev->parent);
+ struct acp_resource *rsrc = chip->rsrc;
+ struct acp_stream *stream = substream->runtime->private_data;
+ u32 reg_dma_size = 0, reg_fifo_size = 0, reg_fifo_addr = 0;
+ u32 phy_addr = 0, acp_fifo_addr = 0, ext_int_ctrl;
+ unsigned int dir = substream->stream;
+
+- chip = dev_get_platdata(dev);
+ switch (dai->driver->id) {
+ case I2S_SP_INSTANCE:
+ if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
+@@ -629,7 +628,7 @@ static int acp_i2s_startup(struct snd_pcm_substream *substream, struct snd_soc_d
+ {
+ struct acp_stream *stream = substream->runtime->private_data;
+ struct device *dev = dai->component->dev;
+- struct acp_chip_info *chip = dev_get_platdata(dev);
++ struct acp_chip_info *chip = dev_get_drvdata(dev->parent);
+ struct acp_resource *rsrc = chip->rsrc;
+ unsigned int dir = substream->stream;
+ unsigned int irq_bit = 0;
+diff --git a/sound/soc/codecs/sma1307.c b/sound/soc/codecs/sma1307.c
+index b3d401ada17601..2d993428f87e3c 100644
+--- a/sound/soc/codecs/sma1307.c
++++ b/sound/soc/codecs/sma1307.c
+@@ -1737,9 +1737,10 @@ static void sma1307_setting_loaded(struct sma1307_priv *sma1307, const char *fil
+ sma1307->set.checksum = data[sma1307->set.header_size - 2];
+ sma1307->set.num_mode = data[sma1307->set.header_size - 1];
+ num_mode = sma1307->set.num_mode;
+- sma1307->set.header = devm_kzalloc(sma1307->dev,
+- sma1307->set.header_size,
+- GFP_KERNEL);
++ sma1307->set.header = devm_kmalloc_array(sma1307->dev,
++ sma1307->set.header_size,
++ sizeof(int),
++ GFP_KERNEL);
+ if (!sma1307->set.header) {
+ sma1307->set.status = false;
+ return;
+diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
+index 401ee20897b1ba..94873ea630146b 100644
+--- a/sound/soc/codecs/wm8940.c
++++ b/sound/soc/codecs/wm8940.c
+@@ -220,7 +220,7 @@ static const struct snd_kcontrol_new wm8940_snd_controls[] = {
+ SOC_SINGLE_TLV("Digital Capture Volume", WM8940_ADCVOL,
+ 0, 255, 0, wm8940_adc_tlv),
+ SOC_ENUM("Mic Bias Level", wm8940_mic_bias_level_enum),
+- SOC_SINGLE_TLV("Capture Boost Volue", WM8940_ADCBOOST,
++ SOC_SINGLE_TLV("Capture Boost Volume", WM8940_ADCBOOST,
+ 8, 1, 0, wm8940_capture_boost_vol_tlv),
+ SOC_SINGLE_TLV("Speaker Playback Volume", WM8940_SPKVOL,
+ 0, 63, 0, wm8940_spk_vol_tlv),
+@@ -693,7 +693,12 @@ static int wm8940_update_clocks(struct snd_soc_dai *dai)
+ f = wm8940_get_mclkdiv(priv->mclk, fs256, &mclkdiv);
+ if (f != priv->mclk) {
+ /* The PLL performs best around 90MHz */
+- fpll = wm8940_get_mclkdiv(22500000, fs256, &mclkdiv);
++ if (fs256 % 8000)
++ f = 22579200;
++ else
++ f = 24576000;
++
++ fpll = wm8940_get_mclkdiv(f, fs256, &mclkdiv);
+ }
+
+ wm8940_set_dai_pll(dai, 0, 0, priv->mclk, fpll);
+diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c
+index bdf437a5403fe2..db16d893a23514 100644
+--- a/sound/soc/codecs/wm8974.c
++++ b/sound/soc/codecs/wm8974.c
+@@ -419,10 +419,14 @@ static int wm8974_update_clocks(struct snd_soc_dai *dai)
+ fs256 = 256 * priv->fs;
+
+ f = wm8974_get_mclkdiv(priv->mclk, fs256, &mclkdiv);
+-
+ if (f != priv->mclk) {
+ /* The PLL performs best around 90MHz */
+- fpll = wm8974_get_mclkdiv(22500000, fs256, &mclkdiv);
++ if (fs256 % 8000)
++ f = 22579200;
++ else
++ f = 24576000;
++
++ fpll = wm8974_get_mclkdiv(f, fs256, &mclkdiv);
+ }
+
+ wm8974_set_dai_pll(dai, 0, 0, priv->mclk, fpll);
+diff --git a/sound/soc/intel/catpt/pcm.c b/sound/soc/intel/catpt/pcm.c
+index 81a2f0339e0552..ff1fa01acb85b2 100644
+--- a/sound/soc/intel/catpt/pcm.c
++++ b/sound/soc/intel/catpt/pcm.c
+@@ -568,8 +568,9 @@ static const struct snd_pcm_hardware catpt_pcm_hardware = {
+ SNDRV_PCM_INFO_RESUME |
+ SNDRV_PCM_INFO_NO_PERIOD_WAKEUP,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+- SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S32_LE,
++ .subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_24 |
++ SNDRV_PCM_SUBFMTBIT_MSBITS_MAX,
+ .period_bytes_min = PAGE_SIZE,
+ .period_bytes_max = CATPT_BUFFER_MAX_SIZE / CATPT_PCM_PERIODS_MIN,
+ .periods_min = CATPT_PCM_PERIODS_MIN,
+@@ -699,14 +700,18 @@ static struct snd_soc_dai_driver dai_drivers[] = {
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_48000,
+- .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
++ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
++ .subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_24 |
++ SNDRV_PCM_SUBFMTBIT_MSBITS_MAX,
+ },
+ .capture = {
+ .stream_name = "Analog Capture",
+ .channels_min = 2,
+ .channels_max = 4,
+ .rates = SNDRV_PCM_RATE_48000,
+- .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
++ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
++ .subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_24 |
++ SNDRV_PCM_SUBFMTBIT_MSBITS_MAX,
+ },
+ },
+ {
+@@ -718,7 +723,9 @@ static struct snd_soc_dai_driver dai_drivers[] = {
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+- .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
++ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
++ .subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_24 |
++ SNDRV_PCM_SUBFMTBIT_MSBITS_MAX,
+ },
+ },
+ {
+@@ -730,7 +737,9 @@ static struct snd_soc_dai_driver dai_drivers[] = {
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+- .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
++ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
++ .subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_24 |
++ SNDRV_PCM_SUBFMTBIT_MSBITS_MAX,
+ },
+ },
+ {
+@@ -742,7 +751,9 @@ static struct snd_soc_dai_driver dai_drivers[] = {
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_48000,
+- .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
++ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
++ .subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_24 |
++ SNDRV_PCM_SUBFMTBIT_MSBITS_MAX,
+ },
+ },
+ {
+diff --git a/sound/soc/qcom/qdsp6/audioreach.c b/sound/soc/qcom/qdsp6/audioreach.c
+index 4ebaaf736fb98a..3f5eed5afce55e 100644
+--- a/sound/soc/qcom/qdsp6/audioreach.c
++++ b/sound/soc/qcom/qdsp6/audioreach.c
+@@ -971,6 +971,7 @@ static int audioreach_i2s_set_media_format(struct q6apm_graph *graph,
+ param_data->param_id = PARAM_ID_I2S_INTF_CFG;
+ param_data->param_size = ic_sz - APM_MODULE_PARAM_DATA_SIZE;
+
++ intf_cfg->cfg.lpaif_type = module->hw_interface_type;
+ intf_cfg->cfg.intf_idx = module->hw_interface_idx;
+ intf_cfg->cfg.sd_line_idx = module->sd_line_idx;
+
+diff --git a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
+index a0d90462fd6a38..528756f1332bcf 100644
+--- a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
++++ b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
+@@ -213,8 +213,10 @@ static int q6apm_lpass_dai_prepare(struct snd_pcm_substream *substream, struct s
+
+ return 0;
+ err:
+- q6apm_graph_close(dai_data->graph[dai->id]);
+- dai_data->graph[dai->id] = NULL;
++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
++ q6apm_graph_close(dai_data->graph[dai->id]);
++ dai_data->graph[dai->id] = NULL;
++ }
+ return rc;
+ }
+
+@@ -260,6 +262,7 @@ static const struct snd_soc_dai_ops q6i2s_ops = {
+ .shutdown = q6apm_lpass_dai_shutdown,
+ .set_channel_map = q6dma_set_channel_map,
+ .hw_params = q6dma_hw_params,
++ .set_fmt = q6i2s_set_fmt,
+ };
+
+ static const struct snd_soc_dai_ops q6hdmi_ops = {
+diff --git a/sound/soc/sdca/sdca_device.c b/sound/soc/sdca/sdca_device.c
+index 0244cdcdd109a7..4798ce2c8f0b40 100644
+--- a/sound/soc/sdca/sdca_device.c
++++ b/sound/soc/sdca/sdca_device.c
+@@ -7,6 +7,7 @@
+ */
+
+ #include <linux/acpi.h>
++#include <linux/dmi.h>
+ #include <linux/module.h>
+ #include <linux/property.h>
+ #include <linux/soundwire/sdw.h>
+@@ -55,11 +56,30 @@ static bool sdca_device_quirk_rt712_vb(struct sdw_slave *slave)
+ return false;
+ }
+
++static bool sdca_device_quirk_skip_func_type_patching(struct sdw_slave *slave)
++{
++ const char *vendor, *sku;
++
++ vendor = dmi_get_system_info(DMI_SYS_VENDOR);
++ sku = dmi_get_system_info(DMI_PRODUCT_SKU);
++
++ if (vendor && sku &&
++ !strcmp(vendor, "Dell Inc.") &&
++ (!strcmp(sku, "0C62") || !strcmp(sku, "0C63") || !strcmp(sku, "0C6B")) &&
++ slave->sdca_data.interface_revision == 0x061c &&
++ slave->id.mfg_id == 0x01fa && slave->id.part_id == 0x4243)
++ return true;
++
++ return false;
++}
++
+ bool sdca_device_quirk_match(struct sdw_slave *slave, enum sdca_quirk quirk)
+ {
+ switch (quirk) {
+ case SDCA_QUIRKS_RT712_VB:
+ return sdca_device_quirk_rt712_vb(slave);
++ case SDCA_QUIRKS_SKIP_FUNC_TYPE_PATCHING:
++ return sdca_device_quirk_skip_func_type_patching(slave);
+ default:
+ break;
+ }
+diff --git a/sound/soc/sdca/sdca_functions.c b/sound/soc/sdca/sdca_functions.c
+index 050f7338aca95a..ea793869c03858 100644
+--- a/sound/soc/sdca/sdca_functions.c
++++ b/sound/soc/sdca/sdca_functions.c
+@@ -89,6 +89,7 @@ static int find_sdca_function(struct acpi_device *adev, void *data)
+ {
+ struct fwnode_handle *function_node = acpi_fwnode_handle(adev);
+ struct sdca_device_data *sdca_data = data;
++ struct sdw_slave *slave = container_of(sdca_data, struct sdw_slave, sdca_data);
+ struct device *dev = &adev->dev;
+ struct fwnode_handle *control5; /* used to identify function type */
+ const char *function_name;
+@@ -136,11 +137,13 @@ static int find_sdca_function(struct acpi_device *adev, void *data)
+ return ret;
+ }
+
+- ret = patch_sdca_function_type(sdca_data->interface_revision, &function_type);
+- if (ret < 0) {
+- dev_err(dev, "SDCA version %#x invalid function type %d\n",
+- sdca_data->interface_revision, function_type);
+- return ret;
++ if (!sdca_device_quirk_match(slave, SDCA_QUIRKS_SKIP_FUNC_TYPE_PATCHING)) {
++ ret = patch_sdca_function_type(sdca_data->interface_revision, &function_type);
++ if (ret < 0) {
++ dev_err(dev, "SDCA version %#x invalid function type %d\n",
++ sdca_data->interface_revision, function_type);
++ return ret;
++ }
+ }
+
+ function_name = get_sdca_function_name(function_type);
+diff --git a/sound/soc/sdca/sdca_regmap.c b/sound/soc/sdca/sdca_regmap.c
+index c41c67c2204a41..ff1f8fe2a39bb7 100644
+--- a/sound/soc/sdca/sdca_regmap.c
++++ b/sound/soc/sdca/sdca_regmap.c
+@@ -196,7 +196,7 @@ int sdca_regmap_mbq_size(struct sdca_function_data *function, unsigned int reg)
+
+ control = function_find_control(function, reg);
+ if (!control)
+- return false;
++ return -EINVAL;
+
+ return clamp_val(control->nbits / BITS_PER_BYTE, sizeof(u8), sizeof(u32));
+ }
+diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c
+index aa6b0247d5c99e..a34f472ef1751f 100644
+--- a/sound/soc/sof/intel/hda-stream.c
++++ b/sound/soc/sof/intel/hda-stream.c
+@@ -890,7 +890,7 @@ int hda_dsp_stream_init(struct snd_sof_dev *sdev)
+
+ if (num_capture >= SOF_HDA_CAPTURE_STREAMS) {
+ dev_err(sdev->dev, "error: too many capture streams %d\n",
+- num_playback);
++ num_capture);
+ return -EINVAL;
+ }
+
+diff --git a/sound/usb/qcom/qc_audio_offload.c b/sound/usb/qcom/qc_audio_offload.c
+index a25c5a5316901c..9ad76fff741b8d 100644
+--- a/sound/usb/qcom/qc_audio_offload.c
++++ b/sound/usb/qcom/qc_audio_offload.c
+@@ -538,38 +538,33 @@ static void uaudio_iommu_unmap(enum mem_type mtype, unsigned long iova,
+ umap_size, iova, mapped_iova_size);
+ }
+
++static int uaudio_iommu_map_prot(bool dma_coherent)
++{
++ int prot = IOMMU_READ | IOMMU_WRITE;
++
++ if (dma_coherent)
++ prot |= IOMMU_CACHE;
++ return prot;
++}
++
+ /**
+- * uaudio_iommu_map() - maps iommu memory for adsp
++ * uaudio_iommu_map_pa() - maps iommu memory for adsp
+ * @mtype: ring type
+ * @dma_coherent: dma coherent
+ * @pa: physical address for ring/buffer
+ * @size: size of memory region
+- * @sgt: sg table for memory region
+ *
+ * Maps the XHCI related resources to a memory region that is assigned to be
+ * used by the adsp. This will be mapped to the domain, which is created by
+ * the ASoC USB backend driver.
+ *
+ */
+-static unsigned long uaudio_iommu_map(enum mem_type mtype, bool dma_coherent,
+- phys_addr_t pa, size_t size,
+- struct sg_table *sgt)
++static unsigned long uaudio_iommu_map_pa(enum mem_type mtype, bool dma_coherent,
++ phys_addr_t pa, size_t size)
+ {
+- struct scatterlist *sg;
+ unsigned long iova = 0;
+- size_t total_len = 0;
+- unsigned long iova_sg;
+- phys_addr_t pa_sg;
+ bool map = true;
+- size_t sg_len;
+- int prot;
+- int ret;
+- int i;
+-
+- prot = IOMMU_READ | IOMMU_WRITE;
+-
+- if (dma_coherent)
+- prot |= IOMMU_CACHE;
++ int prot = uaudio_iommu_map_prot(dma_coherent);
+
+ switch (mtype) {
+ case MEM_EVENT_RING:
+@@ -583,20 +578,41 @@ static unsigned long uaudio_iommu_map(enum mem_type mtype, bool dma_coherent,
+ &uaudio_qdev->xfer_ring_iova_size,
+ &uaudio_qdev->xfer_ring_list, size);
+ break;
+- case MEM_XFER_BUF:
+- iova = uaudio_get_iova(&uaudio_qdev->curr_xfer_buf_iova,
+- &uaudio_qdev->xfer_buf_iova_size,
+- &uaudio_qdev->xfer_buf_list, size);
+- break;
+ default:
+ dev_err(uaudio_qdev->data->dev, "unknown mem type %d\n", mtype);
+ }
+
+ if (!iova || !map)
+- goto done;
++ return 0;
++
++ iommu_map(uaudio_qdev->data->domain, iova, pa, size, prot, GFP_KERNEL);
+
+- if (!sgt)
+- goto skip_sgt_map;
++ return iova;
++}
++
++static unsigned long uaudio_iommu_map_xfer_buf(bool dma_coherent, size_t size,
++ struct sg_table *sgt)
++{
++ struct scatterlist *sg;
++ unsigned long iova = 0;
++ size_t total_len = 0;
++ unsigned long iova_sg;
++ phys_addr_t pa_sg;
++ size_t sg_len;
++ int prot = uaudio_iommu_map_prot(dma_coherent);
++ int ret;
++ int i;
++
++ prot = IOMMU_READ | IOMMU_WRITE;
++
++ if (dma_coherent)
++ prot |= IOMMU_CACHE;
++
++ iova = uaudio_get_iova(&uaudio_qdev->curr_xfer_buf_iova,
++ &uaudio_qdev->xfer_buf_iova_size,
++ &uaudio_qdev->xfer_buf_list, size);
++ if (!iova)
++ goto done;
+
+ iova_sg = iova;
+ for_each_sg(sgt->sgl, sg, sgt->nents, i) {
+@@ -618,11 +634,6 @@ static unsigned long uaudio_iommu_map(enum mem_type mtype, bool dma_coherent,
+ uaudio_iommu_unmap(MEM_XFER_BUF, iova, size, total_len);
+ iova = 0;
+ }
+- return iova;
+-
+-skip_sgt_map:
+- iommu_map(uaudio_qdev->data->domain, iova, pa, size, prot, GFP_KERNEL);
+-
+ done:
+ return iova;
+ }
+@@ -1020,7 +1031,6 @@ static int uaudio_transfer_buffer_setup(struct snd_usb_substream *subs,
+ struct sg_table xfer_buf_sgt;
+ dma_addr_t xfer_buf_dma;
+ void *xfer_buf;
+- phys_addr_t xfer_buf_pa;
+ u32 len = xfer_buf_len;
+ bool dma_coherent;
+ dma_addr_t xfer_buf_dma_sysdev;
+@@ -1051,18 +1061,12 @@ static int uaudio_transfer_buffer_setup(struct snd_usb_substream *subs,
+ if (!xfer_buf)
+ return -ENOMEM;
+
+- /* Remapping is not possible if xfer_buf is outside of linear map */
+- xfer_buf_pa = virt_to_phys(xfer_buf);
+- if (WARN_ON(!page_is_ram(PFN_DOWN(xfer_buf_pa)))) {
+- ret = -ENXIO;
+- goto unmap_sync;
+- }
+ dma_get_sgtable(subs->dev->bus->sysdev, &xfer_buf_sgt, xfer_buf,
+ xfer_buf_dma, len);
+
+ /* map the physical buffer into sysdev as well */
+- xfer_buf_dma_sysdev = uaudio_iommu_map(MEM_XFER_BUF, dma_coherent,
+- xfer_buf_pa, len, &xfer_buf_sgt);
++ xfer_buf_dma_sysdev = uaudio_iommu_map_xfer_buf(dma_coherent,
++ len, &xfer_buf_sgt);
+ if (!xfer_buf_dma_sysdev) {
+ ret = -ENOMEM;
+ goto unmap_sync;
+@@ -1143,8 +1147,8 @@ uaudio_endpoint_setup(struct snd_usb_substream *subs,
+ sg_free_table(sgt);
+
+ /* data transfer ring */
+- iova = uaudio_iommu_map(MEM_XFER_RING, dma_coherent, tr_pa,
+- PAGE_SIZE, NULL);
++ iova = uaudio_iommu_map_pa(MEM_XFER_RING, dma_coherent, tr_pa,
++ PAGE_SIZE);
+ if (!iova) {
+ ret = -ENOMEM;
+ goto clear_pa;
+@@ -1207,8 +1211,8 @@ static int uaudio_event_ring_setup(struct snd_usb_substream *subs,
+ mem_info->dma = sg_dma_address(sgt->sgl);
+ sg_free_table(sgt);
+
+- iova = uaudio_iommu_map(MEM_EVENT_RING, dma_coherent, er_pa,
+- PAGE_SIZE, NULL);
++ iova = uaudio_iommu_map_pa(MEM_EVENT_RING, dma_coherent, er_pa,
++ PAGE_SIZE);
+ if (!iova) {
+ ret = -ENOMEM;
+ goto clear_pa;
+diff --git a/tools/arch/loongarch/include/asm/inst.h b/tools/arch/loongarch/include/asm/inst.h
+index c25b5853181dba..d68fad63c8b732 100644
+--- a/tools/arch/loongarch/include/asm/inst.h
++++ b/tools/arch/loongarch/include/asm/inst.h
+@@ -51,6 +51,10 @@ enum reg2i16_op {
+ bgeu_op = 0x1b,
+ };
+
++enum reg3_op {
++ amswapw_op = 0x70c0,
++};
++
+ struct reg0i15_format {
+ unsigned int immediate : 15;
+ unsigned int opcode : 17;
+@@ -96,6 +100,13 @@ struct reg2i16_format {
+ unsigned int opcode : 6;
+ };
+
++struct reg3_format {
++ unsigned int rd : 5;
++ unsigned int rj : 5;
++ unsigned int rk : 5;
++ unsigned int opcode : 17;
++};
++
+ union loongarch_instruction {
+ unsigned int word;
+ struct reg0i15_format reg0i15_format;
+@@ -105,6 +116,7 @@ union loongarch_instruction {
+ struct reg2i12_format reg2i12_format;
+ struct reg2i14_format reg2i14_format;
+ struct reg2i16_format reg2i16_format;
++ struct reg3_format reg3_format;
+ };
+
+ #define LOONGARCH_INSN_SIZE sizeof(union loongarch_instruction)
+diff --git a/tools/objtool/arch/loongarch/decode.c b/tools/objtool/arch/loongarch/decode.c
+index b6fdc68053cc4e..2e555c4060c5e4 100644
+--- a/tools/objtool/arch/loongarch/decode.c
++++ b/tools/objtool/arch/loongarch/decode.c
+@@ -278,6 +278,25 @@ static bool decode_insn_reg2i16_fomat(union loongarch_instruction inst,
+ return true;
+ }
+
++static bool decode_insn_reg3_fomat(union loongarch_instruction inst,
++ struct instruction *insn)
++{
++ switch (inst.reg3_format.opcode) {
++ case amswapw_op:
++ if (inst.reg3_format.rd == LOONGARCH_GPR_ZERO &&
++ inst.reg3_format.rk == LOONGARCH_GPR_RA &&
++ inst.reg3_format.rj == LOONGARCH_GPR_ZERO) {
++ /* amswap.w $zero, $ra, $zero */
++ insn->type = INSN_BUG;
++ }
++ break;
++ default:
++ return false;
++ }
++
++ return true;
++}
++
+ int arch_decode_instruction(struct objtool_file *file, const struct section *sec,
+ unsigned long offset, unsigned int maxlen,
+ struct instruction *insn)
+@@ -309,11 +328,19 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
+ return 0;
+ if (decode_insn_reg2i16_fomat(inst, insn))
+ return 0;
++ if (decode_insn_reg3_fomat(inst, insn))
++ return 0;
+
+- if (inst.word == 0)
++ if (inst.word == 0) {
++ /* andi $zero, $zero, 0x0 */
+ insn->type = INSN_NOP;
+- else if (inst.reg0i15_format.opcode == break_op) {
+- /* break */
++ } else if (inst.reg0i15_format.opcode == break_op &&
++ inst.reg0i15_format.immediate == 0x0) {
++ /* break 0x0 */
++ insn->type = INSN_TRAP;
++ } else if (inst.reg0i15_format.opcode == break_op &&
++ inst.reg0i15_format.immediate == 0x1) {
++ /* break 0x1 */
+ insn->type = INSN_BUG;
+ } else if (inst.reg2_format.opcode == ertn_op) {
+ /* ertn */
+diff --git a/tools/perf/util/maps.c b/tools/perf/util/maps.c
+index 85b2a93a59ac65..779f6230130af2 100644
+--- a/tools/perf/util/maps.c
++++ b/tools/perf/util/maps.c
+@@ -477,6 +477,7 @@ static int __maps__insert(struct maps *maps, struct map *new)
+ }
+ /* Insert the value at the end. */
+ maps_by_address[nr_maps] = map__get(new);
++ map__set_kmap_maps(new, maps);
+ if (maps_by_name)
+ maps_by_name[nr_maps] = map__get(new);
+
+@@ -502,8 +503,6 @@ static int __maps__insert(struct maps *maps, struct map *new)
+ if (map__end(new) < map__start(new))
+ RC_CHK_ACCESS(maps)->ends_broken = true;
+
+- map__set_kmap_maps(new, maps);
+-
+ return 0;
+ }
+
+@@ -891,6 +890,7 @@ static int __maps__fixup_overlap_and_insert(struct maps *maps, struct map *new)
+ if (before) {
+ map__put(maps_by_address[i]);
+ maps_by_address[i] = before;
++ map__set_kmap_maps(before, maps);
+
+ if (maps_by_name) {
+ map__put(maps_by_name[ni]);
+@@ -918,6 +918,7 @@ static int __maps__fixup_overlap_and_insert(struct maps *maps, struct map *new)
+ */
+ map__put(maps_by_address[i]);
+ maps_by_address[i] = map__get(new);
++ map__set_kmap_maps(new, maps);
+
+ if (maps_by_name) {
+ map__put(maps_by_name[ni]);
+@@ -942,14 +943,13 @@ static int __maps__fixup_overlap_and_insert(struct maps *maps, struct map *new)
+ */
+ map__put(maps_by_address[i]);
+ maps_by_address[i] = map__get(new);
++ map__set_kmap_maps(new, maps);
+
+ if (maps_by_name) {
+ map__put(maps_by_name[ni]);
+ maps_by_name[ni] = map__get(new);
+ }
+
+- map__set_kmap_maps(new, maps);
+-
+ check_invariants(maps);
+ return err;
+ }
+@@ -1019,6 +1019,7 @@ int maps__copy_from(struct maps *dest, struct maps *parent)
+ err = unwind__prepare_access(dest, new, NULL);
+ if (!err) {
+ dest_maps_by_address[i] = new;
++ map__set_kmap_maps(new, dest);
+ if (dest_maps_by_name)
+ dest_maps_by_name[i] = map__get(new);
+ RC_CHK_ACCESS(dest)->nr_maps = i + 1;
+diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.c b/tools/testing/selftests/net/mptcp/mptcp_connect.c
+index 4f07ac9fa207cb..b148cadb96d0b7 100644
+--- a/tools/testing/selftests/net/mptcp/mptcp_connect.c
++++ b/tools/testing/selftests/net/mptcp/mptcp_connect.c
+@@ -1093,6 +1093,7 @@ int main_loop_s(int listensock)
+ struct pollfd polls;
+ socklen_t salen;
+ int remotesock;
++ int err = 0;
+ int fd = 0;
+
+ again:
+@@ -1125,7 +1126,7 @@ int main_loop_s(int listensock)
+ SOCK_TEST_TCPULP(remotesock, 0);
+
+ memset(&winfo, 0, sizeof(winfo));
+- copyfd_io(fd, remotesock, 1, true, &winfo);
++ err = copyfd_io(fd, remotesock, 1, true, &winfo);
+ } else {
+ perror("accept");
+ return 1;
+@@ -1134,10 +1135,10 @@ int main_loop_s(int listensock)
+ if (cfg_input)
+ close(fd);
+
+- if (--cfg_repeat > 0)
++ if (!err && --cfg_repeat > 0)
+ goto again;
+
+- return 0;
++ return err;
+ }
+
+ static void init_rng(void)
+@@ -1247,7 +1248,7 @@ void xdisconnect(int fd)
+ else
+ xerror("bad family");
+
+- strcpy(cmd, "ss -M | grep -q ");
++ strcpy(cmd, "ss -Mnt | grep -q ");
+ cmdlen = strlen(cmd);
+ if (!inet_ntop(addr.ss_family, raw_addr, &cmd[cmdlen],
+ sizeof(cmd) - cmdlen))
+@@ -1257,7 +1258,7 @@ void xdisconnect(int fd)
+
+ /*
+ * wait until the pending data is completely flushed and all
+- * the MPTCP sockets reached the closed status.
++ * the sockets reached the closed status.
+ * disconnect will bypass/ignore/drop any pending data.
+ */
+ for (i = 0; ; i += msec_sleep) {
+diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
+index e934dd26a59d9b..112c07c4c37a3c 100644
+--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
++++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
+@@ -667,22 +667,26 @@ static void process_one_client(int fd, int pipefd)
+
+ do_getsockopts(&s, fd, ret, ret2);
+ if (s.mptcpi_rcv_delta != (uint64_t)ret + 1)
+- xerror("mptcpi_rcv_delta %" PRIu64 ", expect %" PRIu64, s.mptcpi_rcv_delta, ret + 1, s.mptcpi_rcv_delta - ret);
++ xerror("mptcpi_rcv_delta %" PRIu64 ", expect %" PRIu64 ", diff %" PRId64,
++ s.mptcpi_rcv_delta, ret + 1, s.mptcpi_rcv_delta - (ret + 1));
+
+ /* be nice when running on top of older kernel */
+ if (s.pkt_stats_avail) {
+ if (s.last_sample.mptcpi_bytes_sent != ret2)
+- xerror("mptcpi_bytes_sent %" PRIu64 ", expect %" PRIu64,
++ xerror("mptcpi_bytes_sent %" PRIu64 ", expect %" PRIu64
++ ", diff %" PRId64,
+ s.last_sample.mptcpi_bytes_sent, ret2,
+ s.last_sample.mptcpi_bytes_sent - ret2);
+ if (s.last_sample.mptcpi_bytes_received != ret)
+- xerror("mptcpi_bytes_received %" PRIu64 ", expect %" PRIu64,
++ xerror("mptcpi_bytes_received %" PRIu64 ", expect %" PRIu64
++ ", diff %" PRId64,
+ s.last_sample.mptcpi_bytes_received, ret,
+ s.last_sample.mptcpi_bytes_received - ret);
+ if (s.last_sample.mptcpi_bytes_acked != ret)
+- xerror("mptcpi_bytes_acked %" PRIu64 ", expect %" PRIu64,
+- s.last_sample.mptcpi_bytes_acked, ret2,
+- s.last_sample.mptcpi_bytes_acked - ret2);
++ xerror("mptcpi_bytes_acked %" PRIu64 ", expect %" PRIu64
++ ", diff %" PRId64,
++ s.last_sample.mptcpi_bytes_acked, ret,
++ s.last_sample.mptcpi_bytes_acked - ret);
+ }
+
+ close(fd);
+diff --git a/tools/testing/selftests/net/mptcp/pm_nl_ctl.c b/tools/testing/selftests/net/mptcp/pm_nl_ctl.c
+index 994a556f46c151..93fea3442216c8 100644
+--- a/tools/testing/selftests/net/mptcp/pm_nl_ctl.c
++++ b/tools/testing/selftests/net/mptcp/pm_nl_ctl.c
+@@ -188,6 +188,13 @@ static int capture_events(int fd, int event_group)
+ fprintf(stderr, ",error:%u", *(__u8 *)RTA_DATA(attrs));
+ else if (attrs->rta_type == MPTCP_ATTR_SERVER_SIDE)
+ fprintf(stderr, ",server_side:%u", *(__u8 *)RTA_DATA(attrs));
++ else if (attrs->rta_type == MPTCP_ATTR_FLAGS) {
++ __u16 flags = *(__u16 *)RTA_DATA(attrs);
++
++ /* only print when present, easier */
++ if (flags & MPTCP_PM_EV_FLAG_DENY_JOIN_ID0)
++ fprintf(stderr, ",deny_join_id0:1");
++ }
+
+ attrs = RTA_NEXT(attrs, msg_len);
+ }
+diff --git a/tools/testing/selftests/net/mptcp/userspace_pm.sh b/tools/testing/selftests/net/mptcp/userspace_pm.sh
+index 333064b0b5ac03..97819e18578f4d 100755
+--- a/tools/testing/selftests/net/mptcp/userspace_pm.sh
++++ b/tools/testing/selftests/net/mptcp/userspace_pm.sh
+@@ -201,6 +201,9 @@ make_connection()
+ is_v6="v4"
+ fi
+
++ # set this on the client side only: will not affect the rest
++ ip netns exec "$ns2" sysctl -q net.mptcp.allow_join_initial_addr_port=0
++
+ :>"$client_evts"
+ :>"$server_evts"
+
+@@ -223,23 +226,28 @@ make_connection()
+ local client_token
+ local client_port
+ local client_serverside
++ local client_nojoin
+ local server_token
+ local server_serverside
++ local server_nojoin
+
+ client_token=$(mptcp_lib_evts_get_info token "$client_evts")
+ client_port=$(mptcp_lib_evts_get_info sport "$client_evts")
+ client_serverside=$(mptcp_lib_evts_get_info server_side "$client_evts")
++ client_nojoin=$(mptcp_lib_evts_get_info deny_join_id0 "$client_evts")
+ server_token=$(mptcp_lib_evts_get_info token "$server_evts")
+ server_serverside=$(mptcp_lib_evts_get_info server_side "$server_evts")
++ server_nojoin=$(mptcp_lib_evts_get_info deny_join_id0 "$server_evts")
+
+ print_test "Established IP${is_v6} MPTCP Connection ns2 => ns1"
+- if [ "$client_token" != "" ] && [ "$server_token" != "" ] && [ "$client_serverside" = 0 ] &&
+- [ "$server_serverside" = 1 ]
++ if [ "${client_token}" != "" ] && [ "${server_token}" != "" ] &&
++ [ "${client_serverside}" = 0 ] && [ "${server_serverside}" = 1 ] &&
++ [ "${client_nojoin:-0}" = 0 ] && [ "${server_nojoin:-0}" = 1 ]
+ then
+ test_pass
+ print_title "Connection info: ${client_addr}:${client_port} -> ${connect_addr}:${app_port}"
+ else
+- test_fail "Expected tokens (c:${client_token} - s:${server_token}) and server (c:${client_serverside} - s:${server_serverside})"
++ test_fail "Expected tokens (c:${client_token} - s:${server_token}), server (c:${client_serverside} - s:${server_serverside}), nojoin (c:${client_nojoin} - s:${server_nojoin})"
+ mptcp_lib_result_print_all_tap
+ exit ${KSFT_FAIL}
+ fi
next reply other threads:[~2025-09-25 12:02 UTC|newest]
Thread overview: 41+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-09-25 12:02 Arisu Tachibana [this message]
-- strict thread matches above, loose matches on Subject: below --
2025-10-13 11:56 [gentoo-commits] proj/linux-patches:6.16 commit in: / Arisu Tachibana
2025-10-06 12:01 Arisu Tachibana
2025-10-06 11:06 Arisu Tachibana
2025-10-02 14:17 Arisu Tachibana
2025-10-02 14:14 Arisu Tachibana
2025-10-02 13:42 Arisu Tachibana
2025-10-02 13:30 Arisu Tachibana
2025-10-02 13:25 Arisu Tachibana
2025-10-02 3:28 Arisu Tachibana
2025-10-02 3:28 Arisu Tachibana
2025-10-02 3:12 Arisu Tachibana
2025-09-20 6:29 Arisu Tachibana
2025-09-20 6:29 Arisu Tachibana
2025-09-20 5:31 Arisu Tachibana
2025-09-20 5:25 Arisu Tachibana
2025-09-12 3:56 Arisu Tachibana
2025-09-10 6:18 Arisu Tachibana
2025-09-10 5:57 Arisu Tachibana
2025-09-10 5:30 Arisu Tachibana
2025-09-05 14:01 Arisu Tachibana
2025-09-04 15:46 Arisu Tachibana
2025-09-04 15:33 Arisu Tachibana
2025-08-28 16:37 Arisu Tachibana
2025-08-28 16:01 Arisu Tachibana
2025-08-28 15:31 Arisu Tachibana
2025-08-28 15:19 Arisu Tachibana
2025-08-28 15:14 Arisu Tachibana
2025-08-25 0:00 Arisu Tachibana
2025-08-24 23:09 Arisu Tachibana
2025-08-21 4:31 Arisu Tachibana
2025-08-21 4:31 Arisu Tachibana
2025-08-21 1:07 Arisu Tachibana
2025-08-21 1:00 Arisu Tachibana
2025-08-21 0:27 Arisu Tachibana
2025-08-16 5:54 Arisu Tachibana
2025-08-16 5:54 Arisu Tachibana
2025-08-16 5:21 Arisu Tachibana
2025-08-16 4:02 Arisu Tachibana
2025-08-16 3:07 Arisu Tachibana
2025-07-29 7:43 Arisu Tachibana
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=1758801724.fb4386cb8d3a0e3944fcbd135b1a7c53cd28d3ad.alicef@gentoo \
--to=alicef@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