public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
From: "Mike Pagano" <mpagano@gentoo.org>
To: gentoo-commits@lists.gentoo.org
Subject: [gentoo-commits] proj/linux-patches:6.4 commit in: /
Date: Wed, 16 Aug 2023 17:28:34 +0000 (UTC)	[thread overview]
Message-ID: <1692206904.6ac7d6d91eb0fb742af4fcd5f29cb68433c8a24b.mpagano@gentoo> (raw)

commit:     6ac7d6d91eb0fb742af4fcd5f29cb68433c8a24b
Author:     Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Wed Aug 16 17:16:44 2023 +0000
Commit:     Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Wed Aug 16 17:28:24 2023 +0000
URL:        https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=6ac7d6d9

Linux patch 6.4.11

Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org>

 0000_README             |    4 +
 1010_linux-6.4.11.patch | 9168 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 9172 insertions(+)

diff --git a/0000_README b/0000_README
index f63d6a30..c16c1b6b 100644
--- a/0000_README
+++ b/0000_README
@@ -83,6 +83,10 @@ Patch:  1009_linux-6.4.10.patch
 From:   https://www.kernel.org
 Desc:   Linux 6.4.10
 
+Patch:  1010_linux-6.4.11.patch
+From:   https://www.kernel.org
+Desc:   Linux 6.4.11
+
 Patch:  1500_XATTR_USER_PREFIX.patch
 From:   https://bugs.gentoo.org/show_bug.cgi?id=470644
 Desc:   Support for namespace user.pax.* on tmpfs.

diff --git a/1010_linux-6.4.11.patch b/1010_linux-6.4.11.patch
new file mode 100644
index 00000000..0632e5be
--- /dev/null
+++ b/1010_linux-6.4.11.patch
@@ -0,0 +1,9168 @@
+diff --git a/Makefile b/Makefile
+index bf463afef54bf..d0efd84bb7d0f 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ VERSION = 6
+ PATCHLEVEL = 4
+-SUBLEVEL = 10
++SUBLEVEL = 11
+ EXTRAVERSION =
+ NAME = Hurr durr I'ma ninja sloth
+ 
+diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
+index 33bf3a6270027..45a920ba4921d 100644
+--- a/arch/alpha/kernel/setup.c
++++ b/arch/alpha/kernel/setup.c
+@@ -385,8 +385,7 @@ setup_memory(void *kernel_end)
+ #endif /* CONFIG_BLK_DEV_INITRD */
+ }
+ 
+-int __init
+-page_is_ram(unsigned long pfn)
++int page_is_ram(unsigned long pfn)
+ {
+ 	struct memclust_struct * cluster;
+ 	struct memdesc_struct * memdesc;
+diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
+index 3a2606ba3e583..62b164a0041fb 100644
+--- a/arch/arm64/kvm/arm.c
++++ b/arch/arm64/kvm/arm.c
+@@ -1800,8 +1800,6 @@ static void _kvm_arch_hardware_enable(void *discard)
+ 
+ int kvm_arch_hardware_enable(void)
+ {
+-	int was_enabled;
+-
+ 	/*
+ 	 * Most calls to this function are made with migration
+ 	 * disabled, but not with preemption disabled. The former is
+@@ -1810,13 +1808,10 @@ int kvm_arch_hardware_enable(void)
+ 	 */
+ 	preempt_disable();
+ 
+-	was_enabled = __this_cpu_read(kvm_arm_hardware_enabled);
+ 	_kvm_arch_hardware_enable(NULL);
+ 
+-	if (!was_enabled) {
+-		kvm_vgic_cpu_up();
+-		kvm_timer_cpu_up();
+-	}
++	kvm_vgic_cpu_up();
++	kvm_timer_cpu_up();
+ 
+ 	preempt_enable();
+ 
+@@ -1833,10 +1828,8 @@ static void _kvm_arch_hardware_disable(void *discard)
+ 
+ void kvm_arch_hardware_disable(void)
+ {
+-	if (__this_cpu_read(kvm_arm_hardware_enabled)) {
+-		kvm_timer_cpu_down();
+-		kvm_vgic_cpu_down();
+-	}
++	kvm_timer_cpu_down();
++	kvm_vgic_cpu_down();
+ 
+ 	if (!is_protected_kvm_enabled())
+ 		_kvm_arch_hardware_disable(NULL);
+diff --git a/arch/parisc/Kconfig.debug b/arch/parisc/Kconfig.debug
+index 3a059cb5e112f..56d35315f88ed 100644
+--- a/arch/parisc/Kconfig.debug
++++ b/arch/parisc/Kconfig.debug
+@@ -2,7 +2,7 @@
+ #
+ config LIGHTWEIGHT_SPINLOCK_CHECK
+ 	bool "Enable lightweight spinlock checks"
+-	depends on SMP && !DEBUG_SPINLOCK
++	depends on DEBUG_KERNEL && SMP && !DEBUG_SPINLOCK
+ 	default y
+ 	help
+ 	  Add checks with low performance impact to the spinlock functions
+diff --git a/arch/parisc/include/asm/spinlock.h b/arch/parisc/include/asm/spinlock.h
+index edfcb9858bcb7..0b326e52255e1 100644
+--- a/arch/parisc/include/asm/spinlock.h
++++ b/arch/parisc/include/asm/spinlock.h
+@@ -7,8 +7,6 @@
+ #include <asm/processor.h>
+ #include <asm/spinlock_types.h>
+ 
+-#define SPINLOCK_BREAK_INSN	0x0000c006	/* break 6,6 */
+-
+ static inline void arch_spin_val_check(int lock_val)
+ {
+ 	if (IS_ENABLED(CONFIG_LIGHTWEIGHT_SPINLOCK_CHECK))
+diff --git a/arch/parisc/include/asm/spinlock_types.h b/arch/parisc/include/asm/spinlock_types.h
+index d65934079ebdb..efd06a897c6a3 100644
+--- a/arch/parisc/include/asm/spinlock_types.h
++++ b/arch/parisc/include/asm/spinlock_types.h
+@@ -4,6 +4,10 @@
+ 
+ #define __ARCH_SPIN_LOCK_UNLOCKED_VAL	0x1a46
+ 
++#define SPINLOCK_BREAK_INSN	0x0000c006	/* break 6,6 */
++
++#ifndef __ASSEMBLY__
++
+ typedef struct {
+ #ifdef CONFIG_PA20
+ 	volatile unsigned int slock;
+@@ -27,6 +31,8 @@ typedef struct {
+ 	volatile unsigned int	counter;
+ } arch_rwlock_t;
+ 
++#endif /* __ASSEMBLY__ */
++
+ #define __ARCH_RW_LOCK_UNLOCKED__       0x01000000
+ #define __ARCH_RW_LOCK_UNLOCKED         { .lock_mutex = __ARCH_SPIN_LOCK_UNLOCKED, \
+ 					.counter = __ARCH_RW_LOCK_UNLOCKED__ }
+diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c
+index 465b7cb9d44f4..39acccabf2ede 100644
+--- a/arch/parisc/kernel/sys_parisc.c
++++ b/arch/parisc/kernel/sys_parisc.c
+@@ -26,17 +26,12 @@
+ #include <linux/compat.h>
+ 
+ /*
+- * Construct an artificial page offset for the mapping based on the virtual
++ * Construct an artificial page offset for the mapping based on the physical
+  * address of the kernel file mapping variable.
+- * If filp is zero the calculated pgoff value aliases the memory of the given
+- * address. This is useful for io_uring where the mapping shall alias a kernel
+- * address and a userspace adress where both the kernel and the userspace
+- * access the same memory region.
+  */
+-#define GET_FILP_PGOFF(filp, addr)		\
+-	((filp ? (((unsigned long) filp->f_mapping) >> 8)	\
+-		 & ((SHM_COLOUR-1) >> PAGE_SHIFT) : 0UL)	\
+-	  + (addr >> PAGE_SHIFT))
++#define GET_FILP_PGOFF(filp)		\
++	(filp ? (((unsigned long) filp->f_mapping) >> 8)	\
++		 & ((SHM_COLOUR-1) >> PAGE_SHIFT) : 0UL)
+ 
+ static unsigned long shared_align_offset(unsigned long filp_pgoff,
+ 					 unsigned long pgoff)
+@@ -116,7 +111,7 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp,
+ 	do_color_align = 0;
+ 	if (filp || (flags & MAP_SHARED))
+ 		do_color_align = 1;
+-	filp_pgoff = GET_FILP_PGOFF(filp, addr);
++	filp_pgoff = GET_FILP_PGOFF(filp);
+ 
+ 	if (flags & MAP_FIXED) {
+ 		/* Even MAP_FIXED mappings must reside within TASK_SIZE */
+diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S
+index 1373e5129868f..1f51aa9c8230c 100644
+--- a/arch/parisc/kernel/syscall.S
++++ b/arch/parisc/kernel/syscall.S
+@@ -39,6 +39,7 @@ registers).
+ #include <asm/assembly.h>
+ #include <asm/processor.h>
+ #include <asm/cache.h>
++#include <asm/spinlock_types.h>
+ 
+ #include <linux/linkage.h>
+ 
+@@ -66,6 +67,16 @@ registers).
+ 	stw	\reg1, 0(%sr2,\reg2)
+ 	.endm
+ 
++	/* raise exception if spinlock content is not zero or
++	 * __ARCH_SPIN_LOCK_UNLOCKED_VAL */
++	.macro	spinlock_check spin_val,tmpreg
++#ifdef CONFIG_LIGHTWEIGHT_SPINLOCK_CHECK
++	ldi	__ARCH_SPIN_LOCK_UNLOCKED_VAL, \tmpreg
++	andcm,=	\spin_val, \tmpreg, %r0
++	.word	SPINLOCK_BREAK_INSN
++#endif
++	.endm
++
+ 	.text
+ 
+ 	.import syscall_exit,code
+@@ -508,7 +519,8 @@ lws_start:
+ 
+ lws_exit_noerror:
+ 	lws_pagefault_enable	%r1,%r21
+-	stw,ma	%r20, 0(%sr2,%r20)
++	ldi	__ARCH_SPIN_LOCK_UNLOCKED_VAL, %r21
++	stw,ma	%r21, 0(%sr2,%r20)
+ 	ssm	PSW_SM_I, %r0
+ 	b	lws_exit
+ 	copy	%r0, %r21
+@@ -521,7 +533,8 @@ lws_wouldblock:
+ 
+ lws_pagefault:
+ 	lws_pagefault_enable	%r1,%r21
+-	stw,ma	%r20, 0(%sr2,%r20)
++	ldi	__ARCH_SPIN_LOCK_UNLOCKED_VAL, %r21
++	stw,ma	%r21, 0(%sr2,%r20)
+ 	ssm	PSW_SM_I, %r0
+ 	ldo	3(%r0),%r28
+ 	b	lws_exit
+@@ -619,6 +632,7 @@ lws_compare_and_swap:
+ 
+ 	/* Try to acquire the lock */
+ 	LDCW	0(%sr2,%r20), %r28
++	spinlock_check	%r28, %r21
+ 	comclr,<>	%r0, %r28, %r0
+ 	b,n	lws_wouldblock
+ 
+@@ -772,6 +786,7 @@ cas2_lock_start:
+ 
+ 	/* Try to acquire the lock */
+ 	LDCW	0(%sr2,%r20), %r28
++	spinlock_check	%r28, %r21
+ 	comclr,<>	%r0, %r28, %r0
+ 	b,n	lws_wouldblock
+ 
+@@ -1001,6 +1016,7 @@ atomic_xchg_start:
+ 
+ 	/* Try to acquire the lock */
+ 	LDCW	0(%sr2,%r20), %r28
++	spinlock_check	%r28, %r21
+ 	comclr,<>	%r0, %r28, %r0
+ 	b,n	lws_wouldblock
+ 
+@@ -1199,6 +1215,7 @@ atomic_store_start:
+ 
+ 	/* Try to acquire the lock */
+ 	LDCW	0(%sr2,%r20), %r28
++	spinlock_check	%r28, %r21
+ 	comclr,<>	%r0, %r28, %r0
+ 	b,n	lws_wouldblock
+ 
+@@ -1330,7 +1347,7 @@ ENTRY(lws_lock_start)
+ 	/* lws locks */
+ 	.rept 256
+ 	/* Keep locks aligned at 16-bytes */
+-	.word 1
++	.word __ARCH_SPIN_LOCK_UNLOCKED_VAL
+ 	.word 0 
+ 	.word 0
+ 	.word 0
+diff --git a/arch/riscv/include/asm/mmio.h b/arch/riscv/include/asm/mmio.h
+index aff6c33ab0c08..4c58ee7f95ecf 100644
+--- a/arch/riscv/include/asm/mmio.h
++++ b/arch/riscv/include/asm/mmio.h
+@@ -101,9 +101,9 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
+  * Relaxed I/O memory access primitives. These follow the Device memory
+  * ordering rules but do not guarantee any ordering relative to Normal memory
+  * accesses.  These are defined to order the indicated access (either a read or
+- * write) with all other I/O memory accesses. Since the platform specification
+- * defines that all I/O regions are strongly ordered on channel 2, no explicit
+- * fences are required to enforce this ordering.
++ * write) with all other I/O memory accesses to the same peripheral. Since the
++ * platform specification defines that all I/O regions are strongly ordered on
++ * channel 0, no explicit fences are required to enforce this ordering.
+  */
+ /* FIXME: These are now the same as asm-generic */
+ #define __io_rbr()		do {} while (0)
+@@ -125,14 +125,14 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
+ #endif
+ 
+ /*
+- * I/O memory access primitives. Reads are ordered relative to any
+- * following Normal memory access. Writes are ordered relative to any prior
+- * Normal memory access.  The memory barriers here are necessary as RISC-V
++ * I/O memory access primitives.  Reads are ordered relative to any following
++ * Normal memory read and delay() loop.  Writes are ordered relative to any
++ * prior Normal memory write.  The memory barriers here are necessary as RISC-V
+  * doesn't define any ordering between the memory space and the I/O space.
+  */
+ #define __io_br()	do {} while (0)
+-#define __io_ar(v)	__asm__ __volatile__ ("fence i,r" : : : "memory")
+-#define __io_bw()	__asm__ __volatile__ ("fence w,o" : : : "memory")
++#define __io_ar(v)	({ __asm__ __volatile__ ("fence i,ir" : : : "memory"); })
++#define __io_bw()	({ __asm__ __volatile__ ("fence w,o" : : : "memory"); })
+ #define __io_aw()	mmiowb_set_pending()
+ 
+ #define readb(c)	({ u8  __v; __io_br(); __v = readb_cpu(c); __io_ar(__v); __v; })
+diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
+index 75970ee2bda22..b5680c940c1e9 100644
+--- a/arch/riscv/include/asm/pgtable.h
++++ b/arch/riscv/include/asm/pgtable.h
+@@ -188,6 +188,8 @@ extern struct pt_alloc_ops pt_ops __initdata;
+ #define PAGE_KERNEL_IO		__pgprot(_PAGE_IOREMAP)
+ 
+ extern pgd_t swapper_pg_dir[];
++extern pgd_t trampoline_pg_dir[];
++extern pgd_t early_pg_dir[];
+ 
+ #ifdef CONFIG_TRANSPARENT_HUGEPAGE
+ static inline int pmd_present(pmd_t pmd)
+diff --git a/arch/riscv/kernel/elf_kexec.c b/arch/riscv/kernel/elf_kexec.c
+index 5372b708fae21..c08bb5c3b3857 100644
+--- a/arch/riscv/kernel/elf_kexec.c
++++ b/arch/riscv/kernel/elf_kexec.c
+@@ -281,7 +281,7 @@ static void *elf_kexec_load(struct kimage *image, char *kernel_buf,
+ 		kbuf.buffer = initrd;
+ 		kbuf.bufsz = kbuf.memsz = initrd_len;
+ 		kbuf.buf_align = PAGE_SIZE;
+-		kbuf.top_down = false;
++		kbuf.top_down = true;
+ 		kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
+ 		ret = kexec_add_buffer(&kbuf);
+ 		if (ret)
+@@ -425,6 +425,7 @@ int arch_kexec_apply_relocations_add(struct purgatory_info *pi,
+ 		 * sym, instead of searching the whole relsec.
+ 		 */
+ 		case R_RISCV_PCREL_HI20:
++		case R_RISCV_CALL_PLT:
+ 		case R_RISCV_CALL:
+ 			*(u64 *)loc = CLEAN_IMM(UITYPE, *(u64 *)loc) |
+ 				 ENCODE_UJTYPE_IMM(val - addr);
+diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
+index 93e7bb9f67fd4..7e62b4dec650f 100644
+--- a/arch/riscv/mm/init.c
++++ b/arch/riscv/mm/init.c
+@@ -26,12 +26,13 @@
+ #include <linux/kfence.h>
+ 
+ #include <asm/fixmap.h>
+-#include <asm/tlbflush.h>
+-#include <asm/sections.h>
+-#include <asm/soc.h>
+ #include <asm/io.h>
+-#include <asm/ptdump.h>
+ #include <asm/numa.h>
++#include <asm/pgtable.h>
++#include <asm/ptdump.h>
++#include <asm/sections.h>
++#include <asm/soc.h>
++#include <asm/tlbflush.h>
+ 
+ #include "../kernel/head.h"
+ 
+@@ -214,8 +215,13 @@ static void __init setup_bootmem(void)
+ 	memblock_reserve(vmlinux_start, vmlinux_end - vmlinux_start);
+ 
+ 	phys_ram_end = memblock_end_of_DRAM();
++
++	/*
++	 * Make sure we align the start of the memory on a PMD boundary so that
++	 * at worst, we map the linear mapping with PMD mappings.
++	 */
+ 	if (!IS_ENABLED(CONFIG_XIP_KERNEL))
+-		phys_ram_base = memblock_start_of_DRAM();
++		phys_ram_base = memblock_start_of_DRAM() & PMD_MASK;
+ 
+ 	/*
+ 	 * In 64-bit, any use of __va/__pa before this point is wrong as we
+diff --git a/arch/riscv/mm/kasan_init.c b/arch/riscv/mm/kasan_init.c
+index 8fc0efcf905c9..a01bc15dce244 100644
+--- a/arch/riscv/mm/kasan_init.c
++++ b/arch/riscv/mm/kasan_init.c
+@@ -22,7 +22,6 @@
+  * region is not and then we have to go down to the PUD level.
+  */
+ 
+-extern pgd_t early_pg_dir[PTRS_PER_PGD];
+ pgd_t tmp_pg_dir[PTRS_PER_PGD] __page_aligned_bss;
+ p4d_t tmp_p4d[PTRS_PER_P4D] __page_aligned_bss;
+ pud_t tmp_pud[PTRS_PER_PUD] __page_aligned_bss;
+diff --git a/arch/x86/boot/compressed/idt_64.c b/arch/x86/boot/compressed/idt_64.c
+index 6debb816e83dc..3cdf94b414567 100644
+--- a/arch/x86/boot/compressed/idt_64.c
++++ b/arch/x86/boot/compressed/idt_64.c
+@@ -63,7 +63,14 @@ void load_stage2_idt(void)
+ 	set_idt_entry(X86_TRAP_PF, boot_page_fault);
+ 
+ #ifdef CONFIG_AMD_MEM_ENCRYPT
+-	set_idt_entry(X86_TRAP_VC, boot_stage2_vc);
++	/*
++	 * Clear the second stage #VC handler in case guest types
++	 * needing #VC have not been detected.
++	 */
++	if (sev_status & BIT(1))
++		set_idt_entry(X86_TRAP_VC, boot_stage2_vc);
++	else
++		set_idt_entry(X86_TRAP_VC, NULL);
+ #endif
+ 
+ 	load_boot_idt(&boot_idt_desc);
+diff --git a/arch/x86/boot/compressed/sev.c b/arch/x86/boot/compressed/sev.c
+index 014b89c890887..91832133c1e8b 100644
+--- a/arch/x86/boot/compressed/sev.c
++++ b/arch/x86/boot/compressed/sev.c
+@@ -352,13 +352,46 @@ void sev_enable(struct boot_params *bp)
+ 	if (bp)
+ 		bp->cc_blob_address = 0;
+ 
++	/*
++	 * Do an initial SEV capability check before snp_init() which
++	 * loads the CPUID page and the same checks afterwards are done
++	 * without the hypervisor and are trustworthy.
++	 *
++	 * If the HV fakes SEV support, the guest will crash'n'burn
++	 * which is good enough.
++	 */
++
++	/* Check for the SME/SEV support leaf */
++	eax = 0x80000000;
++	ecx = 0;
++	native_cpuid(&eax, &ebx, &ecx, &edx);
++	if (eax < 0x8000001f)
++		return;
++
++	/*
++	 * Check for the SME/SEV feature:
++	 *   CPUID Fn8000_001F[EAX]
++	 *   - Bit 0 - Secure Memory Encryption support
++	 *   - Bit 1 - Secure Encrypted Virtualization support
++	 *   CPUID Fn8000_001F[EBX]
++	 *   - Bits 5:0 - Pagetable bit position used to indicate encryption
++	 */
++	eax = 0x8000001f;
++	ecx = 0;
++	native_cpuid(&eax, &ebx, &ecx, &edx);
++	/* Check whether SEV is supported */
++	if (!(eax & BIT(1)))
++		return;
++
+ 	/*
+ 	 * Setup/preliminary detection of SNP. This will be sanity-checked
+ 	 * against CPUID/MSR values later.
+ 	 */
+ 	snp = snp_init(bp);
+ 
+-	/* Check for the SME/SEV support leaf */
++	/* Now repeat the checks with the SNP CPUID table. */
++
++	/* Recheck the SME/SEV support leaf */
+ 	eax = 0x80000000;
+ 	ecx = 0;
+ 	native_cpuid(&eax, &ebx, &ecx, &edx);
+@@ -366,7 +399,7 @@ void sev_enable(struct boot_params *bp)
+ 		return;
+ 
+ 	/*
+-	 * Check for the SME/SEV feature:
++	 * Recheck for the SME/SEV feature:
+ 	 *   CPUID Fn8000_001F[EAX]
+ 	 *   - Bit 0 - Secure Memory Encryption support
+ 	 *   - Bit 1 - Secure Encrypted Virtualization support
+diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c
+index 11a5c68d12185..7645730dc228f 100644
+--- a/arch/x86/entry/vdso/vma.c
++++ b/arch/x86/entry/vdso/vma.c
+@@ -299,8 +299,8 @@ static unsigned long vdso_addr(unsigned long start, unsigned len)
+ 
+ 	/* Round the lowest possible end address up to a PMD boundary. */
+ 	end = (start + len + PMD_SIZE - 1) & PMD_MASK;
+-	if (end >= TASK_SIZE_MAX)
+-		end = TASK_SIZE_MAX;
++	if (end >= DEFAULT_MAP_WINDOW)
++		end = DEFAULT_MAP_WINDOW;
+ 	end -= len;
+ 
+ 	if (end > start) {
+diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h
+index 8eb74cf386dbe..2888c0ee4df04 100644
+--- a/arch/x86/include/asm/acpi.h
++++ b/arch/x86/include/asm/acpi.h
+@@ -15,6 +15,7 @@
+ #include <asm/mpspec.h>
+ #include <asm/x86_init.h>
+ #include <asm/cpufeature.h>
++#include <asm/irq_vectors.h>
+ 
+ #ifdef CONFIG_ACPI_APEI
+ # include <asm/pgtable_types.h>
+@@ -31,6 +32,7 @@ extern int acpi_skip_timer_override;
+ extern int acpi_use_timer_override;
+ extern int acpi_fix_pin2_polarity;
+ extern int acpi_disable_cmcff;
++extern bool acpi_int_src_ovr[NR_IRQS_LEGACY];
+ 
+ extern u8 acpi_sci_flags;
+ extern u32 acpi_sci_override_gsi;
+diff --git a/arch/x86/include/asm/linkage.h b/arch/x86/include/asm/linkage.h
+index 0953aa32a324a..97a3de7892d3f 100644
+--- a/arch/x86/include/asm/linkage.h
++++ b/arch/x86/include/asm/linkage.h
+@@ -21,7 +21,7 @@
+ #define FUNCTION_PADDING
+ #endif
+ 
+-#if (CONFIG_FUNCTION_ALIGNMENT > 8) && !defined(__DISABLE_EXPORTS) && !defined(BULID_VDSO)
++#if (CONFIG_FUNCTION_ALIGNMENT > 8) && !defined(__DISABLE_EXPORTS) && !defined(BUILD_VDSO)
+ # define __FUNC_ALIGN		__ALIGN; FUNCTION_PADDING
+ #else
+ # define __FUNC_ALIGN		__ALIGN
+diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
+index e8db1cff76fda..54100710605f5 100644
+--- a/arch/x86/include/asm/processor.h
++++ b/arch/x86/include/asm/processor.h
+@@ -732,4 +732,6 @@ bool arch_is_platform_page(u64 paddr);
+ #define arch_is_platform_page arch_is_platform_page
+ #endif
+ 
++extern bool gds_ucode_mitigated(void);
++
+ #endif /* _ASM_X86_PROCESSOR_H */
+diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h
+index 794f696257801..9d6411c659205 100644
+--- a/arch/x86/include/asm/segment.h
++++ b/arch/x86/include/asm/segment.h
+@@ -56,7 +56,7 @@
+ 
+ #define GDT_ENTRY_INVALID_SEG	0
+ 
+-#ifdef CONFIG_X86_32
++#if defined(CONFIG_X86_32) && !defined(BUILD_VDSO32_64)
+ /*
+  * The layout of the per-CPU GDT under Linux:
+  *
+diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
+index 21b542a6866cf..53369c57751ec 100644
+--- a/arch/x86/kernel/acpi/boot.c
++++ b/arch/x86/kernel/acpi/boot.c
+@@ -52,6 +52,7 @@ int acpi_lapic;
+ int acpi_ioapic;
+ int acpi_strict;
+ int acpi_disable_cmcff;
++bool acpi_int_src_ovr[NR_IRQS_LEGACY];
+ 
+ /* ACPI SCI override configuration */
+ u8 acpi_sci_flags __initdata;
+@@ -588,6 +589,9 @@ acpi_parse_int_src_ovr(union acpi_subtable_headers * header,
+ 
+ 	acpi_table_print_madt_entry(&header->common);
+ 
++	if (intsrc->source_irq < NR_IRQS_LEGACY)
++		acpi_int_src_ovr[intsrc->source_irq] = true;
++
+ 	if (intsrc->source_irq == acpi_gbl_FADT.sci_interrupt) {
+ 		acpi_sci_ioapic_setup(intsrc->source_irq,
+ 				      intsrc->inti_flags & ACPI_MADT_POLARITY_MASK,
+diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
+index c37a3a5cdabd3..0b5f33cb32b59 100644
+--- a/arch/x86/kernel/cpu/amd.c
++++ b/arch/x86/kernel/cpu/amd.c
+@@ -73,6 +73,7 @@ static const int amd_erratum_1054[] =
+ static const int amd_zenbleed[] =
+ 	AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x17, 0x30, 0x0, 0x4f, 0xf),
+ 			   AMD_MODEL_RANGE(0x17, 0x60, 0x0, 0x7f, 0xf),
++			   AMD_MODEL_RANGE(0x17, 0x90, 0x0, 0x91, 0xf),
+ 			   AMD_MODEL_RANGE(0x17, 0xa0, 0x0, 0xaf, 0xf));
+ 
+ static const int amd_div0[] =
+diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
+index 84f741b06376f..bac2e2949f01d 100644
+--- a/arch/x86/kernel/vmlinux.lds.S
++++ b/arch/x86/kernel/vmlinux.lds.S
+@@ -529,11 +529,17 @@ INIT_PER_CPU(irq_stack_backing_store);
+ 
+ #ifdef CONFIG_CPU_SRSO
+ /*
+- * GNU ld cannot do XOR so do: (A | B) - (A & B) in order to compute the XOR
++ * GNU ld cannot do XOR until 2.41.
++ * https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=f6f78318fca803c4907fb8d7f6ded8295f1947b1
++ *
++ * LLVM lld cannot do XOR until lld-17.
++ * https://github.com/llvm/llvm-project/commit/fae96104d4378166cbe5c875ef8ed808a356f3fb
++ *
++ * Instead do: (A | B) - (A & B) in order to compute the XOR
+  * of the two function addresses:
+  */
+-. = ASSERT(((srso_untrain_ret_alias | srso_safe_ret_alias) -
+-		(srso_untrain_ret_alias & srso_safe_ret_alias)) == ((1 << 2) | (1 << 8) | (1 << 14) | (1 << 20)),
++. = ASSERT(((ABSOLUTE(srso_untrain_ret_alias) | srso_safe_ret_alias) -
++		(ABSOLUTE(srso_untrain_ret_alias) & srso_safe_ret_alias)) == ((1 << 2) | (1 << 8) | (1 << 14) | (1 << 20)),
+ 		"SRSO function pair won't alias");
+ #endif
+ 
+diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
+index 69ae5e1b31207..3148ed6e57789 100644
+--- a/arch/x86/kvm/svm/sev.c
++++ b/arch/x86/kvm/svm/sev.c
+@@ -2414,15 +2414,18 @@ static void sev_es_sync_from_ghcb(struct vcpu_svm *svm)
+ 	 */
+ 	memset(vcpu->arch.regs, 0, sizeof(vcpu->arch.regs));
+ 
+-	vcpu->arch.regs[VCPU_REGS_RAX] = ghcb_get_rax_if_valid(ghcb);
+-	vcpu->arch.regs[VCPU_REGS_RBX] = ghcb_get_rbx_if_valid(ghcb);
+-	vcpu->arch.regs[VCPU_REGS_RCX] = ghcb_get_rcx_if_valid(ghcb);
+-	vcpu->arch.regs[VCPU_REGS_RDX] = ghcb_get_rdx_if_valid(ghcb);
+-	vcpu->arch.regs[VCPU_REGS_RSI] = ghcb_get_rsi_if_valid(ghcb);
++	BUILD_BUG_ON(sizeof(svm->sev_es.valid_bitmap) != sizeof(ghcb->save.valid_bitmap));
++	memcpy(&svm->sev_es.valid_bitmap, &ghcb->save.valid_bitmap, sizeof(ghcb->save.valid_bitmap));
+ 
+-	svm->vmcb->save.cpl = ghcb_get_cpl_if_valid(ghcb);
++	vcpu->arch.regs[VCPU_REGS_RAX] = kvm_ghcb_get_rax_if_valid(svm, ghcb);
++	vcpu->arch.regs[VCPU_REGS_RBX] = kvm_ghcb_get_rbx_if_valid(svm, ghcb);
++	vcpu->arch.regs[VCPU_REGS_RCX] = kvm_ghcb_get_rcx_if_valid(svm, ghcb);
++	vcpu->arch.regs[VCPU_REGS_RDX] = kvm_ghcb_get_rdx_if_valid(svm, ghcb);
++	vcpu->arch.regs[VCPU_REGS_RSI] = kvm_ghcb_get_rsi_if_valid(svm, ghcb);
+ 
+-	if (ghcb_xcr0_is_valid(ghcb)) {
++	svm->vmcb->save.cpl = kvm_ghcb_get_cpl_if_valid(svm, ghcb);
++
++	if (kvm_ghcb_xcr0_is_valid(svm)) {
+ 		vcpu->arch.xcr0 = ghcb_get_xcr0(ghcb);
+ 		kvm_update_cpuid_runtime(vcpu);
+ 	}
+@@ -2433,14 +2436,21 @@ static void sev_es_sync_from_ghcb(struct vcpu_svm *svm)
+ 	control->exit_code_hi = upper_32_bits(exit_code);
+ 	control->exit_info_1 = ghcb_get_sw_exit_info_1(ghcb);
+ 	control->exit_info_2 = ghcb_get_sw_exit_info_2(ghcb);
++	svm->sev_es.sw_scratch = kvm_ghcb_get_sw_scratch_if_valid(svm, ghcb);
+ 
+ 	/* Clear the valid entries fields */
+ 	memset(ghcb->save.valid_bitmap, 0, sizeof(ghcb->save.valid_bitmap));
+ }
+ 
++static u64 kvm_ghcb_get_sw_exit_code(struct vmcb_control_area *control)
++{
++	return (((u64)control->exit_code_hi) << 32) | control->exit_code;
++}
++
+ static int sev_es_validate_vmgexit(struct vcpu_svm *svm)
+ {
+-	struct kvm_vcpu *vcpu;
++	struct vmcb_control_area *control = &svm->vmcb->control;
++	struct kvm_vcpu *vcpu = &svm->vcpu;
+ 	struct ghcb *ghcb;
+ 	u64 exit_code;
+ 	u64 reason;
+@@ -2451,7 +2461,7 @@ static int sev_es_validate_vmgexit(struct vcpu_svm *svm)
+ 	 * Retrieve the exit code now even though it may not be marked valid
+ 	 * as it could help with debugging.
+ 	 */
+-	exit_code = ghcb_get_sw_exit_code(ghcb);
++	exit_code = kvm_ghcb_get_sw_exit_code(control);
+ 
+ 	/* Only GHCB Usage code 0 is supported */
+ 	if (ghcb->ghcb_usage) {
+@@ -2461,56 +2471,56 @@ static int sev_es_validate_vmgexit(struct vcpu_svm *svm)
+ 
+ 	reason = GHCB_ERR_MISSING_INPUT;
+ 
+-	if (!ghcb_sw_exit_code_is_valid(ghcb) ||
+-	    !ghcb_sw_exit_info_1_is_valid(ghcb) ||
+-	    !ghcb_sw_exit_info_2_is_valid(ghcb))
++	if (!kvm_ghcb_sw_exit_code_is_valid(svm) ||
++	    !kvm_ghcb_sw_exit_info_1_is_valid(svm) ||
++	    !kvm_ghcb_sw_exit_info_2_is_valid(svm))
+ 		goto vmgexit_err;
+ 
+-	switch (ghcb_get_sw_exit_code(ghcb)) {
++	switch (exit_code) {
+ 	case SVM_EXIT_READ_DR7:
+ 		break;
+ 	case SVM_EXIT_WRITE_DR7:
+-		if (!ghcb_rax_is_valid(ghcb))
++		if (!kvm_ghcb_rax_is_valid(svm))
+ 			goto vmgexit_err;
+ 		break;
+ 	case SVM_EXIT_RDTSC:
+ 		break;
+ 	case SVM_EXIT_RDPMC:
+-		if (!ghcb_rcx_is_valid(ghcb))
++		if (!kvm_ghcb_rcx_is_valid(svm))
+ 			goto vmgexit_err;
+ 		break;
+ 	case SVM_EXIT_CPUID:
+-		if (!ghcb_rax_is_valid(ghcb) ||
+-		    !ghcb_rcx_is_valid(ghcb))
++		if (!kvm_ghcb_rax_is_valid(svm) ||
++		    !kvm_ghcb_rcx_is_valid(svm))
+ 			goto vmgexit_err;
+-		if (ghcb_get_rax(ghcb) == 0xd)
+-			if (!ghcb_xcr0_is_valid(ghcb))
++		if (vcpu->arch.regs[VCPU_REGS_RAX] == 0xd)
++			if (!kvm_ghcb_xcr0_is_valid(svm))
+ 				goto vmgexit_err;
+ 		break;
+ 	case SVM_EXIT_INVD:
+ 		break;
+ 	case SVM_EXIT_IOIO:
+-		if (ghcb_get_sw_exit_info_1(ghcb) & SVM_IOIO_STR_MASK) {
+-			if (!ghcb_sw_scratch_is_valid(ghcb))
++		if (control->exit_info_1 & SVM_IOIO_STR_MASK) {
++			if (!kvm_ghcb_sw_scratch_is_valid(svm))
+ 				goto vmgexit_err;
+ 		} else {
+-			if (!(ghcb_get_sw_exit_info_1(ghcb) & SVM_IOIO_TYPE_MASK))
+-				if (!ghcb_rax_is_valid(ghcb))
++			if (!(control->exit_info_1 & SVM_IOIO_TYPE_MASK))
++				if (!kvm_ghcb_rax_is_valid(svm))
+ 					goto vmgexit_err;
+ 		}
+ 		break;
+ 	case SVM_EXIT_MSR:
+-		if (!ghcb_rcx_is_valid(ghcb))
++		if (!kvm_ghcb_rcx_is_valid(svm))
+ 			goto vmgexit_err;
+-		if (ghcb_get_sw_exit_info_1(ghcb)) {
+-			if (!ghcb_rax_is_valid(ghcb) ||
+-			    !ghcb_rdx_is_valid(ghcb))
++		if (control->exit_info_1) {
++			if (!kvm_ghcb_rax_is_valid(svm) ||
++			    !kvm_ghcb_rdx_is_valid(svm))
+ 				goto vmgexit_err;
+ 		}
+ 		break;
+ 	case SVM_EXIT_VMMCALL:
+-		if (!ghcb_rax_is_valid(ghcb) ||
+-		    !ghcb_cpl_is_valid(ghcb))
++		if (!kvm_ghcb_rax_is_valid(svm) ||
++		    !kvm_ghcb_cpl_is_valid(svm))
+ 			goto vmgexit_err;
+ 		break;
+ 	case SVM_EXIT_RDTSCP:
+@@ -2518,19 +2528,19 @@ static int sev_es_validate_vmgexit(struct vcpu_svm *svm)
+ 	case SVM_EXIT_WBINVD:
+ 		break;
+ 	case SVM_EXIT_MONITOR:
+-		if (!ghcb_rax_is_valid(ghcb) ||
+-		    !ghcb_rcx_is_valid(ghcb) ||
+-		    !ghcb_rdx_is_valid(ghcb))
++		if (!kvm_ghcb_rax_is_valid(svm) ||
++		    !kvm_ghcb_rcx_is_valid(svm) ||
++		    !kvm_ghcb_rdx_is_valid(svm))
+ 			goto vmgexit_err;
+ 		break;
+ 	case SVM_EXIT_MWAIT:
+-		if (!ghcb_rax_is_valid(ghcb) ||
+-		    !ghcb_rcx_is_valid(ghcb))
++		if (!kvm_ghcb_rax_is_valid(svm) ||
++		    !kvm_ghcb_rcx_is_valid(svm))
+ 			goto vmgexit_err;
+ 		break;
+ 	case SVM_VMGEXIT_MMIO_READ:
+ 	case SVM_VMGEXIT_MMIO_WRITE:
+-		if (!ghcb_sw_scratch_is_valid(ghcb))
++		if (!kvm_ghcb_sw_scratch_is_valid(svm))
+ 			goto vmgexit_err;
+ 		break;
+ 	case SVM_VMGEXIT_NMI_COMPLETE:
+@@ -2546,8 +2556,6 @@ static int sev_es_validate_vmgexit(struct vcpu_svm *svm)
+ 	return 0;
+ 
+ vmgexit_err:
+-	vcpu = &svm->vcpu;
+-
+ 	if (reason == GHCB_ERR_INVALID_USAGE) {
+ 		vcpu_unimpl(vcpu, "vmgexit: ghcb usage %#x is not valid\n",
+ 			    ghcb->ghcb_usage);
+@@ -2560,9 +2568,6 @@ vmgexit_err:
+ 		dump_ghcb(svm);
+ 	}
+ 
+-	/* Clear the valid entries fields */
+-	memset(ghcb->save.valid_bitmap, 0, sizeof(ghcb->save.valid_bitmap));
+-
+ 	ghcb_set_sw_exit_info_1(ghcb, 2);
+ 	ghcb_set_sw_exit_info_2(ghcb, reason);
+ 
+@@ -2583,7 +2588,7 @@ void sev_es_unmap_ghcb(struct vcpu_svm *svm)
+ 		 */
+ 		if (svm->sev_es.ghcb_sa_sync) {
+ 			kvm_write_guest(svm->vcpu.kvm,
+-					ghcb_get_sw_scratch(svm->sev_es.ghcb),
++					svm->sev_es.sw_scratch,
+ 					svm->sev_es.ghcb_sa,
+ 					svm->sev_es.ghcb_sa_len);
+ 			svm->sev_es.ghcb_sa_sync = false;
+@@ -2634,7 +2639,7 @@ static int setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len)
+ 	u64 scratch_gpa_beg, scratch_gpa_end;
+ 	void *scratch_va;
+ 
+-	scratch_gpa_beg = ghcb_get_sw_scratch(ghcb);
++	scratch_gpa_beg = svm->sev_es.sw_scratch;
+ 	if (!scratch_gpa_beg) {
+ 		pr_err("vmgexit: scratch gpa not provided\n");
+ 		goto e_scratch;
+@@ -2848,16 +2853,15 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
+ 
+ 	trace_kvm_vmgexit_enter(vcpu->vcpu_id, ghcb);
+ 
+-	exit_code = ghcb_get_sw_exit_code(ghcb);
+-
++	sev_es_sync_from_ghcb(svm);
+ 	ret = sev_es_validate_vmgexit(svm);
+ 	if (ret)
+ 		return ret;
+ 
+-	sev_es_sync_from_ghcb(svm);
+ 	ghcb_set_sw_exit_info_1(ghcb, 0);
+ 	ghcb_set_sw_exit_info_2(ghcb, 0);
+ 
++	exit_code = kvm_ghcb_get_sw_exit_code(control);
+ 	switch (exit_code) {
+ 	case SVM_VMGEXIT_MMIO_READ:
+ 		ret = setup_vmgexit_scratch(svm, true, control->exit_info_2);
+diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
+index f44751dd8d5d9..ece0d5959567a 100644
+--- a/arch/x86/kvm/svm/svm.h
++++ b/arch/x86/kvm/svm/svm.h
+@@ -190,10 +190,12 @@ struct vcpu_sev_es_state {
+ 	/* SEV-ES support */
+ 	struct sev_es_save_area *vmsa;
+ 	struct ghcb *ghcb;
++	u8 valid_bitmap[16];
+ 	struct kvm_host_map ghcb_map;
+ 	bool received_first_sipi;
+ 
+ 	/* SEV-ES scratch area support */
++	u64 sw_scratch;
+ 	void *ghcb_sa;
+ 	u32 ghcb_sa_len;
+ 	bool ghcb_sa_sync;
+@@ -745,4 +747,28 @@ void sev_es_unmap_ghcb(struct vcpu_svm *svm);
+ void __svm_sev_es_vcpu_run(struct vcpu_svm *svm, bool spec_ctrl_intercepted);
+ void __svm_vcpu_run(struct vcpu_svm *svm, bool spec_ctrl_intercepted);
+ 
++#define DEFINE_KVM_GHCB_ACCESSORS(field)						\
++	static __always_inline bool kvm_ghcb_##field##_is_valid(const struct vcpu_svm *svm) \
++	{									\
++		return test_bit(GHCB_BITMAP_IDX(field),				\
++				(unsigned long *)&svm->sev_es.valid_bitmap);	\
++	}									\
++										\
++	static __always_inline u64 kvm_ghcb_get_##field##_if_valid(struct vcpu_svm *svm, struct ghcb *ghcb) \
++	{									\
++		return kvm_ghcb_##field##_is_valid(svm) ? ghcb->save.field : 0;	\
++	}									\
++
++DEFINE_KVM_GHCB_ACCESSORS(cpl)
++DEFINE_KVM_GHCB_ACCESSORS(rax)
++DEFINE_KVM_GHCB_ACCESSORS(rcx)
++DEFINE_KVM_GHCB_ACCESSORS(rdx)
++DEFINE_KVM_GHCB_ACCESSORS(rbx)
++DEFINE_KVM_GHCB_ACCESSORS(rsi)
++DEFINE_KVM_GHCB_ACCESSORS(sw_exit_code)
++DEFINE_KVM_GHCB_ACCESSORS(sw_exit_info_1)
++DEFINE_KVM_GHCB_ACCESSORS(sw_exit_info_2)
++DEFINE_KVM_GHCB_ACCESSORS(sw_scratch)
++DEFINE_KVM_GHCB_ACCESSORS(xcr0)
++
+ #endif
+diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
+index a96f0f775ae27..7c9f3b1b42bad 100644
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -314,8 +314,6 @@ u64 __read_mostly host_xcr0;
+ 
+ static struct kmem_cache *x86_emulator_cache;
+ 
+-extern bool gds_ucode_mitigated(void);
+-
+ /*
+  * When called, it means the previous get/set msr reached an invalid msr.
+  * Return true if we want to ignore/silent this failed msr access.
+diff --git a/drivers/accel/ivpu/ivpu_gem.c b/drivers/accel/ivpu/ivpu_gem.c
+index 52b339aefadca..9967fcfa27eca 100644
+--- a/drivers/accel/ivpu/ivpu_gem.c
++++ b/drivers/accel/ivpu/ivpu_gem.c
+@@ -173,6 +173,9 @@ static void internal_free_pages_locked(struct ivpu_bo *bo)
+ {
+ 	unsigned int i, npages = bo->base.size >> PAGE_SHIFT;
+ 
++	if (ivpu_bo_cache_mode(bo) != DRM_IVPU_BO_CACHED)
++		set_pages_array_wb(bo->pages, bo->base.size >> PAGE_SHIFT);
++
+ 	for (i = 0; i < npages; i++)
+ 		put_page(bo->pages[i]);
+ 
+@@ -587,6 +590,11 @@ ivpu_bo_alloc_internal(struct ivpu_device *vdev, u64 vpu_addr, u64 size, u32 fla
+ 	if (ivpu_bo_cache_mode(bo) != DRM_IVPU_BO_CACHED)
+ 		drm_clflush_pages(bo->pages, bo->base.size >> PAGE_SHIFT);
+ 
++	if (bo->flags & DRM_IVPU_BO_WC)
++		set_pages_array_wc(bo->pages, bo->base.size >> PAGE_SHIFT);
++	else if (bo->flags & DRM_IVPU_BO_UNCACHED)
++		set_pages_array_uc(bo->pages, bo->base.size >> PAGE_SHIFT);
++
+ 	prot = ivpu_bo_pgprot(bo, PAGE_KERNEL);
+ 	bo->kvaddr = vmap(bo->pages, bo->base.size >> PAGE_SHIFT, VM_MAP, prot);
+ 	if (!bo->kvaddr) {
+diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
+index 1dd8d5aebf678..a4d9f149b48d7 100644
+--- a/drivers/acpi/resource.c
++++ b/drivers/acpi/resource.c
+@@ -470,6 +470,45 @@ static const struct dmi_system_id asus_laptop[] = {
+ 	{ }
+ };
+ 
++static const struct dmi_system_id tongfang_gm_rg[] = {
++	{
++		.ident = "TongFang GMxRGxx/XMG CORE 15 (M22)/TUXEDO Stellaris 15 Gen4 AMD",
++		.matches = {
++			DMI_MATCH(DMI_BOARD_NAME, "GMxRGxx"),
++		},
++	},
++	{ }
++};
++
++static const struct dmi_system_id maingear_laptop[] = {
++	{
++		.ident = "MAINGEAR Vector Pro 2 15",
++		.matches = {
++			DMI_MATCH(DMI_SYS_VENDOR, "Micro Electronics Inc"),
++			DMI_MATCH(DMI_PRODUCT_NAME, "MG-VCP2-15A3070T"),
++		}
++	},
++	{
++		.ident = "MAINGEAR Vector Pro 2 17",
++		.matches = {
++			DMI_MATCH(DMI_SYS_VENDOR, "Micro Electronics Inc"),
++			DMI_MATCH(DMI_PRODUCT_NAME, "MG-VCP2-17A3070T"),
++		},
++	},
++	{ }
++};
++
++static const struct dmi_system_id pcspecialist_laptop[] = {
++	{
++		.ident = "PCSpecialist Elimina Pro 16 M",
++		.matches = {
++			DMI_MATCH(DMI_SYS_VENDOR, "PCSpecialist"),
++			DMI_MATCH(DMI_PRODUCT_NAME, "Elimina Pro 16 M"),
++		},
++	},
++	{ }
++};
++
+ static const struct dmi_system_id lg_laptop[] = {
+ 	{
+ 		.ident = "LG Electronics 17U70P",
+@@ -493,6 +532,9 @@ struct irq_override_cmp {
+ static const struct irq_override_cmp override_table[] = {
+ 	{ medion_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false },
+ 	{ asus_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false },
++	{ tongfang_gm_rg, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true },
++	{ maingear_laptop, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true },
++	{ pcspecialist_laptop, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true },
+ 	{ lg_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false },
+ };
+ 
+@@ -512,6 +554,28 @@ static bool acpi_dev_irq_override(u32 gsi, u8 triggering, u8 polarity,
+ 			return entry->override;
+ 	}
+ 
++#ifdef CONFIG_X86
++	/*
++	 * Always use the MADT override info, except for the i8042 PS/2 ctrl
++	 * IRQs (1 and 12). For these the DSDT IRQ settings should sometimes
++	 * be used otherwise PS/2 keyboards / mice will not work.
++	 */
++	if (gsi != 1 && gsi != 12)
++		return true;
++
++	/* If the override comes from an INT_SRC_OVR MADT entry, honor it. */
++	if (acpi_int_src_ovr[gsi])
++		return true;
++
++	/*
++	 * IRQ override isn't needed on modern AMD Zen systems and
++	 * this override breaks active low IRQs on AMD Ryzen 6000 and
++	 * newer systems. Skip it.
++	 */
++	if (boot_cpu_has(X86_FEATURE_ZEN))
++		return false;
++#endif
++
+ 	return true;
+ }
+ 
+diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
+index 0c6f06abe3f47..c28c8d5ca0c8d 100644
+--- a/drivers/acpi/scan.c
++++ b/drivers/acpi/scan.c
+@@ -1712,6 +1712,7 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device)
+ 		{"BSG1160", },
+ 		{"BSG2150", },
+ 		{"CSC3551", },
++		{"CSC3556", },
+ 		{"INT33FE", },
+ 		{"INT3515", },
+ 		/* Non-conforming _HID for Cirrus Logic already released */
+diff --git a/drivers/android/binder.c b/drivers/android/binder.c
+index 8fb7672021ee2..16ec3cb143c36 100644
+--- a/drivers/android/binder.c
++++ b/drivers/android/binder.c
+@@ -6610,6 +6610,7 @@ err_init_binder_device_failed:
+ 
+ err_alloc_device_names_failed:
+ 	debugfs_remove_recursive(binder_debugfs_dir_entry_root);
++	binder_alloc_shrinker_exit();
+ 
+ 	return ret;
+ }
+diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c
+index 662a2a2e2e84a..e3db8297095a2 100644
+--- a/drivers/android/binder_alloc.c
++++ b/drivers/android/binder_alloc.c
+@@ -1087,6 +1087,12 @@ int binder_alloc_shrinker_init(void)
+ 	return ret;
+ }
+ 
++void binder_alloc_shrinker_exit(void)
++{
++	unregister_shrinker(&binder_shrinker);
++	list_lru_destroy(&binder_alloc_lru);
++}
++
+ /**
+  * check_buffer() - verify that buffer/offset is safe to access
+  * @alloc: binder_alloc for this proc
+diff --git a/drivers/android/binder_alloc.h b/drivers/android/binder_alloc.h
+index 138d1d5af9ce3..dc1e2b01dd64d 100644
+--- a/drivers/android/binder_alloc.h
++++ b/drivers/android/binder_alloc.h
+@@ -129,6 +129,7 @@ extern struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc,
+ 						  int pid);
+ extern void binder_alloc_init(struct binder_alloc *alloc);
+ extern int binder_alloc_shrinker_init(void);
++extern void binder_alloc_shrinker_exit(void);
+ extern void binder_alloc_vma_close(struct binder_alloc *alloc);
+ extern struct binder_buffer *
+ binder_alloc_prepare_to_free(struct binder_alloc *alloc,
+diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
+index f6d90f1ba5cf7..7d00911f6c5a0 100644
+--- a/drivers/block/zram/zram_drv.c
++++ b/drivers/block/zram/zram_drv.c
+@@ -1870,15 +1870,16 @@ static void zram_bio_discard(struct zram *zram, struct bio *bio)
+ 
+ static void zram_bio_read(struct zram *zram, struct bio *bio)
+ {
+-	struct bvec_iter iter;
+-	struct bio_vec bv;
+-	unsigned long start_time;
++	unsigned long start_time = bio_start_io_acct(bio);
++	struct bvec_iter iter = bio->bi_iter;
+ 
+-	start_time = bio_start_io_acct(bio);
+-	bio_for_each_segment(bv, bio, iter) {
++	do {
+ 		u32 index = iter.bi_sector >> SECTORS_PER_PAGE_SHIFT;
+ 		u32 offset = (iter.bi_sector & (SECTORS_PER_PAGE - 1)) <<
+ 				SECTOR_SHIFT;
++		struct bio_vec bv = bio_iter_iovec(bio, iter);
++
++		bv.bv_len = min_t(u32, bv.bv_len, PAGE_SIZE - offset);
+ 
+ 		if (zram_bvec_read(zram, &bv, index, offset, bio) < 0) {
+ 			atomic64_inc(&zram->stats.failed_reads);
+@@ -1890,22 +1891,26 @@ static void zram_bio_read(struct zram *zram, struct bio *bio)
+ 		zram_slot_lock(zram, index);
+ 		zram_accessed(zram, index);
+ 		zram_slot_unlock(zram, index);
+-	}
++
++		bio_advance_iter_single(bio, &iter, bv.bv_len);
++	} while (iter.bi_size);
++
+ 	bio_end_io_acct(bio, start_time);
+ 	bio_endio(bio);
+ }
+ 
+ static void zram_bio_write(struct zram *zram, struct bio *bio)
+ {
+-	struct bvec_iter iter;
+-	struct bio_vec bv;
+-	unsigned long start_time;
++	unsigned long start_time = bio_start_io_acct(bio);
++	struct bvec_iter iter = bio->bi_iter;
+ 
+-	start_time = bio_start_io_acct(bio);
+-	bio_for_each_segment(bv, bio, iter) {
++	do {
+ 		u32 index = iter.bi_sector >> SECTORS_PER_PAGE_SHIFT;
+ 		u32 offset = (iter.bi_sector & (SECTORS_PER_PAGE - 1)) <<
+ 				SECTOR_SHIFT;
++		struct bio_vec bv = bio_iter_iovec(bio, iter);
++
++		bv.bv_len = min_t(u32, bv.bv_len, PAGE_SIZE - offset);
+ 
+ 		if (zram_bvec_write(zram, &bv, index, offset, bio) < 0) {
+ 			atomic64_inc(&zram->stats.failed_writes);
+@@ -1916,7 +1921,10 @@ static void zram_bio_write(struct zram *zram, struct bio *bio)
+ 		zram_slot_lock(zram, index);
+ 		zram_accessed(zram, index);
+ 		zram_slot_unlock(zram, index);
+-	}
++
++		bio_advance_iter_single(bio, &iter, bv.bv_len);
++	} while (iter.bi_size);
++
+ 	bio_end_io_acct(bio, start_time);
+ 	bio_endio(bio);
+ }
+diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
+index cf5499e51999b..ea6b4013bc38f 100644
+--- a/drivers/char/tpm/tpm-chip.c
++++ b/drivers/char/tpm/tpm-chip.c
+@@ -510,70 +510,6 @@ static int tpm_add_legacy_sysfs(struct tpm_chip *chip)
+ 	return 0;
+ }
+ 
+-/*
+- * Some AMD fTPM versions may cause stutter
+- * https://www.amd.com/en/support/kb/faq/pa-410
+- *
+- * Fixes are available in two series of fTPM firmware:
+- * 6.x.y.z series: 6.0.18.6 +
+- * 3.x.y.z series: 3.57.y.5 +
+- */
+-#ifdef CONFIG_X86
+-static bool tpm_amd_is_rng_defective(struct tpm_chip *chip)
+-{
+-	u32 val1, val2;
+-	u64 version;
+-	int ret;
+-
+-	if (!(chip->flags & TPM_CHIP_FLAG_TPM2))
+-		return false;
+-
+-	ret = tpm_request_locality(chip);
+-	if (ret)
+-		return false;
+-
+-	ret = tpm2_get_tpm_pt(chip, TPM2_PT_MANUFACTURER, &val1, NULL);
+-	if (ret)
+-		goto release;
+-	if (val1 != 0x414D4400U /* AMD */) {
+-		ret = -ENODEV;
+-		goto release;
+-	}
+-	ret = tpm2_get_tpm_pt(chip, TPM2_PT_FIRMWARE_VERSION_1, &val1, NULL);
+-	if (ret)
+-		goto release;
+-	ret = tpm2_get_tpm_pt(chip, TPM2_PT_FIRMWARE_VERSION_2, &val2, NULL);
+-
+-release:
+-	tpm_relinquish_locality(chip);
+-
+-	if (ret)
+-		return false;
+-
+-	version = ((u64)val1 << 32) | val2;
+-	if ((version >> 48) == 6) {
+-		if (version >= 0x0006000000180006ULL)
+-			return false;
+-	} else if ((version >> 48) == 3) {
+-		if (version >= 0x0003005700000005ULL)
+-			return false;
+-	} else {
+-		return false;
+-	}
+-
+-	dev_warn(&chip->dev,
+-		 "AMD fTPM version 0x%llx causes system stutter; hwrng disabled\n",
+-		 version);
+-
+-	return true;
+-}
+-#else
+-static inline bool tpm_amd_is_rng_defective(struct tpm_chip *chip)
+-{
+-	return false;
+-}
+-#endif /* CONFIG_X86 */
+-
+ static int tpm_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait)
+ {
+ 	struct tpm_chip *chip = container_of(rng, struct tpm_chip, hwrng);
+@@ -585,10 +521,20 @@ static int tpm_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait)
+ 	return tpm_get_random(chip, data, max);
+ }
+ 
++static bool tpm_is_hwrng_enabled(struct tpm_chip *chip)
++{
++	if (!IS_ENABLED(CONFIG_HW_RANDOM_TPM))
++		return false;
++	if (tpm_is_firmware_upgrade(chip))
++		return false;
++	if (chip->flags & TPM_CHIP_FLAG_HWRNG_DISABLED)
++		return false;
++	return true;
++}
++
+ static int tpm_add_hwrng(struct tpm_chip *chip)
+ {
+-	if (!IS_ENABLED(CONFIG_HW_RANDOM_TPM) || tpm_is_firmware_upgrade(chip) ||
+-	    tpm_amd_is_rng_defective(chip))
++	if (!tpm_is_hwrng_enabled(chip))
+ 		return 0;
+ 
+ 	snprintf(chip->hwrng_name, sizeof(chip->hwrng_name),
+@@ -693,7 +639,7 @@ int tpm_chip_register(struct tpm_chip *chip)
+ 	return 0;
+ 
+ out_hwrng:
+-	if (IS_ENABLED(CONFIG_HW_RANDOM_TPM) && !tpm_is_firmware_upgrade(chip))
++	if (tpm_is_hwrng_enabled(chip))
+ 		hwrng_unregister(&chip->hwrng);
+ out_ppi:
+ 	tpm_bios_log_teardown(chip);
+@@ -718,8 +664,7 @@ EXPORT_SYMBOL_GPL(tpm_chip_register);
+ void tpm_chip_unregister(struct tpm_chip *chip)
+ {
+ 	tpm_del_legacy_sysfs(chip);
+-	if (IS_ENABLED(CONFIG_HW_RANDOM_TPM) && !tpm_is_firmware_upgrade(chip) &&
+-	    !tpm_amd_is_rng_defective(chip))
++	if (tpm_is_hwrng_enabled(chip))
+ 		hwrng_unregister(&chip->hwrng);
+ 	tpm_bios_log_teardown(chip);
+ 	if (chip->flags & TPM_CHIP_FLAG_TPM2 && !tpm_is_firmware_upgrade(chip))
+diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c
+index 1a5d09b185134..9eb1a18590123 100644
+--- a/drivers/char/tpm/tpm_crb.c
++++ b/drivers/char/tpm/tpm_crb.c
+@@ -463,6 +463,28 @@ static bool crb_req_canceled(struct tpm_chip *chip, u8 status)
+ 	return (cancel & CRB_CANCEL_INVOKE) == CRB_CANCEL_INVOKE;
+ }
+ 
++static int crb_check_flags(struct tpm_chip *chip)
++{
++	u32 val;
++	int ret;
++
++	ret = crb_request_locality(chip, 0);
++	if (ret)
++		return ret;
++
++	ret = tpm2_get_tpm_pt(chip, TPM2_PT_MANUFACTURER, &val, NULL);
++	if (ret)
++		goto release;
++
++	if (val == 0x414D4400U /* AMD */)
++		chip->flags |= TPM_CHIP_FLAG_HWRNG_DISABLED;
++
++release:
++	crb_relinquish_locality(chip, 0);
++
++	return ret;
++}
++
+ static const struct tpm_class_ops tpm_crb = {
+ 	.flags = TPM_OPS_AUTO_STARTUP,
+ 	.status = crb_status,
+@@ -800,6 +822,14 @@ static int crb_acpi_add(struct acpi_device *device)
+ 	chip->acpi_dev_handle = device->handle;
+ 	chip->flags = TPM_CHIP_FLAG_TPM2;
+ 
++	rc = tpm_chip_bootstrap(chip);
++	if (rc)
++		goto out;
++
++	rc = crb_check_flags(chip);
++	if (rc)
++		goto out;
++
+ 	rc = tpm_chip_register(chip);
+ 
+ out:
+diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
+index cc42cf3de960f..7fa3d91042b26 100644
+--- a/drivers/char/tpm/tpm_tis.c
++++ b/drivers/char/tpm/tpm_tis.c
+@@ -89,7 +89,7 @@ static inline void tpm_tis_iowrite32(u32 b, void __iomem *iobase, u32 addr)
+ 	tpm_tis_flush(iobase);
+ }
+ 
+-static int interrupts = -1;
++static int interrupts;
+ module_param(interrupts, int, 0444);
+ MODULE_PARM_DESC(interrupts, "Enable interrupts");
+ 
+@@ -162,12 +162,28 @@ static const struct dmi_system_id tpm_tis_dmi_table[] = {
+ 			DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L590"),
+ 		},
+ 	},
++	{
++		.callback = tpm_tis_disable_irq,
++		.ident = "ThinkStation P620",
++		.matches = {
++			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
++			DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkStation P620"),
++		},
++	},
++	{
++		.callback = tpm_tis_disable_irq,
++		.ident = "TUXEDO InfinityBook S 15/17 Gen7",
++		.matches = {
++			DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
++			DMI_MATCH(DMI_PRODUCT_NAME, "TUXEDO InfinityBook S 15/17 Gen7"),
++		},
++	},
+ 	{
+ 		.callback = tpm_tis_disable_irq,
+ 		.ident = "UPX-TGL",
+ 		.matches = {
+ 			DMI_MATCH(DMI_SYS_VENDOR, "AAEON"),
+-			DMI_MATCH(DMI_PRODUCT_VERSION, "UPX-TGL"),
++			DMI_MATCH(DMI_PRODUCT_NAME, "UPX-TGL01"),
+ 		},
+ 	},
+ 	{}
+diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
+index a5764946434c6..71a766bb6d5ed 100644
+--- a/drivers/cpufreq/amd-pstate.c
++++ b/drivers/cpufreq/amd-pstate.c
+@@ -986,8 +986,8 @@ static int amd_pstate_update_status(const char *buf, size_t size)
+ 	return 0;
+ }
+ 
+-static ssize_t show_status(struct kobject *kobj,
+-			   struct kobj_attribute *attr, char *buf)
++static ssize_t status_show(struct device *dev,
++			   struct device_attribute *attr, char *buf)
+ {
+ 	ssize_t ret;
+ 
+@@ -998,7 +998,7 @@ static ssize_t show_status(struct kobject *kobj,
+ 	return ret;
+ }
+ 
+-static ssize_t store_status(struct kobject *a, struct kobj_attribute *b,
++static ssize_t status_store(struct device *a, struct device_attribute *b,
+ 			    const char *buf, size_t count)
+ {
+ 	char *p = memchr(buf, '\n', count);
+@@ -1017,7 +1017,7 @@ cpufreq_freq_attr_ro(amd_pstate_lowest_nonlinear_freq);
+ cpufreq_freq_attr_ro(amd_pstate_highest_perf);
+ cpufreq_freq_attr_rw(energy_performance_preference);
+ cpufreq_freq_attr_ro(energy_performance_available_preferences);
+-define_one_global_rw(status);
++static DEVICE_ATTR_RW(status);
+ 
+ static struct freq_attr *amd_pstate_attr[] = {
+ 	&amd_pstate_max_freq,
+@@ -1036,7 +1036,7 @@ static struct freq_attr *amd_pstate_epp_attr[] = {
+ };
+ 
+ static struct attribute *pstate_global_attributes[] = {
+-	&status.attr,
++	&dev_attr_status.attr,
+ 	NULL
+ };
+ 
+diff --git a/drivers/cpuidle/cpuidle-psci-domain.c b/drivers/cpuidle/cpuidle-psci-domain.c
+index c2d6d9c3c930d..b88af1262f1ab 100644
+--- a/drivers/cpuidle/cpuidle-psci-domain.c
++++ b/drivers/cpuidle/cpuidle-psci-domain.c
+@@ -120,20 +120,6 @@ static void psci_pd_remove(void)
+ 	}
+ }
+ 
+-static bool psci_pd_try_set_osi_mode(void)
+-{
+-	int ret;
+-
+-	if (!psci_has_osi_support())
+-		return false;
+-
+-	ret = psci_set_osi_mode(true);
+-	if (ret)
+-		return false;
+-
+-	return true;
+-}
+-
+ static void psci_cpuidle_domain_sync_state(struct device *dev)
+ {
+ 	/*
+@@ -152,15 +138,12 @@ static int psci_cpuidle_domain_probe(struct platform_device *pdev)
+ {
+ 	struct device_node *np = pdev->dev.of_node;
+ 	struct device_node *node;
+-	bool use_osi;
++	bool use_osi = psci_has_osi_support();
+ 	int ret = 0, pd_count = 0;
+ 
+ 	if (!np)
+ 		return -ENODEV;
+ 
+-	/* If OSI mode is supported, let's try to enable it. */
+-	use_osi = psci_pd_try_set_osi_mode();
+-
+ 	/*
+ 	 * Parse child nodes for the "#power-domain-cells" property and
+ 	 * initialize a genpd/genpd-of-provider pair when it's found.
+@@ -170,33 +153,37 @@ static int psci_cpuidle_domain_probe(struct platform_device *pdev)
+ 			continue;
+ 
+ 		ret = psci_pd_init(node, use_osi);
+-		if (ret)
+-			goto put_node;
++		if (ret) {
++			of_node_put(node);
++			goto exit;
++		}
+ 
+ 		pd_count++;
+ 	}
+ 
+ 	/* Bail out if not using the hierarchical CPU topology. */
+ 	if (!pd_count)
+-		goto no_pd;
++		return 0;
+ 
+ 	/* Link genpd masters/subdomains to model the CPU topology. */
+ 	ret = dt_idle_pd_init_topology(np);
+ 	if (ret)
+ 		goto remove_pd;
+ 
++	/* let's try to enable OSI. */
++	ret = psci_set_osi_mode(use_osi);
++	if (ret)
++		goto remove_pd;
++
+ 	pr_info("Initialized CPU PM domain topology using %s mode\n",
+ 		use_osi ? "OSI" : "PC");
+ 	return 0;
+ 
+-put_node:
+-	of_node_put(node);
+ remove_pd:
++	dt_idle_pd_remove_topology(np);
+ 	psci_pd_remove();
++exit:
+ 	pr_err("failed to create CPU PM domains ret=%d\n", ret);
+-no_pd:
+-	if (use_osi)
+-		psci_set_osi_mode(false);
+ 	return ret;
+ }
+ 
+diff --git a/drivers/cpuidle/dt_idle_genpd.c b/drivers/cpuidle/dt_idle_genpd.c
+index b37165514d4e7..1af63c189039e 100644
+--- a/drivers/cpuidle/dt_idle_genpd.c
++++ b/drivers/cpuidle/dt_idle_genpd.c
+@@ -152,6 +152,30 @@ int dt_idle_pd_init_topology(struct device_node *np)
+ 	return 0;
+ }
+ 
++int dt_idle_pd_remove_topology(struct device_node *np)
++{
++	struct device_node *node;
++	struct of_phandle_args child, parent;
++	int ret;
++
++	for_each_child_of_node(np, node) {
++		if (of_parse_phandle_with_args(node, "power-domains",
++					"#power-domain-cells", 0, &parent))
++			continue;
++
++		child.np = node;
++		child.args_count = 0;
++		ret = of_genpd_remove_subdomain(&parent, &child);
++		of_node_put(parent.np);
++		if (ret) {
++			of_node_put(node);
++			return ret;
++		}
++	}
++
++	return 0;
++}
++
+ struct device *dt_idle_attach_cpu(int cpu, const char *name)
+ {
+ 	struct device *dev;
+diff --git a/drivers/cpuidle/dt_idle_genpd.h b/drivers/cpuidle/dt_idle_genpd.h
+index a95483d08a02a..3be1f70f55b5c 100644
+--- a/drivers/cpuidle/dt_idle_genpd.h
++++ b/drivers/cpuidle/dt_idle_genpd.h
+@@ -14,6 +14,8 @@ struct generic_pm_domain *dt_idle_pd_alloc(struct device_node *np,
+ 
+ int dt_idle_pd_init_topology(struct device_node *np);
+ 
++int dt_idle_pd_remove_topology(struct device_node *np);
++
+ struct device *dt_idle_attach_cpu(int cpu, const char *name);
+ 
+ void dt_idle_detach_cpu(struct device *dev);
+@@ -36,6 +38,11 @@ static inline int dt_idle_pd_init_topology(struct device_node *np)
+ 	return 0;
+ }
+ 
++static inline int dt_idle_pd_remove_topology(struct device_node *np)
++{
++	return 0;
++}
++
+ static inline struct device *dt_idle_attach_cpu(int cpu, const char *name)
+ {
+ 	return NULL;
+diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c
+index 5abbcc61c5288..9a15f0d12c799 100644
+--- a/drivers/dma/idxd/device.c
++++ b/drivers/dma/idxd/device.c
+@@ -384,9 +384,7 @@ static void idxd_wq_disable_cleanup(struct idxd_wq *wq)
+ 	wq->threshold = 0;
+ 	wq->priority = 0;
+ 	wq->enqcmds_retries = IDXD_ENQCMDS_RETRIES;
+-	clear_bit(WQ_FLAG_DEDICATED, &wq->flags);
+-	clear_bit(WQ_FLAG_BLOCK_ON_FAULT, &wq->flags);
+-	clear_bit(WQ_FLAG_ATS_DISABLE, &wq->flags);
++	wq->flags = 0;
+ 	memset(wq->name, 0, WQ_NAME_SIZE);
+ 	wq->max_xfer_bytes = WQ_DEFAULT_MAX_XFER;
+ 	idxd_wq_set_max_batch_size(idxd->data->type, wq, WQ_DEFAULT_MAX_BATCH);
+diff --git a/drivers/dma/mcf-edma.c b/drivers/dma/mcf-edma.c
+index ebd8733f72ad4..9413fad08a60c 100644
+--- a/drivers/dma/mcf-edma.c
++++ b/drivers/dma/mcf-edma.c
+@@ -190,7 +190,13 @@ static int mcf_edma_probe(struct platform_device *pdev)
+ 		return -EINVAL;
+ 	}
+ 
+-	chans = pdata->dma_channels;
++	if (!pdata->dma_channels) {
++		dev_info(&pdev->dev, "setting default channel number to 64");
++		chans = 64;
++	} else {
++		chans = pdata->dma_channels;
++	}
++
+ 	len = sizeof(*mcf_edma) + sizeof(*mcf_chan) * chans;
+ 	mcf_edma = devm_kzalloc(&pdev->dev, len, GFP_KERNEL);
+ 	if (!mcf_edma)
+@@ -202,11 +208,6 @@ static int mcf_edma_probe(struct platform_device *pdev)
+ 	mcf_edma->drvdata = &mcf_data;
+ 	mcf_edma->big_endian = 1;
+ 
+-	if (!mcf_edma->n_chans) {
+-		dev_info(&pdev->dev, "setting default channel number to 64");
+-		mcf_edma->n_chans = 64;
+-	}
+-
+ 	mutex_init(&mcf_edma->fsl_edma_mutex);
+ 
+ 	mcf_edma->membase = devm_platform_ioremap_resource(pdev, 0);
+diff --git a/drivers/dma/owl-dma.c b/drivers/dma/owl-dma.c
+index 95a462a1f5111..b6e0ac8314e5c 100644
+--- a/drivers/dma/owl-dma.c
++++ b/drivers/dma/owl-dma.c
+@@ -192,7 +192,7 @@ struct owl_dma_pchan {
+ };
+ 
+ /**
+- * struct owl_dma_pchan - Wrapper for DMA ENGINE channel
++ * struct owl_dma_vchan - Wrapper for DMA ENGINE channel
+  * @vc: wrapped virtual channel
+  * @pchan: the physical channel utilized by this channel
+  * @txd: active transaction on this channel
+diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
+index b4731fe6bbc14..3cf0b38387ae5 100644
+--- a/drivers/dma/pl330.c
++++ b/drivers/dma/pl330.c
+@@ -403,6 +403,12 @@ enum desc_status {
+ 	 * of a channel can be BUSY at any time.
+ 	 */
+ 	BUSY,
++	/*
++	 * Pause was called while descriptor was BUSY. Due to hardware
++	 * limitations, only termination is possible for descriptors
++	 * that have been paused.
++	 */
++	PAUSED,
+ 	/*
+ 	 * Sitting on the channel work_list but xfer done
+ 	 * by PL330 core
+@@ -2041,7 +2047,7 @@ static inline void fill_queue(struct dma_pl330_chan *pch)
+ 	list_for_each_entry(desc, &pch->work_list, node) {
+ 
+ 		/* If already submitted */
+-		if (desc->status == BUSY)
++		if (desc->status == BUSY || desc->status == PAUSED)
+ 			continue;
+ 
+ 		ret = pl330_submit_req(pch->thread, desc);
+@@ -2326,6 +2332,7 @@ static int pl330_pause(struct dma_chan *chan)
+ {
+ 	struct dma_pl330_chan *pch = to_pchan(chan);
+ 	struct pl330_dmac *pl330 = pch->dmac;
++	struct dma_pl330_desc *desc;
+ 	unsigned long flags;
+ 
+ 	pm_runtime_get_sync(pl330->ddma.dev);
+@@ -2335,6 +2342,10 @@ static int pl330_pause(struct dma_chan *chan)
+ 	_stop(pch->thread);
+ 	spin_unlock(&pl330->lock);
+ 
++	list_for_each_entry(desc, &pch->work_list, node) {
++		if (desc->status == BUSY)
++			desc->status = PAUSED;
++	}
+ 	spin_unlock_irqrestore(&pch->lock, flags);
+ 	pm_runtime_mark_last_busy(pl330->ddma.dev);
+ 	pm_runtime_put_autosuspend(pl330->ddma.dev);
+@@ -2425,7 +2436,7 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
+ 		else if (running && desc == running)
+ 			transferred =
+ 				pl330_get_current_xferred_count(pch, desc);
+-		else if (desc->status == BUSY)
++		else if (desc->status == BUSY || desc->status == PAUSED)
+ 			/*
+ 			 * Busy but not running means either just enqueued,
+ 			 * or finished and not yet marked done
+@@ -2442,6 +2453,9 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
+ 			case DONE:
+ 				ret = DMA_COMPLETE;
+ 				break;
++			case PAUSED:
++				ret = DMA_PAUSED;
++				break;
+ 			case PREP:
+ 			case BUSY:
+ 				ret = DMA_IN_PROGRESS;
+diff --git a/drivers/dma/xilinx/xdma.c b/drivers/dma/xilinx/xdma.c
+index 93ee298d52b89..e0bfd129d563f 100644
+--- a/drivers/dma/xilinx/xdma.c
++++ b/drivers/dma/xilinx/xdma.c
+@@ -668,6 +668,8 @@ static int xdma_set_vector_reg(struct xdma_device *xdev, u32 vec_tbl_start,
+ 			val |= irq_start << shift;
+ 			irq_start++;
+ 			irq_num--;
++			if (!irq_num)
++				break;
+ 		}
+ 
+ 		/* write IRQ register */
+@@ -715,7 +717,7 @@ static int xdma_irq_init(struct xdma_device *xdev)
+ 		ret = request_irq(irq, xdma_channel_isr, 0,
+ 				  "xdma-c2h-channel", &xdev->c2h_chans[j]);
+ 		if (ret) {
+-			xdma_err(xdev, "H2C channel%d request irq%d failed: %d",
++			xdma_err(xdev, "C2H channel%d request irq%d failed: %d",
+ 				 j, irq, ret);
+ 			goto failed_init_c2h;
+ 		}
+@@ -892,7 +894,7 @@ static int xdma_probe(struct platform_device *pdev)
+ 	}
+ 
+ 	reg_base = devm_ioremap_resource(&pdev->dev, res);
+-	if (!reg_base) {
++	if (IS_ERR(reg_base)) {
+ 		xdma_err(xdev, "ioremap failed");
+ 		goto failed;
+ 	}
+diff --git a/drivers/gpio/gpio-sim.c b/drivers/gpio/gpio-sim.c
+index 8b49b0abacd51..f1f6f1c329877 100644
+--- a/drivers/gpio/gpio-sim.c
++++ b/drivers/gpio/gpio-sim.c
+@@ -429,6 +429,7 @@ static int gpio_sim_add_bank(struct fwnode_handle *swnode, struct device *dev)
+ 	gc->set_config = gpio_sim_set_config;
+ 	gc->to_irq = gpio_sim_to_irq;
+ 	gc->free = gpio_sim_free;
++	gc->can_sleep = true;
+ 
+ 	ret = devm_gpiochip_add_data(dev, gc, chip);
+ 	if (ret)
+diff --git a/drivers/gpio/gpio-ws16c48.c b/drivers/gpio/gpio-ws16c48.c
+index e73885a4dc328..afb42a8e916fe 100644
+--- a/drivers/gpio/gpio-ws16c48.c
++++ b/drivers/gpio/gpio-ws16c48.c
+@@ -18,7 +18,7 @@
+ #include <linux/spinlock.h>
+ #include <linux/types.h>
+ 
+-#define WS16C48_EXTENT 10
++#define WS16C48_EXTENT 11
+ #define MAX_NUM_WS16C48 max_num_isa_dev(WS16C48_EXTENT)
+ 
+ static unsigned int base[MAX_NUM_WS16C48];
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+index 129081ffa0a5f..5e9df7158ea4e 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+@@ -282,6 +282,9 @@ extern int amdgpu_sg_display;
+ #define AMDGPU_SMARTSHIFT_MAX_BIAS (100)
+ #define AMDGPU_SMARTSHIFT_MIN_BIAS (-100)
+ 
++/* Extra time delay(in ms) to eliminate the influence of temperature momentary fluctuation */
++#define AMDGPU_SWCTF_EXTRA_DELAY		50
++
+ struct amdgpu_device;
+ struct amdgpu_irq_src;
+ struct amdgpu_fpriv;
+@@ -1246,6 +1249,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
+ void amdgpu_device_pci_config_reset(struct amdgpu_device *adev);
+ int amdgpu_device_pci_reset(struct amdgpu_device *adev);
+ bool amdgpu_device_need_post(struct amdgpu_device *adev);
++bool amdgpu_sg_display_supported(struct amdgpu_device *adev);
+ bool amdgpu_device_pcie_dynamic_switching_supported(void);
+ bool amdgpu_device_should_use_aspm(struct amdgpu_device *adev);
+ bool amdgpu_device_aspm_support_quirk(void);
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+index 5612caf77dd65..a989ae72a58a9 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+@@ -291,7 +291,7 @@ static int amdgpu_cs_pass1(struct amdgpu_cs_parser *p,
+ 
+ 	if (!p->gang_size) {
+ 		ret = -EINVAL;
+-		goto free_partial_kdata;
++		goto free_all_kdata;
+ 	}
+ 
+ 	for (i = 0; i < p->gang_size; ++i) {
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+index 167b2a1c416eb..44a902d9b5c7b 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+@@ -1352,6 +1352,32 @@ bool amdgpu_device_need_post(struct amdgpu_device *adev)
+ 	return true;
+ }
+ 
++/*
++ * On APUs with >= 64GB white flickering has been observed w/ SG enabled.
++ * Disable S/G on such systems until we have a proper fix.
++ * https://gitlab.freedesktop.org/drm/amd/-/issues/2354
++ * https://gitlab.freedesktop.org/drm/amd/-/issues/2735
++ */
++bool amdgpu_sg_display_supported(struct amdgpu_device *adev)
++{
++	switch (amdgpu_sg_display) {
++	case -1:
++		break;
++	case 0:
++		return false;
++	case 1:
++		return true;
++	default:
++		return false;
++	}
++	if ((totalram_pages() << (PAGE_SHIFT - 10)) +
++	    (adev->gmc.real_vram_size / 1024) >= 64000000) {
++		DRM_WARN("Disabling S/G due to >=64GB RAM\n");
++		return false;
++	}
++	return true;
++}
++
+ /*
+  * Intel hosts such as Raptor Lake and Sapphire Rapids don't support dynamic
+  * speed switching. Until we have confirmation from Intel that a specific host
+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 812d7dd4c04b4..bdce367544368 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -1630,9 +1630,8 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
+ 		}
+ 		break;
+ 	}
+-	if (init_data.flags.gpu_vm_support &&
+-	    (amdgpu_sg_display == 0))
+-		init_data.flags.gpu_vm_support = false;
++	if (init_data.flags.gpu_vm_support)
++		init_data.flags.gpu_vm_support = amdgpu_sg_display_supported(adev);
+ 
+ 	if (init_data.flags.gpu_vm_support)
+ 		adev->mode_info.gpu_vm_support = true;
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+index 9bc86deac9e8e..b885c39bd16ba 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+@@ -1320,7 +1320,7 @@ int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
+ 		if (computed_streams[i])
+ 			continue;
+ 
+-		if (!res_pool->funcs->remove_stream_from_ctx ||
++		if (res_pool->funcs->remove_stream_from_ctx &&
+ 		    res_pool->funcs->remove_stream_from_ctx(stream->ctx->dc, dc_state, stream) != DC_OK)
+ 			return -EINVAL;
+ 
+diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
+index 8d2460d06bced..58e8fda04b861 100644
+--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
++++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
+@@ -780,7 +780,8 @@ void dce110_edp_wait_for_hpd_ready(
+ 	dal_gpio_destroy_irq(&hpd);
+ 
+ 	/* ensure that the panel is detected */
+-	ASSERT(edp_hpd_high);
++	if (!edp_hpd_high)
++		DC_LOG_DC("%s: wait timed out!\n", __func__);
+ }
+ 
+ void dce110_edp_power_control(
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c
+index e5b7ef7422b83..50dc834046446 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c
+@@ -357,8 +357,11 @@ void dpp3_set_cursor_attributes(
+ 	int cur_rom_en = 0;
+ 
+ 	if (color_format == CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA ||
+-		color_format == CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA)
+-		cur_rom_en = 1;
++		color_format == CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA) {
++		if (cursor_attributes->attribute_flags.bits.ENABLE_CURSOR_DEGAMMA) {
++			cur_rom_en = 1;
++		}
++	}
+ 
+ 	REG_UPDATE_3(CURSOR0_CONTROL,
+ 			CUR0_MODE, color_format,
+diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
+index d178f3f440816..42172b00be66d 100644
+--- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
++++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
+@@ -89,6 +89,8 @@ struct amdgpu_dpm_thermal {
+ 	int                max_mem_crit_temp;
+ 	/* memory max emergency(shutdown) temp */
+ 	int                max_mem_emergency_temp;
++	/* SWCTF threshold */
++	int                sw_ctf_threshold;
+ 	/* was last interrupt low to high or high to low */
+ 	bool               high_to_low;
+ 	/* interrupt source */
+diff --git a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c
+index 11b7b4cffaae0..ff360c6991712 100644
+--- a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c
++++ b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c
+@@ -26,6 +26,7 @@
+ #include <linux/gfp.h>
+ #include <linux/slab.h>
+ #include <linux/firmware.h>
++#include <linux/reboot.h>
+ #include "amd_shared.h"
+ #include "amd_powerplay.h"
+ #include "power_state.h"
+@@ -91,6 +92,45 @@ static int pp_early_init(void *handle)
+ 	return 0;
+ }
+ 
++static void pp_swctf_delayed_work_handler(struct work_struct *work)
++{
++	struct pp_hwmgr *hwmgr =
++		container_of(work, struct pp_hwmgr, swctf_delayed_work.work);
++	struct amdgpu_device *adev = hwmgr->adev;
++	struct amdgpu_dpm_thermal *range =
++				&adev->pm.dpm.thermal;
++	uint32_t gpu_temperature, size;
++	int ret;
++
++	/*
++	 * If the hotspot/edge temperature is confirmed as below SW CTF setting point
++	 * after the delay enforced, nothing will be done.
++	 * Otherwise, a graceful shutdown will be performed to prevent further damage.
++	 */
++	if (range->sw_ctf_threshold &&
++	    hwmgr->hwmgr_func->read_sensor) {
++		ret = hwmgr->hwmgr_func->read_sensor(hwmgr,
++						     AMDGPU_PP_SENSOR_HOTSPOT_TEMP,
++						     &gpu_temperature,
++						     &size);
++		/*
++		 * For some legacy ASICs, hotspot temperature retrieving might be not
++		 * supported. Check the edge temperature instead then.
++		 */
++		if (ret == -EOPNOTSUPP)
++			ret = hwmgr->hwmgr_func->read_sensor(hwmgr,
++							     AMDGPU_PP_SENSOR_EDGE_TEMP,
++							     &gpu_temperature,
++							     &size);
++		if (!ret && gpu_temperature / 1000 < range->sw_ctf_threshold)
++			return;
++	}
++
++	dev_emerg(adev->dev, "ERROR: GPU over temperature range(SW CTF) detected!\n");
++	dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU SW CTF!\n");
++	orderly_poweroff(true);
++}
++
+ static int pp_sw_init(void *handle)
+ {
+ 	struct amdgpu_device *adev = handle;
+@@ -101,6 +141,10 @@ static int pp_sw_init(void *handle)
+ 
+ 	pr_debug("powerplay sw init %s\n", ret ? "failed" : "successfully");
+ 
++	if (!ret)
++		INIT_DELAYED_WORK(&hwmgr->swctf_delayed_work,
++				  pp_swctf_delayed_work_handler);
++
+ 	return ret;
+ }
+ 
+@@ -135,6 +179,8 @@ static int pp_hw_fini(void *handle)
+ 	struct amdgpu_device *adev = handle;
+ 	struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
+ 
++	cancel_delayed_work_sync(&hwmgr->swctf_delayed_work);
++
+ 	hwmgr_hw_fini(hwmgr);
+ 
+ 	return 0;
+@@ -221,6 +267,8 @@ static int pp_suspend(void *handle)
+ 	struct amdgpu_device *adev = handle;
+ 	struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
+ 
++	cancel_delayed_work_sync(&hwmgr->swctf_delayed_work);
++
+ 	return hwmgr_suspend(hwmgr);
+ }
+ 
+diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c
+index 981dc8c7112d6..90452b66e1071 100644
+--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c
++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c
+@@ -241,7 +241,8 @@ int phm_start_thermal_controller(struct pp_hwmgr *hwmgr)
+ 		TEMP_RANGE_MAX,
+ 		TEMP_RANGE_MIN,
+ 		TEMP_RANGE_MAX,
+-		TEMP_RANGE_MAX};
++		TEMP_RANGE_MAX,
++		0};
+ 	struct amdgpu_device *adev = hwmgr->adev;
+ 
+ 	if (!hwmgr->not_vf)
+@@ -265,6 +266,7 @@ int phm_start_thermal_controller(struct pp_hwmgr *hwmgr)
+ 	adev->pm.dpm.thermal.min_mem_temp = range.mem_min;
+ 	adev->pm.dpm.thermal.max_mem_crit_temp = range.mem_crit_max;
+ 	adev->pm.dpm.thermal.max_mem_emergency_temp = range.mem_emergency_max;
++	adev->pm.dpm.thermal.sw_ctf_threshold = range.sw_ctf_threshold;
+ 
+ 	return ret;
+ }
+diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
+index e10cc5e7928e6..6841a4bce186f 100644
+--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
+@@ -5432,6 +5432,8 @@ static int smu7_get_thermal_temperature_range(struct pp_hwmgr *hwmgr,
+ 		thermal_data->max = data->thermal_temp_setting.temperature_shutdown *
+ 			PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ 
++	thermal_data->sw_ctf_threshold = thermal_data->max;
++
+ 	return 0;
+ }
+ 
+diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.c
+index bfe80ac0ad8c8..d0b1ab6c45231 100644
+--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.c
++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.c
+@@ -603,21 +603,17 @@ int phm_irq_process(struct amdgpu_device *adev,
+ 			   struct amdgpu_irq_src *source,
+ 			   struct amdgpu_iv_entry *entry)
+ {
++	struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
+ 	uint32_t client_id = entry->client_id;
+ 	uint32_t src_id = entry->src_id;
+ 
+ 	if (client_id == AMDGPU_IRQ_CLIENTID_LEGACY) {
+ 		if (src_id == VISLANDS30_IV_SRCID_CG_TSS_THERMAL_LOW_TO_HIGH) {
+-			dev_emerg(adev->dev, "ERROR: GPU over temperature range(SW CTF) detected!\n");
+-			/*
+-			 * SW CTF just occurred.
+-			 * Try to do a graceful shutdown to prevent further damage.
+-			 */
+-			dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU SW CTF!\n");
+-			orderly_poweroff(true);
+-		} else if (src_id == VISLANDS30_IV_SRCID_CG_TSS_THERMAL_HIGH_TO_LOW)
++			schedule_delayed_work(&hwmgr->swctf_delayed_work,
++					      msecs_to_jiffies(AMDGPU_SWCTF_EXTRA_DELAY));
++		} else if (src_id == VISLANDS30_IV_SRCID_CG_TSS_THERMAL_HIGH_TO_LOW) {
+ 			dev_emerg(adev->dev, "ERROR: GPU under temperature range detected!\n");
+-		else if (src_id == VISLANDS30_IV_SRCID_GPIO_19) {
++		} else if (src_id == VISLANDS30_IV_SRCID_GPIO_19) {
+ 			dev_emerg(adev->dev, "ERROR: GPU HW Critical Temperature Fault(aka CTF) detected!\n");
+ 			/*
+ 			 * HW CTF just occurred. Shutdown to prevent further damage.
+@@ -626,15 +622,10 @@ int phm_irq_process(struct amdgpu_device *adev,
+ 			orderly_poweroff(true);
+ 		}
+ 	} else if (client_id == SOC15_IH_CLIENTID_THM) {
+-		if (src_id == 0) {
+-			dev_emerg(adev->dev, "ERROR: GPU over temperature range(SW CTF) detected!\n");
+-			/*
+-			 * SW CTF just occurred.
+-			 * Try to do a graceful shutdown to prevent further damage.
+-			 */
+-			dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU SW CTF!\n");
+-			orderly_poweroff(true);
+-		} else
++		if (src_id == 0)
++			schedule_delayed_work(&hwmgr->swctf_delayed_work,
++					      msecs_to_jiffies(AMDGPU_SWCTF_EXTRA_DELAY));
++		else
+ 			dev_emerg(adev->dev, "ERROR: GPU under temperature range detected!\n");
+ 	} else if (client_id == SOC15_IH_CLIENTID_ROM_SMUIO) {
+ 		dev_emerg(adev->dev, "ERROR: GPU HW Critical Temperature Fault(aka CTF) detected!\n");
+diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c
+index 99cd2e63afdd4..c51dd4c74fe9d 100644
+--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c
++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c
+@@ -5241,6 +5241,9 @@ static int vega10_get_thermal_temperature_range(struct pp_hwmgr *hwmgr,
+ {
+ 	struct vega10_hwmgr *data = hwmgr->backend;
+ 	PPTable_t *pp_table = &(data->smc_state_table.pp_table);
++	struct phm_ppt_v2_information *pp_table_info =
++		(struct phm_ppt_v2_information *)(hwmgr->pptable);
++	struct phm_tdp_table *tdp_table = pp_table_info->tdp_table;
+ 
+ 	memcpy(thermal_data, &SMU7ThermalWithDelayPolicy[0], sizeof(struct PP_TemperatureRange));
+ 
+@@ -5257,6 +5260,13 @@ static int vega10_get_thermal_temperature_range(struct pp_hwmgr *hwmgr,
+ 	thermal_data->mem_emergency_max = (pp_table->ThbmLimit + CTF_OFFSET_HBM)*
+ 		PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ 
++	if (tdp_table->usSoftwareShutdownTemp > pp_table->ThotspotLimit &&
++	    tdp_table->usSoftwareShutdownTemp < VEGA10_THERMAL_MAXIMUM_ALERT_TEMP)
++		thermal_data->sw_ctf_threshold = tdp_table->usSoftwareShutdownTemp;
++	else
++		thermal_data->sw_ctf_threshold = VEGA10_THERMAL_MAXIMUM_ALERT_TEMP;
++	thermal_data->sw_ctf_threshold *= PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
++
+ 	return 0;
+ }
+ 
+diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c
+index e9db137cd1c6c..1937be1cf5b46 100644
+--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c
++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c
+@@ -2763,6 +2763,8 @@ static int vega12_notify_cac_buffer_info(struct pp_hwmgr *hwmgr,
+ static int vega12_get_thermal_temperature_range(struct pp_hwmgr *hwmgr,
+ 		struct PP_TemperatureRange *thermal_data)
+ {
++	struct phm_ppt_v3_information *pptable_information =
++		(struct phm_ppt_v3_information *)hwmgr->pptable;
+ 	struct vega12_hwmgr *data =
+ 			(struct vega12_hwmgr *)(hwmgr->backend);
+ 	PPTable_t *pp_table = &(data->smc_state_table.pp_table);
+@@ -2781,6 +2783,8 @@ static int vega12_get_thermal_temperature_range(struct pp_hwmgr *hwmgr,
+ 		PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ 	thermal_data->mem_emergency_max = (pp_table->ThbmLimit + CTF_OFFSET_HBM)*
+ 		PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
++	thermal_data->sw_ctf_threshold = pptable_information->us_software_shutdown_temp *
++		PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ 
+ 	return 0;
+ }
+diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c
+index 0d4d4811527c6..4e19ccbdb8077 100644
+--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c
++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c
+@@ -4206,6 +4206,8 @@ static int vega20_notify_cac_buffer_info(struct pp_hwmgr *hwmgr,
+ static int vega20_get_thermal_temperature_range(struct pp_hwmgr *hwmgr,
+ 		struct PP_TemperatureRange *thermal_data)
+ {
++	struct phm_ppt_v3_information *pptable_information =
++		(struct phm_ppt_v3_information *)hwmgr->pptable;
+ 	struct vega20_hwmgr *data =
+ 			(struct vega20_hwmgr *)(hwmgr->backend);
+ 	PPTable_t *pp_table = &(data->smc_state_table.pp_table);
+@@ -4224,6 +4226,8 @@ static int vega20_get_thermal_temperature_range(struct pp_hwmgr *hwmgr,
+ 		PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ 	thermal_data->mem_emergency_max = (pp_table->ThbmLimit + CTF_OFFSET_HBM)*
+ 		PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
++	thermal_data->sw_ctf_threshold = pptable_information->us_software_shutdown_temp *
++		PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ 
+ 	return 0;
+ }
+diff --git a/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h
+index 5ce433e2c16a5..ec10643edea3e 100644
+--- a/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h
++++ b/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h
+@@ -811,6 +811,8 @@ struct pp_hwmgr {
+ 	bool gfxoff_state_changed_by_workload;
+ 	uint32_t pstate_sclk_peak;
+ 	uint32_t pstate_mclk_peak;
++
++	struct delayed_work swctf_delayed_work;
+ };
+ 
+ int hwmgr_early_init(struct pp_hwmgr *hwmgr);
+diff --git a/drivers/gpu/drm/amd/pm/powerplay/inc/power_state.h b/drivers/gpu/drm/amd/pm/powerplay/inc/power_state.h
+index a5f2227a3971c..0ffc2347829d0 100644
+--- a/drivers/gpu/drm/amd/pm/powerplay/inc/power_state.h
++++ b/drivers/gpu/drm/amd/pm/powerplay/inc/power_state.h
+@@ -131,6 +131,7 @@ struct PP_TemperatureRange {
+ 	int mem_min;
+ 	int mem_crit_max;
+ 	int mem_emergency_max;
++	int sw_ctf_threshold;
+ };
+ 
+ struct PP_StateValidationBlock {
+diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+index 2ddf5198e5c48..ea03e8d9a3f6c 100644
+--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+@@ -24,6 +24,7 @@
+ 
+ #include <linux/firmware.h>
+ #include <linux/pci.h>
++#include <linux/reboot.h>
+ 
+ #include "amdgpu.h"
+ #include "amdgpu_smu.h"
+@@ -1070,6 +1071,34 @@ static void smu_interrupt_work_fn(struct work_struct *work)
+ 		smu->ppt_funcs->interrupt_work(smu);
+ }
+ 
++static void smu_swctf_delayed_work_handler(struct work_struct *work)
++{
++	struct smu_context *smu =
++		container_of(work, struct smu_context, swctf_delayed_work.work);
++	struct smu_temperature_range *range =
++				&smu->thermal_range;
++	struct amdgpu_device *adev = smu->adev;
++	uint32_t hotspot_tmp, size;
++
++	/*
++	 * If the hotspot temperature is confirmed as below SW CTF setting point
++	 * after the delay enforced, nothing will be done.
++	 * Otherwise, a graceful shutdown will be performed to prevent further damage.
++	 */
++	if (range->software_shutdown_temp &&
++	    smu->ppt_funcs->read_sensor &&
++	    !smu->ppt_funcs->read_sensor(smu,
++					 AMDGPU_PP_SENSOR_HOTSPOT_TEMP,
++					 &hotspot_tmp,
++					 &size) &&
++	    hotspot_tmp / 1000 < range->software_shutdown_temp)
++		return;
++
++	dev_emerg(adev->dev, "ERROR: GPU over temperature range(SW CTF) detected!\n");
++	dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU SW CTF!\n");
++	orderly_poweroff(true);
++}
++
+ static int smu_sw_init(void *handle)
+ {
+ 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+@@ -1112,6 +1141,9 @@ static int smu_sw_init(void *handle)
+ 	smu->smu_dpm.dpm_level = AMD_DPM_FORCED_LEVEL_AUTO;
+ 	smu->smu_dpm.requested_dpm_level = AMD_DPM_FORCED_LEVEL_AUTO;
+ 
++	INIT_DELAYED_WORK(&smu->swctf_delayed_work,
++			  smu_swctf_delayed_work_handler);
++
+ 	ret = smu_smc_table_sw_init(smu);
+ 	if (ret) {
+ 		dev_err(adev->dev, "Failed to sw init smc table!\n");
+@@ -1592,6 +1624,8 @@ static int smu_smc_hw_cleanup(struct smu_context *smu)
+ 		return ret;
+ 	}
+ 
++	cancel_delayed_work_sync(&smu->swctf_delayed_work);
++
+ 	ret = smu_disable_dpms(smu);
+ 	if (ret) {
+ 		dev_err(adev->dev, "Fail to disable dpm features!\n");
+diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
+index 09469c750a96b..6e2069dcb6b9d 100644
+--- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
++++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
+@@ -573,6 +573,8 @@ struct smu_context
+ 	u32 debug_param_reg;
+ 	u32 debug_msg_reg;
+ 	u32 debug_resp_reg;
++
++	struct delayed_work		swctf_delayed_work;
+ };
+ 
+ struct i2c_adapter;
+diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
+index e1ef88ee1ed39..aa4a5498a12f7 100644
+--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
+@@ -1412,13 +1412,8 @@ static int smu_v11_0_irq_process(struct amdgpu_device *adev,
+ 	if (client_id == SOC15_IH_CLIENTID_THM) {
+ 		switch (src_id) {
+ 		case THM_11_0__SRCID__THM_DIG_THERM_L2H:
+-			dev_emerg(adev->dev, "ERROR: GPU over temperature range(SW CTF) detected!\n");
+-			/*
+-			 * SW CTF just occurred.
+-			 * Try to do a graceful shutdown to prevent further damage.
+-			 */
+-			dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU SW CTF!\n");
+-			orderly_poweroff(true);
++			schedule_delayed_work(&smu->swctf_delayed_work,
++					      msecs_to_jiffies(AMDGPU_SWCTF_EXTRA_DELAY));
+ 		break;
+ 		case THM_11_0__SRCID__THM_DIG_THERM_H2L:
+ 			dev_emerg(adev->dev, "ERROR: GPU under temperature range detected\n");
+diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
+index 79e9230fc7960..048f4018d0b90 100644
+--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
+@@ -1377,13 +1377,8 @@ static int smu_v13_0_irq_process(struct amdgpu_device *adev,
+ 	if (client_id == SOC15_IH_CLIENTID_THM) {
+ 		switch (src_id) {
+ 		case THM_11_0__SRCID__THM_DIG_THERM_L2H:
+-			dev_emerg(adev->dev, "ERROR: GPU over temperature range(SW CTF) detected!\n");
+-			/*
+-			 * SW CTF just occurred.
+-			 * Try to do a graceful shutdown to prevent further damage.
+-			 */
+-			dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU SW CTF!\n");
+-			orderly_poweroff(true);
++			schedule_delayed_work(&smu->swctf_delayed_work,
++					      msecs_to_jiffies(AMDGPU_SWCTF_EXTRA_DELAY));
+ 			break;
+ 		case THM_11_0__SRCID__THM_DIG_THERM_H2L:
+ 			dev_emerg(adev->dev, "ERROR: GPU under temperature range detected\n");
+diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
+index 907cc43d16a90..d7f09af2fb018 100644
+--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
+@@ -1030,7 +1030,6 @@ static int smu_v13_0_0_print_clk_levels(struct smu_context *smu,
+ 	struct smu_13_0_dpm_context *dpm_context = smu_dpm->dpm_context;
+ 	struct smu_13_0_dpm_table *single_dpm_table;
+ 	struct smu_13_0_pcie_table *pcie_table;
+-	const int link_width[] = {0, 1, 2, 4, 8, 12, 16};
+ 	uint32_t gen_speed, lane_width;
+ 	int i, curr_freq, size = 0;
+ 	int ret = 0;
+@@ -1145,7 +1144,7 @@ static int smu_v13_0_0_print_clk_levels(struct smu_context *smu,
+ 					(pcie_table->pcie_lane[i] == 6) ? "x16" : "",
+ 					pcie_table->clk_freq[i],
+ 					(gen_speed == DECODE_GEN_SPEED(pcie_table->pcie_gen[i])) &&
+-					(lane_width == DECODE_LANE_WIDTH(link_width[pcie_table->pcie_lane[i]])) ?
++					(lane_width == DECODE_LANE_WIDTH(pcie_table->pcie_lane[i])) ?
+ 					"*" : "");
+ 		break;
+ 
+diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c
+index 45f579c365e7f..94b1497dfb017 100644
+--- a/drivers/gpu/drm/bridge/ite-it6505.c
++++ b/drivers/gpu/drm/bridge/ite-it6505.c
+@@ -2517,9 +2517,11 @@ static irqreturn_t it6505_int_threaded_handler(int unused, void *data)
+ 	};
+ 	int int_status[3], i;
+ 
+-	if (it6505->enable_drv_hold || pm_runtime_get_if_in_use(dev) <= 0)
++	if (it6505->enable_drv_hold || !it6505->powered)
+ 		return IRQ_HANDLED;
+ 
++	pm_runtime_get_sync(dev);
++
+ 	int_status[0] = it6505_read(it6505, INT_STATUS_01);
+ 	int_status[1] = it6505_read(it6505, INT_STATUS_02);
+ 	int_status[2] = it6505_read(it6505, INT_STATUS_03);
+diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c b/drivers/gpu/drm/drm_gem_shmem_helper.c
+index 4ea6507a77e5d..baaf0e0feb063 100644
+--- a/drivers/gpu/drm/drm_gem_shmem_helper.c
++++ b/drivers/gpu/drm/drm_gem_shmem_helper.c
+@@ -623,7 +623,13 @@ int drm_gem_shmem_mmap(struct drm_gem_shmem_object *shmem, struct vm_area_struct
+ 	int ret;
+ 
+ 	if (obj->import_attach) {
++		/* Reset both vm_ops and vm_private_data, so we don't end up with
++		 * vm_ops pointing to our implementation if the dma-buf backend
++		 * doesn't set those fields.
++		 */
+ 		vma->vm_private_data = NULL;
++		vma->vm_ops = NULL;
++
+ 		ret = dma_buf_mmap(obj->dma_buf, vma, 0);
+ 
+ 		/* Drop the reference drm_gem_mmap_obj() acquired.*/
+diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
+index f75c6f09dd2af..a2e0033e8a260 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
++++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
+@@ -967,7 +967,7 @@ nouveau_connector_get_modes(struct drm_connector *connector)
+ 	/* Determine display colour depth for everything except LVDS now,
+ 	 * DP requires this before mode_valid() is called.
+ 	 */
+-	if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS && nv_connector->native_mode)
++	if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS)
+ 		nouveau_connector_detect_depth(connector);
+ 
+ 	/* Find the native mode if this is a digital panel, if we didn't
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
+index 40c8ea43c42f2..b8ac66b4a2c4b 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
+@@ -26,6 +26,8 @@
+ #include "head.h"
+ #include "ior.h"
+ 
++#include <drm/display/drm_dp.h>
++
+ #include <subdev/bios.h>
+ #include <subdev/bios/init.h>
+ #include <subdev/gpio.h>
+@@ -634,6 +636,50 @@ nvkm_dp_enable_supported_link_rates(struct nvkm_outp *outp)
+ 	return outp->dp.rates != 0;
+ }
+ 
++/* XXX: This is a big fat hack, and this is just drm_dp_read_dpcd_caps()
++ * converted to work inside nvkm. This is a temporary holdover until we start
++ * passing the drm_dp_aux device through NVKM
++ */
++static int
++nvkm_dp_read_dpcd_caps(struct nvkm_outp *outp)
++{
++	struct nvkm_i2c_aux *aux = outp->dp.aux;
++	u8 dpcd_ext[DP_RECEIVER_CAP_SIZE];
++	int ret;
++
++	ret = nvkm_rdaux(aux, DPCD_RC00_DPCD_REV, outp->dp.dpcd, DP_RECEIVER_CAP_SIZE);
++	if (ret < 0)
++		return ret;
++
++	/*
++	 * Prior to DP1.3 the bit represented by
++	 * DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT was reserved.
++	 * If it is set DP_DPCD_REV at 0000h could be at a value less than
++	 * the true capability of the panel. The only way to check is to
++	 * then compare 0000h and 2200h.
++	 */
++	if (!(outp->dp.dpcd[DP_TRAINING_AUX_RD_INTERVAL] &
++	      DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT))
++		return 0;
++
++	ret = nvkm_rdaux(aux, DP_DP13_DPCD_REV, dpcd_ext, sizeof(dpcd_ext));
++	if (ret < 0)
++		return ret;
++
++	if (outp->dp.dpcd[DP_DPCD_REV] > dpcd_ext[DP_DPCD_REV]) {
++		OUTP_DBG(outp, "Extended DPCD rev less than base DPCD rev (%d > %d)\n",
++			 outp->dp.dpcd[DP_DPCD_REV], dpcd_ext[DP_DPCD_REV]);
++		return 0;
++	}
++
++	if (!memcmp(outp->dp.dpcd, dpcd_ext, sizeof(dpcd_ext)))
++		return 0;
++
++	memcpy(outp->dp.dpcd, dpcd_ext, sizeof(dpcd_ext));
++
++	return 0;
++}
++
+ void
+ nvkm_dp_enable(struct nvkm_outp *outp, bool auxpwr)
+ {
+@@ -689,7 +735,7 @@ nvkm_dp_enable(struct nvkm_outp *outp, bool auxpwr)
+ 			memset(outp->dp.lttpr, 0x00, sizeof(outp->dp.lttpr));
+ 		}
+ 
+-		if (!nvkm_rdaux(aux, DPCD_RC00_DPCD_REV, outp->dp.dpcd, sizeof(outp->dp.dpcd))) {
++		if (!nvkm_dp_read_dpcd_caps(outp)) {
+ 			const u8 rates[] = { 0x1e, 0x14, 0x0a, 0x06, 0 };
+ 			const u8 *rate;
+ 			int rate_max;
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h
+index 00dbeda7e3464..de161e7a04aa6 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h
+@@ -117,6 +117,7 @@ void gk104_grctx_generate_r418800(struct gf100_gr *);
+ 
+ extern const struct gf100_grctx_func gk110_grctx;
+ void gk110_grctx_generate_r419eb0(struct gf100_gr *);
++void gk110_grctx_generate_r419f78(struct gf100_gr *);
+ 
+ extern const struct gf100_grctx_func gk110b_grctx;
+ extern const struct gf100_grctx_func gk208_grctx;
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c
+index 94233d0119dff..52a234b1ef010 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c
+@@ -906,7 +906,9 @@ static void
+ gk104_grctx_generate_r419f78(struct gf100_gr *gr)
+ {
+ 	struct nvkm_device *device = gr->base.engine.subdev.device;
+-	nvkm_mask(device, 0x419f78, 0x00000001, 0x00000000);
++
++	/* bit 3 set disables loads in fp helper invocations, we need it enabled */
++	nvkm_mask(device, 0x419f78, 0x00000009, 0x00000000);
+ }
+ 
+ void
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110.c
+index 4391458e1fb2f..3acdd9eeb74a7 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110.c
+@@ -820,6 +820,15 @@ gk110_grctx_generate_r419eb0(struct gf100_gr *gr)
+ 	nvkm_mask(device, 0x419eb0, 0x00001000, 0x00001000);
+ }
+ 
++void
++gk110_grctx_generate_r419f78(struct gf100_gr *gr)
++{
++	struct nvkm_device *device = gr->base.engine.subdev.device;
++
++	/* bit 3 set disables loads in fp helper invocations, we need it enabled */
++	nvkm_mask(device, 0x419f78, 0x00000008, 0x00000000);
++}
++
+ const struct gf100_grctx_func
+ gk110_grctx = {
+ 	.main  = gf100_grctx_generate_main,
+@@ -854,4 +863,5 @@ gk110_grctx = {
+ 	.gpc_tpc_nr = gk104_grctx_generate_gpc_tpc_nr,
+ 	.r418800 = gk104_grctx_generate_r418800,
+ 	.r419eb0 = gk110_grctx_generate_r419eb0,
++	.r419f78 = gk110_grctx_generate_r419f78,
+ };
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110b.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110b.c
+index 7b9a34f9ec3c7..5597e87624acd 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110b.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110b.c
+@@ -103,4 +103,5 @@ gk110b_grctx = {
+ 	.gpc_tpc_nr = gk104_grctx_generate_gpc_tpc_nr,
+ 	.r418800 = gk104_grctx_generate_r418800,
+ 	.r419eb0 = gk110_grctx_generate_r419eb0,
++	.r419f78 = gk110_grctx_generate_r419f78,
+ };
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk208.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk208.c
+index c78d07a8bb7df..612656496541d 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk208.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk208.c
+@@ -568,4 +568,5 @@ gk208_grctx = {
+ 	.dist_skip_table = gf117_grctx_generate_dist_skip_table,
+ 	.gpc_tpc_nr = gk104_grctx_generate_gpc_tpc_nr,
+ 	.r418800 = gk104_grctx_generate_r418800,
++	.r419f78 = gk110_grctx_generate_r419f78,
+ };
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c
+index beac66eb2a803..9906974ac3f07 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c
+@@ -988,4 +988,5 @@ gm107_grctx = {
+ 	.r406500 = gm107_grctx_generate_r406500,
+ 	.gpc_tpc_nr = gk104_grctx_generate_gpc_tpc_nr,
+ 	.r419e00 = gm107_grctx_generate_r419e00,
++	.r419f78 = gk110_grctx_generate_r419f78,
+ };
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c
+index 3b6c8100a2428..a7775aa185415 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c
+@@ -206,19 +206,6 @@ tu102_gr_av_to_init_veid(struct nvkm_blob *blob, struct gf100_gr_pack **ppack)
+ 	return gk20a_gr_av_to_init_(blob, 64, 0x00100000, ppack);
+ }
+ 
+-int
+-tu102_gr_load(struct gf100_gr *gr, int ver, const struct gf100_gr_fwif *fwif)
+-{
+-	int ret;
+-
+-	ret = gm200_gr_load(gr, ver, fwif);
+-	if (ret)
+-		return ret;
+-
+-	return gk20a_gr_load_net(gr, "gr/", "sw_veid_bundle_init", ver, tu102_gr_av_to_init_veid,
+-				 &gr->bundle_veid);
+-}
+-
+ static const struct gf100_gr_fwif
+ tu102_gr_fwif[] = {
+ 	{  0, gm200_gr_load, &tu102_gr, &gp108_gr_fecs_acr, &gp108_gr_gpccs_acr },
+diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+index a530ecc4d207c..bf34498c1b6d7 100644
+--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+@@ -833,12 +833,12 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
+ 	 * need align with 2 pixel.
+ 	 */
+ 	if (fb->format->is_yuv && ((new_plane_state->src.x1 >> 16) % 2)) {
+-		DRM_ERROR("Invalid Source: Yuv format not support odd xpos\n");
++		DRM_DEBUG_KMS("Invalid Source: Yuv format not support odd xpos\n");
+ 		return -EINVAL;
+ 	}
+ 
+ 	if (fb->format->is_yuv && new_plane_state->rotation & DRM_MODE_REFLECT_Y) {
+-		DRM_ERROR("Invalid Source: Yuv format does not support this rotation\n");
++		DRM_DEBUG_KMS("Invalid Source: Yuv format does not support this rotation\n");
+ 		return -EINVAL;
+ 	}
+ 
+@@ -846,7 +846,7 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
+ 		struct vop *vop = to_vop(crtc);
+ 
+ 		if (!vop->data->afbc) {
+-			DRM_ERROR("vop does not support AFBC\n");
++			DRM_DEBUG_KMS("vop does not support AFBC\n");
+ 			return -EINVAL;
+ 		}
+ 
+@@ -855,15 +855,16 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
+ 			return ret;
+ 
+ 		if (new_plane_state->src.x1 || new_plane_state->src.y1) {
+-			DRM_ERROR("AFBC does not support offset display, xpos=%d, ypos=%d, offset=%d\n",
+-				  new_plane_state->src.x1,
+-				  new_plane_state->src.y1, fb->offsets[0]);
++			DRM_DEBUG_KMS("AFBC does not support offset display, " \
++				      "xpos=%d, ypos=%d, offset=%d\n",
++				      new_plane_state->src.x1, new_plane_state->src.y1,
++				      fb->offsets[0]);
+ 			return -EINVAL;
+ 		}
+ 
+ 		if (new_plane_state->rotation && new_plane_state->rotation != DRM_MODE_ROTATE_0) {
+-			DRM_ERROR("No rotation support in AFBC, rotation=%d\n",
+-				  new_plane_state->rotation);
++			DRM_DEBUG_KMS("No rotation support in AFBC, rotation=%d\n",
++				      new_plane_state->rotation);
+ 			return -EINVAL;
+ 		}
+ 	}
+diff --git a/drivers/hwmon/aquacomputer_d5next.c b/drivers/hwmon/aquacomputer_d5next.c
+index c2b99fd4f436c..e6126a5319520 100644
+--- a/drivers/hwmon/aquacomputer_d5next.c
++++ b/drivers/hwmon/aquacomputer_d5next.c
+@@ -13,9 +13,11 @@
+ 
+ #include <linux/crc16.h>
+ #include <linux/debugfs.h>
++#include <linux/delay.h>
+ #include <linux/hid.h>
+ #include <linux/hwmon.h>
+ #include <linux/jiffies.h>
++#include <linux/ktime.h>
+ #include <linux/module.h>
+ #include <linux/mutex.h>
+ #include <linux/seq_file.h>
+@@ -61,6 +63,8 @@ static const char *const aqc_device_names[] = {
+ #define CTRL_REPORT_ID			0x03
+ #define AQUAERO_CTRL_REPORT_ID		0x0b
+ 
++#define CTRL_REPORT_DELAY		200	/* ms */
++
+ /* The HID report that the official software always sends
+  * after writing values, currently same for all devices
+  */
+@@ -496,6 +500,9 @@ struct aqc_data {
+ 	int secondary_ctrl_report_size;
+ 	u8 *secondary_ctrl_report;
+ 
++	ktime_t last_ctrl_report_op;
++	int ctrl_report_delay;	/* Delay between two ctrl report operations, in ms */
++
+ 	int buffer_size;
+ 	u8 *buffer;
+ 	int checksum_start;
+@@ -577,17 +584,35 @@ static int aqc_aquastreamxt_convert_fan_rpm(u16 val)
+ 	return 0;
+ }
+ 
++static void aqc_delay_ctrl_report(struct aqc_data *priv)
++{
++	/*
++	 * If previous read or write is too close to this one, delay the current operation
++	 * to give the device enough time to process the previous one.
++	 */
++	if (priv->ctrl_report_delay) {
++		s64 delta = ktime_ms_delta(ktime_get(), priv->last_ctrl_report_op);
++
++		if (delta < priv->ctrl_report_delay)
++			msleep(priv->ctrl_report_delay - delta);
++	}
++}
++
+ /* Expects the mutex to be locked */
+ static int aqc_get_ctrl_data(struct aqc_data *priv)
+ {
+ 	int ret;
+ 
++	aqc_delay_ctrl_report(priv);
++
+ 	memset(priv->buffer, 0x00, priv->buffer_size);
+ 	ret = hid_hw_raw_request(priv->hdev, priv->ctrl_report_id, priv->buffer, priv->buffer_size,
+ 				 HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
+ 	if (ret < 0)
+ 		ret = -ENODATA;
+ 
++	priv->last_ctrl_report_op = ktime_get();
++
+ 	return ret;
+ }
+ 
+@@ -597,6 +622,8 @@ static int aqc_send_ctrl_data(struct aqc_data *priv)
+ 	int ret;
+ 	u16 checksum;
+ 
++	aqc_delay_ctrl_report(priv);
++
+ 	/* Checksum is not needed for Aquaero */
+ 	if (priv->kind != aquaero) {
+ 		/* Init and xorout value for CRC-16/USB is 0xffff */
+@@ -612,12 +639,16 @@ static int aqc_send_ctrl_data(struct aqc_data *priv)
+ 	ret = hid_hw_raw_request(priv->hdev, priv->ctrl_report_id, priv->buffer, priv->buffer_size,
+ 				 HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
+ 	if (ret < 0)
+-		return ret;
++		goto record_access_and_ret;
+ 
+ 	/* The official software sends this report after every change, so do it here as well */
+ 	ret = hid_hw_raw_request(priv->hdev, priv->secondary_ctrl_report_id,
+ 				 priv->secondary_ctrl_report, priv->secondary_ctrl_report_size,
+ 				 HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
++
++record_access_and_ret:
++	priv->last_ctrl_report_op = ktime_get();
++
+ 	return ret;
+ }
+ 
+@@ -1443,6 +1474,7 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
+ 
+ 		priv->buffer_size = AQUAERO_CTRL_REPORT_SIZE;
+ 		priv->temp_ctrl_offset = AQUAERO_TEMP_CTRL_OFFSET;
++		priv->ctrl_report_delay = CTRL_REPORT_DELAY;
+ 
+ 		priv->temp_label = label_temp_sensors;
+ 		priv->virtual_temp_label = label_virtual_temp_sensors;
+@@ -1466,6 +1498,7 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
+ 		priv->temp_ctrl_offset = D5NEXT_TEMP_CTRL_OFFSET;
+ 
+ 		priv->buffer_size = D5NEXT_CTRL_REPORT_SIZE;
++		priv->ctrl_report_delay = CTRL_REPORT_DELAY;
+ 
+ 		priv->power_cycle_count_offset = D5NEXT_POWER_CYCLES;
+ 
+@@ -1516,6 +1549,7 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
+ 		priv->temp_ctrl_offset = OCTO_TEMP_CTRL_OFFSET;
+ 
+ 		priv->buffer_size = OCTO_CTRL_REPORT_SIZE;
++		priv->ctrl_report_delay = CTRL_REPORT_DELAY;
+ 
+ 		priv->power_cycle_count_offset = OCTO_POWER_CYCLES;
+ 
+@@ -1543,6 +1577,7 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
+ 		priv->temp_ctrl_offset = QUADRO_TEMP_CTRL_OFFSET;
+ 
+ 		priv->buffer_size = QUADRO_CTRL_REPORT_SIZE;
++		priv->ctrl_report_delay = CTRL_REPORT_DELAY;
+ 
+ 		priv->flow_pulses_ctrl_offset = QUADRO_FLOW_PULSES_CTRL_OFFSET;
+ 		priv->power_cycle_count_offset = QUADRO_POWER_CYCLES;
+diff --git a/drivers/hwmon/pmbus/bel-pfe.c b/drivers/hwmon/pmbus/bel-pfe.c
+index 4100eefb7ac32..61c195f8fd3b8 100644
+--- a/drivers/hwmon/pmbus/bel-pfe.c
++++ b/drivers/hwmon/pmbus/bel-pfe.c
+@@ -17,12 +17,13 @@
+ enum chips {pfe1100, pfe3000};
+ 
+ /*
+- * Disable status check for pfe3000 devices, because some devices report
+- * communication error (invalid command) for VOUT_MODE command (0x20)
+- * although correct VOUT_MODE (0x16) is returned: it leads to incorrect
+- * exponent in linear mode.
++ * Disable status check because some devices report communication error
++ * (invalid command) for VOUT_MODE command (0x20) although the correct
++ * VOUT_MODE (0x16) is returned: it leads to incorrect exponent in linear
++ * mode.
++ * This affects both pfe3000 and pfe1100.
+  */
+-static struct pmbus_platform_data pfe3000_plat_data = {
++static struct pmbus_platform_data pfe_plat_data = {
+ 	.flags = PMBUS_SKIP_STATUS_CHECK,
+ };
+ 
+@@ -94,16 +95,15 @@ static int pfe_pmbus_probe(struct i2c_client *client)
+ 	int model;
+ 
+ 	model = (int)i2c_match_id(pfe_device_id, client)->driver_data;
++	client->dev.platform_data = &pfe_plat_data;
+ 
+ 	/*
+ 	 * PFE3000-12-069RA devices may not stay in page 0 during device
+ 	 * probe which leads to probe failure (read status word failed).
+ 	 * So let's set the device to page 0 at the beginning.
+ 	 */
+-	if (model == pfe3000) {
+-		client->dev.platform_data = &pfe3000_plat_data;
++	if (model == pfe3000)
+ 		i2c_smbus_write_byte_data(client, PMBUS_PAGE, 0);
+-	}
+ 
+ 	return pmbus_do_probe(client, &pfe_driver_info[model]);
+ }
+diff --git a/drivers/iio/adc/ad7192.c b/drivers/iio/adc/ad7192.c
+index 8685e0b58a838..7bc3ebfe8081b 100644
+--- a/drivers/iio/adc/ad7192.c
++++ b/drivers/iio/adc/ad7192.c
+@@ -62,7 +62,6 @@
+ #define AD7192_MODE_STA_MASK	BIT(20) /* Status Register transmission Mask */
+ #define AD7192_MODE_CLKSRC(x)	(((x) & 0x3) << 18) /* Clock Source Select */
+ #define AD7192_MODE_SINC3	BIT(15) /* SINC3 Filter Select */
+-#define AD7192_MODE_ACX		BIT(14) /* AC excitation enable(AD7195 only)*/
+ #define AD7192_MODE_ENPAR	BIT(13) /* Parity Enable */
+ #define AD7192_MODE_CLKDIV	BIT(12) /* Clock divide by 2 (AD7190/2 only)*/
+ #define AD7192_MODE_SCYCLE	BIT(11) /* Single cycle conversion */
+@@ -91,6 +90,7 @@
+ /* Configuration Register Bit Designations (AD7192_REG_CONF) */
+ 
+ #define AD7192_CONF_CHOP	BIT(23) /* CHOP enable */
++#define AD7192_CONF_ACX		BIT(22) /* AC excitation enable(AD7195 only) */
+ #define AD7192_CONF_REFSEL	BIT(20) /* REFIN1/REFIN2 Reference Select */
+ #define AD7192_CONF_CHAN(x)	((x) << 8) /* Channel select */
+ #define AD7192_CONF_CHAN_MASK	(0x7FF << 8) /* Channel select mask */
+@@ -472,7 +472,7 @@ static ssize_t ad7192_show_ac_excitation(struct device *dev,
+ 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ 	struct ad7192_state *st = iio_priv(indio_dev);
+ 
+-	return sysfs_emit(buf, "%d\n", !!(st->mode & AD7192_MODE_ACX));
++	return sysfs_emit(buf, "%d\n", !!(st->conf & AD7192_CONF_ACX));
+ }
+ 
+ static ssize_t ad7192_show_bridge_switch(struct device *dev,
+@@ -513,13 +513,13 @@ static ssize_t ad7192_set(struct device *dev,
+ 
+ 		ad_sd_write_reg(&st->sd, AD7192_REG_GPOCON, 1, st->gpocon);
+ 		break;
+-	case AD7192_REG_MODE:
++	case AD7192_REG_CONF:
+ 		if (val)
+-			st->mode |= AD7192_MODE_ACX;
++			st->conf |= AD7192_CONF_ACX;
+ 		else
+-			st->mode &= ~AD7192_MODE_ACX;
++			st->conf &= ~AD7192_CONF_ACX;
+ 
+-		ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode);
++		ad_sd_write_reg(&st->sd, AD7192_REG_CONF, 3, st->conf);
+ 		break;
+ 	default:
+ 		ret = -EINVAL;
+@@ -579,12 +579,11 @@ static IIO_DEVICE_ATTR(bridge_switch_en, 0644,
+ 
+ static IIO_DEVICE_ATTR(ac_excitation_en, 0644,
+ 		       ad7192_show_ac_excitation, ad7192_set,
+-		       AD7192_REG_MODE);
++		       AD7192_REG_CONF);
+ 
+ static struct attribute *ad7192_attributes[] = {
+ 	&iio_dev_attr_filter_low_pass_3db_frequency_available.dev_attr.attr,
+ 	&iio_dev_attr_bridge_switch_en.dev_attr.attr,
+-	&iio_dev_attr_ac_excitation_en.dev_attr.attr,
+ 	NULL
+ };
+ 
+@@ -595,6 +594,7 @@ static const struct attribute_group ad7192_attribute_group = {
+ static struct attribute *ad7195_attributes[] = {
+ 	&iio_dev_attr_filter_low_pass_3db_frequency_available.dev_attr.attr,
+ 	&iio_dev_attr_bridge_switch_en.dev_attr.attr,
++	&iio_dev_attr_ac_excitation_en.dev_attr.attr,
+ 	NULL
+ };
+ 
+diff --git a/drivers/iio/adc/ina2xx-adc.c b/drivers/iio/adc/ina2xx-adc.c
+index 38d9d7b2313ea..2090bdf03cbee 100644
+--- a/drivers/iio/adc/ina2xx-adc.c
++++ b/drivers/iio/adc/ina2xx-adc.c
+@@ -124,6 +124,7 @@ static const struct regmap_config ina2xx_regmap_config = {
+ enum ina2xx_ids { ina219, ina226 };
+ 
+ struct ina2xx_config {
++	const char *name;
+ 	u16 config_default;
+ 	int calibration_value;
+ 	int shunt_voltage_lsb;	/* nV */
+@@ -155,6 +156,7 @@ struct ina2xx_chip_info {
+ 
+ static const struct ina2xx_config ina2xx_config[] = {
+ 	[ina219] = {
++		.name = "ina219",
+ 		.config_default = INA219_CONFIG_DEFAULT,
+ 		.calibration_value = 4096,
+ 		.shunt_voltage_lsb = 10000,
+@@ -164,6 +166,7 @@ static const struct ina2xx_config ina2xx_config[] = {
+ 		.chip_id = ina219,
+ 	},
+ 	[ina226] = {
++		.name = "ina226",
+ 		.config_default = INA226_CONFIG_DEFAULT,
+ 		.calibration_value = 2048,
+ 		.shunt_voltage_lsb = 2500,
+@@ -996,7 +999,7 @@ static int ina2xx_probe(struct i2c_client *client)
+ 	/* Patch the current config register with default. */
+ 	val = chip->config->config_default;
+ 
+-	if (id->driver_data == ina226) {
++	if (type == ina226) {
+ 		ina226_set_average(chip, INA226_DEFAULT_AVG, &val);
+ 		ina226_set_int_time_vbus(chip, INA226_DEFAULT_IT, &val);
+ 		ina226_set_int_time_vshunt(chip, INA226_DEFAULT_IT, &val);
+@@ -1015,7 +1018,7 @@ static int ina2xx_probe(struct i2c_client *client)
+ 	}
+ 
+ 	indio_dev->modes = INDIO_DIRECT_MODE;
+-	if (id->driver_data == ina226) {
++	if (type == ina226) {
+ 		indio_dev->channels = ina226_channels;
+ 		indio_dev->num_channels = ARRAY_SIZE(ina226_channels);
+ 		indio_dev->info = &ina226_info;
+@@ -1024,7 +1027,7 @@ static int ina2xx_probe(struct i2c_client *client)
+ 		indio_dev->num_channels = ARRAY_SIZE(ina219_channels);
+ 		indio_dev->info = &ina219_info;
+ 	}
+-	indio_dev->name = id->name;
++	indio_dev->name = id ? id->name : chip->config->name;
+ 
+ 	ret = devm_iio_kfifo_buffer_setup(&client->dev, indio_dev,
+ 					  &ina2xx_setup_ops);
+diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c
+index af6bfcc190752..eb78a6f17fd07 100644
+--- a/drivers/iio/adc/meson_saradc.c
++++ b/drivers/iio/adc/meson_saradc.c
+@@ -916,12 +916,6 @@ static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev)
+ 		goto err_vref;
+ 	}
+ 
+-	ret = clk_prepare_enable(priv->core_clk);
+-	if (ret) {
+-		dev_err(dev, "failed to enable core clk\n");
+-		goto err_core_clk;
+-	}
+-
+ 	regval = FIELD_PREP(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, 1);
+ 	regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
+ 			   MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval);
+@@ -948,8 +942,6 @@ err_adc_clk:
+ 	regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3,
+ 			   MESON_SAR_ADC_REG3_ADC_EN, 0);
+ 	meson_sar_adc_set_bandgap(indio_dev, false);
+-	clk_disable_unprepare(priv->core_clk);
+-err_core_clk:
+ 	regulator_disable(priv->vref);
+ err_vref:
+ 	meson_sar_adc_unlock(indio_dev);
+@@ -977,8 +969,6 @@ static void meson_sar_adc_hw_disable(struct iio_dev *indio_dev)
+ 
+ 	meson_sar_adc_set_bandgap(indio_dev, false);
+ 
+-	clk_disable_unprepare(priv->core_clk);
+-
+ 	regulator_disable(priv->vref);
+ 
+ 	if (!ret)
+@@ -1211,7 +1201,7 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
+ 	if (IS_ERR(priv->clkin))
+ 		return dev_err_probe(dev, PTR_ERR(priv->clkin), "failed to get clkin\n");
+ 
+-	priv->core_clk = devm_clk_get(dev, "core");
++	priv->core_clk = devm_clk_get_enabled(dev, "core");
+ 	if (IS_ERR(priv->core_clk))
+ 		return dev_err_probe(dev, PTR_ERR(priv->core_clk), "failed to get core clk\n");
+ 
+@@ -1294,15 +1284,26 @@ static int meson_sar_adc_remove(struct platform_device *pdev)
+ static int meson_sar_adc_suspend(struct device *dev)
+ {
+ 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
++	struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
+ 
+ 	meson_sar_adc_hw_disable(indio_dev);
+ 
++	clk_disable_unprepare(priv->core_clk);
++
+ 	return 0;
+ }
+ 
+ static int meson_sar_adc_resume(struct device *dev)
+ {
+ 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
++	struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
++	int ret;
++
++	ret = clk_prepare_enable(priv->core_clk);
++	if (ret) {
++		dev_err(dev, "failed to enable core clk\n");
++		return ret;
++	}
+ 
+ 	return meson_sar_adc_hw_enable(indio_dev);
+ }
+diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
+index 943e9e14d1e99..b72d39fc2434e 100644
+--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
++++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
+@@ -253,7 +253,7 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
+ 	platform_set_drvdata(pdev, indio_dev);
+ 
+ 	state->ec = ec->ec_dev;
+-	state->msg = devm_kzalloc(&pdev->dev,
++	state->msg = devm_kzalloc(&pdev->dev, sizeof(*state->msg) +
+ 				max((u16)sizeof(struct ec_params_motion_sense),
+ 				state->ec->max_response), GFP_KERNEL);
+ 	if (!state->msg)
+diff --git a/drivers/iio/frequency/admv1013.c b/drivers/iio/frequency/admv1013.c
+index 9bf8337806fcf..8c8e0bbfc99f2 100644
+--- a/drivers/iio/frequency/admv1013.c
++++ b/drivers/iio/frequency/admv1013.c
+@@ -344,9 +344,12 @@ static int admv1013_update_quad_filters(struct admv1013_state *st)
+ 
+ static int admv1013_update_mixer_vgate(struct admv1013_state *st)
+ {
+-	unsigned int vcm, mixer_vgate;
++	unsigned int mixer_vgate;
++	int vcm;
+ 
+ 	vcm = regulator_get_voltage(st->reg);
++	if (vcm < 0)
++		return vcm;
+ 
+ 	if (vcm < 1800000)
+ 		mixer_vgate = (2389 * vcm / 1000000 + 8100) / 100;
+diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
+index 6a18b363cf73b..b6e6b1df8a618 100644
+--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
++++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
+@@ -2687,7 +2687,7 @@ unknown_format:
+ static int lsm6dsx_get_acpi_mount_matrix(struct device *dev,
+ 					  struct iio_mount_matrix *orientation)
+ {
+-	return false;
++	return -EOPNOTSUPP;
+ }
+ 
+ #endif
+diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
+index c117f50d0cf37..adcba832e6fa1 100644
+--- a/drivers/iio/industrialio-core.c
++++ b/drivers/iio/industrialio-core.c
+@@ -1888,7 +1888,7 @@ static const struct iio_buffer_setup_ops noop_ring_setup_ops;
+ int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod)
+ {
+ 	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
+-	struct fwnode_handle *fwnode;
++	struct fwnode_handle *fwnode = NULL;
+ 	int ret;
+ 
+ 	if (!indio_dev->info)
+@@ -1899,7 +1899,8 @@ int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod)
+ 	/* If the calling driver did not initialize firmware node, do it here */
+ 	if (dev_fwnode(&indio_dev->dev))
+ 		fwnode = dev_fwnode(&indio_dev->dev);
+-	else
++	/* The default dummy IIO device has no parent */
++	else if (indio_dev->dev.parent)
+ 		fwnode = dev_fwnode(indio_dev->dev.parent);
+ 	device_set_node(&indio_dev->dev, fwnode);
+ 
+diff --git a/drivers/iio/light/rohm-bu27034.c b/drivers/iio/light/rohm-bu27034.c
+index f85194fda6b09..021a622ad6116 100644
+--- a/drivers/iio/light/rohm-bu27034.c
++++ b/drivers/iio/light/rohm-bu27034.c
+@@ -575,7 +575,7 @@ static int bu27034_set_scale(struct bu27034_data *data, int chan,
+ 		return -EINVAL;
+ 
+ 	if (chan == BU27034_CHAN_ALS) {
+-		if (val == 0 && val2 == 1000)
++		if (val == 0 && val2 == 1000000)
+ 			return 0;
+ 
+ 		return -EINVAL;
+@@ -587,7 +587,7 @@ static int bu27034_set_scale(struct bu27034_data *data, int chan,
+ 		goto unlock_out;
+ 
+ 	ret = iio_gts_find_gain_sel_for_scale_using_time(&data->gts, time_sel,
+-						val, val2 * 1000, &gain_sel);
++						val, val2, &gain_sel);
+ 	if (ret) {
+ 		/*
+ 		 * Could not support scale with given time. Need to change time.
+@@ -624,7 +624,7 @@ static int bu27034_set_scale(struct bu27034_data *data, int chan,
+ 
+ 			/* Can we provide requested scale with this time? */
+ 			ret = iio_gts_find_gain_sel_for_scale_using_time(
+-				&data->gts, new_time_sel, val, val2 * 1000,
++				&data->gts, new_time_sel, val, val2,
+ 				&gain_sel);
+ 			if (ret)
+ 				continue;
+@@ -1217,6 +1217,21 @@ static int bu27034_read_raw(struct iio_dev *idev,
+ 	}
+ }
+ 
++static int bu27034_write_raw_get_fmt(struct iio_dev *indio_dev,
++				     struct iio_chan_spec const *chan,
++				     long mask)
++{
++
++	switch (mask) {
++	case IIO_CHAN_INFO_SCALE:
++		return IIO_VAL_INT_PLUS_NANO;
++	case IIO_CHAN_INFO_INT_TIME:
++		return IIO_VAL_INT_PLUS_MICRO;
++	default:
++		return -EINVAL;
++	}
++}
++
+ static int bu27034_write_raw(struct iio_dev *idev,
+ 			     struct iio_chan_spec const *chan,
+ 			     int val, int val2, long mask)
+@@ -1267,6 +1282,7 @@ static int bu27034_read_avail(struct iio_dev *idev,
+ static const struct iio_info bu27034_info = {
+ 	.read_raw = &bu27034_read_raw,
+ 	.write_raw = &bu27034_write_raw,
++	.write_raw_get_fmt = &bu27034_write_raw_get_fmt,
+ 	.read_avail = &bu27034_read_avail,
+ };
+ 
+diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
+index 755a9c57db6f3..f9ab671c8eda5 100644
+--- a/drivers/infiniband/core/umem.c
++++ b/drivers/infiniband/core/umem.c
+@@ -85,6 +85,8 @@ unsigned long ib_umem_find_best_pgsz(struct ib_umem *umem,
+ 	dma_addr_t mask;
+ 	int i;
+ 
++	umem->iova = va = virt;
++
+ 	if (umem->is_odp) {
+ 		unsigned int page_size = BIT(to_ib_umem_odp(umem)->page_shift);
+ 
+@@ -100,7 +102,6 @@ unsigned long ib_umem_find_best_pgsz(struct ib_umem *umem,
+ 	 */
+ 	pgsz_bitmap &= GENMASK(BITS_PER_LONG - 1, PAGE_SHIFT);
+ 
+-	umem->iova = va = virt;
+ 	/* The best result is the smallest page size that results in the minimum
+ 	 * number of required pages. Compute the largest page size that could
+ 	 * work based on VA address bits that don't change.
+diff --git a/drivers/infiniband/hw/bnxt_re/main.c b/drivers/infiniband/hw/bnxt_re/main.c
+index 1936f4b4002a7..4f00fb7869f8e 100644
+--- a/drivers/infiniband/hw/bnxt_re/main.c
++++ b/drivers/infiniband/hw/bnxt_re/main.c
+@@ -1152,6 +1152,8 @@ static int bnxt_re_dev_init(struct bnxt_re_dev *rdev, u8 wqe_mode)
+ 
+ 	rc = bnxt_re_setup_chip_ctx(rdev, wqe_mode);
+ 	if (rc) {
++		bnxt_unregister_dev(rdev->en_dev);
++		clear_bit(BNXT_RE_FLAG_NETDEV_REGISTERED, &rdev->flags);
+ 		ibdev_err(&rdev->ibdev, "Failed to get chip context\n");
+ 		return -EINVAL;
+ 	}
+@@ -1425,8 +1427,8 @@ static void bnxt_re_remove(struct auxiliary_device *adev)
+ 	}
+ 	bnxt_re_setup_cc(rdev, false);
+ 	ib_unregister_device(&rdev->ibdev);
+-	ib_dealloc_device(&rdev->ibdev);
+ 	bnxt_re_dev_uninit(rdev);
++	ib_dealloc_device(&rdev->ibdev);
+ skip_remove:
+ 	mutex_unlock(&bnxt_re_mutex);
+ }
+diff --git a/drivers/infiniband/hw/hfi1/chip.c b/drivers/infiniband/hw/hfi1/chip.c
+index 9dbb89e9f4afc..baaa4406d5e60 100644
+--- a/drivers/infiniband/hw/hfi1/chip.c
++++ b/drivers/infiniband/hw/hfi1/chip.c
+@@ -12307,6 +12307,7 @@ static void free_cntrs(struct hfi1_devdata *dd)
+ 
+ 	if (dd->synth_stats_timer.function)
+ 		del_timer_sync(&dd->synth_stats_timer);
++	cancel_work_sync(&dd->update_cntr_work);
+ 	ppd = (struct hfi1_pportdata *)(dd + 1);
+ 	for (i = 0; i < dd->num_pports; i++, ppd++) {
+ 		kfree(ppd->cntrs);
+diff --git a/drivers/interconnect/qcom/bcm-voter.c b/drivers/interconnect/qcom/bcm-voter.c
+index 8f385f9c2dd38..d5f2a6b5376bd 100644
+--- a/drivers/interconnect/qcom/bcm-voter.c
++++ b/drivers/interconnect/qcom/bcm-voter.c
+@@ -83,6 +83,11 @@ static void bcm_aggregate(struct qcom_icc_bcm *bcm)
+ 
+ 		temp = agg_peak[bucket] * bcm->vote_scale;
+ 		bcm->vote_y[bucket] = bcm_div(temp, bcm->aux_data.unit);
++
++		if (bcm->enable_mask && (bcm->vote_x[bucket] || bcm->vote_y[bucket])) {
++			bcm->vote_x[bucket] = 0;
++			bcm->vote_y[bucket] = bcm->enable_mask;
++		}
+ 	}
+ 
+ 	if (bcm->keepalive && bcm->vote_x[QCOM_ICC_BUCKET_AMC] == 0 &&
+diff --git a/drivers/interconnect/qcom/icc-rpmh.h b/drivers/interconnect/qcom/icc-rpmh.h
+index 04391c1ba465c..7843d8864d6ba 100644
+--- a/drivers/interconnect/qcom/icc-rpmh.h
++++ b/drivers/interconnect/qcom/icc-rpmh.h
+@@ -81,6 +81,7 @@ struct qcom_icc_node {
+  * @vote_x: aggregated threshold values, represents sum_bw when @type is bw bcm
+  * @vote_y: aggregated threshold values, represents peak_bw when @type is bw bcm
+  * @vote_scale: scaling factor for vote_x and vote_y
++ * @enable_mask: optional mask to send as vote instead of vote_x/vote_y
+  * @dirty: flag used to indicate whether the bcm needs to be committed
+  * @keepalive: flag used to indicate whether a keepalive is required
+  * @aux_data: auxiliary data used when calculating threshold values and
+@@ -97,6 +98,7 @@ struct qcom_icc_bcm {
+ 	u64 vote_x[QCOM_ICC_NUM_BUCKETS];
+ 	u64 vote_y[QCOM_ICC_NUM_BUCKETS];
+ 	u64 vote_scale;
++	u32 enable_mask;
+ 	bool dirty;
+ 	bool keepalive;
+ 	struct bcm_db aux_data;
+diff --git a/drivers/interconnect/qcom/sa8775p.c b/drivers/interconnect/qcom/sa8775p.c
+index da21cc31a5808..f56538669de0e 100644
+--- a/drivers/interconnect/qcom/sa8775p.c
++++ b/drivers/interconnect/qcom/sa8775p.c
+@@ -1873,6 +1873,7 @@ static struct qcom_icc_node srvc_snoc = {
+ 
+ static struct qcom_icc_bcm bcm_acv = {
+ 	.name = "ACV",
++	.enable_mask = 0x8,
+ 	.num_nodes = 1,
+ 	.nodes = { &ebi },
+ };
+diff --git a/drivers/interconnect/qcom/sm8450.c b/drivers/interconnect/qcom/sm8450.c
+index 2d7a8e7b85ec2..e64c214b40209 100644
+--- a/drivers/interconnect/qcom/sm8450.c
++++ b/drivers/interconnect/qcom/sm8450.c
+@@ -1337,6 +1337,7 @@ static struct qcom_icc_node qns_mem_noc_sf_disp = {
+ 
+ static struct qcom_icc_bcm bcm_acv = {
+ 	.name = "ACV",
++	.enable_mask = 0x8,
+ 	.num_nodes = 1,
+ 	.nodes = { &ebi },
+ };
+@@ -1349,6 +1350,7 @@ static struct qcom_icc_bcm bcm_ce0 = {
+ 
+ static struct qcom_icc_bcm bcm_cn0 = {
+ 	.name = "CN0",
++	.enable_mask = 0x1,
+ 	.keepalive = true,
+ 	.num_nodes = 55,
+ 	.nodes = { &qnm_gemnoc_cnoc, &qnm_gemnoc_pcie,
+@@ -1383,6 +1385,7 @@ static struct qcom_icc_bcm bcm_cn0 = {
+ 
+ static struct qcom_icc_bcm bcm_co0 = {
+ 	.name = "CO0",
++	.enable_mask = 0x1,
+ 	.num_nodes = 2,
+ 	.nodes = { &qxm_nsp, &qns_nsp_gemnoc },
+ };
+@@ -1403,6 +1406,7 @@ static struct qcom_icc_bcm bcm_mm0 = {
+ 
+ static struct qcom_icc_bcm bcm_mm1 = {
+ 	.name = "MM1",
++	.enable_mask = 0x1,
+ 	.num_nodes = 12,
+ 	.nodes = { &qnm_camnoc_hf, &qnm_camnoc_icp,
+ 		   &qnm_camnoc_sf, &qnm_mdp,
+@@ -1445,6 +1449,7 @@ static struct qcom_icc_bcm bcm_sh0 = {
+ 
+ static struct qcom_icc_bcm bcm_sh1 = {
+ 	.name = "SH1",
++	.enable_mask = 0x1,
+ 	.num_nodes = 7,
+ 	.nodes = { &alm_gpu_tcu, &alm_sys_tcu,
+ 		   &qnm_nsp_gemnoc, &qnm_pcie,
+@@ -1461,6 +1466,7 @@ static struct qcom_icc_bcm bcm_sn0 = {
+ 
+ static struct qcom_icc_bcm bcm_sn1 = {
+ 	.name = "SN1",
++	.enable_mask = 0x1,
+ 	.num_nodes = 4,
+ 	.nodes = { &qhm_gic, &qxm_pimem,
+ 		   &xm_gic, &qns_gemnoc_gc },
+@@ -1492,6 +1498,7 @@ static struct qcom_icc_bcm bcm_sn7 = {
+ 
+ static struct qcom_icc_bcm bcm_acv_disp = {
+ 	.name = "ACV",
++	.enable_mask = 0x1,
+ 	.num_nodes = 1,
+ 	.nodes = { &ebi_disp },
+ };
+@@ -1510,6 +1517,7 @@ static struct qcom_icc_bcm bcm_mm0_disp = {
+ 
+ static struct qcom_icc_bcm bcm_mm1_disp = {
+ 	.name = "MM1",
++	.enable_mask = 0x1,
+ 	.num_nodes = 3,
+ 	.nodes = { &qnm_mdp_disp, &qnm_rot_disp,
+ 		   &qns_mem_noc_sf_disp },
+@@ -1523,6 +1531,7 @@ static struct qcom_icc_bcm bcm_sh0_disp = {
+ 
+ static struct qcom_icc_bcm bcm_sh1_disp = {
+ 	.name = "SH1",
++	.enable_mask = 0x1,
+ 	.num_nodes = 1,
+ 	.nodes = { &qnm_pcie_disp },
+ };
+diff --git a/drivers/interconnect/qcom/sm8550.c b/drivers/interconnect/qcom/sm8550.c
+index d823ba988ef68..0864ed285375e 100644
+--- a/drivers/interconnect/qcom/sm8550.c
++++ b/drivers/interconnect/qcom/sm8550.c
+@@ -1473,6 +1473,7 @@ static struct qcom_icc_node qns_mem_noc_sf_cam_ife_2 = {
+ 
+ static struct qcom_icc_bcm bcm_acv = {
+ 	.name = "ACV",
++	.enable_mask = 0x8,
+ 	.num_nodes = 1,
+ 	.nodes = { &ebi },
+ };
+@@ -1485,6 +1486,7 @@ static struct qcom_icc_bcm bcm_ce0 = {
+ 
+ static struct qcom_icc_bcm bcm_cn0 = {
+ 	.name = "CN0",
++	.enable_mask = 0x1,
+ 	.keepalive = true,
+ 	.num_nodes = 54,
+ 	.nodes = { &qsm_cfg, &qhs_ahb2phy0,
+@@ -1524,6 +1526,7 @@ static struct qcom_icc_bcm bcm_cn1 = {
+ 
+ static struct qcom_icc_bcm bcm_co0 = {
+ 	.name = "CO0",
++	.enable_mask = 0x1,
+ 	.num_nodes = 2,
+ 	.nodes = { &qxm_nsp, &qns_nsp_gemnoc },
+ };
+@@ -1549,6 +1552,7 @@ static struct qcom_icc_bcm bcm_mm0 = {
+ 
+ static struct qcom_icc_bcm bcm_mm1 = {
+ 	.name = "MM1",
++	.enable_mask = 0x1,
+ 	.num_nodes = 8,
+ 	.nodes = { &qnm_camnoc_hf, &qnm_camnoc_icp,
+ 		   &qnm_camnoc_sf, &qnm_vapss_hcp,
+@@ -1589,6 +1593,7 @@ static struct qcom_icc_bcm bcm_sh0 = {
+ 
+ static struct qcom_icc_bcm bcm_sh1 = {
+ 	.name = "SH1",
++	.enable_mask = 0x1,
+ 	.num_nodes = 13,
+ 	.nodes = { &alm_gpu_tcu, &alm_sys_tcu,
+ 		   &chm_apps, &qnm_gpu,
+@@ -1608,6 +1613,7 @@ static struct qcom_icc_bcm bcm_sn0 = {
+ 
+ static struct qcom_icc_bcm bcm_sn1 = {
+ 	.name = "SN1",
++	.enable_mask = 0x1,
+ 	.num_nodes = 3,
+ 	.nodes = { &qhm_gic, &xm_gic,
+ 		   &qns_gemnoc_gc },
+@@ -1633,6 +1639,7 @@ static struct qcom_icc_bcm bcm_sn7 = {
+ 
+ static struct qcom_icc_bcm bcm_acv_disp = {
+ 	.name = "ACV",
++	.enable_mask = 0x1,
+ 	.num_nodes = 1,
+ 	.nodes = { &ebi_disp },
+ };
+@@ -1657,12 +1664,14 @@ static struct qcom_icc_bcm bcm_sh0_disp = {
+ 
+ static struct qcom_icc_bcm bcm_sh1_disp = {
+ 	.name = "SH1",
++	.enable_mask = 0x1,
+ 	.num_nodes = 2,
+ 	.nodes = { &qnm_mnoc_hf_disp, &qnm_pcie_disp },
+ };
+ 
+ static struct qcom_icc_bcm bcm_acv_cam_ife_0 = {
+ 	.name = "ACV",
++	.enable_mask = 0x0,
+ 	.num_nodes = 1,
+ 	.nodes = { &ebi_cam_ife_0 },
+ };
+@@ -1681,6 +1690,7 @@ static struct qcom_icc_bcm bcm_mm0_cam_ife_0 = {
+ 
+ static struct qcom_icc_bcm bcm_mm1_cam_ife_0 = {
+ 	.name = "MM1",
++	.enable_mask = 0x1,
+ 	.num_nodes = 4,
+ 	.nodes = { &qnm_camnoc_hf_cam_ife_0, &qnm_camnoc_icp_cam_ife_0,
+ 		   &qnm_camnoc_sf_cam_ife_0, &qns_mem_noc_sf_cam_ife_0 },
+@@ -1694,6 +1704,7 @@ static struct qcom_icc_bcm bcm_sh0_cam_ife_0 = {
+ 
+ static struct qcom_icc_bcm bcm_sh1_cam_ife_0 = {
+ 	.name = "SH1",
++	.enable_mask = 0x1,
+ 	.num_nodes = 3,
+ 	.nodes = { &qnm_mnoc_hf_cam_ife_0, &qnm_mnoc_sf_cam_ife_0,
+ 		   &qnm_pcie_cam_ife_0 },
+@@ -1701,6 +1712,7 @@ static struct qcom_icc_bcm bcm_sh1_cam_ife_0 = {
+ 
+ static struct qcom_icc_bcm bcm_acv_cam_ife_1 = {
+ 	.name = "ACV",
++	.enable_mask = 0x0,
+ 	.num_nodes = 1,
+ 	.nodes = { &ebi_cam_ife_1 },
+ };
+@@ -1719,6 +1731,7 @@ static struct qcom_icc_bcm bcm_mm0_cam_ife_1 = {
+ 
+ static struct qcom_icc_bcm bcm_mm1_cam_ife_1 = {
+ 	.name = "MM1",
++	.enable_mask = 0x1,
+ 	.num_nodes = 4,
+ 	.nodes = { &qnm_camnoc_hf_cam_ife_1, &qnm_camnoc_icp_cam_ife_1,
+ 		   &qnm_camnoc_sf_cam_ife_1, &qns_mem_noc_sf_cam_ife_1 },
+@@ -1732,6 +1745,7 @@ static struct qcom_icc_bcm bcm_sh0_cam_ife_1 = {
+ 
+ static struct qcom_icc_bcm bcm_sh1_cam_ife_1 = {
+ 	.name = "SH1",
++	.enable_mask = 0x1,
+ 	.num_nodes = 3,
+ 	.nodes = { &qnm_mnoc_hf_cam_ife_1, &qnm_mnoc_sf_cam_ife_1,
+ 		   &qnm_pcie_cam_ife_1 },
+@@ -1739,6 +1753,7 @@ static struct qcom_icc_bcm bcm_sh1_cam_ife_1 = {
+ 
+ static struct qcom_icc_bcm bcm_acv_cam_ife_2 = {
+ 	.name = "ACV",
++	.enable_mask = 0x0,
+ 	.num_nodes = 1,
+ 	.nodes = { &ebi_cam_ife_2 },
+ };
+@@ -1757,6 +1772,7 @@ static struct qcom_icc_bcm bcm_mm0_cam_ife_2 = {
+ 
+ static struct qcom_icc_bcm bcm_mm1_cam_ife_2 = {
+ 	.name = "MM1",
++	.enable_mask = 0x1,
+ 	.num_nodes = 4,
+ 	.nodes = { &qnm_camnoc_hf_cam_ife_2, &qnm_camnoc_icp_cam_ife_2,
+ 		   &qnm_camnoc_sf_cam_ife_2, &qns_mem_noc_sf_cam_ife_2 },
+@@ -1770,6 +1786,7 @@ static struct qcom_icc_bcm bcm_sh0_cam_ife_2 = {
+ 
+ static struct qcom_icc_bcm bcm_sh1_cam_ife_2 = {
+ 	.name = "SH1",
++	.enable_mask = 0x1,
+ 	.num_nodes = 3,
+ 	.nodes = { &qnm_mnoc_hf_cam_ife_2, &qnm_mnoc_sf_cam_ife_2,
+ 		   &qnm_pcie_cam_ife_2 },
+diff --git a/drivers/isdn/mISDN/dsp.h b/drivers/isdn/mISDN/dsp.h
+index fa09d511a8eda..baf31258f5c90 100644
+--- a/drivers/isdn/mISDN/dsp.h
++++ b/drivers/isdn/mISDN/dsp.h
+@@ -247,7 +247,7 @@ extern void dsp_cmx_hardware(struct dsp_conf *conf, struct dsp *dsp);
+ extern int dsp_cmx_conf(struct dsp *dsp, u32 conf_id);
+ extern void dsp_cmx_receive(struct dsp *dsp, struct sk_buff *skb);
+ extern void dsp_cmx_hdlc(struct dsp *dsp, struct sk_buff *skb);
+-extern void dsp_cmx_send(void *arg);
++extern void dsp_cmx_send(struct timer_list *arg);
+ extern void dsp_cmx_transmit(struct dsp *dsp, struct sk_buff *skb);
+ extern int dsp_cmx_del_conf_member(struct dsp *dsp);
+ extern int dsp_cmx_del_conf(struct dsp_conf *conf);
+diff --git a/drivers/isdn/mISDN/dsp_cmx.c b/drivers/isdn/mISDN/dsp_cmx.c
+index 357b87592eb48..61cb45c5d0d84 100644
+--- a/drivers/isdn/mISDN/dsp_cmx.c
++++ b/drivers/isdn/mISDN/dsp_cmx.c
+@@ -1614,7 +1614,7 @@ static u16	dsp_count; /* last sample count */
+ static int	dsp_count_valid; /* if we have last sample count */
+ 
+ void
+-dsp_cmx_send(void *arg)
++dsp_cmx_send(struct timer_list *arg)
+ {
+ 	struct dsp_conf *conf;
+ 	struct dsp_conf_member *member;
+diff --git a/drivers/isdn/mISDN/dsp_core.c b/drivers/isdn/mISDN/dsp_core.c
+index 386084530c2f8..fae95f1666883 100644
+--- a/drivers/isdn/mISDN/dsp_core.c
++++ b/drivers/isdn/mISDN/dsp_core.c
+@@ -1195,7 +1195,7 @@ static int __init dsp_init(void)
+ 	}
+ 
+ 	/* set sample timer */
+-	timer_setup(&dsp_spl_tl, (void *)dsp_cmx_send, 0);
++	timer_setup(&dsp_spl_tl, dsp_cmx_send, 0);
+ 	dsp_spl_tl.expires = jiffies + dsp_tics;
+ 	dsp_spl_jiffies = dsp_spl_tl.expires;
+ 	add_timer(&dsp_spl_tl);
+diff --git a/drivers/misc/cardreader/rts5227.c b/drivers/misc/cardreader/rts5227.c
+index d676cf63a9669..3dae5e3a16976 100644
+--- a/drivers/misc/cardreader/rts5227.c
++++ b/drivers/misc/cardreader/rts5227.c
+@@ -195,7 +195,7 @@ static int rts5227_extra_init_hw(struct rtsx_pcr *pcr)
+ 		}
+ 	}
+ 
+-	if (option->force_clkreq_0)
++	if (option->force_clkreq_0 && pcr->aspm_mode == ASPM_MODE_CFG)
+ 		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG,
+ 				FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW);
+ 	else
+diff --git a/drivers/misc/cardreader/rts5228.c b/drivers/misc/cardreader/rts5228.c
+index cfebad51d1d80..f4ab09439da70 100644
+--- a/drivers/misc/cardreader/rts5228.c
++++ b/drivers/misc/cardreader/rts5228.c
+@@ -435,17 +435,10 @@ static void rts5228_init_from_cfg(struct rtsx_pcr *pcr)
+ 			option->ltr_enabled = false;
+ 		}
+ 	}
+-
+-	if (rtsx_check_dev_flag(pcr, ASPM_L1_1_EN | ASPM_L1_2_EN
+-				| PM_L1_1_EN | PM_L1_2_EN))
+-		option->force_clkreq_0 = false;
+-	else
+-		option->force_clkreq_0 = true;
+ }
+ 
+ static int rts5228_extra_init_hw(struct rtsx_pcr *pcr)
+ {
+-	struct rtsx_cr_option *option = &pcr->option;
+ 
+ 	rtsx_pci_write_register(pcr, RTS5228_AUTOLOAD_CFG1,
+ 			CD_RESUME_EN_MASK, CD_RESUME_EN_MASK);
+@@ -476,17 +469,6 @@ static int rts5228_extra_init_hw(struct rtsx_pcr *pcr)
+ 	else
+ 		rtsx_pci_write_register(pcr, PETXCFG, 0x30, 0x00);
+ 
+-	/*
+-	 * If u_force_clkreq_0 is enabled, CLKREQ# PIN will be forced
+-	 * to drive low, and we forcibly request clock.
+-	 */
+-	if (option->force_clkreq_0)
+-		rtsx_pci_write_register(pcr, PETXCFG,
+-				 FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW);
+-	else
+-		rtsx_pci_write_register(pcr, PETXCFG,
+-				 FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_HIGH);
+-
+ 	rtsx_pci_write_register(pcr, PWD_SUSPEND_EN, 0xFF, 0xFB);
+ 
+ 	if (pcr->rtd3_en) {
+diff --git a/drivers/misc/cardreader/rts5249.c b/drivers/misc/cardreader/rts5249.c
+index 91d240dd68faa..47ab72a43256b 100644
+--- a/drivers/misc/cardreader/rts5249.c
++++ b/drivers/misc/cardreader/rts5249.c
+@@ -327,12 +327,11 @@ static int rts5249_extra_init_hw(struct rtsx_pcr *pcr)
+ 		}
+ 	}
+ 
+-
+ 	/*
+ 	 * If u_force_clkreq_0 is enabled, CLKREQ# PIN will be forced
+ 	 * to drive low, and we forcibly request clock.
+ 	 */
+-	if (option->force_clkreq_0)
++	if (option->force_clkreq_0 && pcr->aspm_mode == ASPM_MODE_CFG)
+ 		rtsx_pci_write_register(pcr, PETXCFG,
+ 			FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW);
+ 	else
+diff --git a/drivers/misc/cardreader/rts5260.c b/drivers/misc/cardreader/rts5260.c
+index 9b42b20a3e5ae..79b18f6f73a8a 100644
+--- a/drivers/misc/cardreader/rts5260.c
++++ b/drivers/misc/cardreader/rts5260.c
+@@ -517,17 +517,10 @@ static void rts5260_init_from_cfg(struct rtsx_pcr *pcr)
+ 			option->ltr_enabled = false;
+ 		}
+ 	}
+-
+-	if (rtsx_check_dev_flag(pcr, ASPM_L1_1_EN | ASPM_L1_2_EN
+-				| PM_L1_1_EN | PM_L1_2_EN))
+-		option->force_clkreq_0 = false;
+-	else
+-		option->force_clkreq_0 = true;
+ }
+ 
+ static int rts5260_extra_init_hw(struct rtsx_pcr *pcr)
+ {
+-	struct rtsx_cr_option *option = &pcr->option;
+ 
+ 	/* Set mcu_cnt to 7 to ensure data can be sampled properly */
+ 	rtsx_pci_write_register(pcr, 0xFC03, 0x7F, 0x07);
+@@ -546,17 +539,6 @@ static int rts5260_extra_init_hw(struct rtsx_pcr *pcr)
+ 
+ 	rts5260_init_hw(pcr);
+ 
+-	/*
+-	 * If u_force_clkreq_0 is enabled, CLKREQ# PIN will be forced
+-	 * to drive low, and we forcibly request clock.
+-	 */
+-	if (option->force_clkreq_0)
+-		rtsx_pci_write_register(pcr, PETXCFG,
+-				 FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW);
+-	else
+-		rtsx_pci_write_register(pcr, PETXCFG,
+-				 FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_HIGH);
+-
+ 	rtsx_pci_write_register(pcr, pcr->reg_pm_ctrl3, 0x10, 0x00);
+ 
+ 	return 0;
+diff --git a/drivers/misc/cardreader/rts5261.c b/drivers/misc/cardreader/rts5261.c
+index b1e76030cafda..94af6bf8a25a6 100644
+--- a/drivers/misc/cardreader/rts5261.c
++++ b/drivers/misc/cardreader/rts5261.c
+@@ -498,17 +498,10 @@ static void rts5261_init_from_cfg(struct rtsx_pcr *pcr)
+ 			option->ltr_enabled = false;
+ 		}
+ 	}
+-
+-	if (rtsx_check_dev_flag(pcr, ASPM_L1_1_EN | ASPM_L1_2_EN
+-				| PM_L1_1_EN | PM_L1_2_EN))
+-		option->force_clkreq_0 = false;
+-	else
+-		option->force_clkreq_0 = true;
+ }
+ 
+ static int rts5261_extra_init_hw(struct rtsx_pcr *pcr)
+ {
+-	struct rtsx_cr_option *option = &pcr->option;
+ 	u32 val;
+ 
+ 	rtsx_pci_write_register(pcr, RTS5261_AUTOLOAD_CFG1,
+@@ -554,17 +547,6 @@ static int rts5261_extra_init_hw(struct rtsx_pcr *pcr)
+ 	else
+ 		rtsx_pci_write_register(pcr, PETXCFG, 0x30, 0x00);
+ 
+-	/*
+-	 * If u_force_clkreq_0 is enabled, CLKREQ# PIN will be forced
+-	 * to drive low, and we forcibly request clock.
+-	 */
+-	if (option->force_clkreq_0)
+-		rtsx_pci_write_register(pcr, PETXCFG,
+-				 FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW);
+-	else
+-		rtsx_pci_write_register(pcr, PETXCFG,
+-				 FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_HIGH);
+-
+ 	rtsx_pci_write_register(pcr, PWD_SUSPEND_EN, 0xFF, 0xFB);
+ 
+ 	if (pcr->rtd3_en) {
+diff --git a/drivers/misc/cardreader/rtsx_pcr.c b/drivers/misc/cardreader/rtsx_pcr.c
+index 32b7783e9d4fa..a3f4b52bb159f 100644
+--- a/drivers/misc/cardreader/rtsx_pcr.c
++++ b/drivers/misc/cardreader/rtsx_pcr.c
+@@ -1326,8 +1326,11 @@ static int rtsx_pci_init_hw(struct rtsx_pcr *pcr)
+ 			return err;
+ 	}
+ 
+-	if (pcr->aspm_mode == ASPM_MODE_REG)
++	if (pcr->aspm_mode == ASPM_MODE_REG) {
+ 		rtsx_pci_write_register(pcr, ASPM_FORCE_CTL, 0x30, 0x30);
++		rtsx_pci_write_register(pcr, PETXCFG,
++				FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_HIGH);
++	}
+ 
+ 	/* No CD interrupt if probing driver with card inserted.
+ 	 * So we need to initialize pcr->card_exist here.
+diff --git a/drivers/mmc/host/moxart-mmc.c b/drivers/mmc/host/moxart-mmc.c
+index 2d002c81dcf36..d0d6ffcf78d40 100644
+--- a/drivers/mmc/host/moxart-mmc.c
++++ b/drivers/mmc/host/moxart-mmc.c
+@@ -338,13 +338,7 @@ static void moxart_transfer_pio(struct moxart_host *host)
+ 				return;
+ 			}
+ 			for (len = 0; len < remain && len < host->fifo_width;) {
+-				/* SCR data must be read in big endian. */
+-				if (data->mrq->cmd->opcode == SD_APP_SEND_SCR)
+-					*sgp = ioread32be(host->base +
+-							  REG_DATA_WINDOW);
+-				else
+-					*sgp = ioread32(host->base +
+-							REG_DATA_WINDOW);
++				*sgp = ioread32(host->base + REG_DATA_WINDOW);
+ 				sgp++;
+ 				len += 4;
+ 			}
+diff --git a/drivers/mmc/host/sdhci_f_sdh30.c b/drivers/mmc/host/sdhci_f_sdh30.c
+index a202a69a4b084..b01ffb4d09737 100644
+--- a/drivers/mmc/host/sdhci_f_sdh30.c
++++ b/drivers/mmc/host/sdhci_f_sdh30.c
+@@ -29,9 +29,16 @@ struct f_sdhost_priv {
+ 	bool enable_cmd_dat_delay;
+ };
+ 
++static void *sdhci_f_sdhost_priv(struct sdhci_host *host)
++{
++	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
++
++	return sdhci_pltfm_priv(pltfm_host);
++}
++
+ static void sdhci_f_sdh30_soft_voltage_switch(struct sdhci_host *host)
+ {
+-	struct f_sdhost_priv *priv = sdhci_priv(host);
++	struct f_sdhost_priv *priv = sdhci_f_sdhost_priv(host);
+ 	u32 ctrl = 0;
+ 
+ 	usleep_range(2500, 3000);
+@@ -64,7 +71,7 @@ static unsigned int sdhci_f_sdh30_get_min_clock(struct sdhci_host *host)
+ 
+ static void sdhci_f_sdh30_reset(struct sdhci_host *host, u8 mask)
+ {
+-	struct f_sdhost_priv *priv = sdhci_priv(host);
++	struct f_sdhost_priv *priv = sdhci_f_sdhost_priv(host);
+ 	u32 ctl;
+ 
+ 	if (sdhci_readw(host, SDHCI_CLOCK_CONTROL) == 0)
+@@ -95,30 +102,32 @@ static const struct sdhci_ops sdhci_f_sdh30_ops = {
+ 	.set_uhs_signaling = sdhci_set_uhs_signaling,
+ };
+ 
++static const struct sdhci_pltfm_data sdhci_f_sdh30_pltfm_data = {
++	.ops = &sdhci_f_sdh30_ops,
++	.quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC
++		| SDHCI_QUIRK_INVERTED_WRITE_PROTECT,
++	.quirks2 = SDHCI_QUIRK2_SUPPORT_SINGLE
++		|  SDHCI_QUIRK2_TUNING_WORK_AROUND,
++};
++
+ static int sdhci_f_sdh30_probe(struct platform_device *pdev)
+ {
+ 	struct sdhci_host *host;
+ 	struct device *dev = &pdev->dev;
+-	int irq, ctrl = 0, ret = 0;
++	int ctrl = 0, ret = 0;
+ 	struct f_sdhost_priv *priv;
++	struct sdhci_pltfm_host *pltfm_host;
+ 	u32 reg = 0;
+ 
+-	irq = platform_get_irq(pdev, 0);
+-	if (irq < 0)
+-		return irq;
+-
+-	host = sdhci_alloc_host(dev, sizeof(struct f_sdhost_priv));
++	host = sdhci_pltfm_init(pdev, &sdhci_f_sdh30_pltfm_data,
++				sizeof(struct f_sdhost_priv));
+ 	if (IS_ERR(host))
+ 		return PTR_ERR(host);
+ 
+-	priv = sdhci_priv(host);
++	pltfm_host = sdhci_priv(host);
++	priv = sdhci_pltfm_priv(pltfm_host);
+ 	priv->dev = dev;
+ 
+-	host->quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC |
+-		       SDHCI_QUIRK_INVERTED_WRITE_PROTECT;
+-	host->quirks2 = SDHCI_QUIRK2_SUPPORT_SINGLE |
+-			SDHCI_QUIRK2_TUNING_WORK_AROUND;
+-
+ 	priv->enable_cmd_dat_delay = device_property_read_bool(dev,
+ 						"fujitsu,cmd-dat-delay-select");
+ 
+@@ -126,18 +135,6 @@ static int sdhci_f_sdh30_probe(struct platform_device *pdev)
+ 	if (ret)
+ 		goto err;
+ 
+-	platform_set_drvdata(pdev, host);
+-
+-	host->hw_name = "f_sdh30";
+-	host->ops = &sdhci_f_sdh30_ops;
+-	host->irq = irq;
+-
+-	host->ioaddr = devm_platform_ioremap_resource(pdev, 0);
+-	if (IS_ERR(host->ioaddr)) {
+-		ret = PTR_ERR(host->ioaddr);
+-		goto err;
+-	}
+-
+ 	if (dev_of_node(dev)) {
+ 		sdhci_get_of_property(pdev);
+ 
+@@ -204,24 +201,21 @@ err_rst:
+ err_clk:
+ 	clk_disable_unprepare(priv->clk_iface);
+ err:
+-	sdhci_free_host(host);
++	sdhci_pltfm_free(pdev);
++
+ 	return ret;
+ }
+ 
+ static int sdhci_f_sdh30_remove(struct platform_device *pdev)
+ {
+ 	struct sdhci_host *host = platform_get_drvdata(pdev);
+-	struct f_sdhost_priv *priv = sdhci_priv(host);
+-
+-	sdhci_remove_host(host, readl(host->ioaddr + SDHCI_INT_STATUS) ==
+-			  0xffffffff);
++	struct f_sdhost_priv *priv = sdhci_f_sdhost_priv(host);
+ 
+ 	reset_control_assert(priv->rst);
+ 	clk_disable_unprepare(priv->clk);
+ 	clk_disable_unprepare(priv->clk_iface);
+ 
+-	sdhci_free_host(host);
+-	platform_set_drvdata(pdev, NULL);
++	sdhci_pltfm_unregister(pdev);
+ 
+ 	return 0;
+ }
+diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
+index 1a0776f9b008a..7be484f2c9264 100644
+--- a/drivers/net/bonding/bond_main.c
++++ b/drivers/net/bonding/bond_main.c
+@@ -5898,7 +5898,9 @@ void bond_setup(struct net_device *bond_dev)
+ 
+ 	bond_dev->hw_features = BOND_VLAN_FEATURES |
+ 				NETIF_F_HW_VLAN_CTAG_RX |
+-				NETIF_F_HW_VLAN_CTAG_FILTER;
++				NETIF_F_HW_VLAN_CTAG_FILTER |
++				NETIF_F_HW_VLAN_STAG_RX |
++				NETIF_F_HW_VLAN_STAG_FILTER;
+ 
+ 	bond_dev->hw_features |= NETIF_F_GSO_ENCAP_ALL;
+ 	bond_dev->features |= bond_dev->hw_features;
+diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c
+index d78b4bd4787e8..b090b4408e3a0 100644
+--- a/drivers/net/dsa/ocelot/felix.c
++++ b/drivers/net/dsa/ocelot/felix.c
+@@ -1625,8 +1625,10 @@ static void felix_teardown(struct dsa_switch *ds)
+ 	struct felix *felix = ocelot_to_felix(ocelot);
+ 	struct dsa_port *dp;
+ 
++	rtnl_lock();
+ 	if (felix->tag_proto_ops)
+ 		felix->tag_proto_ops->teardown(ds);
++	rtnl_unlock();
+ 
+ 	dsa_switch_for_each_available_port(dp, ds)
+ 		ocelot_deinit_port(ocelot, dp->index);
+diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+index 7cd22d370caa3..4b371fbe67eac 100644
+--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
++++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+@@ -1222,50 +1222,81 @@ static int enetc_pf_register_with_ierb(struct pci_dev *pdev)
+ 	return enetc_ierb_register_pf(ierb_pdev, pdev);
+ }
+ 
+-static int enetc_pf_probe(struct pci_dev *pdev,
+-			  const struct pci_device_id *ent)
++static struct enetc_si *enetc_psi_create(struct pci_dev *pdev)
+ {
+-	struct device_node *node = pdev->dev.of_node;
+-	struct enetc_ndev_priv *priv;
+-	struct net_device *ndev;
+ 	struct enetc_si *si;
+-	struct enetc_pf *pf;
+ 	int err;
+ 
+-	err = enetc_pf_register_with_ierb(pdev);
+-	if (err == -EPROBE_DEFER)
+-		return err;
+-	if (err)
+-		dev_warn(&pdev->dev,
+-			 "Could not register with IERB driver: %pe, please update the device tree\n",
+-			 ERR_PTR(err));
+-
+-	err = enetc_pci_probe(pdev, KBUILD_MODNAME, sizeof(*pf));
+-	if (err)
+-		return dev_err_probe(&pdev->dev, err, "PCI probing failed\n");
++	err = enetc_pci_probe(pdev, KBUILD_MODNAME, sizeof(struct enetc_pf));
++	if (err) {
++		dev_err_probe(&pdev->dev, err, "PCI probing failed\n");
++		goto out;
++	}
+ 
+ 	si = pci_get_drvdata(pdev);
+ 	if (!si->hw.port || !si->hw.global) {
+ 		err = -ENODEV;
+ 		dev_err(&pdev->dev, "could not map PF space, probing a VF?\n");
+-		goto err_map_pf_space;
++		goto out_pci_remove;
+ 	}
+ 
+ 	err = enetc_setup_cbdr(&pdev->dev, &si->hw, ENETC_CBDR_DEFAULT_SIZE,
+ 			       &si->cbd_ring);
+ 	if (err)
+-		goto err_setup_cbdr;
++		goto out_pci_remove;
+ 
+ 	err = enetc_init_port_rfs_memory(si);
+ 	if (err) {
+ 		dev_err(&pdev->dev, "Failed to initialize RFS memory\n");
+-		goto err_init_port_rfs;
++		goto out_teardown_cbdr;
+ 	}
+ 
+ 	err = enetc_init_port_rss_memory(si);
+ 	if (err) {
+ 		dev_err(&pdev->dev, "Failed to initialize RSS memory\n");
+-		goto err_init_port_rss;
++		goto out_teardown_cbdr;
++	}
++
++	return si;
++
++out_teardown_cbdr:
++	enetc_teardown_cbdr(&si->cbd_ring);
++out_pci_remove:
++	enetc_pci_remove(pdev);
++out:
++	return ERR_PTR(err);
++}
++
++static void enetc_psi_destroy(struct pci_dev *pdev)
++{
++	struct enetc_si *si = pci_get_drvdata(pdev);
++
++	enetc_teardown_cbdr(&si->cbd_ring);
++	enetc_pci_remove(pdev);
++}
++
++static int enetc_pf_probe(struct pci_dev *pdev,
++			  const struct pci_device_id *ent)
++{
++	struct device_node *node = pdev->dev.of_node;
++	struct enetc_ndev_priv *priv;
++	struct net_device *ndev;
++	struct enetc_si *si;
++	struct enetc_pf *pf;
++	int err;
++
++	err = enetc_pf_register_with_ierb(pdev);
++	if (err == -EPROBE_DEFER)
++		return err;
++	if (err)
++		dev_warn(&pdev->dev,
++			 "Could not register with IERB driver: %pe, please update the device tree\n",
++			 ERR_PTR(err));
++
++	si = enetc_psi_create(pdev);
++	if (IS_ERR(si)) {
++		err = PTR_ERR(si);
++		goto err_psi_create;
+ 	}
+ 
+ 	if (node && !of_device_is_available(node)) {
+@@ -1353,15 +1384,10 @@ err_alloc_si_res:
+ 	si->ndev = NULL;
+ 	free_netdev(ndev);
+ err_alloc_netdev:
+-err_init_port_rss:
+-err_init_port_rfs:
+ err_device_disabled:
+ err_setup_mac_addresses:
+-	enetc_teardown_cbdr(&si->cbd_ring);
+-err_setup_cbdr:
+-err_map_pf_space:
+-	enetc_pci_remove(pdev);
+-
++	enetc_psi_destroy(pdev);
++err_psi_create:
+ 	return err;
+ }
+ 
+@@ -1384,12 +1410,29 @@ static void enetc_pf_remove(struct pci_dev *pdev)
+ 	enetc_free_msix(priv);
+ 
+ 	enetc_free_si_resources(priv);
+-	enetc_teardown_cbdr(&si->cbd_ring);
+ 
+ 	free_netdev(si->ndev);
+ 
+-	enetc_pci_remove(pdev);
++	enetc_psi_destroy(pdev);
++}
++
++static void enetc_fixup_clear_rss_rfs(struct pci_dev *pdev)
++{
++	struct device_node *node = pdev->dev.of_node;
++	struct enetc_si *si;
++
++	/* Only apply quirk for disabled functions. For the ones
++	 * that are enabled, enetc_pf_probe() will apply it.
++	 */
++	if (node && of_device_is_available(node))
++		return;
++
++	si = enetc_psi_create(pdev);
++	if (si)
++		enetc_psi_destroy(pdev);
+ }
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID_PF,
++			enetc_fixup_clear_rss_rfs);
+ 
+ static const struct pci_device_id enetc_pf_id_table[] = {
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID_PF) },
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
+index 32bb14303473b..207b2e3f3fc2b 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
+@@ -461,9 +461,9 @@ static void hns3_dbg_fill_content(char *content, u16 len,
+ 		if (result) {
+ 			if (item_len < strlen(result[i]))
+ 				break;
+-			strscpy(pos, result[i], strlen(result[i]));
++			memcpy(pos, result[i], strlen(result[i]));
+ 		} else {
+-			strscpy(pos, items[i].name, strlen(items[i].name));
++			memcpy(pos, items[i].name, strlen(items[i].name));
+ 		}
+ 		pos += item_len;
+ 		len -= item_len;
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+index b676496ec6d7c..94acefd153bf7 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+@@ -5854,6 +5854,9 @@ void hns3_external_lb_prepare(struct net_device *ndev, bool if_running)
+ 	if (!if_running)
+ 		return;
+ 
++	if (test_and_set_bit(HNS3_NIC_STATE_DOWN, &priv->state))
++		return;
++
+ 	netif_carrier_off(ndev);
+ 	netif_tx_disable(ndev);
+ 
+@@ -5882,7 +5885,16 @@ void hns3_external_lb_restore(struct net_device *ndev, bool if_running)
+ 	if (!if_running)
+ 		return;
+ 
+-	hns3_nic_reset_all_ring(priv->ae_handle);
++	if (hns3_nic_resetting(ndev))
++		return;
++
++	if (!test_bit(HNS3_NIC_STATE_DOWN, &priv->state))
++		return;
++
++	if (hns3_nic_reset_all_ring(priv->ae_handle))
++		return;
++
++	clear_bit(HNS3_NIC_STATE_DOWN, &priv->state);
+ 
+ 	for (i = 0; i < priv->vector_num; i++)
+ 		hns3_vector_enable(&priv->tqp_vector[i]);
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
+index 409db2e709651..0fb2eaee3e8a0 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
+@@ -111,9 +111,9 @@ static void hclge_dbg_fill_content(char *content, u16 len,
+ 		if (result) {
+ 			if (item_len < strlen(result[i]))
+ 				break;
+-			strscpy(pos, result[i], strlen(result[i]));
++			memcpy(pos, result[i], strlen(result[i]));
+ 		} else {
+-			strscpy(pos, items[i].name, strlen(items[i].name));
++			memcpy(pos, items[i].name, strlen(items[i].name));
+ 		}
+ 		pos += item_len;
+ 		len -= item_len;
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+index 2689b108f7df7..c3e94598f3983 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+@@ -72,6 +72,8 @@ static void hclge_restore_hw_table(struct hclge_dev *hdev);
+ static void hclge_sync_promisc_mode(struct hclge_dev *hdev);
+ static void hclge_sync_fd_table(struct hclge_dev *hdev);
+ static void hclge_update_fec_stats(struct hclge_dev *hdev);
++static int hclge_mac_link_status_wait(struct hclge_dev *hdev, int link_ret,
++				      int wait_cnt);
+ 
+ static struct hnae3_ae_algo ae_algo;
+ 
+@@ -7567,6 +7569,8 @@ static void hclge_enable_fd(struct hnae3_handle *handle, bool enable)
+ 
+ static void hclge_cfg_mac_mode(struct hclge_dev *hdev, bool enable)
+ {
++#define HCLGE_LINK_STATUS_WAIT_CNT  3
++
+ 	struct hclge_desc desc;
+ 	struct hclge_config_mac_mode_cmd *req =
+ 		(struct hclge_config_mac_mode_cmd *)desc.data;
+@@ -7591,9 +7595,15 @@ static void hclge_cfg_mac_mode(struct hclge_dev *hdev, bool enable)
+ 	req->txrx_pad_fcs_loop_en = cpu_to_le32(loop_en);
+ 
+ 	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+-	if (ret)
++	if (ret) {
+ 		dev_err(&hdev->pdev->dev,
+ 			"mac enable fail, ret =%d.\n", ret);
++		return;
++	}
++
++	if (!enable)
++		hclge_mac_link_status_wait(hdev, HCLGE_LINK_STATUS_DOWN,
++					   HCLGE_LINK_STATUS_WAIT_CNT);
+ }
+ 
+ static int hclge_config_switch_param(struct hclge_dev *hdev, int vfid,
+@@ -7656,10 +7666,9 @@ static void hclge_phy_link_status_wait(struct hclge_dev *hdev,
+ 	} while (++i < HCLGE_PHY_LINK_STATUS_NUM);
+ }
+ 
+-static int hclge_mac_link_status_wait(struct hclge_dev *hdev, int link_ret)
++static int hclge_mac_link_status_wait(struct hclge_dev *hdev, int link_ret,
++				      int wait_cnt)
+ {
+-#define HCLGE_MAC_LINK_STATUS_NUM  100
+-
+ 	int link_status;
+ 	int i = 0;
+ 	int ret;
+@@ -7672,13 +7681,15 @@ static int hclge_mac_link_status_wait(struct hclge_dev *hdev, int link_ret)
+ 			return 0;
+ 
+ 		msleep(HCLGE_LINK_STATUS_MS);
+-	} while (++i < HCLGE_MAC_LINK_STATUS_NUM);
++	} while (++i < wait_cnt);
+ 	return -EBUSY;
+ }
+ 
+ static int hclge_mac_phy_link_status_wait(struct hclge_dev *hdev, bool en,
+ 					  bool is_phy)
+ {
++#define HCLGE_MAC_LINK_STATUS_NUM  100
++
+ 	int link_ret;
+ 
+ 	link_ret = en ? HCLGE_LINK_STATUS_UP : HCLGE_LINK_STATUS_DOWN;
+@@ -7686,7 +7697,8 @@ static int hclge_mac_phy_link_status_wait(struct hclge_dev *hdev, bool en,
+ 	if (is_phy)
+ 		hclge_phy_link_status_wait(hdev, link_ret);
+ 
+-	return hclge_mac_link_status_wait(hdev, link_ret);
++	return hclge_mac_link_status_wait(hdev, link_ret,
++					  HCLGE_MAC_LINK_STATUS_NUM);
+ }
+ 
+ static int hclge_set_app_loopback(struct hclge_dev *hdev, bool en)
+diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
+index 763d613adbcc0..df76cdaddcfb0 100644
+--- a/drivers/net/ethernet/ibm/ibmvnic.c
++++ b/drivers/net/ethernet/ibm/ibmvnic.c
+@@ -97,6 +97,8 @@ static int pending_scrq(struct ibmvnic_adapter *,
+ static union sub_crq *ibmvnic_next_scrq(struct ibmvnic_adapter *,
+ 					struct ibmvnic_sub_crq_queue *);
+ static int ibmvnic_poll(struct napi_struct *napi, int data);
++static int reset_sub_crq_queues(struct ibmvnic_adapter *adapter);
++static inline void reinit_init_done(struct ibmvnic_adapter *adapter);
+ static void send_query_map(struct ibmvnic_adapter *adapter);
+ static int send_request_map(struct ibmvnic_adapter *, dma_addr_t, u32, u8);
+ static int send_request_unmap(struct ibmvnic_adapter *, u8);
+@@ -114,6 +116,7 @@ static void ibmvnic_tx_scrq_clean_buffer(struct ibmvnic_adapter *adapter,
+ static void free_long_term_buff(struct ibmvnic_adapter *adapter,
+ 				struct ibmvnic_long_term_buff *ltb);
+ static void ibmvnic_disable_irqs(struct ibmvnic_adapter *adapter);
++static void flush_reset_queue(struct ibmvnic_adapter *adapter);
+ 
+ struct ibmvnic_stat {
+ 	char name[ETH_GSTRING_LEN];
+@@ -1505,8 +1508,8 @@ static const char *adapter_state_to_string(enum vnic_state state)
+ 
+ static int ibmvnic_login(struct net_device *netdev)
+ {
++	unsigned long flags, timeout = msecs_to_jiffies(20000);
+ 	struct ibmvnic_adapter *adapter = netdev_priv(netdev);
+-	unsigned long timeout = msecs_to_jiffies(20000);
+ 	int retry_count = 0;
+ 	int retries = 10;
+ 	bool retry;
+@@ -1527,11 +1530,9 @@ static int ibmvnic_login(struct net_device *netdev)
+ 
+ 		if (!wait_for_completion_timeout(&adapter->init_done,
+ 						 timeout)) {
+-			netdev_warn(netdev, "Login timed out, retrying...\n");
+-			retry = true;
+-			adapter->init_done_rc = 0;
+-			retry_count++;
+-			continue;
++			netdev_warn(netdev, "Login timed out\n");
++			adapter->login_pending = false;
++			goto partial_reset;
+ 		}
+ 
+ 		if (adapter->init_done_rc == ABORTED) {
+@@ -1573,10 +1574,69 @@ static int ibmvnic_login(struct net_device *netdev)
+ 					    "SCRQ irq initialization failed\n");
+ 				return rc;
+ 			}
++		/* Default/timeout error handling, reset and start fresh */
+ 		} else if (adapter->init_done_rc) {
+ 			netdev_warn(netdev, "Adapter login failed, init_done_rc = %d\n",
+ 				    adapter->init_done_rc);
+-			return -EIO;
++
++partial_reset:
++			/* adapter login failed, so free any CRQs or sub-CRQs
++			 * and register again before attempting to login again.
++			 * If we don't do this then the VIOS may think that
++			 * we are already logged in and reject any subsequent
++			 * attempts
++			 */
++			netdev_warn(netdev,
++				    "Freeing and re-registering CRQs before attempting to login again\n");
++			retry = true;
++			adapter->init_done_rc = 0;
++			release_sub_crqs(adapter, true);
++			/* Much of this is similar logic as ibmvnic_probe(),
++			 * we are essentially re-initializing communication
++			 * with the server. We really should not run any
++			 * resets/failovers here because this is already a form
++			 * of reset and we do not want parallel resets occurring
++			 */
++			do {
++				reinit_init_done(adapter);
++				/* Clear any failovers we got in the previous
++				 * pass since we are re-initializing the CRQ
++				 */
++				adapter->failover_pending = false;
++				release_crq_queue(adapter);
++				/* If we don't sleep here then we risk an
++				 * unnecessary failover event from the VIOS.
++				 * This is a known VIOS issue caused by a vnic
++				 * device freeing and registering a CRQ too
++				 * quickly.
++				 */
++				msleep(1500);
++				/* Avoid any resets, since we are currently
++				 * resetting.
++				 */
++				spin_lock_irqsave(&adapter->rwi_lock, flags);
++				flush_reset_queue(adapter);
++				spin_unlock_irqrestore(&adapter->rwi_lock,
++						       flags);
++
++				rc = init_crq_queue(adapter);
++				if (rc) {
++					netdev_err(netdev, "login recovery: init CRQ failed %d\n",
++						   rc);
++					return -EIO;
++				}
++
++				rc = ibmvnic_reset_init(adapter, false);
++				if (rc)
++					netdev_err(netdev, "login recovery: Reset init failed %d\n",
++						   rc);
++				/* IBMVNIC_CRQ_INIT will return EAGAIN if it
++				 * fails, since ibmvnic_reset_init will free
++				 * irq's in failure, we won't be able to receive
++				 * new CRQs so we need to keep trying. probe()
++				 * handles this similarly.
++				 */
++			} while (rc == -EAGAIN && retry_count++ < retries);
+ 		}
+ 	} while (retry);
+ 
+@@ -1588,12 +1648,22 @@ static int ibmvnic_login(struct net_device *netdev)
+ 
+ static void release_login_buffer(struct ibmvnic_adapter *adapter)
+ {
++	if (!adapter->login_buf)
++		return;
++
++	dma_unmap_single(&adapter->vdev->dev, adapter->login_buf_token,
++			 adapter->login_buf_sz, DMA_TO_DEVICE);
+ 	kfree(adapter->login_buf);
+ 	adapter->login_buf = NULL;
+ }
+ 
+ static void release_login_rsp_buffer(struct ibmvnic_adapter *adapter)
+ {
++	if (!adapter->login_rsp_buf)
++		return;
++
++	dma_unmap_single(&adapter->vdev->dev, adapter->login_rsp_buf_token,
++			 adapter->login_rsp_buf_sz, DMA_FROM_DEVICE);
+ 	kfree(adapter->login_rsp_buf);
+ 	adapter->login_rsp_buf = NULL;
+ }
+@@ -4830,11 +4900,14 @@ static int send_login(struct ibmvnic_adapter *adapter)
+ 	if (rc) {
+ 		adapter->login_pending = false;
+ 		netdev_err(adapter->netdev, "Failed to send login, rc=%d\n", rc);
+-		goto buf_rsp_map_failed;
++		goto buf_send_failed;
+ 	}
+ 
+ 	return 0;
+ 
++buf_send_failed:
++	dma_unmap_single(dev, rsp_buffer_token, rsp_buffer_size,
++			 DMA_FROM_DEVICE);
+ buf_rsp_map_failed:
+ 	kfree(login_rsp_buffer);
+ 	adapter->login_rsp_buf = NULL;
+@@ -5396,6 +5469,7 @@ static int handle_login_rsp(union ibmvnic_crq *login_rsp_crq,
+ 	int num_tx_pools;
+ 	int num_rx_pools;
+ 	u64 *size_array;
++	u32 rsp_len;
+ 	int i;
+ 
+ 	/* CHECK: Test/set of login_pending does not need to be atomic
+@@ -5407,11 +5481,6 @@ static int handle_login_rsp(union ibmvnic_crq *login_rsp_crq,
+ 	}
+ 	adapter->login_pending = false;
+ 
+-	dma_unmap_single(dev, adapter->login_buf_token, adapter->login_buf_sz,
+-			 DMA_TO_DEVICE);
+-	dma_unmap_single(dev, adapter->login_rsp_buf_token,
+-			 adapter->login_rsp_buf_sz, DMA_FROM_DEVICE);
+-
+ 	/* If the number of queues requested can't be allocated by the
+ 	 * server, the login response will return with code 1. We will need
+ 	 * to resend the login buffer with fewer queues requested.
+@@ -5447,6 +5516,23 @@ static int handle_login_rsp(union ibmvnic_crq *login_rsp_crq,
+ 		ibmvnic_reset(adapter, VNIC_RESET_FATAL);
+ 		return -EIO;
+ 	}
++
++	rsp_len = be32_to_cpu(login_rsp->len);
++	if (be32_to_cpu(login->login_rsp_len) < rsp_len ||
++	    rsp_len <= be32_to_cpu(login_rsp->off_txsubm_subcrqs) ||
++	    rsp_len <= be32_to_cpu(login_rsp->off_rxadd_subcrqs) ||
++	    rsp_len <= be32_to_cpu(login_rsp->off_rxadd_buff_size) ||
++	    rsp_len <= be32_to_cpu(login_rsp->off_supp_tx_desc)) {
++		/* This can happen if a login request times out and there are
++		 * 2 outstanding login requests sent, the LOGIN_RSP crq
++		 * could have been for the older login request. So we are
++		 * parsing the newer response buffer which may be incomplete
++		 */
++		dev_err(dev, "FATAL: Login rsp offsets/lengths invalid\n");
++		ibmvnic_reset(adapter, VNIC_RESET_FATAL);
++		return -EIO;
++	}
++
+ 	size_array = (u64 *)((u8 *)(adapter->login_rsp_buf) +
+ 		be32_to_cpu(adapter->login_rsp_buf->off_rxadd_buff_size));
+ 	/* variable buffer sizes are not supported, so just read the
+diff --git a/drivers/net/ethernet/intel/iavf/iavf_ethtool.c b/drivers/net/ethernet/intel/iavf/iavf_ethtool.c
+index 2f47cfa7f06e2..460ca561819a9 100644
+--- a/drivers/net/ethernet/intel/iavf/iavf_ethtool.c
++++ b/drivers/net/ethernet/intel/iavf/iavf_ethtool.c
+@@ -1401,14 +1401,15 @@ static int iavf_add_fdir_ethtool(struct iavf_adapter *adapter, struct ethtool_rx
+ 	if (fsp->flow_type & FLOW_MAC_EXT)
+ 		return -EINVAL;
+ 
++	spin_lock_bh(&adapter->fdir_fltr_lock);
+ 	if (adapter->fdir_active_fltr >= IAVF_MAX_FDIR_FILTERS) {
++		spin_unlock_bh(&adapter->fdir_fltr_lock);
+ 		dev_err(&adapter->pdev->dev,
+ 			"Unable to add Flow Director filter because VF reached the limit of max allowed filters (%u)\n",
+ 			IAVF_MAX_FDIR_FILTERS);
+ 		return -ENOSPC;
+ 	}
+ 
+-	spin_lock_bh(&adapter->fdir_fltr_lock);
+ 	if (iavf_find_fdir_fltr_by_loc(adapter, fsp->location)) {
+ 		dev_err(&adapter->pdev->dev, "Failed to add Flow Director filter, it already exists\n");
+ 		spin_unlock_bh(&adapter->fdir_fltr_lock);
+@@ -1781,7 +1782,9 @@ static int iavf_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd,
+ 	case ETHTOOL_GRXCLSRLCNT:
+ 		if (!FDIR_FLTR_SUPPORT(adapter))
+ 			break;
++		spin_lock_bh(&adapter->fdir_fltr_lock);
+ 		cmd->rule_cnt = adapter->fdir_active_fltr;
++		spin_unlock_bh(&adapter->fdir_fltr_lock);
+ 		cmd->data = IAVF_MAX_FDIR_FILTERS;
+ 		ret = 0;
+ 		break;
+diff --git a/drivers/net/ethernet/intel/iavf/iavf_fdir.c b/drivers/net/ethernet/intel/iavf/iavf_fdir.c
+index 6146203efd84a..505e82ebafe47 100644
+--- a/drivers/net/ethernet/intel/iavf/iavf_fdir.c
++++ b/drivers/net/ethernet/intel/iavf/iavf_fdir.c
+@@ -722,7 +722,9 @@ void iavf_print_fdir_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *f
+ bool iavf_fdir_is_dup_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr)
+ {
+ 	struct iavf_fdir_fltr *tmp;
++	bool ret = false;
+ 
++	spin_lock_bh(&adapter->fdir_fltr_lock);
+ 	list_for_each_entry(tmp, &adapter->fdir_list_head, list) {
+ 		if (tmp->flow_type != fltr->flow_type)
+ 			continue;
+@@ -732,11 +734,14 @@ bool iavf_fdir_is_dup_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *
+ 		    !memcmp(&tmp->ip_data, &fltr->ip_data,
+ 			    sizeof(fltr->ip_data)) &&
+ 		    !memcmp(&tmp->ext_data, &fltr->ext_data,
+-			    sizeof(fltr->ext_data)))
+-			return true;
++			    sizeof(fltr->ext_data))) {
++			ret = true;
++			break;
++		}
+ 	}
++	spin_unlock_bh(&adapter->fdir_fltr_lock);
+ 
+-	return false;
++	return ret;
+ }
+ 
+ /**
+diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h
+index 345d3a4e8ed44..2bd042dcd00f9 100644
+--- a/drivers/net/ethernet/intel/igc/igc.h
++++ b/drivers/net/ethernet/intel/igc/igc.h
+@@ -195,6 +195,10 @@ struct igc_adapter {
+ 	u32 qbv_config_change_errors;
+ 	bool qbv_transition;
+ 	unsigned int qbv_count;
++	/* Access to oper_gate_closed, admin_gate_closed and qbv_transition
++	 * are protected by the qbv_tx_lock.
++	 */
++	spinlock_t qbv_tx_lock;
+ 
+ 	/* OS defined structs */
+ 	struct pci_dev *pdev;
+diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
+index 3ccf2fedc5af7..2ae74870bbae2 100644
+--- a/drivers/net/ethernet/intel/igc/igc_main.c
++++ b/drivers/net/ethernet/intel/igc/igc_main.c
+@@ -4799,6 +4799,7 @@ static int igc_sw_init(struct igc_adapter *adapter)
+ 	adapter->nfc_rule_count = 0;
+ 
+ 	spin_lock_init(&adapter->stats64_lock);
++	spin_lock_init(&adapter->qbv_tx_lock);
+ 	/* Assume MSI-X interrupts, will be checked during IRQ allocation */
+ 	adapter->flags |= IGC_FLAG_HAS_MSIX;
+ 
+@@ -6117,15 +6118,15 @@ static int igc_tsn_enable_launchtime(struct igc_adapter *adapter,
+ 	return igc_tsn_offload_apply(adapter);
+ }
+ 
+-static int igc_tsn_clear_schedule(struct igc_adapter *adapter)
++static int igc_qbv_clear_schedule(struct igc_adapter *adapter)
+ {
++	unsigned long flags;
+ 	int i;
+ 
+ 	adapter->base_time = 0;
+ 	adapter->cycle_time = NSEC_PER_SEC;
+ 	adapter->taprio_offload_enable = false;
+ 	adapter->qbv_config_change_errors = 0;
+-	adapter->qbv_transition = false;
+ 	adapter->qbv_count = 0;
+ 
+ 	for (i = 0; i < adapter->num_tx_queues; i++) {
+@@ -6134,10 +6135,28 @@ static int igc_tsn_clear_schedule(struct igc_adapter *adapter)
+ 		ring->start_time = 0;
+ 		ring->end_time = NSEC_PER_SEC;
+ 		ring->max_sdu = 0;
++	}
++
++	spin_lock_irqsave(&adapter->qbv_tx_lock, flags);
++
++	adapter->qbv_transition = false;
++
++	for (i = 0; i < adapter->num_tx_queues; i++) {
++		struct igc_ring *ring = adapter->tx_ring[i];
++
+ 		ring->oper_gate_closed = false;
+ 		ring->admin_gate_closed = false;
+ 	}
+ 
++	spin_unlock_irqrestore(&adapter->qbv_tx_lock, flags);
++
++	return 0;
++}
++
++static int igc_tsn_clear_schedule(struct igc_adapter *adapter)
++{
++	igc_qbv_clear_schedule(adapter);
++
+ 	return 0;
+ }
+ 
+@@ -6148,6 +6167,7 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
+ 	struct igc_hw *hw = &adapter->hw;
+ 	u32 start_time = 0, end_time = 0;
+ 	struct timespec64 now;
++	unsigned long flags;
+ 	size_t n;
+ 	int i;
+ 
+@@ -6215,6 +6235,8 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
+ 		start_time += e->interval;
+ 	}
+ 
++	spin_lock_irqsave(&adapter->qbv_tx_lock, flags);
++
+ 	/* Check whether a queue gets configured.
+ 	 * If not, set the start and end time to be end time.
+ 	 */
+@@ -6239,6 +6261,8 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
+ 		}
+ 	}
+ 
++	spin_unlock_irqrestore(&adapter->qbv_tx_lock, flags);
++
+ 	for (i = 0; i < adapter->num_tx_queues; i++) {
+ 		struct igc_ring *ring = adapter->tx_ring[i];
+ 		struct net_device *dev = adapter->netdev;
+@@ -6603,8 +6627,11 @@ static enum hrtimer_restart igc_qbv_scheduling_timer(struct hrtimer *timer)
+ {
+ 	struct igc_adapter *adapter = container_of(timer, struct igc_adapter,
+ 						   hrtimer);
++	unsigned long flags;
+ 	unsigned int i;
+ 
++	spin_lock_irqsave(&adapter->qbv_tx_lock, flags);
++
+ 	adapter->qbv_transition = true;
+ 	for (i = 0; i < adapter->num_tx_queues; i++) {
+ 		struct igc_ring *tx_ring = adapter->tx_ring[i];
+@@ -6617,6 +6644,9 @@ static enum hrtimer_restart igc_qbv_scheduling_timer(struct hrtimer *timer)
+ 		}
+ 	}
+ 	adapter->qbv_transition = false;
++
++	spin_unlock_irqrestore(&adapter->qbv_tx_lock, flags);
++
+ 	return HRTIMER_NORESTART;
+ }
+ 
+diff --git a/drivers/net/ethernet/marvell/prestera/prestera_router.c b/drivers/net/ethernet/marvell/prestera/prestera_router.c
+index a9a1028cb17bb..de317179a7dcc 100644
+--- a/drivers/net/ethernet/marvell/prestera/prestera_router.c
++++ b/drivers/net/ethernet/marvell/prestera/prestera_router.c
+@@ -166,11 +166,11 @@ prestera_util_neigh2nc_key(struct prestera_switch *sw, struct neighbour *n,
+ 
+ static bool __prestera_fi_is_direct(struct fib_info *fi)
+ {
+-	struct fib_nh *fib_nh;
++	struct fib_nh_common *fib_nhc;
+ 
+ 	if (fib_info_num_path(fi) == 1) {
+-		fib_nh = fib_info_nh(fi, 0);
+-		if (fib_nh->fib_nh_gw_family == AF_UNSPEC)
++		fib_nhc = fib_info_nhc(fi, 0);
++		if (fib_nhc->nhc_gw_family == AF_UNSPEC)
+ 			return true;
+ 	}
+ 
+@@ -261,7 +261,7 @@ static bool
+ __prestera_util_kern_n_is_reachable_v4(u32 tb_id, __be32 *addr,
+ 				       struct net_device *dev)
+ {
+-	struct fib_nh *fib_nh;
++	struct fib_nh_common *fib_nhc;
+ 	struct fib_result res;
+ 	bool reachable;
+ 
+@@ -269,8 +269,8 @@ __prestera_util_kern_n_is_reachable_v4(u32 tb_id, __be32 *addr,
+ 
+ 	if (!prestera_util_kern_get_route(&res, tb_id, addr))
+ 		if (prestera_fi_is_direct(res.fi)) {
+-			fib_nh = fib_info_nh(res.fi, 0);
+-			if (dev == fib_nh->fib_nh_dev)
++			fib_nhc = fib_info_nhc(res.fi, 0);
++			if (dev == fib_nhc->nhc_dev)
+ 				reachable = true;
+ 		}
+ 
+@@ -324,7 +324,7 @@ prestera_kern_fib_info_nhc(struct fib_notifier_info *info, int n)
+ 	if (info->family == AF_INET) {
+ 		fen4_info = container_of(info, struct fib_entry_notifier_info,
+ 					 info);
+-		return &fib_info_nh(fen4_info->fi, n)->nh_common;
++		return fib_info_nhc(fen4_info->fi, n);
+ 	} else if (info->family == AF_INET6) {
+ 		fen6_info = container_of(info, struct fib6_entry_notifier_info,
+ 					 info);
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c
+index 0c88cf47af01b..1730f6a716eea 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c
+@@ -1461,10 +1461,12 @@ static void mlx5e_invalidate_encap(struct mlx5e_priv *priv,
+ 		attr = mlx5e_tc_get_encap_attr(flow);
+ 		esw_attr = attr->esw_attr;
+ 
+-		if (flow_flag_test(flow, SLOW))
++		if (flow_flag_test(flow, SLOW)) {
+ 			mlx5e_tc_unoffload_from_slow_path(esw, flow);
+-		else
++		} else {
+ 			mlx5e_tc_unoffload_fdb_rules(esw, flow, flow->attr);
++			mlx5e_tc_unoffload_flow_post_acts(flow);
++		}
+ 
+ 		mlx5e_tc_detach_mod_hdr(priv, flow, attr);
+ 		attr->modify_hdr = NULL;
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+index f084513fbead4..7e6d0489854e3 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+@@ -5266,6 +5266,7 @@ void mlx5e_destroy_q_counters(struct mlx5e_priv *priv)
+ static int mlx5e_nic_init(struct mlx5_core_dev *mdev,
+ 			  struct net_device *netdev)
+ {
++	const bool take_rtnl = netdev->reg_state == NETREG_REGISTERED;
+ 	struct mlx5e_priv *priv = netdev_priv(netdev);
+ 	struct mlx5e_flow_steering *fs;
+ 	int err;
+@@ -5294,9 +5295,19 @@ static int mlx5e_nic_init(struct mlx5_core_dev *mdev,
+ 		mlx5_core_err(mdev, "TLS initialization failed, %d\n", err);
+ 
+ 	mlx5e_health_create_reporters(priv);
++
++	/* If netdev is already registered (e.g. move from uplink to nic profile),
++	 * RTNL lock must be held before triggering netdev notifiers.
++	 */
++	if (take_rtnl)
++		rtnl_lock();
++
+ 	/* update XDP supported features */
+ 	mlx5e_set_xdp_feature(netdev);
+ 
++	if (take_rtnl)
++		rtnl_unlock();
++
+ 	return 0;
+ }
+ 
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+index e002f013fa015..73c827ee1a94e 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+@@ -1943,9 +1943,7 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv,
+ {
+ 	struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
+ 	struct mlx5_flow_attr *attr = flow->attr;
+-	struct mlx5_esw_flow_attr *esw_attr;
+ 
+-	esw_attr = attr->esw_attr;
+ 	mlx5e_put_flow_tunnel_id(flow);
+ 
+ 	remove_unready_flow(flow);
+@@ -1966,12 +1964,6 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv,
+ 
+ 	mlx5_tc_ct_match_del(get_ct_priv(priv), &flow->attr->ct_attr);
+ 
+-	if (esw_attr->int_port)
+-		mlx5e_tc_int_port_put(mlx5e_get_int_port_priv(priv), esw_attr->int_port);
+-
+-	if (esw_attr->dest_int_port)
+-		mlx5e_tc_int_port_put(mlx5e_get_int_port_priv(priv), esw_attr->dest_int_port);
+-
+ 	if (flow_flag_test(flow, L3_TO_L2_DECAP))
+ 		mlx5e_detach_decap(priv, flow);
+ 
+@@ -4250,6 +4242,7 @@ static void
+ mlx5_free_flow_attr_actions(struct mlx5e_tc_flow *flow, struct mlx5_flow_attr *attr)
+ {
+ 	struct mlx5_core_dev *counter_dev = get_flow_counter_dev(flow);
++	struct mlx5_esw_flow_attr *esw_attr;
+ 
+ 	if (!attr)
+ 		return;
+@@ -4267,6 +4260,18 @@ mlx5_free_flow_attr_actions(struct mlx5e_tc_flow *flow, struct mlx5_flow_attr *a
+ 		mlx5e_tc_detach_mod_hdr(flow->priv, flow, attr);
+ 	}
+ 
++	if (mlx5e_is_eswitch_flow(flow)) {
++		esw_attr = attr->esw_attr;
++
++		if (esw_attr->int_port)
++			mlx5e_tc_int_port_put(mlx5e_get_int_port_priv(flow->priv),
++					      esw_attr->int_port);
++
++		if (esw_attr->dest_int_port)
++			mlx5e_tc_int_port_put(mlx5e_get_int_port_priv(flow->priv),
++					      esw_attr->dest_int_port);
++	}
++
+ 	mlx5_tc_ct_delete_flow(get_ct_priv(flow->priv), attr);
+ 
+ 	free_branch_attr(flow, attr->branch_true);
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c
+index d3a3fe4ce6702..7d9bbb494d95b 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c
+@@ -574,7 +574,7 @@ static int __mlx5_lag_modify_definers_destinations(struct mlx5_lag *ldev,
+ 	for (i = 0; i < ldev->ports; i++) {
+ 		for (j = 0; j < ldev->buckets; j++) {
+ 			idx = i * ldev->buckets + j;
+-			if (ldev->v2p_map[i] == ports[i])
++			if (ldev->v2p_map[idx] == ports[idx])
+ 				continue;
+ 
+ 			dest.vport.vhca_id = MLX5_CAP_GEN(ldev->pf[ports[idx] - 1].dev,
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
+index 932fbc843c692..dba4c5e2f7667 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
+@@ -221,10 +221,15 @@ static void mlx5_timestamp_overflow(struct work_struct *work)
+ 	clock = container_of(timer, struct mlx5_clock, timer);
+ 	mdev = container_of(clock, struct mlx5_core_dev, clock);
+ 
++	if (mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR)
++		goto out;
++
+ 	write_seqlock_irqsave(&clock->lock, flags);
+ 	timecounter_read(&timer->tc);
+ 	mlx5_update_clock_info_page(mdev);
+ 	write_sequnlock_irqrestore(&clock->lock, flags);
++
++out:
+ 	schedule_delayed_work(&timer->overflow_work, timer->overflow_period);
+ }
+ 
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
+index c7a06c8bbb7a3..3216839776548 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
+@@ -1845,7 +1845,7 @@ static pci_ers_result_t mlx5_pci_err_detected(struct pci_dev *pdev,
+ 
+ 	mlx5_enter_error_state(dev, false);
+ 	mlx5_error_sw_reset(dev);
+-	mlx5_unload_one(dev, true);
++	mlx5_unload_one(dev, false);
+ 	mlx5_drain_health_wq(dev);
+ 	mlx5_pci_disable_device(dev);
+ 
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sriov.c b/drivers/net/ethernet/mellanox/mlx5/core/sriov.c
+index 20d7662c10fb6..5f2195e65dd62 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/sriov.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/sriov.c
+@@ -264,8 +264,7 @@ static u16 mlx5_get_max_vfs(struct mlx5_core_dev *dev)
+ 		host_total_vfs = MLX5_GET(query_esw_functions_out, out,
+ 					  host_params_context.host_total_vfs);
+ 		kvfree(out);
+-		if (host_total_vfs)
+-			return host_total_vfs;
++		return host_total_vfs;
+ 	}
+ 
+ done:
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ptrn.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ptrn.c
+index d6947fe13d560..8ca534ef5d031 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ptrn.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ptrn.c
+@@ -82,7 +82,7 @@ dr_ptrn_alloc_pattern(struct mlx5dr_ptrn_mgr *mgr,
+ 	u32 chunk_size;
+ 	u32 index;
+ 
+-	chunk_size = ilog2(num_of_actions);
++	chunk_size = ilog2(roundup_pow_of_two(num_of_actions));
+ 	/* HW modify action index granularity is at least 64B */
+ 	chunk_size = max_t(u32, chunk_size, DR_CHUNK_SIZE_8);
+ 
+diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
+index d907727c7b7a5..96c78f7db2543 100644
+--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
++++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
+@@ -8,6 +8,7 @@
+ #include <linux/ethtool.h>
+ #include <linux/filter.h>
+ #include <linux/mm.h>
++#include <linux/pci.h>
+ 
+ #include <net/checksum.h>
+ #include <net/ip6_checksum.h>
+@@ -2328,9 +2329,12 @@ int mana_attach(struct net_device *ndev)
+ static int mana_dealloc_queues(struct net_device *ndev)
+ {
+ 	struct mana_port_context *apc = netdev_priv(ndev);
++	unsigned long timeout = jiffies + 120 * HZ;
+ 	struct gdma_dev *gd = apc->ac->gdma_dev;
+ 	struct mana_txq *txq;
++	struct sk_buff *skb;
+ 	int i, err;
++	u32 tsleep;
+ 
+ 	if (apc->port_is_up)
+ 		return -EINVAL;
+@@ -2346,15 +2350,40 @@ static int mana_dealloc_queues(struct net_device *ndev)
+ 	 * to false, but it doesn't matter since mana_start_xmit() drops any
+ 	 * new packets due to apc->port_is_up being false.
+ 	 *
+-	 * Drain all the in-flight TX packets
++	 * Drain all the in-flight TX packets.
++	 * A timeout of 120 seconds for all the queues is used.
++	 * This will break the while loop when h/w is not responding.
++	 * This value of 120 has been decided here considering max
++	 * number of queues.
+ 	 */
++
+ 	for (i = 0; i < apc->num_queues; i++) {
+ 		txq = &apc->tx_qp[i].txq;
+-
+-		while (atomic_read(&txq->pending_sends) > 0)
+-			usleep_range(1000, 2000);
++		tsleep = 1000;
++		while (atomic_read(&txq->pending_sends) > 0 &&
++		       time_before(jiffies, timeout)) {
++			usleep_range(tsleep, tsleep + 1000);
++			tsleep <<= 1;
++		}
++		if (atomic_read(&txq->pending_sends)) {
++			err = pcie_flr(to_pci_dev(gd->gdma_context->dev));
++			if (err) {
++				netdev_err(ndev, "flr failed %d with %d pkts pending in txq %u\n",
++					   err, atomic_read(&txq->pending_sends),
++					   txq->gdma_txq_id);
++			}
++			break;
++		}
+ 	}
+ 
++	for (i = 0; i < apc->num_queues; i++) {
++		txq = &apc->tx_qp[i].txq;
++		while ((skb = skb_dequeue(&txq->pending_skbs))) {
++			mana_unmap_skb(skb, apc);
++			dev_kfree_skb_any(skb);
++		}
++		atomic_set(&txq->pending_sends, 0);
++	}
+ 	/* We're 100% sure the queues can no longer be woken up, because
+ 	 * we're sure now mana_poll_tx_cq() can't be running.
+ 	 */
+diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
+index e03a94f2469ab..a25a202ad75ae 100644
+--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c
++++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
+@@ -1816,6 +1816,7 @@ static int ionic_change_mtu(struct net_device *netdev, int new_mtu)
+ static void ionic_tx_timeout_work(struct work_struct *ws)
+ {
+ 	struct ionic_lif *lif = container_of(ws, struct ionic_lif, tx_timeout_work);
++	int err;
+ 
+ 	if (test_bit(IONIC_LIF_F_FW_RESET, lif->state))
+ 		return;
+@@ -1828,8 +1829,11 @@ static void ionic_tx_timeout_work(struct work_struct *ws)
+ 
+ 	mutex_lock(&lif->queue_lock);
+ 	ionic_stop_queues_reconfig(lif);
+-	ionic_start_queues_reconfig(lif);
++	err = ionic_start_queues_reconfig(lif);
+ 	mutex_unlock(&lif->queue_lock);
++
++	if (err)
++		dev_err(lif->ionic->dev, "%s: Restarting queues failed\n", __func__);
+ }
+ 
+ static void ionic_tx_timeout(struct net_device *netdev, unsigned int txqueue)
+@@ -2799,17 +2803,22 @@ static int ionic_cmb_reconfig(struct ionic_lif *lif,
+ 			if (err) {
+ 				dev_err(lif->ionic->dev,
+ 					"CMB restore failed: %d\n", err);
+-				goto errout;
++				goto err_out;
+ 			}
+ 		}
+ 
+-		ionic_start_queues_reconfig(lif);
+-	} else {
+-		/* This was detached in ionic_stop_queues_reconfig() */
+-		netif_device_attach(lif->netdev);
++		err = ionic_start_queues_reconfig(lif);
++		if (err) {
++			dev_err(lif->ionic->dev,
++				"CMB reconfig failed: %d\n", err);
++			goto err_out;
++		}
+ 	}
+ 
+-errout:
++err_out:
++	/* This was detached in ionic_stop_queues_reconfig() */
++	netif_device_attach(lif->netdev);
++
+ 	return err;
+ }
+ 
+diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
+index 984dfa5d6c11c..144ec756c796a 100644
+--- a/drivers/net/macsec.c
++++ b/drivers/net/macsec.c
+@@ -743,7 +743,7 @@ static bool macsec_post_decrypt(struct sk_buff *skb, struct macsec_secy *secy, u
+ 		u64_stats_update_begin(&rxsc_stats->syncp);
+ 		rxsc_stats->stats.InPktsLate++;
+ 		u64_stats_update_end(&rxsc_stats->syncp);
+-		secy->netdev->stats.rx_dropped++;
++		DEV_STATS_INC(secy->netdev, rx_dropped);
+ 		return false;
+ 	}
+ 
+@@ -767,7 +767,7 @@ static bool macsec_post_decrypt(struct sk_buff *skb, struct macsec_secy *secy, u
+ 			rxsc_stats->stats.InPktsNotValid++;
+ 			u64_stats_update_end(&rxsc_stats->syncp);
+ 			this_cpu_inc(rx_sa->stats->InPktsNotValid);
+-			secy->netdev->stats.rx_errors++;
++			DEV_STATS_INC(secy->netdev, rx_errors);
+ 			return false;
+ 		}
+ 
+@@ -1069,7 +1069,7 @@ static enum rx_handler_result handle_not_macsec(struct sk_buff *skb)
+ 			u64_stats_update_begin(&secy_stats->syncp);
+ 			secy_stats->stats.InPktsNoTag++;
+ 			u64_stats_update_end(&secy_stats->syncp);
+-			macsec->secy.netdev->stats.rx_dropped++;
++			DEV_STATS_INC(macsec->secy.netdev, rx_dropped);
+ 			continue;
+ 		}
+ 
+@@ -1179,7 +1179,7 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb)
+ 		u64_stats_update_begin(&secy_stats->syncp);
+ 		secy_stats->stats.InPktsBadTag++;
+ 		u64_stats_update_end(&secy_stats->syncp);
+-		secy->netdev->stats.rx_errors++;
++		DEV_STATS_INC(secy->netdev, rx_errors);
+ 		goto drop_nosa;
+ 	}
+ 
+@@ -1196,7 +1196,7 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb)
+ 			u64_stats_update_begin(&rxsc_stats->syncp);
+ 			rxsc_stats->stats.InPktsNotUsingSA++;
+ 			u64_stats_update_end(&rxsc_stats->syncp);
+-			secy->netdev->stats.rx_errors++;
++			DEV_STATS_INC(secy->netdev, rx_errors);
+ 			if (active_rx_sa)
+ 				this_cpu_inc(active_rx_sa->stats->InPktsNotUsingSA);
+ 			goto drop_nosa;
+@@ -1230,7 +1230,7 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb)
+ 			u64_stats_update_begin(&rxsc_stats->syncp);
+ 			rxsc_stats->stats.InPktsLate++;
+ 			u64_stats_update_end(&rxsc_stats->syncp);
+-			macsec->secy.netdev->stats.rx_dropped++;
++			DEV_STATS_INC(macsec->secy.netdev, rx_dropped);
+ 			goto drop;
+ 		}
+ 	}
+@@ -1271,7 +1271,7 @@ deliver:
+ 	if (ret == NET_RX_SUCCESS)
+ 		count_rx(dev, len);
+ 	else
+-		macsec->secy.netdev->stats.rx_dropped++;
++		DEV_STATS_INC(macsec->secy.netdev, rx_dropped);
+ 
+ 	rcu_read_unlock();
+ 
+@@ -1308,7 +1308,7 @@ nosci:
+ 			u64_stats_update_begin(&secy_stats->syncp);
+ 			secy_stats->stats.InPktsNoSCI++;
+ 			u64_stats_update_end(&secy_stats->syncp);
+-			macsec->secy.netdev->stats.rx_errors++;
++			DEV_STATS_INC(macsec->secy.netdev, rx_errors);
+ 			continue;
+ 		}
+ 
+@@ -1327,7 +1327,7 @@ nosci:
+ 			secy_stats->stats.InPktsUnknownSCI++;
+ 			u64_stats_update_end(&secy_stats->syncp);
+ 		} else {
+-			macsec->secy.netdev->stats.rx_dropped++;
++			DEV_STATS_INC(macsec->secy.netdev, rx_dropped);
+ 		}
+ 	}
+ 
+@@ -3422,7 +3422,7 @@ static netdev_tx_t macsec_start_xmit(struct sk_buff *skb,
+ 
+ 	if (!secy->operational) {
+ 		kfree_skb(skb);
+-		dev->stats.tx_dropped++;
++		DEV_STATS_INC(dev, tx_dropped);
+ 		return NETDEV_TX_OK;
+ 	}
+ 
+@@ -3430,7 +3430,7 @@ static netdev_tx_t macsec_start_xmit(struct sk_buff *skb,
+ 	skb = macsec_encrypt(skb, dev);
+ 	if (IS_ERR(skb)) {
+ 		if (PTR_ERR(skb) != -EINPROGRESS)
+-			dev->stats.tx_dropped++;
++			DEV_STATS_INC(dev, tx_dropped);
+ 		return NETDEV_TX_OK;
+ 	}
+ 
+@@ -3667,9 +3667,9 @@ static void macsec_get_stats64(struct net_device *dev,
+ 
+ 	dev_fetch_sw_netstats(s, dev->tstats);
+ 
+-	s->rx_dropped = dev->stats.rx_dropped;
+-	s->tx_dropped = dev->stats.tx_dropped;
+-	s->rx_errors = dev->stats.rx_errors;
++	s->rx_dropped = atomic_long_read(&dev->stats.__rx_dropped);
++	s->tx_dropped = atomic_long_read(&dev->stats.__tx_dropped);
++	s->rx_errors = atomic_long_read(&dev->stats.__rx_errors);
+ }
+ 
+ static int macsec_get_iflink(const struct net_device *dev)
+diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
+index 656136628ffd8..ef6dc008e4c50 100644
+--- a/drivers/net/phy/at803x.c
++++ b/drivers/net/phy/at803x.c
+@@ -2086,8 +2086,6 @@ static struct phy_driver at803x_driver[] = {
+ 	.flags			= PHY_POLL_CABLE_TEST,
+ 	.config_init		= at803x_config_init,
+ 	.link_change_notify	= at803x_link_change_notify,
+-	.set_wol		= at803x_set_wol,
+-	.get_wol		= at803x_get_wol,
+ 	.suspend		= at803x_suspend,
+ 	.resume			= at803x_resume,
+ 	/* PHY_BASIC_FEATURES */
+diff --git a/drivers/net/tun.c b/drivers/net/tun.c
+index 25f0191df00bf..100339bc8b04a 100644
+--- a/drivers/net/tun.c
++++ b/drivers/net/tun.c
+@@ -1594,7 +1594,7 @@ static bool tun_can_build_skb(struct tun_struct *tun, struct tun_file *tfile,
+ 	if (zerocopy)
+ 		return false;
+ 
+-	if (SKB_DATA_ALIGN(len + TUN_RX_PAD) +
++	if (SKB_DATA_ALIGN(len + TUN_RX_PAD + XDP_PACKET_HEADROOM) +
+ 	    SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) > PAGE_SIZE)
+ 		return false;
+ 
+diff --git a/drivers/net/vxlan/vxlan_vnifilter.c b/drivers/net/vxlan/vxlan_vnifilter.c
+index a3de081cda5ee..c3ff30ab782e9 100644
+--- a/drivers/net/vxlan/vxlan_vnifilter.c
++++ b/drivers/net/vxlan/vxlan_vnifilter.c
+@@ -713,6 +713,12 @@ static struct vxlan_vni_node *vxlan_vni_alloc(struct vxlan_dev *vxlan,
+ 	return vninode;
+ }
+ 
++static void vxlan_vni_free(struct vxlan_vni_node *vninode)
++{
++	free_percpu(vninode->stats);
++	kfree(vninode);
++}
++
+ static int vxlan_vni_add(struct vxlan_dev *vxlan,
+ 			 struct vxlan_vni_group *vg,
+ 			 u32 vni, union vxlan_addr *group,
+@@ -740,7 +746,7 @@ static int vxlan_vni_add(struct vxlan_dev *vxlan,
+ 					    &vninode->vnode,
+ 					    vxlan_vni_rht_params);
+ 	if (err) {
+-		kfree(vninode);
++		vxlan_vni_free(vninode);
+ 		return err;
+ 	}
+ 
+@@ -763,8 +769,7 @@ static void vxlan_vni_node_rcu_free(struct rcu_head *rcu)
+ 	struct vxlan_vni_node *v;
+ 
+ 	v = container_of(rcu, struct vxlan_vni_node, rcu);
+-	free_percpu(v->stats);
+-	kfree(v);
++	vxlan_vni_free(v);
+ }
+ 
+ static int vxlan_vni_del(struct vxlan_dev *vxlan,
+diff --git a/drivers/net/wireguard/allowedips.c b/drivers/net/wireguard/allowedips.c
+index 5bf7822c53f18..0ba714ca5185c 100644
+--- a/drivers/net/wireguard/allowedips.c
++++ b/drivers/net/wireguard/allowedips.c
+@@ -6,7 +6,7 @@
+ #include "allowedips.h"
+ #include "peer.h"
+ 
+-enum { MAX_ALLOWEDIPS_BITS = 128 };
++enum { MAX_ALLOWEDIPS_DEPTH = 129 };
+ 
+ static struct kmem_cache *node_cache;
+ 
+@@ -42,7 +42,7 @@ static void push_rcu(struct allowedips_node **stack,
+ 		     struct allowedips_node __rcu *p, unsigned int *len)
+ {
+ 	if (rcu_access_pointer(p)) {
+-		if (WARN_ON(IS_ENABLED(DEBUG) && *len >= MAX_ALLOWEDIPS_BITS))
++		if (WARN_ON(IS_ENABLED(DEBUG) && *len >= MAX_ALLOWEDIPS_DEPTH))
+ 			return;
+ 		stack[(*len)++] = rcu_dereference_raw(p);
+ 	}
+@@ -55,7 +55,7 @@ static void node_free_rcu(struct rcu_head *rcu)
+ 
+ static void root_free_rcu(struct rcu_head *rcu)
+ {
+-	struct allowedips_node *node, *stack[MAX_ALLOWEDIPS_BITS] = {
++	struct allowedips_node *node, *stack[MAX_ALLOWEDIPS_DEPTH] = {
+ 		container_of(rcu, struct allowedips_node, rcu) };
+ 	unsigned int len = 1;
+ 
+@@ -68,7 +68,7 @@ static void root_free_rcu(struct rcu_head *rcu)
+ 
+ static void root_remove_peer_lists(struct allowedips_node *root)
+ {
+-	struct allowedips_node *node, *stack[MAX_ALLOWEDIPS_BITS] = { root };
++	struct allowedips_node *node, *stack[MAX_ALLOWEDIPS_DEPTH] = { root };
+ 	unsigned int len = 1;
+ 
+ 	while (len > 0 && (node = stack[--len])) {
+diff --git a/drivers/net/wireguard/selftest/allowedips.c b/drivers/net/wireguard/selftest/allowedips.c
+index 78ebe2892a788..3d1f64ff2e122 100644
+--- a/drivers/net/wireguard/selftest/allowedips.c
++++ b/drivers/net/wireguard/selftest/allowedips.c
+@@ -593,16 +593,20 @@ bool __init wg_allowedips_selftest(void)
+ 	wg_allowedips_remove_by_peer(&t, a, &mutex);
+ 	test_negative(4, a, 192, 168, 0, 1);
+ 
+-	/* These will hit the WARN_ON(len >= MAX_ALLOWEDIPS_BITS) in free_node
++	/* These will hit the WARN_ON(len >= MAX_ALLOWEDIPS_DEPTH) in free_node
+ 	 * if something goes wrong.
+ 	 */
+-	for (i = 0; i < MAX_ALLOWEDIPS_BITS; ++i) {
+-		part = cpu_to_be64(~(1LLU << (i % 64)));
+-		memset(&ip, 0xff, 16);
+-		memcpy((u8 *)&ip + (i < 64) * 8, &part, 8);
++	for (i = 0; i < 64; ++i) {
++		part = cpu_to_be64(~0LLU << i);
++		memset(&ip, 0xff, 8);
++		memcpy((u8 *)&ip + 8, &part, 8);
++		wg_allowedips_insert_v6(&t, &ip, 128, a, &mutex);
++		memcpy(&ip, &part, 8);
++		memset((u8 *)&ip + 8, 0, 8);
+ 		wg_allowedips_insert_v6(&t, &ip, 128, a, &mutex);
+ 	}
+-
++	memset(&ip, 0, 16);
++	wg_allowedips_insert_v6(&t, &ip, 128, a, &mutex);
+ 	wg_allowedips_free(&t, &mutex);
+ 
+ 	wg_allowedips_init(&t);
+diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+index de8a2e27f49c7..2a90bb24ba77f 100644
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -1456,6 +1456,10 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
+ 		params_size -= BRCMF_SCAN_PARAMS_V2_FIXED_SIZE;
+ 		params_size += BRCMF_SCAN_PARAMS_FIXED_SIZE;
+ 		params_v1 = kzalloc(params_size, GFP_KERNEL);
++		if (!params_v1) {
++			err = -ENOMEM;
++			goto exit_params;
++		}
+ 		params_v1->version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION);
+ 		brcmf_scan_params_v2_to_v1(&params->params_v2_le, &params_v1->params_le);
+ 		kfree(params);
+@@ -1473,6 +1477,7 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
+ 			bphy_err(drvr, "error (%d)\n", err);
+ 	}
+ 
++exit_params:
+ 	kfree(params);
+ exit:
+ 	return err;
+diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
+index 512de491a064b..e31c0cdfd16c8 100644
+--- a/drivers/net/wireless/realtek/rtw89/mac.c
++++ b/drivers/net/wireless/realtek/rtw89/mac.c
+@@ -2484,7 +2484,7 @@ static int cmac_dma_init(struct rtw89_dev *rtwdev, u8 mac_idx)
+ 	u32 reg;
+ 	int ret;
+ 
+-	if (chip_id != RTL8852A && chip_id != RTL8852B)
++	if (chip_id != RTL8852B)
+ 		return 0;
+ 
+ 	ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL);
+diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
+index 45f1dac07685d..c61173be41270 100644
+--- a/drivers/nvme/host/core.c
++++ b/drivers/nvme/host/core.c
+@@ -4728,6 +4728,12 @@ void nvme_remove_namespaces(struct nvme_ctrl *ctrl)
+ 	 */
+ 	nvme_mpath_clear_ctrl_paths(ctrl);
+ 
++	/*
++	 * Unquiesce io queues so any pending IO won't hang, especially
++	 * those submitted from scan work
++	 */
++	nvme_unquiesce_io_queues(ctrl);
++
+ 	/* prevent racing with ns scanning */
+ 	flush_work(&ctrl->scan_work);
+ 
+@@ -4737,10 +4743,8 @@ void nvme_remove_namespaces(struct nvme_ctrl *ctrl)
+ 	 * removing the namespaces' disks; fail all the queues now to avoid
+ 	 * potentially having to clean up the failed sync later.
+ 	 */
+-	if (ctrl->state == NVME_CTRL_DEAD) {
++	if (ctrl->state == NVME_CTRL_DEAD)
+ 		nvme_mark_namespaces_dead(ctrl);
+-		nvme_unquiesce_io_queues(ctrl);
+-	}
+ 
+ 	/* this is a no-op when called from the controller reset handler */
+ 	nvme_change_ctrl_state(ctrl, NVME_CTRL_DELETING_NOIO);
+diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
+index 5b5303f0e2c20..a277ef16392ca 100644
+--- a/drivers/nvme/host/pci.c
++++ b/drivers/nvme/host/pci.c
+@@ -3391,7 +3391,8 @@ static const struct pci_device_id nvme_id_table[] = {
+ 	{ PCI_DEVICE(0x1d97, 0x2263),   /* SPCC */
+ 		.driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, },
+ 	{ PCI_DEVICE(0x144d, 0xa80b),   /* Samsung PM9B1 256G and 512G */
+-		.driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, },
++		.driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES |
++				NVME_QUIRK_BOGUS_NID, },
+ 	{ PCI_DEVICE(0x144d, 0xa809),   /* Samsung MZALQ256HBJD 256G */
+ 		.driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, },
+ 	{ PCI_DEVICE(0x1cc4, 0x6303),   /* UMIS RPJTJ512MGE1QDY 512G */
+diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c
+index 0eb79696fb736..354cce8853c1c 100644
+--- a/drivers/nvme/host/rdma.c
++++ b/drivers/nvme/host/rdma.c
+@@ -918,6 +918,7 @@ static int nvme_rdma_configure_io_queues(struct nvme_rdma_ctrl *ctrl, bool new)
+ 		goto out_cleanup_tagset;
+ 
+ 	if (!new) {
++		nvme_start_freeze(&ctrl->ctrl);
+ 		nvme_unquiesce_io_queues(&ctrl->ctrl);
+ 		if (!nvme_wait_freeze_timeout(&ctrl->ctrl, NVME_IO_TIMEOUT)) {
+ 			/*
+@@ -926,6 +927,7 @@ static int nvme_rdma_configure_io_queues(struct nvme_rdma_ctrl *ctrl, bool new)
+ 			 * to be safe.
+ 			 */
+ 			ret = -ENODEV;
++			nvme_unfreeze(&ctrl->ctrl);
+ 			goto out_wait_freeze_timed_out;
+ 		}
+ 		blk_mq_update_nr_hw_queues(ctrl->ctrl.tagset,
+@@ -975,7 +977,6 @@ static void nvme_rdma_teardown_io_queues(struct nvme_rdma_ctrl *ctrl,
+ 		bool remove)
+ {
+ 	if (ctrl->ctrl.queue_count > 1) {
+-		nvme_start_freeze(&ctrl->ctrl);
+ 		nvme_quiesce_io_queues(&ctrl->ctrl);
+ 		nvme_sync_io_queues(&ctrl->ctrl);
+ 		nvme_rdma_stop_io_queues(ctrl);
+diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c
+index bf0230442d570..5ae08e9cb16de 100644
+--- a/drivers/nvme/host/tcp.c
++++ b/drivers/nvme/host/tcp.c
+@@ -1909,6 +1909,7 @@ static int nvme_tcp_configure_io_queues(struct nvme_ctrl *ctrl, bool new)
+ 		goto out_cleanup_connect_q;
+ 
+ 	if (!new) {
++		nvme_start_freeze(ctrl);
+ 		nvme_unquiesce_io_queues(ctrl);
+ 		if (!nvme_wait_freeze_timeout(ctrl, NVME_IO_TIMEOUT)) {
+ 			/*
+@@ -1917,6 +1918,7 @@ static int nvme_tcp_configure_io_queues(struct nvme_ctrl *ctrl, bool new)
+ 			 * to be safe.
+ 			 */
+ 			ret = -ENODEV;
++			nvme_unfreeze(ctrl);
+ 			goto out_wait_freeze_timed_out;
+ 		}
+ 		blk_mq_update_nr_hw_queues(ctrl->tagset,
+@@ -2021,7 +2023,6 @@ static void nvme_tcp_teardown_io_queues(struct nvme_ctrl *ctrl,
+ 	if (ctrl->queue_count <= 1)
+ 		return;
+ 	nvme_quiesce_admin_queue(ctrl);
+-	nvme_start_freeze(ctrl);
+ 	nvme_quiesce_io_queues(ctrl);
+ 	nvme_sync_io_queues(ctrl);
+ 	nvme_tcp_stop_io_queues(ctrl);
+diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
+index 5bc81cc0a2de4..46b252bbe5000 100644
+--- a/drivers/pci/bus.c
++++ b/drivers/pci/bus.c
+@@ -11,6 +11,7 @@
+ #include <linux/pci.h>
+ #include <linux/errno.h>
+ #include <linux/ioport.h>
++#include <linux/of.h>
+ #include <linux/proc_fs.h>
+ #include <linux/slab.h>
+ 
+@@ -332,6 +333,7 @@ void __weak pcibios_bus_add_device(struct pci_dev *pdev) { }
+  */
+ void pci_bus_add_device(struct pci_dev *dev)
+ {
++	struct device_node *dn = dev->dev.of_node;
+ 	int retval;
+ 
+ 	/*
+@@ -344,7 +346,7 @@ void pci_bus_add_device(struct pci_dev *dev)
+ 	pci_proc_attach_device(dev);
+ 	pci_bridge_d3_update(dev);
+ 
+-	dev->match_driver = true;
++	dev->match_driver = !dn || of_device_is_available(dn);
+ 	retval = device_attach(&dev->dev);
+ 	if (retval < 0 && retval != -EPROBE_DEFER)
+ 		pci_warn(dev, "device attach failed (%d)\n", retval);
+diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig
+index 8d49bad7f8472..0859be86e7183 100644
+--- a/drivers/pci/controller/Kconfig
++++ b/drivers/pci/controller/Kconfig
+@@ -179,7 +179,6 @@ config PCI_MVEBU
+ 	depends on MVEBU_MBUS
+ 	depends on ARM
+ 	depends on OF
+-	depends on BROKEN
+ 	select PCI_BRIDGE_EMUL
+ 	help
+ 	 Add support for Marvell EBU PCIe controller. This PCIe controller
+diff --git a/drivers/pci/of.c b/drivers/pci/of.c
+index 2c25f4fa0225a..6f305362ba304 100644
+--- a/drivers/pci/of.c
++++ b/drivers/pci/of.c
+@@ -34,11 +34,6 @@ int pci_set_of_node(struct pci_dev *dev)
+ 	if (!node)
+ 		return 0;
+ 
+-	if (!of_device_is_available(node)) {
+-		of_node_put(node);
+-		return -ENODEV;
+-	}
+-
+ 	dev->dev.of_node = node;
+ 	dev->dev.fwnode = &node->fwnode;
+ 	return 0;
+diff --git a/drivers/platform/x86/lenovo-ymc.c b/drivers/platform/x86/lenovo-ymc.c
+index 41676188b3738..f360370d50027 100644
+--- a/drivers/platform/x86/lenovo-ymc.c
++++ b/drivers/platform/x86/lenovo-ymc.c
+@@ -24,6 +24,10 @@ static bool ec_trigger __read_mostly;
+ module_param(ec_trigger, bool, 0444);
+ MODULE_PARM_DESC(ec_trigger, "Enable EC triggering work-around to force emitting tablet mode events");
+ 
++static bool force;
++module_param(force, bool, 0444);
++MODULE_PARM_DESC(force, "Force loading on boards without a convertible DMI chassis-type");
++
+ static const struct dmi_system_id ec_trigger_quirk_dmi_table[] = {
+ 	{
+ 		/* Lenovo Yoga 7 14ARB7 */
+@@ -35,6 +39,20 @@ static const struct dmi_system_id ec_trigger_quirk_dmi_table[] = {
+ 	{ }
+ };
+ 
++static const struct dmi_system_id allowed_chasis_types_dmi_table[] = {
++	{
++		.matches = {
++			DMI_EXACT_MATCH(DMI_CHASSIS_TYPE, "31" /* Convertible */),
++		},
++	},
++	{
++		.matches = {
++			DMI_EXACT_MATCH(DMI_CHASSIS_TYPE, "32" /* Detachable */),
++		},
++	},
++	{ }
++};
++
+ struct lenovo_ymc_private {
+ 	struct input_dev *input_dev;
+ 	struct acpi_device *ec_acpi_dev;
+@@ -111,6 +129,13 @@ static int lenovo_ymc_probe(struct wmi_device *wdev, const void *ctx)
+ 	struct input_dev *input_dev;
+ 	int err;
+ 
++	if (!dmi_check_system(allowed_chasis_types_dmi_table)) {
++		if (force)
++			dev_info(&wdev->dev, "Force loading Lenovo YMC support\n");
++		else
++			return -ENODEV;
++	}
++
+ 	ec_trigger |= dmi_check_system(ec_trigger_quirk_dmi_table);
+ 
+ 	priv = devm_kzalloc(&wdev->dev, sizeof(*priv), GFP_KERNEL);
+diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c
+index 67367f010139e..7d33977d9c609 100644
+--- a/drivers/platform/x86/mlx-platform.c
++++ b/drivers/platform/x86/mlx-platform.c
+@@ -62,10 +62,6 @@
+ #define MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET	0x37
+ #define MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET	0x3a
+ #define MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET	0x3b
+-#define MLXPLAT_CPLD_LPC_REG_DBG1_OFFSET	0x3c
+-#define MLXPLAT_CPLD_LPC_REG_DBG2_OFFSET	0x3d
+-#define MLXPLAT_CPLD_LPC_REG_DBG3_OFFSET	0x3e
+-#define MLXPLAT_CPLD_LPC_REG_DBG4_OFFSET	0x3f
+ #define MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET	0x40
+ #define MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET	0x41
+ #define MLXPLAT_CPLD_LPC_REG_AGGRCO_OFFSET	0x42
+@@ -126,6 +122,10 @@
+ #define MLXPLAT_CPLD_LPC_REG_LC_SD_EVENT_OFFSET	0xaa
+ #define MLXPLAT_CPLD_LPC_REG_LC_SD_MASK_OFFSET	0xab
+ #define MLXPLAT_CPLD_LPC_REG_LC_PWR_ON		0xb2
++#define MLXPLAT_CPLD_LPC_REG_DBG1_OFFSET	0xb6
++#define MLXPLAT_CPLD_LPC_REG_DBG2_OFFSET	0xb7
++#define MLXPLAT_CPLD_LPC_REG_DBG3_OFFSET	0xb8
++#define MLXPLAT_CPLD_LPC_REG_DBG4_OFFSET	0xb9
+ #define MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET	0xc2
+ #define MLXPLAT_CPLD_LPC_REG_SPI_CHNL_SELECT	0xc3
+ #define MLXPLAT_CPLD_LPC_REG_WD_CLEAR_OFFSET	0xc7
+@@ -222,7 +222,7 @@
+ 					 MLXPLAT_CPLD_AGGR_MASK_LC_SDWN)
+ #define MLXPLAT_CPLD_LOW_AGGR_MASK_LOW	0xc1
+ #define MLXPLAT_CPLD_LOW_AGGR_MASK_ASIC2	BIT(2)
+-#define MLXPLAT_CPLD_LOW_AGGR_MASK_PWR_BUT	BIT(4)
++#define MLXPLAT_CPLD_LOW_AGGR_MASK_PWR_BUT	GENMASK(5, 4)
+ #define MLXPLAT_CPLD_LOW_AGGR_MASK_I2C	BIT(6)
+ #define MLXPLAT_CPLD_PSU_MASK		GENMASK(1, 0)
+ #define MLXPLAT_CPLD_PWR_MASK		GENMASK(1, 0)
+@@ -237,7 +237,7 @@
+ #define MLXPLAT_CPLD_GWP_MASK		GENMASK(0, 0)
+ #define MLXPLAT_CPLD_EROT_MASK		GENMASK(1, 0)
+ #define MLXPLAT_CPLD_PWR_BUTTON_MASK	BIT(0)
+-#define MLXPLAT_CPLD_LATCH_RST_MASK	BIT(5)
++#define MLXPLAT_CPLD_LATCH_RST_MASK	BIT(6)
+ #define MLXPLAT_CPLD_THERMAL1_PDB_MASK	BIT(3)
+ #define MLXPLAT_CPLD_THERMAL2_PDB_MASK	BIT(4)
+ #define MLXPLAT_CPLD_INTRUSION_MASK	BIT(6)
+@@ -2356,7 +2356,7 @@ mlxplat_mlxcpld_l1_switch_pwr_events_handler(void *handle, enum mlxreg_hotplug_k
+ 					     u8 action)
+ {
+ 	dev_info(&mlxplat_dev->dev, "System shutdown due to short press of power button");
+-	kernel_halt();
++	kernel_power_off();
+ 	return 0;
+ }
+ 
+@@ -2475,7 +2475,7 @@ static struct mlxreg_core_item mlxplat_mlxcpld_l1_switch_events_items[] = {
+ 		.reg = MLXPLAT_CPLD_LPC_REG_PWRB_OFFSET,
+ 		.mask = MLXPLAT_CPLD_PWR_BUTTON_MASK,
+ 		.count = ARRAY_SIZE(mlxplat_mlxcpld_l1_switch_pwr_events_items_data),
+-		.inversed = 0,
++		.inversed = 1,
+ 		.health = false,
+ 	},
+ 	{
+@@ -2484,7 +2484,7 @@ static struct mlxreg_core_item mlxplat_mlxcpld_l1_switch_events_items[] = {
+ 		.reg = MLXPLAT_CPLD_LPC_REG_BRD_OFFSET,
+ 		.mask = MLXPLAT_CPLD_L1_CHA_HEALTH_MASK,
+ 		.count = ARRAY_SIZE(mlxplat_mlxcpld_l1_switch_health_events_items_data),
+-		.inversed = 0,
++		.inversed = 1,
+ 		.health = false,
+ 		.ind = 8,
+ 	},
+@@ -3677,7 +3677,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = {
+ 	{
+ 		.label = "latch_reset",
+ 		.reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
+-		.mask = GENMASK(7, 0) & ~BIT(5),
++		.mask = GENMASK(7, 0) & ~BIT(6),
+ 		.mode = 0200,
+ 	},
+ 	{
+@@ -6238,8 +6238,6 @@ static void mlxplat_i2c_mux_topolgy_exit(struct mlxplat_priv *priv)
+ 		if (priv->pdev_mux[i])
+ 			platform_device_unregister(priv->pdev_mux[i]);
+ 	}
+-
+-	mlxplat_post_exit();
+ }
+ 
+ static int mlxplat_i2c_main_complition_notify(void *handle, int id)
+@@ -6369,6 +6367,7 @@ static void __exit mlxplat_exit(void)
+ 		pm_power_off = NULL;
+ 	mlxplat_pre_exit(priv);
+ 	mlxplat_i2c_main_exit(priv);
++	mlxplat_post_exit();
+ }
+ module_exit(mlxplat_exit);
+ 
+diff --git a/drivers/platform/x86/msi-ec.c b/drivers/platform/x86/msi-ec.c
+index ff93986e3d35a..f26a3121092f9 100644
+--- a/drivers/platform/x86/msi-ec.c
++++ b/drivers/platform/x86/msi-ec.c
+@@ -27,15 +27,15 @@
+ #include <linux/seq_file.h>
+ #include <linux/string.h>
+ 
+-static const char *const SM_ECO_NAME       = "eco";
+-static const char *const SM_COMFORT_NAME   = "comfort";
+-static const char *const SM_SPORT_NAME     = "sport";
+-static const char *const SM_TURBO_NAME     = "turbo";
+-
+-static const char *const FM_AUTO_NAME     = "auto";
+-static const char *const FM_SILENT_NAME   = "silent";
+-static const char *const FM_BASIC_NAME    = "basic";
+-static const char *const FM_ADVANCED_NAME = "advanced";
++#define SM_ECO_NAME		"eco"
++#define SM_COMFORT_NAME		"comfort"
++#define SM_SPORT_NAME		"sport"
++#define SM_TURBO_NAME		"turbo"
++
++#define FM_AUTO_NAME		"auto"
++#define FM_SILENT_NAME		"silent"
++#define FM_BASIC_NAME		"basic"
++#define FM_ADVANCED_NAME	"advanced"
+ 
+ static const char * const ALLOWED_FW_0[] __initconst = {
+ 	"14C1EMS1.012",
+diff --git a/drivers/platform/x86/serial-multi-instantiate.c b/drivers/platform/x86/serial-multi-instantiate.c
+index f3dcbdd72fec7..8158e3cf5d6de 100644
+--- a/drivers/platform/x86/serial-multi-instantiate.c
++++ b/drivers/platform/x86/serial-multi-instantiate.c
+@@ -21,6 +21,7 @@
+ #define IRQ_RESOURCE_NONE	0
+ #define IRQ_RESOURCE_GPIO	1
+ #define IRQ_RESOURCE_APIC	2
++#define IRQ_RESOURCE_AUTO   3
+ 
+ enum smi_bus_type {
+ 	SMI_I2C,
+@@ -52,6 +53,18 @@ static int smi_get_irq(struct platform_device *pdev, struct acpi_device *adev,
+ 	int ret;
+ 
+ 	switch (inst->flags & IRQ_RESOURCE_TYPE) {
++	case IRQ_RESOURCE_AUTO:
++		ret = acpi_dev_gpio_irq_get(adev, inst->irq_idx);
++		if (ret > 0) {
++			dev_dbg(&pdev->dev, "Using gpio irq\n");
++			break;
++		}
++		ret = platform_get_irq(pdev, inst->irq_idx);
++		if (ret > 0) {
++			dev_dbg(&pdev->dev, "Using platform irq\n");
++			break;
++		}
++		break;
+ 	case IRQ_RESOURCE_GPIO:
+ 		ret = acpi_dev_gpio_irq_get(adev, inst->irq_idx);
+ 		break;
+@@ -307,10 +320,23 @@ static const struct smi_node int3515_data = {
+ 
+ static const struct smi_node cs35l41_hda = {
+ 	.instances = {
+-		{ "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
+-		{ "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
+-		{ "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
+-		{ "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
++		{ "cs35l41-hda", IRQ_RESOURCE_AUTO, 0 },
++		{ "cs35l41-hda", IRQ_RESOURCE_AUTO, 0 },
++		{ "cs35l41-hda", IRQ_RESOURCE_AUTO, 0 },
++		{ "cs35l41-hda", IRQ_RESOURCE_AUTO, 0 },
++		{}
++	},
++	.bus_type = SMI_AUTO_DETECT,
++};
++
++static const struct smi_node cs35l56_hda = {
++	.instances = {
++		{ "cs35l56-hda", IRQ_RESOURCE_AUTO, 0 },
++		{ "cs35l56-hda", IRQ_RESOURCE_AUTO, 0 },
++		{ "cs35l56-hda", IRQ_RESOURCE_AUTO, 0 },
++		{ "cs35l56-hda", IRQ_RESOURCE_AUTO, 0 },
++		/* a 5th entry is an alias address, not a real device */
++		{ "cs35l56-hda_dummy_dev" },
+ 		{}
+ 	},
+ 	.bus_type = SMI_AUTO_DETECT,
+@@ -324,6 +350,7 @@ static const struct acpi_device_id smi_acpi_ids[] = {
+ 	{ "BSG1160", (unsigned long)&bsg1160_data },
+ 	{ "BSG2150", (unsigned long)&bsg2150_data },
+ 	{ "CSC3551", (unsigned long)&cs35l41_hda },
++	{ "CSC3556", (unsigned long)&cs35l56_hda },
+ 	{ "INT3515", (unsigned long)&int3515_data },
+ 	/* Non-conforming _HID for Cirrus Logic already released */
+ 	{ "CLSA0100", (unsigned long)&cs35l41_hda },
+diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
+index e1e4f9d108879..857be0f3ae5b9 100644
+--- a/drivers/scsi/53c700.c
++++ b/drivers/scsi/53c700.c
+@@ -1598,7 +1598,7 @@ NCR_700_intr(int irq, void *dev_id)
+ 				printk("scsi%d (%d:%d) PHASE MISMATCH IN SEND MESSAGE %d remain, return %p[%04x], phase %s\n", host->host_no, pun, lun, count, (void *)temp, temp - hostdata->pScript, sbcl_to_string(NCR_700_readb(host, SBCL_REG)));
+ #endif
+ 				resume_offset = hostdata->pScript + Ent_SendMessagePhaseMismatch;
+-			} else if(dsp >= to32bit(&slot->pSG[0].ins) &&
++			} else if (slot && dsp >= to32bit(&slot->pSG[0].ins) &&
+ 				  dsp <= to32bit(&slot->pSG[NCR_700_SG_SEGMENTS].ins)) {
+ 				int data_transfer = NCR_700_readl(host, DBC_REG) & 0xffffff;
+ 				int SGcount = (dsp - to32bit(&slot->pSG[0].ins))/sizeof(struct NCR_700_SG_List);
+diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h
+index d82de34f6fd73..e51e92f932fa8 100644
+--- a/drivers/scsi/fnic/fnic.h
++++ b/drivers/scsi/fnic/fnic.h
+@@ -27,7 +27,7 @@
+ 
+ #define DRV_NAME		"fnic"
+ #define DRV_DESCRIPTION		"Cisco FCoE HBA Driver"
+-#define DRV_VERSION		"1.6.0.54"
++#define DRV_VERSION		"1.6.0.55"
+ #define PFX			DRV_NAME ": "
+ #define DFX                     DRV_NAME "%d: "
+ 
+diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c
+index 26dbd347156ef..be89ce96df46c 100644
+--- a/drivers/scsi/fnic/fnic_scsi.c
++++ b/drivers/scsi/fnic/fnic_scsi.c
+@@ -2139,7 +2139,7 @@ static int fnic_clean_pending_aborts(struct fnic *fnic,
+ 				     bool new_sc)
+ 
+ {
+-	int ret = SUCCESS;
++	int ret = 0;
+ 	struct fnic_pending_aborts_iter_data iter_data = {
+ 		.fnic = fnic,
+ 		.lun_dev = lr_sc->device,
+@@ -2159,9 +2159,11 @@ static int fnic_clean_pending_aborts(struct fnic *fnic,
+ 
+ 	/* walk again to check, if IOs are still pending in fw */
+ 	if (fnic_is_abts_pending(fnic, lr_sc))
+-		ret = FAILED;
++		ret = 1;
+ 
+ clean_pending_aborts_end:
++	FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host,
++			"%s: exit status: %d\n", __func__, ret);
+ 	return ret;
+ }
+ 
+diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c
+index 2a31ddc99dde5..7825765c936cd 100644
+--- a/drivers/scsi/qedf/qedf_main.c
++++ b/drivers/scsi/qedf/qedf_main.c
+@@ -31,6 +31,7 @@ static void qedf_remove(struct pci_dev *pdev);
+ static void qedf_shutdown(struct pci_dev *pdev);
+ static void qedf_schedule_recovery_handler(void *dev);
+ static void qedf_recovery_handler(struct work_struct *work);
++static int qedf_suspend(struct pci_dev *pdev, pm_message_t state);
+ 
+ /*
+  * Driver module parameters.
+@@ -3271,6 +3272,7 @@ static struct pci_driver qedf_pci_driver = {
+ 	.probe = qedf_probe,
+ 	.remove = qedf_remove,
+ 	.shutdown = qedf_shutdown,
++	.suspend = qedf_suspend,
+ };
+ 
+ static int __qedf_probe(struct pci_dev *pdev, int mode)
+@@ -4000,6 +4002,22 @@ static void qedf_shutdown(struct pci_dev *pdev)
+ 	__qedf_remove(pdev, QEDF_MODE_NORMAL);
+ }
+ 
++static int qedf_suspend(struct pci_dev *pdev, pm_message_t state)
++{
++	struct qedf_ctx *qedf;
++
++	if (!pdev) {
++		QEDF_ERR(NULL, "pdev is NULL.\n");
++		return -ENODEV;
++	}
++
++	qedf = pci_get_drvdata(pdev);
++
++	QEDF_ERR(&qedf->dbg_ctx, "%s: Device does not support suspend operation\n", __func__);
++
++	return -EPERM;
++}
++
+ /*
+  * Recovery handler code
+  */
+diff --git a/drivers/scsi/qedi/qedi_main.c b/drivers/scsi/qedi/qedi_main.c
+index 45d3595541820..ef62dbbc1868e 100644
+--- a/drivers/scsi/qedi/qedi_main.c
++++ b/drivers/scsi/qedi/qedi_main.c
+@@ -69,6 +69,7 @@ static struct nvm_iscsi_block *qedi_get_nvram_block(struct qedi_ctx *qedi);
+ static void qedi_recovery_handler(struct work_struct *work);
+ static void qedi_schedule_hw_err_handler(void *dev,
+ 					 enum qed_hw_err_type err_type);
++static int qedi_suspend(struct pci_dev *pdev, pm_message_t state);
+ 
+ static int qedi_iscsi_event_cb(void *context, u8 fw_event_code, void *fw_handle)
+ {
+@@ -2510,6 +2511,22 @@ static void qedi_shutdown(struct pci_dev *pdev)
+ 	__qedi_remove(pdev, QEDI_MODE_SHUTDOWN);
+ }
+ 
++static int qedi_suspend(struct pci_dev *pdev, pm_message_t state)
++{
++	struct qedi_ctx *qedi;
++
++	if (!pdev) {
++		QEDI_ERR(NULL, "pdev is NULL.\n");
++		return -ENODEV;
++	}
++
++	qedi = pci_get_drvdata(pdev);
++
++	QEDI_ERR(&qedi->dbg_ctx, "%s: Device does not support suspend operation\n", __func__);
++
++	return -EPERM;
++}
++
+ static int __qedi_probe(struct pci_dev *pdev, int mode)
+ {
+ 	struct qedi_ctx *qedi;
+@@ -2868,6 +2885,7 @@ static struct pci_driver qedi_pci_driver = {
+ 	.remove = qedi_remove,
+ 	.shutdown = qedi_shutdown,
+ 	.err_handler = &qedi_err_handler,
++	.suspend = qedi_suspend,
+ };
+ 
+ static int __init qedi_init(void)
+diff --git a/drivers/scsi/raid_class.c b/drivers/scsi/raid_class.c
+index 898a0bdf8df67..711252e52d8e1 100644
+--- a/drivers/scsi/raid_class.c
++++ b/drivers/scsi/raid_class.c
+@@ -248,6 +248,7 @@ int raid_component_add(struct raid_template *r,struct device *raid_dev,
+ 	return 0;
+ 
+ err_out:
++	put_device(&rc->dev);
+ 	list_del(&rc->node);
+ 	rd->component_count--;
+ 	put_device(component_dev);
+diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c
+index 4a6eb1741be0d..41f23cd0bfb45 100644
+--- a/drivers/scsi/scsi_proc.c
++++ b/drivers/scsi/scsi_proc.c
+@@ -406,7 +406,7 @@ static ssize_t proc_scsi_write(struct file *file, const char __user *buf,
+ 			       size_t length, loff_t *ppos)
+ {
+ 	int host, channel, id, lun;
+-	char *buffer, *p;
++	char *buffer, *end, *p;
+ 	int err;
+ 
+ 	if (!buf || length > PAGE_SIZE)
+@@ -421,10 +421,14 @@ static ssize_t proc_scsi_write(struct file *file, const char __user *buf,
+ 		goto out;
+ 
+ 	err = -EINVAL;
+-	if (length < PAGE_SIZE)
+-		buffer[length] = '\0';
+-	else if (buffer[PAGE_SIZE-1])
+-		goto out;
++	if (length < PAGE_SIZE) {
++		end = buffer + length;
++		*end = '\0';
++	} else {
++		end = buffer + PAGE_SIZE - 1;
++		if (*end)
++			goto out;
++	}
+ 
+ 	/*
+ 	 * Usage: echo "scsi add-single-device 0 1 2 3" >/proc/scsi/scsi
+@@ -433,10 +437,10 @@ static ssize_t proc_scsi_write(struct file *file, const char __user *buf,
+ 	if (!strncmp("scsi add-single-device", buffer, 22)) {
+ 		p = buffer + 23;
+ 
+-		host = simple_strtoul(p, &p, 0);
+-		channel = simple_strtoul(p + 1, &p, 0);
+-		id = simple_strtoul(p + 1, &p, 0);
+-		lun = simple_strtoul(p + 1, &p, 0);
++		host    = (p     < end) ? simple_strtoul(p, &p, 0) : 0;
++		channel = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0;
++		id      = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0;
++		lun     = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0;
+ 
+ 		err = scsi_add_single_device(host, channel, id, lun);
+ 
+@@ -447,10 +451,10 @@ static ssize_t proc_scsi_write(struct file *file, const char __user *buf,
+ 	} else if (!strncmp("scsi remove-single-device", buffer, 25)) {
+ 		p = buffer + 26;
+ 
+-		host = simple_strtoul(p, &p, 0);
+-		channel = simple_strtoul(p + 1, &p, 0);
+-		id = simple_strtoul(p + 1, &p, 0);
+-		lun = simple_strtoul(p + 1, &p, 0);
++		host    = (p     < end) ? simple_strtoul(p, &p, 0) : 0;
++		channel = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0;
++		id      = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0;
++		lun     = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0;
+ 
+ 		err = scsi_remove_single_device(host, channel, id, lun);
+ 	}
+diff --git a/drivers/scsi/snic/snic_disc.c b/drivers/scsi/snic/snic_disc.c
+index 8fbf3c1b1311d..cd27562ec922e 100644
+--- a/drivers/scsi/snic/snic_disc.c
++++ b/drivers/scsi/snic/snic_disc.c
+@@ -303,6 +303,7 @@ snic_tgt_create(struct snic *snic, struct snic_tgt_id *tgtid)
+ 			      "Snic Tgt: device_add, with err = %d\n",
+ 			      ret);
+ 
++		put_device(&tgt->dev);
+ 		put_device(&snic->shost->shost_gendev);
+ 		spin_lock_irqsave(snic->shost->host_lock, flags);
+ 		list_del(&tgt->list);
+diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
+index 4d72d82f73586..182cf916f0835 100644
+--- a/drivers/scsi/storvsc_drv.c
++++ b/drivers/scsi/storvsc_drv.c
+@@ -1672,10 +1672,6 @@ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd)
+  */
+ static enum scsi_timeout_action storvsc_eh_timed_out(struct scsi_cmnd *scmnd)
+ {
+-#if IS_ENABLED(CONFIG_SCSI_FC_ATTRS)
+-	if (scmnd->device->host->transportt == fc_transport_template)
+-		return fc_eh_timed_out(scmnd);
+-#endif
+ 	return SCSI_EH_RESET_TIMER;
+ }
+ 
+diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c
+index c1af712ca7288..7c67476efa78d 100644
+--- a/drivers/thunderbolt/tb.c
++++ b/drivers/thunderbolt/tb.c
+@@ -1810,6 +1810,8 @@ unlock:
+ 
+ 	pm_runtime_mark_last_busy(&tb->dev);
+ 	pm_runtime_put_autosuspend(&tb->dev);
++
++	kfree(ev);
+ }
+ 
+ static void tb_queue_dp_bandwidth_request(struct tb *tb, u64 route, u8 port)
+diff --git a/drivers/ufs/host/ufs-renesas.c b/drivers/ufs/host/ufs-renesas.c
+index f8a5e79ed3b4e..ab0652d8705ac 100644
+--- a/drivers/ufs/host/ufs-renesas.c
++++ b/drivers/ufs/host/ufs-renesas.c
+@@ -359,7 +359,7 @@ static int ufs_renesas_init(struct ufs_hba *hba)
+ {
+ 	struct ufs_renesas_priv *priv;
+ 
+-	priv = devm_kmalloc(hba->dev, sizeof(*priv), GFP_KERNEL);
++	priv = devm_kzalloc(hba->dev, sizeof(*priv), GFP_KERNEL);
+ 	if (!priv)
+ 		return -ENOMEM;
+ 	ufshcd_set_variant(hba, priv);
+diff --git a/drivers/usb/common/usb-conn-gpio.c b/drivers/usb/common/usb-conn-gpio.c
+index e20874caba363..3f5180d64931b 100644
+--- a/drivers/usb/common/usb-conn-gpio.c
++++ b/drivers/usb/common/usb-conn-gpio.c
+@@ -42,6 +42,7 @@ struct usb_conn_info {
+ 
+ 	struct power_supply_desc desc;
+ 	struct power_supply *charger;
++	bool initial_detection;
+ };
+ 
+ /*
+@@ -86,11 +87,13 @@ static void usb_conn_detect_cable(struct work_struct *work)
+ 	dev_dbg(info->dev, "role %s -> %s, gpios: id %d, vbus %d\n",
+ 		usb_role_string(info->last_role), usb_role_string(role), id, vbus);
+ 
+-	if (info->last_role == role) {
++	if (!info->initial_detection && info->last_role == role) {
+ 		dev_warn(info->dev, "repeated role: %s\n", usb_role_string(role));
+ 		return;
+ 	}
+ 
++	info->initial_detection = false;
++
+ 	if (info->last_role == USB_ROLE_HOST && info->vbus)
+ 		regulator_disable(info->vbus);
+ 
+@@ -258,6 +261,7 @@ static int usb_conn_probe(struct platform_device *pdev)
+ 	device_set_wakeup_capable(&pdev->dev, true);
+ 
+ 	/* Perform initial detection */
++	info->initial_detection = true;
+ 	usb_conn_queue_dwork(info, 0);
+ 
+ 	return 0;
+diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
+index 550dc8f4d16ad..f7957a93abd26 100644
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -4448,9 +4448,14 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt)
+ 	u32 count;
+ 
+ 	if (pm_runtime_suspended(dwc->dev)) {
++		dwc->pending_events = true;
++		/*
++		 * Trigger runtime resume. The get() function will be balanced
++		 * after processing the pending events in dwc3_process_pending
++		 * events().
++		 */
+ 		pm_runtime_get(dwc->dev);
+ 		disable_irq_nosync(dwc->irq_gadget);
+-		dwc->pending_events = true;
+ 		return IRQ_HANDLED;
+ 	}
+ 
+@@ -4711,6 +4716,8 @@ void dwc3_gadget_process_pending_events(struct dwc3 *dwc)
+ {
+ 	if (dwc->pending_events) {
+ 		dwc3_interrupt(dwc->irq_gadget, dwc->ev_buf);
++		dwc3_thread_interrupt(dwc->irq_gadget, dwc->ev_buf);
++		pm_runtime_put(dwc->dev);
+ 		dwc->pending_events = false;
+ 		enable_irq(dwc->irq_gadget);
+ 	}
+diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
+index 0068d0c448658..d5bc2892184ca 100644
+--- a/drivers/usb/gadget/udc/core.c
++++ b/drivers/usb/gadget/udc/core.c
+@@ -822,6 +822,9 @@ EXPORT_SYMBOL_GPL(usb_gadget_disconnect);
+  * usb_gadget_activate() is called.  For example, user mode components may
+  * need to be activated before the system can talk to hosts.
+  *
++ * This routine may sleep; it must not be called in interrupt context
++ * (such as from within a gadget driver's disconnect() callback).
++ *
+  * Returns zero on success, else negative errno.
+  */
+ int usb_gadget_deactivate(struct usb_gadget *gadget)
+@@ -860,6 +863,8 @@ EXPORT_SYMBOL_GPL(usb_gadget_deactivate);
+  * This routine activates gadget which was previously deactivated with
+  * usb_gadget_deactivate() call. It calls usb_gadget_connect() if needed.
+  *
++ * This routine may sleep; it must not be called in interrupt context.
++ *
+  * Returns zero on success, else negative errno.
+  */
+ int usb_gadget_activate(struct usb_gadget *gadget)
+@@ -1638,7 +1643,11 @@ static void gadget_unbind_driver(struct device *dev)
+ 	usb_gadget_disable_async_callbacks(udc);
+ 	if (gadget->irq)
+ 		synchronize_irq(gadget->irq);
++	mutex_unlock(&udc->connect_lock);
++
+ 	udc->driver->unbind(gadget);
++
++	mutex_lock(&udc->connect_lock);
+ 	usb_gadget_udc_stop_locked(udc);
+ 	mutex_unlock(&udc->connect_lock);
+ 
+diff --git a/drivers/usb/storage/alauda.c b/drivers/usb/storage/alauda.c
+index 5e912dd29b4c9..115f05a6201a1 100644
+--- a/drivers/usb/storage/alauda.c
++++ b/drivers/usb/storage/alauda.c
+@@ -318,7 +318,8 @@ static int alauda_get_media_status(struct us_data *us, unsigned char *data)
+ 	rc = usb_stor_ctrl_transfer(us, us->recv_ctrl_pipe,
+ 		command, 0xc0, 0, 1, data, 2);
+ 
+-	usb_stor_dbg(us, "Media status %02X %02X\n", data[0], data[1]);
++	if (rc == USB_STOR_XFER_GOOD)
++		usb_stor_dbg(us, "Media status %02X %02X\n", data[0], data[1]);
+ 
+ 	return rc;
+ }
+@@ -454,9 +455,14 @@ static int alauda_init_media(struct us_data *us)
+ static int alauda_check_media(struct us_data *us)
+ {
+ 	struct alauda_info *info = (struct alauda_info *) us->extra;
+-	unsigned char status[2];
++	unsigned char *status = us->iobuf;
++	int rc;
+ 
+-	alauda_get_media_status(us, status);
++	rc = alauda_get_media_status(us, status);
++	if (rc != USB_STOR_XFER_GOOD) {
++		status[0] = 0xF0;	/* Pretend there's no media */
++		status[1] = 0;
++	}
+ 
+ 	/* Check for no media or door open */
+ 	if ((status[0] & 0x80) || ((status[0] & 0x1F) == 0x10)
+diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c
+index 66de880b28d01..cdf8261e22dbd 100644
+--- a/drivers/usb/typec/altmodes/displayport.c
++++ b/drivers/usb/typec/altmodes/displayport.c
+@@ -60,6 +60,7 @@ struct dp_altmode {
+ 
+ 	enum dp_state state;
+ 	bool hpd;
++	bool pending_hpd;
+ 
+ 	struct mutex lock; /* device lock */
+ 	struct work_struct work;
+@@ -144,8 +145,13 @@ static int dp_altmode_status_update(struct dp_altmode *dp)
+ 		dp->state = DP_STATE_EXIT;
+ 	} else if (!(con & DP_CONF_CURRENTLY(dp->data.conf))) {
+ 		ret = dp_altmode_configure(dp, con);
+-		if (!ret)
++		if (!ret) {
+ 			dp->state = DP_STATE_CONFIGURE;
++			if (dp->hpd != hpd) {
++				dp->hpd = hpd;
++				dp->pending_hpd = true;
++			}
++		}
+ 	} else {
+ 		if (dp->hpd != hpd) {
+ 			drm_connector_oob_hotplug_event(dp->connector_fwnode);
+@@ -161,6 +167,16 @@ static int dp_altmode_configured(struct dp_altmode *dp)
+ {
+ 	sysfs_notify(&dp->alt->dev.kobj, "displayport", "configuration");
+ 	sysfs_notify(&dp->alt->dev.kobj, "displayport", "pin_assignment");
++	/*
++	 * If the DFP_D/UFP_D sends a change in HPD when first notifying the
++	 * DisplayPort driver that it is connected, then we wait until
++	 * configuration is complete to signal HPD.
++	 */
++	if (dp->pending_hpd) {
++		drm_connector_oob_hotplug_event(dp->connector_fwnode);
++		sysfs_notify(&dp->alt->dev.kobj, "displayport", "hpd");
++		dp->pending_hpd = false;
++	}
+ 
+ 	return dp_altmode_notify(dp);
+ }
+diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
+index 3c6b0c8e2d3ae..dc113cbb3bed8 100644
+--- a/drivers/usb/typec/tcpm/tcpm.c
++++ b/drivers/usb/typec/tcpm/tcpm.c
+@@ -5348,6 +5348,10 @@ static void _tcpm_pd_vbus_off(struct tcpm_port *port)
+ 		/* Do nothing, vbus drop expected */
+ 		break;
+ 
++	case SNK_HARD_RESET_WAIT_VBUS:
++		/* Do nothing, its OK to receive vbus off events */
++		break;
++
+ 	default:
+ 		if (port->pwr_role == TYPEC_SINK && port->attached)
+ 			tcpm_set_state(port, SNK_UNATTACHED, tcpm_wait_for_discharge(port));
+@@ -5394,6 +5398,9 @@ static void _tcpm_pd_vbus_vsafe0v(struct tcpm_port *port)
+ 	case SNK_DEBOUNCED:
+ 		/*Do nothing, still waiting for VSAFE5V for connect */
+ 		break;
++	case SNK_HARD_RESET_WAIT_VBUS:
++		/* Do nothing, its OK to receive vbus off events */
++		break;
+ 	default:
+ 		if (port->pwr_role == TYPEC_SINK && port->auto_vbus_discharge_enabled)
+ 			tcpm_set_state(port, SNK_UNATTACHED, 0);
+diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c
+index ad14dd745e4ae..2a60033d907bf 100644
+--- a/fs/btrfs/block-group.c
++++ b/fs/btrfs/block-group.c
+@@ -441,13 +441,23 @@ void btrfs_wait_block_group_cache_progress(struct btrfs_block_group *cache,
+ 					   u64 num_bytes)
+ {
+ 	struct btrfs_caching_control *caching_ctl;
++	int progress;
+ 
+ 	caching_ctl = btrfs_get_caching_control(cache);
+ 	if (!caching_ctl)
+ 		return;
+ 
++	/*
++	 * We've already failed to allocate from this block group, so even if
++	 * there's enough space in the block group it isn't contiguous enough to
++	 * allow for an allocation, so wait for at least the next wakeup tick,
++	 * or for the thing to be done.
++	 */
++	progress = atomic_read(&caching_ctl->progress);
++
+ 	wait_event(caching_ctl->wait, btrfs_block_group_done(cache) ||
+-		   (cache->free_space_ctl->free_space >= num_bytes));
++		   (progress != atomic_read(&caching_ctl->progress) &&
++		    (cache->free_space_ctl->free_space >= num_bytes)));
+ 
+ 	btrfs_put_caching_control(caching_ctl);
+ }
+@@ -802,8 +812,10 @@ next:
+ 
+ 			if (total_found > CACHING_CTL_WAKE_UP) {
+ 				total_found = 0;
+-				if (wakeup)
++				if (wakeup) {
++					atomic_inc(&caching_ctl->progress);
+ 					wake_up(&caching_ctl->wait);
++				}
+ 			}
+ 		}
+ 		path->slots[0]++;
+@@ -910,6 +922,7 @@ int btrfs_cache_block_group(struct btrfs_block_group *cache, bool wait)
+ 	init_waitqueue_head(&caching_ctl->wait);
+ 	caching_ctl->block_group = cache;
+ 	refcount_set(&caching_ctl->count, 2);
++	atomic_set(&caching_ctl->progress, 0);
+ 	btrfs_init_work(&caching_ctl->work, caching_thread, NULL, NULL);
+ 
+ 	spin_lock(&cache->lock);
+diff --git a/fs/btrfs/block-group.h b/fs/btrfs/block-group.h
+index 3195d0b0dbed8..471f591db7c0c 100644
+--- a/fs/btrfs/block-group.h
++++ b/fs/btrfs/block-group.h
+@@ -85,6 +85,8 @@ struct btrfs_caching_control {
+ 	wait_queue_head_t wait;
+ 	struct btrfs_work work;
+ 	struct btrfs_block_group *block_group;
++	/* Track progress of caching during allocation. */
++	atomic_t progress;
+ 	refcount_t count;
+ };
+ 
+diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
+index 9f056ad41df04..f890c4c71cdaf 100644
+--- a/fs/btrfs/disk-io.c
++++ b/fs/btrfs/disk-io.c
+@@ -1351,7 +1351,8 @@ static int btrfs_init_fs_root(struct btrfs_root *root, dev_t anon_dev)
+ 	btrfs_drew_lock_init(&root->snapshot_lock);
+ 
+ 	if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID &&
+-	    !btrfs_is_data_reloc_root(root)) {
++	    !btrfs_is_data_reloc_root(root) &&
++	    is_fstree(root->root_key.objectid)) {
+ 		set_bit(BTRFS_ROOT_SHAREABLE, &root->state);
+ 		btrfs_check_and_init_root_item(&root->root_item);
+ 	}
+diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
+index 5cd289de4e92e..10bffcb379148 100644
+--- a/fs/btrfs/extent-tree.c
++++ b/fs/btrfs/extent-tree.c
+@@ -4318,8 +4318,11 @@ have_block_group:
+ 			ret = 0;
+ 		}
+ 
+-		if (unlikely(block_group->cached == BTRFS_CACHE_ERROR))
++		if (unlikely(block_group->cached == BTRFS_CACHE_ERROR)) {
++			if (!cache_block_group_error)
++				cache_block_group_error = -EIO;
+ 			goto loop;
++		}
+ 
+ 		if (!find_free_extent_check_size_class(ffe_ctl, block_group))
+ 			goto loop;
+diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
+index 82b9779deaa88..54eed5a8a412b 100644
+--- a/fs/btrfs/extent_io.c
++++ b/fs/btrfs/extent_io.c
+@@ -2181,11 +2181,12 @@ retry:
+ 			}
+ 
+ 			/*
+-			 * the filesystem may choose to bump up nr_to_write.
++			 * The filesystem may choose to bump up nr_to_write.
+ 			 * We have to make sure to honor the new nr_to_write
+-			 * at any time
++			 * at any time.
+ 			 */
+-			nr_to_write_done = wbc->nr_to_write <= 0;
++			nr_to_write_done = (wbc->sync_mode == WB_SYNC_NONE &&
++					    wbc->nr_to_write <= 0);
+ 		}
+ 		folio_batch_release(&fbatch);
+ 		cond_resched();
+@@ -2344,6 +2345,12 @@ retry:
+ 				continue;
+ 			}
+ 
++			if (!folio_test_dirty(folio)) {
++				/* Someone wrote it for us. */
++				folio_unlock(folio);
++				continue;
++			}
++
+ 			if (wbc->sync_mode != WB_SYNC_NONE) {
+ 				if (folio_test_writeback(folio))
+ 					submit_write_bio(bio_ctrl, 0);
+diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
+index c89071186388b..ace949bc75059 100644
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -1453,8 +1453,6 @@ out_unlock:
+ 					     clear_bits,
+ 					     page_ops);
+ 		start += cur_alloc_size;
+-		if (start >= end)
+-			return ret;
+ 	}
+ 
+ 	/*
+@@ -1463,9 +1461,11 @@ out_unlock:
+ 	 * space_info's bytes_may_use counter, reserved in
+ 	 * btrfs_check_data_free_space().
+ 	 */
+-	extent_clear_unlock_delalloc(inode, start, end, locked_page,
+-				     clear_bits | EXTENT_CLEAR_DATA_RESV,
+-				     page_ops);
++	if (start < end) {
++		clear_bits |= EXTENT_CLEAR_DATA_RESV;
++		extent_clear_unlock_delalloc(inode, start, end, locked_page,
++					     clear_bits, page_ops);
++	}
+ 	return ret;
+ }
+ 
+diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
+index 59a06499c647e..5b077e57cdd5e 100644
+--- a/fs/btrfs/relocation.c
++++ b/fs/btrfs/relocation.c
+@@ -1916,7 +1916,39 @@ again:
+ 				err = PTR_ERR(root);
+ 			break;
+ 		}
+-		ASSERT(root->reloc_root == reloc_root);
++
++		if (unlikely(root->reloc_root != reloc_root)) {
++			if (root->reloc_root) {
++				btrfs_err(fs_info,
++"reloc tree mismatch, root %lld has reloc root key (%lld %u %llu) gen %llu, expect reloc root key (%lld %u %llu) gen %llu",
++					  root->root_key.objectid,
++					  root->reloc_root->root_key.objectid,
++					  root->reloc_root->root_key.type,
++					  root->reloc_root->root_key.offset,
++					  btrfs_root_generation(
++						  &root->reloc_root->root_item),
++					  reloc_root->root_key.objectid,
++					  reloc_root->root_key.type,
++					  reloc_root->root_key.offset,
++					  btrfs_root_generation(
++						  &reloc_root->root_item));
++			} else {
++				btrfs_err(fs_info,
++"reloc tree mismatch, root %lld has no reloc root, expect reloc root key (%lld %u %llu) gen %llu",
++					  root->root_key.objectid,
++					  reloc_root->root_key.objectid,
++					  reloc_root->root_key.type,
++					  reloc_root->root_key.offset,
++					  btrfs_root_generation(
++						  &reloc_root->root_item));
++			}
++			list_add(&reloc_root->root_list, &reloc_roots);
++			btrfs_put_root(root);
++			btrfs_abort_transaction(trans, -EUCLEAN);
++			if (!err)
++				err = -EUCLEAN;
++			break;
++		}
+ 
+ 		/*
+ 		 * set reference count to 1, so btrfs_recover_relocation
+@@ -1989,7 +2021,7 @@ again:
+ 		root = btrfs_get_fs_root(fs_info, reloc_root->root_key.offset,
+ 					 false);
+ 		if (btrfs_root_refs(&reloc_root->root_item) > 0) {
+-			if (IS_ERR(root)) {
++			if (WARN_ON(IS_ERR(root))) {
+ 				/*
+ 				 * For recovery we read the fs roots on mount,
+ 				 * and if we didn't find the root then we marked
+@@ -1998,17 +2030,14 @@ again:
+ 				 * memory.  However there's no reason we can't
+ 				 * handle the error properly here just in case.
+ 				 */
+-				ASSERT(0);
+ 				ret = PTR_ERR(root);
+ 				goto out;
+ 			}
+-			if (root->reloc_root != reloc_root) {
++			if (WARN_ON(root->reloc_root != reloc_root)) {
+ 				/*
+-				 * This is actually impossible without something
+-				 * going really wrong (like weird race condition
+-				 * or cosmic rays).
++				 * This can happen if on-disk metadata has some
++				 * corruption, e.g. bad reloc tree key offset.
+ 				 */
+-				ASSERT(0);
+ 				ret = -EINVAL;
+ 				goto out;
+ 			}
+diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c
+index 2138e9fc05647..9bbcb93755300 100644
+--- a/fs/btrfs/tree-checker.c
++++ b/fs/btrfs/tree-checker.c
+@@ -446,6 +446,20 @@ static int check_root_key(struct extent_buffer *leaf, struct btrfs_key *key,
+ 	btrfs_item_key_to_cpu(leaf, &item_key, slot);
+ 	is_root_item = (item_key.type == BTRFS_ROOT_ITEM_KEY);
+ 
++	/*
++	 * Bad rootid for reloc trees.
++	 *
++	 * Reloc trees are only for subvolume trees, other trees only need
++	 * to be COWed to be relocated.
++	 */
++	if (unlikely(is_root_item && key->objectid == BTRFS_TREE_RELOC_OBJECTID &&
++		     !is_fstree(key->offset))) {
++		generic_err(leaf, slot,
++		"invalid reloc tree for root %lld, root id is not a subvolume tree",
++			    key->offset);
++		return -EUCLEAN;
++	}
++
+ 	/* No such tree id */
+ 	if (unlikely(key->objectid == 0)) {
+ 		if (is_root_item)
+diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c
+index a8ce522ac7479..35bc793053180 100644
+--- a/fs/nilfs2/inode.c
++++ b/fs/nilfs2/inode.c
+@@ -1101,9 +1101,17 @@ int nilfs_set_file_dirty(struct inode *inode, unsigned int nr_dirty)
+ 
+ int __nilfs_mark_inode_dirty(struct inode *inode, int flags)
+ {
++	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
+ 	struct buffer_head *ibh;
+ 	int err;
+ 
++	/*
++	 * Do not dirty inodes after the log writer has been detached
++	 * and its nilfs_root struct has been freed.
++	 */
++	if (unlikely(nilfs_purging(nilfs)))
++		return 0;
++
+ 	err = nilfs_load_inode_block(inode, &ibh);
+ 	if (unlikely(err)) {
+ 		nilfs_warn(inode->i_sb,
+diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
+index c2553024bd25e..581691e4be491 100644
+--- a/fs/nilfs2/segment.c
++++ b/fs/nilfs2/segment.c
+@@ -2845,6 +2845,7 @@ void nilfs_detach_log_writer(struct super_block *sb)
+ 		nilfs_segctor_destroy(nilfs->ns_writer);
+ 		nilfs->ns_writer = NULL;
+ 	}
++	set_nilfs_purging(nilfs);
+ 
+ 	/* Force to free the list of dirty files */
+ 	spin_lock(&nilfs->ns_inode_lock);
+@@ -2857,4 +2858,5 @@ void nilfs_detach_log_writer(struct super_block *sb)
+ 	up_write(&nilfs->ns_segctor_sem);
+ 
+ 	nilfs_dispose_list(nilfs, &garbage_list, 1);
++	clear_nilfs_purging(nilfs);
+ }
+diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h
+index 47c7dfbb7ea58..cd4ae1b8ae165 100644
+--- a/fs/nilfs2/the_nilfs.h
++++ b/fs/nilfs2/the_nilfs.h
+@@ -29,6 +29,7 @@ enum {
+ 	THE_NILFS_DISCONTINUED,	/* 'next' pointer chain has broken */
+ 	THE_NILFS_GC_RUNNING,	/* gc process is running */
+ 	THE_NILFS_SB_DIRTY,	/* super block is dirty */
++	THE_NILFS_PURGING,	/* disposing dirty files for cleanup */
+ };
+ 
+ /**
+@@ -208,6 +209,7 @@ THE_NILFS_FNS(INIT, init)
+ THE_NILFS_FNS(DISCONTINUED, discontinued)
+ THE_NILFS_FNS(GC_RUNNING, gc_running)
+ THE_NILFS_FNS(SB_DIRTY, sb_dirty)
++THE_NILFS_FNS(PURGING, purging)
+ 
+ /*
+  * Mount option operations
+diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c
+index 25b44b303b355..2669035f7eb1f 100644
+--- a/fs/proc/kcore.c
++++ b/fs/proc/kcore.c
+@@ -309,6 +309,8 @@ static void append_kcore_note(char *notes, size_t *i, const char *name,
+ 
+ static ssize_t read_kcore_iter(struct kiocb *iocb, struct iov_iter *iter)
+ {
++	struct file *file = iocb->ki_filp;
++	char *buf = file->private_data;
+ 	loff_t *fpos = &iocb->ki_pos;
+ 	size_t phdrs_offset, notes_offset, data_offset;
+ 	size_t page_offline_frozen = 1;
+@@ -555,10 +557,21 @@ static ssize_t read_kcore_iter(struct kiocb *iocb, struct iov_iter *iter)
+ 		case KCORE_VMEMMAP:
+ 		case KCORE_TEXT:
+ 			/*
+-			 * We use _copy_to_iter() to bypass usermode hardening
+-			 * which would otherwise prevent this operation.
++			 * Sadly we must use a bounce buffer here to be able to
++			 * make use of copy_from_kernel_nofault(), as these
++			 * memory regions might not always be mapped on all
++			 * architectures.
+ 			 */
+-			if (_copy_to_iter((char *)start, tsz, iter) != tsz) {
++			if (copy_from_kernel_nofault(buf, (void *)start, tsz)) {
++				if (iov_iter_zero(tsz, iter) != tsz) {
++					ret = -EFAULT;
++					goto out;
++				}
++			/*
++			 * We know the bounce buffer is safe to copy from, so
++			 * use _copy_to_iter() directly.
++			 */
++			} else if (_copy_to_iter(buf, tsz, iter) != tsz) {
+ 				ret = -EFAULT;
+ 				goto out;
+ 			}
+@@ -595,6 +608,10 @@ static int open_kcore(struct inode *inode, struct file *filp)
+ 	if (ret)
+ 		return ret;
+ 
++	filp->private_data = kmalloc(PAGE_SIZE, GFP_KERNEL);
++	if (!filp->private_data)
++		return -ENOMEM;
++
+ 	if (kcore_need_update)
+ 		kcore_update_ram();
+ 	if (i_size_read(inode) != proc_root_kcore->size) {
+@@ -605,9 +622,16 @@ static int open_kcore(struct inode *inode, struct file *filp)
+ 	return 0;
+ }
+ 
++static int release_kcore(struct inode *inode, struct file *file)
++{
++	kfree(file->private_data);
++	return 0;
++}
++
+ static const struct proc_ops kcore_proc_ops = {
+ 	.proc_read_iter	= read_kcore_iter,
+ 	.proc_open	= open_kcore,
++	.proc_release	= release_kcore,
+ 	.proc_lseek	= default_llseek,
+ };
+ 
+diff --git a/fs/smb/server/smb2misc.c b/fs/smb/server/smb2misc.c
+index 33b7e6c4ceffb..e881df1d10cbd 100644
+--- a/fs/smb/server/smb2misc.c
++++ b/fs/smb/server/smb2misc.c
+@@ -380,13 +380,13 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work)
+ 	}
+ 
+ 	if (smb2_req_struct_sizes[command] != pdu->StructureSize2) {
+-		if (command == SMB2_OPLOCK_BREAK_HE &&
+-		    le16_to_cpu(pdu->StructureSize2) != OP_BREAK_STRUCT_SIZE_20 &&
+-		    le16_to_cpu(pdu->StructureSize2) != OP_BREAK_STRUCT_SIZE_21) {
++		if (!(command == SMB2_OPLOCK_BREAK_HE &&
++		    (le16_to_cpu(pdu->StructureSize2) == OP_BREAK_STRUCT_SIZE_20 ||
++		    le16_to_cpu(pdu->StructureSize2) == OP_BREAK_STRUCT_SIZE_21))) {
+ 			/* special case for SMB2.1 lease break message */
+ 			ksmbd_debug(SMB,
+-				    "Illegal request size %d for oplock break\n",
+-				    le16_to_cpu(pdu->StructureSize2));
++				"Illegal request size %u for command %d\n",
++				le16_to_cpu(pdu->StructureSize2), command);
+ 			return 1;
+ 		}
+ 	}
+diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
+index d7e5196485604..4b4764abcdffa 100644
+--- a/fs/smb/server/smb2pdu.c
++++ b/fs/smb/server/smb2pdu.c
+@@ -2324,9 +2324,16 @@ next:
+ 			break;
+ 		buf_len -= next;
+ 		eabuf = (struct smb2_ea_info *)((char *)eabuf + next);
+-		if (next < (u32)eabuf->EaNameLength + le16_to_cpu(eabuf->EaValueLength))
++		if (buf_len < sizeof(struct smb2_ea_info)) {
++			rc = -EINVAL;
+ 			break;
++		}
+ 
++		if (buf_len < sizeof(struct smb2_ea_info) + eabuf->EaNameLength +
++				le16_to_cpu(eabuf->EaValueLength)) {
++			rc = -EINVAL;
++			break;
++		}
+ 	} while (next != 0);
+ 
+ 	kfree(attr_name);
+diff --git a/include/linux/cpu.h b/include/linux/cpu.h
+index ce41922470a5d..e81edf076f291 100644
+--- a/include/linux/cpu.h
++++ b/include/linux/cpu.h
+@@ -72,6 +72,8 @@ extern ssize_t cpu_show_retbleed(struct device *dev,
+ 				 struct device_attribute *attr, char *buf);
+ extern ssize_t cpu_show_spec_rstack_overflow(struct device *dev,
+ 					     struct device_attribute *attr, char *buf);
++extern ssize_t cpu_show_gds(struct device *dev,
++			    struct device_attribute *attr, char *buf);
+ 
+ extern __printf(4, 5)
+ struct device *cpu_device_create(struct device *parent, void *drvdata,
+diff --git a/include/linux/skmsg.h b/include/linux/skmsg.h
+index 054d7911bfc9f..c1637515a8a41 100644
+--- a/include/linux/skmsg.h
++++ b/include/linux/skmsg.h
+@@ -62,6 +62,7 @@ struct sk_psock_progs {
+ 
+ enum sk_psock_state_bits {
+ 	SK_PSOCK_TX_ENABLED,
++	SK_PSOCK_RX_STRP_ENABLED,
+ };
+ 
+ struct sk_psock_link {
+diff --git a/include/linux/tpm.h b/include/linux/tpm.h
+index 6a1e8f1572551..4ee9d13749adc 100644
+--- a/include/linux/tpm.h
++++ b/include/linux/tpm.h
+@@ -283,6 +283,7 @@ enum tpm_chip_flags {
+ 	TPM_CHIP_FLAG_FIRMWARE_POWER_MANAGED	= BIT(6),
+ 	TPM_CHIP_FLAG_FIRMWARE_UPGRADE		= BIT(7),
+ 	TPM_CHIP_FLAG_SUSPENDED			= BIT(8),
++	TPM_CHIP_FLAG_HWRNG_DISABLED		= BIT(9),
+ };
+ 
+ #define to_tpm_chip(d) container_of(d, struct tpm_chip, dev)
+diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
+index 9e04f69712b16..f67f705c5ad03 100644
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -562,6 +562,9 @@ ieee80211_get_sband_iftype_data(const struct ieee80211_supported_band *sband,
+ 	if (WARN_ON(iftype >= NL80211_IFTYPE_MAX))
+ 		return NULL;
+ 
++	if (iftype == NL80211_IFTYPE_AP_VLAN)
++		iftype = NL80211_IFTYPE_AP;
++
+ 	for (i = 0; i < sband->n_iftype_data; i++)  {
+ 		const struct ieee80211_sband_iftype_data *data =
+ 			&sband->iftype_data[i];
+diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
+index 1b0beb8f08aee..ad97049e28881 100644
+--- a/include/net/netfilter/nf_tables.h
++++ b/include/net/netfilter/nf_tables.h
+@@ -512,6 +512,7 @@ struct nft_set_elem_expr {
+  *
+  *	@list: table set list node
+  *	@bindings: list of set bindings
++ *	@refs: internal refcounting for async set destruction
+  *	@table: table this set belongs to
+  *	@net: netnamespace this set belongs to
+  * 	@name: name of the set
+@@ -541,6 +542,7 @@ struct nft_set_elem_expr {
+ struct nft_set {
+ 	struct list_head		list;
+ 	struct list_head		bindings;
++	refcount_t			refs;
+ 	struct nft_table		*table;
+ 	possible_net_t			net;
+ 	char				*name;
+@@ -562,7 +564,8 @@ struct nft_set {
+ 	struct list_head		pending_update;
+ 	/* runtime data below here */
+ 	const struct nft_set_ops	*ops ____cacheline_aligned;
+-	u16				flags:14,
++	u16				flags:13,
++					dead:1,
+ 					genmask:2;
+ 	u8				klen;
+ 	u8				dlen;
+@@ -1592,6 +1595,32 @@ static inline void nft_set_elem_clear_busy(struct nft_set_ext *ext)
+ 	clear_bit(NFT_SET_ELEM_BUSY_BIT, word);
+ }
+ 
++#define NFT_SET_ELEM_DEAD_MASK	(1 << 3)
++
++#if defined(__LITTLE_ENDIAN_BITFIELD)
++#define NFT_SET_ELEM_DEAD_BIT	3
++#elif defined(__BIG_ENDIAN_BITFIELD)
++#define NFT_SET_ELEM_DEAD_BIT	(BITS_PER_LONG - BITS_PER_BYTE + 3)
++#else
++#error
++#endif
++
++static inline void nft_set_elem_dead(struct nft_set_ext *ext)
++{
++	unsigned long *word = (unsigned long *)ext;
++
++	BUILD_BUG_ON(offsetof(struct nft_set_ext, genmask) != 0);
++	set_bit(NFT_SET_ELEM_DEAD_BIT, word);
++}
++
++static inline int nft_set_elem_is_dead(const struct nft_set_ext *ext)
++{
++	unsigned long *word = (unsigned long *)ext;
++
++	BUILD_BUG_ON(offsetof(struct nft_set_ext, genmask) != 0);
++	return test_bit(NFT_SET_ELEM_DEAD_BIT, word);
++}
++
+ /**
+  *	struct nft_trans - nf_tables object update in transaction
+  *
+@@ -1729,6 +1758,38 @@ struct nft_trans_flowtable {
+ #define nft_trans_flowtable_flags(trans)	\
+ 	(((struct nft_trans_flowtable *)trans->data)->flags)
+ 
++#define NFT_TRANS_GC_BATCHCOUNT	256
++
++struct nft_trans_gc {
++	struct list_head	list;
++	struct net		*net;
++	struct nft_set		*set;
++	u32			seq;
++	u8			count;
++	void			*priv[NFT_TRANS_GC_BATCHCOUNT];
++	struct rcu_head		rcu;
++};
++
++struct nft_trans_gc *nft_trans_gc_alloc(struct nft_set *set,
++					unsigned int gc_seq, gfp_t gfp);
++void nft_trans_gc_destroy(struct nft_trans_gc *trans);
++
++struct nft_trans_gc *nft_trans_gc_queue_async(struct nft_trans_gc *gc,
++					      unsigned int gc_seq, gfp_t gfp);
++void nft_trans_gc_queue_async_done(struct nft_trans_gc *gc);
++
++struct nft_trans_gc *nft_trans_gc_queue_sync(struct nft_trans_gc *gc, gfp_t gfp);
++void nft_trans_gc_queue_sync_done(struct nft_trans_gc *trans);
++
++void nft_trans_gc_elem_add(struct nft_trans_gc *gc, void *priv);
++
++struct nft_trans_gc *nft_trans_gc_catchall(struct nft_trans_gc *gc,
++					   unsigned int gc_seq);
++
++void nft_setelem_data_deactivate(const struct net *net,
++				 const struct nft_set *set,
++				 struct nft_set_elem *elem);
++
+ int __init nft_chain_filter_init(void);
+ void nft_chain_filter_fini(void);
+ 
+@@ -1755,6 +1816,7 @@ struct nftables_pernet {
+ 	struct mutex		commit_mutex;
+ 	u64			table_handle;
+ 	unsigned int		base_seq;
++	unsigned int		gc_seq;
+ };
+ 
+ extern unsigned int nf_tables_net_id;
+diff --git a/include/trace/events/tcp.h b/include/trace/events/tcp.h
+index bf06db8d2046c..7b1ddffa3dfc8 100644
+--- a/include/trace/events/tcp.h
++++ b/include/trace/events/tcp.h
+@@ -381,6 +381,7 @@ TRACE_EVENT(tcp_cong_state_set,
+ 		__field(const void *, skaddr)
+ 		__field(__u16, sport)
+ 		__field(__u16, dport)
++		__field(__u16, family)
+ 		__array(__u8, saddr, 4)
+ 		__array(__u8, daddr, 4)
+ 		__array(__u8, saddr_v6, 16)
+@@ -396,6 +397,7 @@ TRACE_EVENT(tcp_cong_state_set,
+ 
+ 		__entry->sport = ntohs(inet->inet_sport);
+ 		__entry->dport = ntohs(inet->inet_dport);
++		__entry->family = sk->sk_family;
+ 
+ 		p32 = (__be32 *) __entry->saddr;
+ 		*p32 = inet->inet_saddr;
+@@ -409,7 +411,8 @@ TRACE_EVENT(tcp_cong_state_set,
+ 		__entry->cong_state = ca_state;
+ 	),
+ 
+-	TP_printk("sport=%hu dport=%hu saddr=%pI4 daddr=%pI4 saddrv6=%pI6c daddrv6=%pI6c cong_state=%u",
++	TP_printk("family=%s sport=%hu dport=%hu saddr=%pI4 daddr=%pI4 saddrv6=%pI6c daddrv6=%pI6c cong_state=%u",
++		  show_family_name(__entry->family),
+ 		  __entry->sport, __entry->dport,
+ 		  __entry->saddr, __entry->daddr,
+ 		  __entry->saddr_v6, __entry->daddr_v6,
+diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
+index 2989b81cca82a..a57bdf336ca8a 100644
+--- a/io_uring/io_uring.c
++++ b/io_uring/io_uring.c
+@@ -3466,6 +3466,8 @@ static unsigned long io_uring_mmu_get_unmapped_area(struct file *filp,
+ 	 * - use the kernel virtual address of the shared io_uring context
+ 	 *   (instead of the userspace-provided address, which has to be 0UL
+ 	 *   anyway).
++	 * - use the same pgoff which the get_unmapped_area() uses to
++	 *   calculate the page colouring.
+ 	 * For architectures without such aliasing requirements, the
+ 	 * architecture will return any suitable mapping because addr is 0.
+ 	 */
+@@ -3474,6 +3476,7 @@ static unsigned long io_uring_mmu_get_unmapped_area(struct file *filp,
+ 	pgoff = 0;	/* has been translated to ptr above */
+ #ifdef SHM_COLOUR
+ 	addr = (uintptr_t) ptr;
++	pgoff = addr >> PAGE_SHIFT;
+ #else
+ 	addr = 0UL;
+ #endif
+diff --git a/io_uring/openclose.c b/io_uring/openclose.c
+index a1b98c81a52d9..1b4a06a8572df 100644
+--- a/io_uring/openclose.c
++++ b/io_uring/openclose.c
+@@ -35,9 +35,11 @@ static bool io_openat_force_async(struct io_open *open)
+ {
+ 	/*
+ 	 * Don't bother trying for O_TRUNC, O_CREAT, or O_TMPFILE open,
+-	 * it'll always -EAGAIN
++	 * it'll always -EAGAIN. Note that we test for __O_TMPFILE because
++	 * O_TMPFILE includes O_DIRECTORY, which isn't a flag we need to force
++	 * async for.
+ 	 */
+-	return open->how.flags & (O_TRUNC | O_CREAT | O_TMPFILE);
++	return open->how.flags & (O_TRUNC | O_CREAT | __O_TMPFILE);
+ }
+ 
+ static int __io_openat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
+diff --git a/mm/damon/core.c b/mm/damon/core.c
+index 91cff7f2997ef..eb9580942a5c3 100644
+--- a/mm/damon/core.c
++++ b/mm/damon/core.c
+@@ -273,6 +273,7 @@ struct damos_filter *damos_new_filter(enum damos_filter_type type,
+ 		return NULL;
+ 	filter->type = type;
+ 	filter->matching = matching;
++	INIT_LIST_HEAD(&filter->list);
+ 	return filter;
+ }
+ 
+diff --git a/mm/hugetlb.c b/mm/hugetlb.c
+index f791076da157c..a9fae660d1635 100644
+--- a/mm/hugetlb.c
++++ b/mm/hugetlb.c
+@@ -1580,9 +1580,37 @@ static inline void destroy_compound_gigantic_folio(struct folio *folio,
+ 						unsigned int order) { }
+ #endif
+ 
++static inline void __clear_hugetlb_destructor(struct hstate *h,
++						struct folio *folio)
++{
++	lockdep_assert_held(&hugetlb_lock);
++
++	/*
++	 * Very subtle
++	 *
++	 * For non-gigantic pages set the destructor to the normal compound
++	 * page dtor.  This is needed in case someone takes an additional
++	 * temporary ref to the page, and freeing is delayed until they drop
++	 * their reference.
++	 *
++	 * For gigantic pages set the destructor to the null dtor.  This
++	 * destructor will never be called.  Before freeing the gigantic
++	 * page destroy_compound_gigantic_folio will turn the folio into a
++	 * simple group of pages.  After this the destructor does not
++	 * apply.
++	 *
++	 */
++	if (hstate_is_gigantic(h))
++		folio_set_compound_dtor(folio, NULL_COMPOUND_DTOR);
++	else
++		folio_set_compound_dtor(folio, COMPOUND_PAGE_DTOR);
++}
++
+ /*
+- * Remove hugetlb folio from lists, and update dtor so that the folio appears
+- * as just a compound page.
++ * Remove hugetlb folio from lists.
++ * If vmemmap exists for the folio, update dtor so that the folio appears
++ * as just a compound page.  Otherwise, wait until after allocating vmemmap
++ * to update dtor.
+  *
+  * A reference is held on the folio, except in the case of demote.
+  *
+@@ -1613,31 +1641,19 @@ static void __remove_hugetlb_folio(struct hstate *h, struct folio *folio,
+ 	}
+ 
+ 	/*
+-	 * Very subtle
+-	 *
+-	 * For non-gigantic pages set the destructor to the normal compound
+-	 * page dtor.  This is needed in case someone takes an additional
+-	 * temporary ref to the page, and freeing is delayed until they drop
+-	 * their reference.
+-	 *
+-	 * For gigantic pages set the destructor to the null dtor.  This
+-	 * destructor will never be called.  Before freeing the gigantic
+-	 * page destroy_compound_gigantic_folio will turn the folio into a
+-	 * simple group of pages.  After this the destructor does not
+-	 * apply.
+-	 *
+-	 * This handles the case where more than one ref is held when and
+-	 * after update_and_free_hugetlb_folio is called.
+-	 *
+-	 * In the case of demote we do not ref count the page as it will soon
+-	 * be turned into a page of smaller size.
++	 * We can only clear the hugetlb destructor after allocating vmemmap
++	 * pages.  Otherwise, someone (memory error handling) may try to write
++	 * to tail struct pages.
++	 */
++	if (!folio_test_hugetlb_vmemmap_optimized(folio))
++		__clear_hugetlb_destructor(h, folio);
++
++	 /*
++	  * In the case of demote we do not ref count the page as it will soon
++	  * be turned into a page of smaller size.
+ 	 */
+ 	if (!demote)
+ 		folio_ref_unfreeze(folio, 1);
+-	if (hstate_is_gigantic(h))
+-		folio_set_compound_dtor(folio, NULL_COMPOUND_DTOR);
+-	else
+-		folio_set_compound_dtor(folio, COMPOUND_PAGE_DTOR);
+ 
+ 	h->nr_huge_pages--;
+ 	h->nr_huge_pages_node[nid]--;
+@@ -1706,6 +1722,7 @@ static void __update_and_free_hugetlb_folio(struct hstate *h,
+ {
+ 	int i;
+ 	struct page *subpage;
++	bool clear_dtor = folio_test_hugetlb_vmemmap_optimized(folio);
+ 
+ 	if (hstate_is_gigantic(h) && !gigantic_page_runtime_supported())
+ 		return;
+@@ -1736,6 +1753,16 @@ static void __update_and_free_hugetlb_folio(struct hstate *h,
+ 	if (unlikely(folio_test_hwpoison(folio)))
+ 		folio_clear_hugetlb_hwpoison(folio);
+ 
++	/*
++	 * If vmemmap pages were allocated above, then we need to clear the
++	 * hugetlb destructor under the hugetlb lock.
++	 */
++	if (clear_dtor) {
++		spin_lock_irq(&hugetlb_lock);
++		__clear_hugetlb_destructor(h, folio);
++		spin_unlock_irq(&hugetlb_lock);
++	}
++
+ 	for (i = 0; i < pages_per_huge_page(h); i++) {
+ 		subpage = folio_page(folio, i);
+ 		subpage->flags &= ~(1 << PG_locked | 1 << PG_error |
+diff --git a/mm/memory-failure.c b/mm/memory-failure.c
+index 47e2b545ffcc6..244dbfe075a25 100644
+--- a/mm/memory-failure.c
++++ b/mm/memory-failure.c
+@@ -2469,7 +2469,7 @@ int unpoison_memory(unsigned long pfn)
+ {
+ 	struct folio *folio;
+ 	struct page *p;
+-	int ret = -EBUSY;
++	int ret = -EBUSY, ghp;
+ 	unsigned long count = 1;
+ 	bool huge = false;
+ 	static DEFINE_RATELIMIT_STATE(unpoison_rs, DEFAULT_RATELIMIT_INTERVAL,
+@@ -2502,6 +2502,13 @@ int unpoison_memory(unsigned long pfn)
+ 		goto unlock_mutex;
+ 	}
+ 
++	if (folio_test_slab(folio) || PageTable(&folio->page) || folio_test_reserved(folio))
++		goto unlock_mutex;
++
++	/*
++	 * Note that folio->_mapcount is overloaded in SLAB, so the simple test
++	 * in folio_mapped() has to be done after folio_test_slab() is checked.
++	 */
+ 	if (folio_mapped(folio)) {
+ 		unpoison_pr_info("Unpoison: Someone maps the hwpoison page %#lx\n",
+ 				 pfn, &unpoison_rs);
+@@ -2514,32 +2521,28 @@ int unpoison_memory(unsigned long pfn)
+ 		goto unlock_mutex;
+ 	}
+ 
+-	if (folio_test_slab(folio) || PageTable(&folio->page) || folio_test_reserved(folio))
+-		goto unlock_mutex;
+-
+-	ret = get_hwpoison_page(p, MF_UNPOISON);
+-	if (!ret) {
++	ghp = get_hwpoison_page(p, MF_UNPOISON);
++	if (!ghp) {
+ 		if (PageHuge(p)) {
+ 			huge = true;
+ 			count = folio_free_raw_hwp(folio, false);
+-			if (count == 0) {
+-				ret = -EBUSY;
++			if (count == 0)
+ 				goto unlock_mutex;
+-			}
+ 		}
+ 		ret = folio_test_clear_hwpoison(folio) ? 0 : -EBUSY;
+-	} else if (ret < 0) {
+-		if (ret == -EHWPOISON) {
++	} else if (ghp < 0) {
++		if (ghp == -EHWPOISON) {
+ 			ret = put_page_back_buddy(p) ? 0 : -EBUSY;
+-		} else
++		} else {
++			ret = ghp;
+ 			unpoison_pr_info("Unpoison: failed to grab page %#lx\n",
+ 					 pfn, &unpoison_rs);
++		}
+ 	} else {
+ 		if (PageHuge(p)) {
+ 			huge = true;
+ 			count = folio_free_raw_hwp(folio, false);
+ 			if (count == 0) {
+-				ret = -EBUSY;
+ 				folio_put(folio);
+ 				goto unlock_mutex;
+ 			}
+diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
+index 02f7f414aade0..4def13ee071c7 100644
+--- a/mm/zsmalloc.c
++++ b/mm/zsmalloc.c
+@@ -1977,6 +1977,7 @@ static void replace_sub_page(struct size_class *class, struct zspage *zspage,
+ 
+ static bool zs_page_isolate(struct page *page, isolate_mode_t mode)
+ {
++	struct zs_pool *pool;
+ 	struct zspage *zspage;
+ 
+ 	/*
+@@ -1986,9 +1987,10 @@ static bool zs_page_isolate(struct page *page, isolate_mode_t mode)
+ 	VM_BUG_ON_PAGE(PageIsolated(page), page);
+ 
+ 	zspage = get_zspage(page);
+-	migrate_write_lock(zspage);
++	pool = zspage->pool;
++	spin_lock(&pool->lock);
+ 	inc_zspage_isolation(zspage);
+-	migrate_write_unlock(zspage);
++	spin_unlock(&pool->lock);
+ 
+ 	return true;
+ }
+@@ -2054,12 +2056,12 @@ static int zs_page_migrate(struct page *newpage, struct page *page,
+ 	kunmap_atomic(s_addr);
+ 
+ 	replace_sub_page(class, zspage, newpage, page);
++	dec_zspage_isolation(zspage);
+ 	/*
+ 	 * Since we complete the data copy and set up new zspage structure,
+ 	 * it's okay to release the pool's lock.
+ 	 */
+ 	spin_unlock(&pool->lock);
+-	dec_zspage_isolation(zspage);
+ 	migrate_write_unlock(zspage);
+ 
+ 	get_page(newpage);
+@@ -2076,14 +2078,16 @@ static int zs_page_migrate(struct page *newpage, struct page *page,
+ 
+ static void zs_page_putback(struct page *page)
+ {
++	struct zs_pool *pool;
+ 	struct zspage *zspage;
+ 
+ 	VM_BUG_ON_PAGE(!PageIsolated(page), page);
+ 
+ 	zspage = get_zspage(page);
+-	migrate_write_lock(zspage);
++	pool = zspage->pool;
++	spin_lock(&pool->lock);
+ 	dec_zspage_isolation(zspage);
+-	migrate_write_unlock(zspage);
++	spin_unlock(&pool->lock);
+ }
+ 
+ static const struct movable_operations zsmalloc_mops = {
+diff --git a/net/core/filter.c b/net/core/filter.c
+index 1c959794a8862..f15ae393c2767 100644
+--- a/net/core/filter.c
++++ b/net/core/filter.c
+@@ -4115,12 +4115,6 @@ BPF_CALL_2(bpf_xdp_adjust_tail, struct xdp_buff *, xdp, int, offset)
+ 	if (unlikely(data_end > data_hard_end))
+ 		return -EINVAL;
+ 
+-	/* ALL drivers MUST init xdp->frame_sz, chicken check below */
+-	if (unlikely(xdp->frame_sz > PAGE_SIZE)) {
+-		WARN_ONCE(1, "Too BIG xdp->frame_sz = %d\n", xdp->frame_sz);
+-		return -EINVAL;
+-	}
+-
+ 	if (unlikely(data_end < xdp->data + ETH_HLEN))
+ 		return -EINVAL;
+ 
+diff --git a/net/core/skmsg.c b/net/core/skmsg.c
+index a29508e1ff356..ef1a2eb6520bf 100644
+--- a/net/core/skmsg.c
++++ b/net/core/skmsg.c
+@@ -1120,13 +1120,19 @@ static void sk_psock_strp_data_ready(struct sock *sk)
+ 
+ int sk_psock_init_strp(struct sock *sk, struct sk_psock *psock)
+ {
++	int ret;
++
+ 	static const struct strp_callbacks cb = {
+ 		.rcv_msg	= sk_psock_strp_read,
+ 		.read_sock_done	= sk_psock_strp_read_done,
+ 		.parse_msg	= sk_psock_strp_parse,
+ 	};
+ 
+-	return strp_init(&psock->strp, sk, &cb);
++	ret = strp_init(&psock->strp, sk, &cb);
++	if (!ret)
++		sk_psock_set_state(psock, SK_PSOCK_RX_STRP_ENABLED);
++
++	return ret;
+ }
+ 
+ void sk_psock_start_strp(struct sock *sk, struct sk_psock *psock)
+@@ -1154,7 +1160,7 @@ void sk_psock_stop_strp(struct sock *sk, struct sk_psock *psock)
+ static void sk_psock_done_strp(struct sk_psock *psock)
+ {
+ 	/* Parser has been stopped */
+-	if (psock->progs.stream_parser)
++	if (sk_psock_test_state(psock, SK_PSOCK_RX_STRP_ENABLED))
+ 		strp_done(&psock->strp);
+ }
+ #else
+diff --git a/net/core/sock_map.c b/net/core/sock_map.c
+index 08ab108206bf8..8f07fea39d9ea 100644
+--- a/net/core/sock_map.c
++++ b/net/core/sock_map.c
+@@ -146,13 +146,13 @@ static void sock_map_del_link(struct sock *sk,
+ 	list_for_each_entry_safe(link, tmp, &psock->link, list) {
+ 		if (link->link_raw == link_raw) {
+ 			struct bpf_map *map = link->map;
+-			struct bpf_stab *stab = container_of(map, struct bpf_stab,
+-							     map);
+-			if (psock->saved_data_ready && stab->progs.stream_parser)
++			struct sk_psock_progs *progs = sock_map_progs(map);
++
++			if (psock->saved_data_ready && progs->stream_parser)
+ 				strp_stop = true;
+-			if (psock->saved_data_ready && stab->progs.stream_verdict)
++			if (psock->saved_data_ready && progs->stream_verdict)
+ 				verdict_stop = true;
+-			if (psock->saved_data_ready && stab->progs.skb_verdict)
++			if (psock->saved_data_ready && progs->skb_verdict)
+ 				verdict_stop = true;
+ 			list_del(&link->list);
+ 			sk_psock_free_link(link);
+diff --git a/net/dccp/output.c b/net/dccp/output.c
+index b8a24734385ef..fd2eb148d24de 100644
+--- a/net/dccp/output.c
++++ b/net/dccp/output.c
+@@ -187,7 +187,7 @@ unsigned int dccp_sync_mss(struct sock *sk, u32 pmtu)
+ 
+ 	/* And store cached results */
+ 	icsk->icsk_pmtu_cookie = pmtu;
+-	dp->dccps_mss_cache = cur_mps;
++	WRITE_ONCE(dp->dccps_mss_cache, cur_mps);
+ 
+ 	return cur_mps;
+ }
+diff --git a/net/dccp/proto.c b/net/dccp/proto.c
+index b0ebf853cb07b..18873f2308ec8 100644
+--- a/net/dccp/proto.c
++++ b/net/dccp/proto.c
+@@ -630,7 +630,7 @@ static int do_dccp_getsockopt(struct sock *sk, int level, int optname,
+ 		return dccp_getsockopt_service(sk, len,
+ 					       (__be32 __user *)optval, optlen);
+ 	case DCCP_SOCKOPT_GET_CUR_MPS:
+-		val = dp->dccps_mss_cache;
++		val = READ_ONCE(dp->dccps_mss_cache);
+ 		break;
+ 	case DCCP_SOCKOPT_AVAILABLE_CCIDS:
+ 		return ccid_getsockopt_builtin_ccids(sk, len, optval, optlen);
+@@ -739,7 +739,7 @@ int dccp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
+ 
+ 	trace_dccp_probe(sk, len);
+ 
+-	if (len > dp->dccps_mss_cache)
++	if (len > READ_ONCE(dp->dccps_mss_cache))
+ 		return -EMSGSIZE;
+ 
+ 	lock_sock(sk);
+@@ -772,6 +772,12 @@ int dccp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
+ 		goto out_discard;
+ 	}
+ 
++	/* We need to check dccps_mss_cache after socket is locked. */
++	if (len > dp->dccps_mss_cache) {
++		rc = -EMSGSIZE;
++		goto out_discard;
++	}
++
+ 	skb_reserve(skb, sk->sk_prot->max_header);
+ 	rc = memcpy_from_msg(skb_put(skb, len), msg, len);
+ 	if (rc != 0)
+diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c
+index 92c02c886fe73..586b1b3e35b80 100644
+--- a/net/ipv4/ip_tunnel_core.c
++++ b/net/ipv4/ip_tunnel_core.c
+@@ -224,7 +224,7 @@ static int iptunnel_pmtud_build_icmp(struct sk_buff *skb, int mtu)
+ 		.un.frag.__unused	= 0,
+ 		.un.frag.mtu		= htons(mtu),
+ 	};
+-	icmph->checksum = ip_compute_csum(icmph, len);
++	icmph->checksum = csum_fold(skb_checksum(skb, 0, len, 0));
+ 	skb_reset_transport_header(skb);
+ 
+ 	niph = skb_push(skb, sizeof(*niph));
+diff --git a/net/ipv4/nexthop.c b/net/ipv4/nexthop.c
+index f95142e56da05..be5498f5dd319 100644
+--- a/net/ipv4/nexthop.c
++++ b/net/ipv4/nexthop.c
+@@ -3221,13 +3221,9 @@ static int rtm_dump_nexthop(struct sk_buff *skb, struct netlink_callback *cb)
+ 				     &rtm_dump_nexthop_cb, &filter);
+ 	if (err < 0) {
+ 		if (likely(skb->len))
+-			goto out;
+-		goto out_err;
++			err = skb->len;
+ 	}
+ 
+-out:
+-	err = skb->len;
+-out_err:
+ 	cb->seq = net->nexthop.seq;
+ 	nl_dump_check_consistent(cb, nlmsg_hdr(skb));
+ 	return err;
+@@ -3367,25 +3363,19 @@ static int rtm_dump_nexthop_bucket_nh(struct sk_buff *skb,
+ 		    dd->filter.res_bucket_nh_id != nhge->nh->id)
+ 			continue;
+ 
++		dd->ctx->bucket_index = bucket_index;
+ 		err = nh_fill_res_bucket(skb, nh, bucket, bucket_index,
+ 					 RTM_NEWNEXTHOPBUCKET, portid,
+ 					 cb->nlh->nlmsg_seq, NLM_F_MULTI,
+ 					 cb->extack);
+-		if (err < 0) {
+-			if (likely(skb->len))
+-				goto out;
+-			goto out_err;
+-		}
++		if (err)
++			return err;
+ 	}
+ 
+ 	dd->ctx->done_nh_idx = dd->ctx->nh.idx + 1;
+-	bucket_index = 0;
++	dd->ctx->bucket_index = 0;
+ 
+-out:
+-	err = skb->len;
+-out_err:
+-	dd->ctx->bucket_index = bucket_index;
+-	return err;
++	return 0;
+ }
+ 
+ static int rtm_dump_nexthop_bucket_cb(struct sk_buff *skb,
+@@ -3434,13 +3424,9 @@ static int rtm_dump_nexthop_bucket(struct sk_buff *skb,
+ 
+ 	if (err < 0) {
+ 		if (likely(skb->len))
+-			goto out;
+-		goto out_err;
++			err = skb->len;
+ 	}
+ 
+-out:
+-	err = skb->len;
+-out_err:
+ 	cb->seq = net->nexthop.seq;
+ 	nl_dump_check_consistent(cb, nlmsg_hdr(skb));
+ 	return err;
+diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
+index 18634ebd20a47..a42be96ae209b 100644
+--- a/net/ipv6/ndisc.c
++++ b/net/ipv6/ndisc.c
+@@ -197,7 +197,8 @@ static struct nd_opt_hdr *ndisc_next_option(struct nd_opt_hdr *cur,
+ static inline int ndisc_is_useropt(const struct net_device *dev,
+ 				   struct nd_opt_hdr *opt)
+ {
+-	return opt->nd_opt_type == ND_OPT_RDNSS ||
++	return opt->nd_opt_type == ND_OPT_PREFIX_INFO ||
++		opt->nd_opt_type == ND_OPT_RDNSS ||
+ 		opt->nd_opt_type == ND_OPT_DNSSL ||
+ 		opt->nd_opt_type == ND_OPT_CAPTIVE_PORTAL ||
+ 		opt->nd_opt_type == ND_OPT_PREF64 ||
+diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
+index f2eeb8a850af2..39daf5915bae2 100644
+--- a/net/mptcp/protocol.c
++++ b/net/mptcp/protocol.c
+@@ -2335,7 +2335,7 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
+ 
+ 	lock_sock_nested(ssk, SINGLE_DEPTH_NESTING);
+ 
+-	if (flags & MPTCP_CF_FASTCLOSE) {
++	if ((flags & MPTCP_CF_FASTCLOSE) && !__mptcp_check_fallback(msk)) {
+ 		/* be sure to force the tcp_disconnect() path,
+ 		 * to generate the egress reset
+ 		 */
+@@ -3321,7 +3321,7 @@ static void mptcp_release_cb(struct sock *sk)
+ 
+ 	if (__test_and_clear_bit(MPTCP_CLEAN_UNA, &msk->cb_flags))
+ 		__mptcp_clean_una_wakeup(sk);
+-	if (unlikely(&msk->cb_flags)) {
++	if (unlikely(msk->cb_flags)) {
+ 		/* be sure to set the current sk state before tacking actions
+ 		 * depending on sk_state, that is processing MPTCP_ERROR_REPORT
+ 		 */
+diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
+index d3783a7056e17..16c9c3197adad 100644
+--- a/net/mptcp/protocol.h
++++ b/net/mptcp/protocol.h
+@@ -320,7 +320,6 @@ struct mptcp_sock {
+ 
+ 	u32 setsockopt_seq;
+ 	char		ca_name[TCP_CA_NAME_MAX];
+-	struct mptcp_sock	*dl_next;
+ };
+ 
+ #define mptcp_data_lock(sk) spin_lock_bh(&(sk)->sk_lock.slock)
+diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
+index d9c8b21c6076e..521d6817464a9 100644
+--- a/net/mptcp/subflow.c
++++ b/net/mptcp/subflow.c
+@@ -1785,16 +1785,31 @@ static void subflow_state_change(struct sock *sk)
+ void mptcp_subflow_queue_clean(struct sock *listener_sk, struct sock *listener_ssk)
+ {
+ 	struct request_sock_queue *queue = &inet_csk(listener_ssk)->icsk_accept_queue;
+-	struct mptcp_sock *msk, *next, *head = NULL;
+-	struct request_sock *req;
+-	struct sock *sk;
++	struct request_sock *req, *head, *tail;
++	struct mptcp_subflow_context *subflow;
++	struct sock *sk, *ssk;
+ 
+-	/* build a list of all unaccepted mptcp sockets */
++	/* Due to lock dependencies no relevant lock can be acquired under rskq_lock.
++	 * Splice the req list, so that accept() can not reach the pending ssk after
++	 * the listener socket is released below.
++	 */
+ 	spin_lock_bh(&queue->rskq_lock);
+-	for (req = queue->rskq_accept_head; req; req = req->dl_next) {
+-		struct mptcp_subflow_context *subflow;
+-		struct sock *ssk = req->sk;
++	head = queue->rskq_accept_head;
++	tail = queue->rskq_accept_tail;
++	queue->rskq_accept_head = NULL;
++	queue->rskq_accept_tail = NULL;
++	spin_unlock_bh(&queue->rskq_lock);
++
++	if (!head)
++		return;
+ 
++	/* can't acquire the msk socket lock under the subflow one,
++	 * or will cause ABBA deadlock
++	 */
++	release_sock(listener_ssk);
++
++	for (req = head; req; req = req->dl_next) {
++		ssk = req->sk;
+ 		if (!sk_is_mptcp(ssk))
+ 			continue;
+ 
+@@ -1802,32 +1817,10 @@ void mptcp_subflow_queue_clean(struct sock *listener_sk, struct sock *listener_s
+ 		if (!subflow || !subflow->conn)
+ 			continue;
+ 
+-		/* skip if already in list */
+ 		sk = subflow->conn;
+-		msk = mptcp_sk(sk);
+-		if (msk->dl_next || msk == head)
+-			continue;
+-
+ 		sock_hold(sk);
+-		msk->dl_next = head;
+-		head = msk;
+-	}
+-	spin_unlock_bh(&queue->rskq_lock);
+-	if (!head)
+-		return;
+-
+-	/* can't acquire the msk socket lock under the subflow one,
+-	 * or will cause ABBA deadlock
+-	 */
+-	release_sock(listener_ssk);
+-
+-	for (msk = head; msk; msk = next) {
+-		sk = (struct sock *)msk;
+ 
+ 		lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
+-		next = msk->dl_next;
+-		msk->dl_next = NULL;
+-
+ 		__mptcp_unaccepted_force_close(sk);
+ 		release_sock(sk);
+ 
+@@ -1851,6 +1844,13 @@ void mptcp_subflow_queue_clean(struct sock *listener_sk, struct sock *listener_s
+ 
+ 	/* we are still under the listener msk socket lock */
+ 	lock_sock_nested(listener_ssk, SINGLE_DEPTH_NESTING);
++
++	/* restore the listener queue, to let the TCP code clean it up */
++	spin_lock_bh(&queue->rskq_lock);
++	WARN_ON_ONCE(queue->rskq_accept_head);
++	queue->rskq_accept_head = head;
++	queue->rskq_accept_tail = tail;
++	spin_unlock_bh(&queue->rskq_lock);
+ }
+ 
+ static int subflow_ulp_init(struct sock *sk)
+diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
+index da00c411a9cd4..c6de10f458fa4 100644
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -31,7 +31,9 @@ static LIST_HEAD(nf_tables_expressions);
+ static LIST_HEAD(nf_tables_objects);
+ static LIST_HEAD(nf_tables_flowtables);
+ static LIST_HEAD(nf_tables_destroy_list);
++static LIST_HEAD(nf_tables_gc_list);
+ static DEFINE_SPINLOCK(nf_tables_destroy_list_lock);
++static DEFINE_SPINLOCK(nf_tables_gc_list_lock);
+ 
+ enum {
+ 	NFT_VALIDATE_SKIP	= 0,
+@@ -120,6 +122,9 @@ static void nft_validate_state_update(struct nft_table *table, u8 new_validate_s
+ static void nf_tables_trans_destroy_work(struct work_struct *w);
+ static DECLARE_WORK(trans_destroy_work, nf_tables_trans_destroy_work);
+ 
++static void nft_trans_gc_work(struct work_struct *work);
++static DECLARE_WORK(trans_gc_work, nft_trans_gc_work);
++
+ static void nft_ctx_init(struct nft_ctx *ctx,
+ 			 struct net *net,
+ 			 const struct sk_buff *skb,
+@@ -581,10 +586,6 @@ static int nft_trans_set_add(const struct nft_ctx *ctx, int msg_type,
+ 	return __nft_trans_set_add(ctx, msg_type, set, NULL);
+ }
+ 
+-static void nft_setelem_data_deactivate(const struct net *net,
+-					const struct nft_set *set,
+-					struct nft_set_elem *elem);
+-
+ static int nft_mapelem_deactivate(const struct nft_ctx *ctx,
+ 				  struct nft_set *set,
+ 				  const struct nft_set_iter *iter,
+@@ -5054,6 +5055,7 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
+ 
+ 	INIT_LIST_HEAD(&set->bindings);
+ 	INIT_LIST_HEAD(&set->catchall_list);
++	refcount_set(&set->refs, 1);
+ 	set->table = table;
+ 	write_pnet(&set->net, net);
+ 	set->ops = ops;
+@@ -5121,6 +5123,14 @@ static void nft_set_catchall_destroy(const struct nft_ctx *ctx,
+ 	}
+ }
+ 
++static void nft_set_put(struct nft_set *set)
++{
++	if (refcount_dec_and_test(&set->refs)) {
++		kfree(set->name);
++		kvfree(set);
++	}
++}
++
+ static void nft_set_destroy(const struct nft_ctx *ctx, struct nft_set *set)
+ {
+ 	int i;
+@@ -5133,8 +5143,7 @@ static void nft_set_destroy(const struct nft_ctx *ctx, struct nft_set *set)
+ 
+ 	set->ops->destroy(ctx, set);
+ 	nft_set_catchall_destroy(ctx, set);
+-	kfree(set->name);
+-	kvfree(set);
++	nft_set_put(set);
+ }
+ 
+ static int nf_tables_delset(struct sk_buff *skb, const struct nfnl_info *info,
+@@ -5590,8 +5599,12 @@ static int nf_tables_dump_setelem(const struct nft_ctx *ctx,
+ 				  const struct nft_set_iter *iter,
+ 				  struct nft_set_elem *elem)
+ {
++	const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv);
+ 	struct nft_set_dump_args *args;
+ 
++	if (nft_set_elem_expired(ext))
++		return 0;
++
+ 	args = container_of(iter, struct nft_set_dump_args, iter);
+ 	return nf_tables_fill_setelem(args->skb, set, elem);
+ }
+@@ -6251,7 +6264,8 @@ struct nft_set_ext *nft_set_catchall_lookup(const struct net *net,
+ 	list_for_each_entry_rcu(catchall, &set->catchall_list, list) {
+ 		ext = nft_set_elem_ext(set, catchall->elem);
+ 		if (nft_set_elem_active(ext, genmask) &&
+-		    !nft_set_elem_expired(ext))
++		    !nft_set_elem_expired(ext) &&
++		    !nft_set_elem_is_dead(ext))
+ 			return ext;
+ 	}
+ 
+@@ -6343,7 +6357,6 @@ static void nft_setelem_activate(struct net *net, struct nft_set *set,
+ 
+ 	if (nft_setelem_is_catchall(set, elem)) {
+ 		nft_set_elem_change_active(net, set, ext);
+-		nft_set_elem_clear_busy(ext);
+ 	} else {
+ 		set->ops->activate(net, set, elem);
+ 	}
+@@ -6358,8 +6371,7 @@ static int nft_setelem_catchall_deactivate(const struct net *net,
+ 
+ 	list_for_each_entry(catchall, &set->catchall_list, list) {
+ 		ext = nft_set_elem_ext(set, catchall->elem);
+-		if (!nft_is_active(net, ext) ||
+-		    nft_set_elem_mark_busy(ext))
++		if (!nft_is_active(net, ext))
+ 			continue;
+ 
+ 		kfree(elem->priv);
+@@ -6903,9 +6915,9 @@ static void nft_setelem_data_activate(const struct net *net,
+ 		nft_use_inc_restore(&(*nft_set_ext_obj(ext))->use);
+ }
+ 
+-static void nft_setelem_data_deactivate(const struct net *net,
+-					const struct nft_set *set,
+-					struct nft_set_elem *elem)
++void nft_setelem_data_deactivate(const struct net *net,
++				 const struct nft_set *set,
++				 struct nft_set_elem *elem)
+ {
+ 	const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv);
+ 
+@@ -7069,8 +7081,7 @@ static int nft_set_catchall_flush(const struct nft_ctx *ctx,
+ 
+ 	list_for_each_entry_rcu(catchall, &set->catchall_list, list) {
+ 		ext = nft_set_elem_ext(set, catchall->elem);
+-		if (!nft_set_elem_active(ext, genmask) ||
+-		    nft_set_elem_mark_busy(ext))
++		if (!nft_set_elem_active(ext, genmask))
+ 			continue;
+ 
+ 		elem.priv = catchall->elem;
+@@ -9382,6 +9393,207 @@ void nft_chain_del(struct nft_chain *chain)
+ 	list_del_rcu(&chain->list);
+ }
+ 
++static void nft_trans_gc_setelem_remove(struct nft_ctx *ctx,
++					struct nft_trans_gc *trans)
++{
++	void **priv = trans->priv;
++	unsigned int i;
++
++	for (i = 0; i < trans->count; i++) {
++		struct nft_set_elem elem = {
++			.priv = priv[i],
++		};
++
++		nft_setelem_data_deactivate(ctx->net, trans->set, &elem);
++		nft_setelem_remove(ctx->net, trans->set, &elem);
++	}
++}
++
++void nft_trans_gc_destroy(struct nft_trans_gc *trans)
++{
++	nft_set_put(trans->set);
++	put_net(trans->net);
++	kfree(trans);
++}
++
++static void nft_trans_gc_trans_free(struct rcu_head *rcu)
++{
++	struct nft_set_elem elem = {};
++	struct nft_trans_gc *trans;
++	struct nft_ctx ctx = {};
++	unsigned int i;
++
++	trans = container_of(rcu, struct nft_trans_gc, rcu);
++	ctx.net	= read_pnet(&trans->set->net);
++
++	for (i = 0; i < trans->count; i++) {
++		elem.priv = trans->priv[i];
++		if (!nft_setelem_is_catchall(trans->set, &elem))
++			atomic_dec(&trans->set->nelems);
++
++		nf_tables_set_elem_destroy(&ctx, trans->set, elem.priv);
++	}
++
++	nft_trans_gc_destroy(trans);
++}
++
++static bool nft_trans_gc_work_done(struct nft_trans_gc *trans)
++{
++	struct nftables_pernet *nft_net;
++	struct nft_ctx ctx = {};
++
++	nft_net = nft_pernet(trans->net);
++
++	mutex_lock(&nft_net->commit_mutex);
++
++	/* Check for race with transaction, otherwise this batch refers to
++	 * stale objects that might not be there anymore. Skip transaction if
++	 * set has been destroyed from control plane transaction in case gc
++	 * worker loses race.
++	 */
++	if (READ_ONCE(nft_net->gc_seq) != trans->seq || trans->set->dead) {
++		mutex_unlock(&nft_net->commit_mutex);
++		return false;
++	}
++
++	ctx.net = trans->net;
++	ctx.table = trans->set->table;
++
++	nft_trans_gc_setelem_remove(&ctx, trans);
++	mutex_unlock(&nft_net->commit_mutex);
++
++	return true;
++}
++
++static void nft_trans_gc_work(struct work_struct *work)
++{
++	struct nft_trans_gc *trans, *next;
++	LIST_HEAD(trans_gc_list);
++
++	spin_lock(&nf_tables_destroy_list_lock);
++	list_splice_init(&nf_tables_gc_list, &trans_gc_list);
++	spin_unlock(&nf_tables_destroy_list_lock);
++
++	list_for_each_entry_safe(trans, next, &trans_gc_list, list) {
++		list_del(&trans->list);
++		if (!nft_trans_gc_work_done(trans)) {
++			nft_trans_gc_destroy(trans);
++			continue;
++		}
++		call_rcu(&trans->rcu, nft_trans_gc_trans_free);
++	}
++}
++
++struct nft_trans_gc *nft_trans_gc_alloc(struct nft_set *set,
++					unsigned int gc_seq, gfp_t gfp)
++{
++	struct net *net = read_pnet(&set->net);
++	struct nft_trans_gc *trans;
++
++	trans = kzalloc(sizeof(*trans), gfp);
++	if (!trans)
++		return NULL;
++
++	refcount_inc(&set->refs);
++	trans->set = set;
++	trans->net = get_net(net);
++	trans->seq = gc_seq;
++
++	return trans;
++}
++
++void nft_trans_gc_elem_add(struct nft_trans_gc *trans, void *priv)
++{
++	trans->priv[trans->count++] = priv;
++}
++
++static void nft_trans_gc_queue_work(struct nft_trans_gc *trans)
++{
++	spin_lock(&nf_tables_gc_list_lock);
++	list_add_tail(&trans->list, &nf_tables_gc_list);
++	spin_unlock(&nf_tables_gc_list_lock);
++
++	schedule_work(&trans_gc_work);
++}
++
++static int nft_trans_gc_space(struct nft_trans_gc *trans)
++{
++	return NFT_TRANS_GC_BATCHCOUNT - trans->count;
++}
++
++struct nft_trans_gc *nft_trans_gc_queue_async(struct nft_trans_gc *gc,
++					      unsigned int gc_seq, gfp_t gfp)
++{
++	if (nft_trans_gc_space(gc))
++		return gc;
++
++	nft_trans_gc_queue_work(gc);
++
++	return nft_trans_gc_alloc(gc->set, gc_seq, gfp);
++}
++
++void nft_trans_gc_queue_async_done(struct nft_trans_gc *trans)
++{
++	if (trans->count == 0) {
++		nft_trans_gc_destroy(trans);
++		return;
++	}
++
++	nft_trans_gc_queue_work(trans);
++}
++
++struct nft_trans_gc *nft_trans_gc_queue_sync(struct nft_trans_gc *gc, gfp_t gfp)
++{
++	if (WARN_ON_ONCE(!lockdep_commit_lock_is_held(gc->net)))
++		return NULL;
++
++	if (nft_trans_gc_space(gc))
++		return gc;
++
++	call_rcu(&gc->rcu, nft_trans_gc_trans_free);
++
++	return nft_trans_gc_alloc(gc->set, 0, gfp);
++}
++
++void nft_trans_gc_queue_sync_done(struct nft_trans_gc *trans)
++{
++	WARN_ON_ONCE(!lockdep_commit_lock_is_held(trans->net));
++
++	if (trans->count == 0) {
++		nft_trans_gc_destroy(trans);
++		return;
++	}
++
++	call_rcu(&trans->rcu, nft_trans_gc_trans_free);
++}
++
++struct nft_trans_gc *nft_trans_gc_catchall(struct nft_trans_gc *gc,
++					   unsigned int gc_seq)
++{
++	struct nft_set_elem_catchall *catchall;
++	const struct nft_set *set = gc->set;
++	struct nft_set_ext *ext;
++
++	list_for_each_entry_rcu(catchall, &set->catchall_list, list) {
++		ext = nft_set_elem_ext(set, catchall->elem);
++
++		if (!nft_set_elem_expired(ext))
++			continue;
++		if (nft_set_elem_is_dead(ext))
++			goto dead_elem;
++
++		nft_set_elem_dead(ext);
++dead_elem:
++		gc = nft_trans_gc_queue_async(gc, gc_seq, GFP_ATOMIC);
++		if (!gc)
++			return NULL;
++
++		nft_trans_gc_elem_add(gc, catchall->elem);
++	}
++
++	return gc;
++}
++
+ static void nf_tables_module_autoload_cleanup(struct net *net)
+ {
+ 	struct nftables_pernet *nft_net = nft_pernet(net);
+@@ -9544,11 +9756,11 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
+ {
+ 	struct nftables_pernet *nft_net = nft_pernet(net);
+ 	struct nft_trans *trans, *next;
++	unsigned int base_seq, gc_seq;
+ 	LIST_HEAD(set_update_list);
+ 	struct nft_trans_elem *te;
+ 	struct nft_chain *chain;
+ 	struct nft_table *table;
+-	unsigned int base_seq;
+ 	LIST_HEAD(adl);
+ 	int err;
+ 
+@@ -9625,6 +9837,10 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
+ 
+ 	WRITE_ONCE(nft_net->base_seq, base_seq);
+ 
++	/* Bump gc counter, it becomes odd, this is the busy mark. */
++	gc_seq = READ_ONCE(nft_net->gc_seq);
++	WRITE_ONCE(nft_net->gc_seq, ++gc_seq);
++
+ 	/* step 3. Start new generation, rules_gen_X now in use. */
+ 	net->nft.gencursor = nft_gencursor_next(net);
+ 
+@@ -9729,6 +9945,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
+ 			break;
+ 		case NFT_MSG_DELSET:
+ 		case NFT_MSG_DESTROYSET:
++			nft_trans_set(trans)->dead = 1;
+ 			list_del_rcu(&nft_trans_set(trans)->list);
+ 			nf_tables_set_notify(&trans->ctx, nft_trans_set(trans),
+ 					     trans->msg_type, GFP_KERNEL);
+@@ -9831,6 +10048,8 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
+ 	nft_commit_notify(net, NETLINK_CB(skb).portid);
+ 	nf_tables_gen_notify(net, skb, NFT_MSG_NEWGEN);
+ 	nf_tables_commit_audit_log(&adl, nft_net->base_seq);
++
++	WRITE_ONCE(nft_net->gc_seq, ++gc_seq);
+ 	nf_tables_commit_release(net);
+ 
+ 	return 0;
+@@ -10880,6 +11099,7 @@ static int __net_init nf_tables_init_net(struct net *net)
+ 	INIT_LIST_HEAD(&nft_net->notify_list);
+ 	mutex_init(&nft_net->commit_mutex);
+ 	nft_net->base_seq = 1;
++	nft_net->gc_seq = 0;
+ 
+ 	return 0;
+ }
+@@ -10908,10 +11128,16 @@ static void __net_exit nf_tables_exit_net(struct net *net)
+ 	WARN_ON_ONCE(!list_empty(&nft_net->notify_list));
+ }
+ 
++static void nf_tables_exit_batch(struct list_head *net_exit_list)
++{
++	flush_work(&trans_gc_work);
++}
++
+ static struct pernet_operations nf_tables_net_ops = {
+ 	.init		= nf_tables_init_net,
+ 	.pre_exit	= nf_tables_pre_exit_net,
+ 	.exit		= nf_tables_exit_net,
++	.exit_batch	= nf_tables_exit_batch,
+ 	.id		= &nf_tables_net_id,
+ 	.size		= sizeof(struct nftables_pernet),
+ };
+@@ -10983,6 +11209,7 @@ static void __exit nf_tables_module_exit(void)
+ 	nft_chain_filter_fini();
+ 	nft_chain_route_fini();
+ 	unregister_pernet_subsys(&nf_tables_net_ops);
++	cancel_work_sync(&trans_gc_work);
+ 	cancel_work_sync(&trans_destroy_work);
+ 	rcu_barrier();
+ 	rhltable_destroy(&nft_objname_ht);
+diff --git a/net/netfilter/nft_set_hash.c b/net/netfilter/nft_set_hash.c
+index 0b73cb0e752f7..cef5df8460009 100644
+--- a/net/netfilter/nft_set_hash.c
++++ b/net/netfilter/nft_set_hash.c
+@@ -59,6 +59,8 @@ static inline int nft_rhash_cmp(struct rhashtable_compare_arg *arg,
+ 
+ 	if (memcmp(nft_set_ext_key(&he->ext), x->key, x->set->klen))
+ 		return 1;
++	if (nft_set_elem_is_dead(&he->ext))
++		return 1;
+ 	if (nft_set_elem_expired(&he->ext))
+ 		return 1;
+ 	if (!nft_set_elem_active(&he->ext, x->genmask))
+@@ -188,7 +190,6 @@ static void nft_rhash_activate(const struct net *net, const struct nft_set *set,
+ 	struct nft_rhash_elem *he = elem->priv;
+ 
+ 	nft_set_elem_change_active(net, set, &he->ext);
+-	nft_set_elem_clear_busy(&he->ext);
+ }
+ 
+ static bool nft_rhash_flush(const struct net *net,
+@@ -196,12 +197,9 @@ static bool nft_rhash_flush(const struct net *net,
+ {
+ 	struct nft_rhash_elem *he = priv;
+ 
+-	if (!nft_set_elem_mark_busy(&he->ext) ||
+-	    !nft_is_active(net, &he->ext)) {
+-		nft_set_elem_change_active(net, set, &he->ext);
+-		return true;
+-	}
+-	return false;
++	nft_set_elem_change_active(net, set, &he->ext);
++
++	return true;
+ }
+ 
+ static void *nft_rhash_deactivate(const struct net *net,
+@@ -218,9 +216,8 @@ static void *nft_rhash_deactivate(const struct net *net,
+ 
+ 	rcu_read_lock();
+ 	he = rhashtable_lookup(&priv->ht, &arg, nft_rhash_params);
+-	if (he != NULL &&
+-	    !nft_rhash_flush(net, set, he))
+-		he = NULL;
++	if (he)
++		nft_set_elem_change_active(net, set, &he->ext);
+ 
+ 	rcu_read_unlock();
+ 
+@@ -252,7 +249,9 @@ static bool nft_rhash_delete(const struct nft_set *set,
+ 	if (he == NULL)
+ 		return false;
+ 
+-	return rhashtable_remove_fast(&priv->ht, &he->node, nft_rhash_params) == 0;
++	nft_set_elem_dead(&he->ext);
++
++	return true;
+ }
+ 
+ static void nft_rhash_walk(const struct nft_ctx *ctx, struct nft_set *set,
+@@ -278,8 +277,6 @@ static void nft_rhash_walk(const struct nft_ctx *ctx, struct nft_set *set,
+ 
+ 		if (iter->count < iter->skip)
+ 			goto cont;
+-		if (nft_set_elem_expired(&he->ext))
+-			goto cont;
+ 		if (!nft_set_elem_active(&he->ext, iter->genmask))
+ 			goto cont;
+ 
+@@ -314,25 +311,48 @@ static bool nft_rhash_expr_needs_gc_run(const struct nft_set *set,
+ 
+ static void nft_rhash_gc(struct work_struct *work)
+ {
++	struct nftables_pernet *nft_net;
+ 	struct nft_set *set;
+ 	struct nft_rhash_elem *he;
+ 	struct nft_rhash *priv;
+-	struct nft_set_gc_batch *gcb = NULL;
+ 	struct rhashtable_iter hti;
++	struct nft_trans_gc *gc;
++	struct net *net;
++	u32 gc_seq;
+ 
+ 	priv = container_of(work, struct nft_rhash, gc_work.work);
+ 	set  = nft_set_container_of(priv);
++	net  = read_pnet(&set->net);
++	nft_net = nft_pernet(net);
++	gc_seq = READ_ONCE(nft_net->gc_seq);
++
++	gc = nft_trans_gc_alloc(set, gc_seq, GFP_KERNEL);
++	if (!gc)
++		goto done;
+ 
+ 	rhashtable_walk_enter(&priv->ht, &hti);
+ 	rhashtable_walk_start(&hti);
+ 
+ 	while ((he = rhashtable_walk_next(&hti))) {
+ 		if (IS_ERR(he)) {
+-			if (PTR_ERR(he) != -EAGAIN)
+-				break;
++			if (PTR_ERR(he) != -EAGAIN) {
++				nft_trans_gc_destroy(gc);
++				gc = NULL;
++				goto try_later;
++			}
+ 			continue;
+ 		}
+ 
++		/* Ruleset has been updated, try later. */
++		if (READ_ONCE(nft_net->gc_seq) != gc_seq) {
++			nft_trans_gc_destroy(gc);
++			gc = NULL;
++			goto try_later;
++		}
++
++		if (nft_set_elem_is_dead(&he->ext))
++			goto dead_elem;
++
+ 		if (nft_set_ext_exists(&he->ext, NFT_SET_EXT_EXPRESSIONS) &&
+ 		    nft_rhash_expr_needs_gc_run(set, &he->ext))
+ 			goto needs_gc_run;
+@@ -340,26 +360,26 @@ static void nft_rhash_gc(struct work_struct *work)
+ 		if (!nft_set_elem_expired(&he->ext))
+ 			continue;
+ needs_gc_run:
+-		if (nft_set_elem_mark_busy(&he->ext))
+-			continue;
++		nft_set_elem_dead(&he->ext);
++dead_elem:
++		gc = nft_trans_gc_queue_async(gc, gc_seq, GFP_ATOMIC);
++		if (!gc)
++			goto try_later;
+ 
+-		gcb = nft_set_gc_batch_check(set, gcb, GFP_ATOMIC);
+-		if (gcb == NULL)
+-			break;
+-		rhashtable_remove_fast(&priv->ht, &he->node, nft_rhash_params);
+-		atomic_dec(&set->nelems);
+-		nft_set_gc_batch_add(gcb, he);
++		nft_trans_gc_elem_add(gc, he);
+ 	}
++
++	gc = nft_trans_gc_catchall(gc, gc_seq);
++
++try_later:
++	/* catchall list iteration requires rcu read side lock. */
+ 	rhashtable_walk_stop(&hti);
+ 	rhashtable_walk_exit(&hti);
+ 
+-	he = nft_set_catchall_gc(set);
+-	if (he) {
+-		gcb = nft_set_gc_batch_check(set, gcb, GFP_ATOMIC);
+-		if (gcb)
+-			nft_set_gc_batch_add(gcb, he);
+-	}
+-	nft_set_gc_batch_complete(gcb);
++	if (gc)
++		nft_trans_gc_queue_async_done(gc);
++
++done:
+ 	queue_delayed_work(system_power_efficient_wq, &priv->gc_work,
+ 			   nft_set_gc_interval(set));
+ }
+@@ -394,7 +414,7 @@ static int nft_rhash_init(const struct nft_set *set,
+ 		return err;
+ 
+ 	INIT_DEFERRABLE_WORK(&priv->gc_work, nft_rhash_gc);
+-	if (set->flags & NFT_SET_TIMEOUT)
++	if (set->flags & (NFT_SET_TIMEOUT | NFT_SET_EVAL))
+ 		nft_rhash_gc_init(set);
+ 
+ 	return 0;
+@@ -422,7 +442,6 @@ static void nft_rhash_destroy(const struct nft_ctx *ctx,
+ 	};
+ 
+ 	cancel_delayed_work_sync(&priv->gc_work);
+-	rcu_barrier();
+ 	rhashtable_free_and_destroy(&priv->ht, nft_rhash_elem_destroy,
+ 				    (void *)&rhash_ctx);
+ }
+diff --git a/net/netfilter/nft_set_pipapo.c b/net/netfilter/nft_set_pipapo.c
+index a81829c10feab..92b108e3000eb 100644
+--- a/net/netfilter/nft_set_pipapo.c
++++ b/net/netfilter/nft_set_pipapo.c
+@@ -566,8 +566,7 @@ next_match:
+ 			goto out;
+ 
+ 		if (last) {
+-			if (nft_set_elem_expired(&f->mt[b].e->ext) ||
+-			    (genmask &&
++			if ((genmask &&
+ 			     !nft_set_elem_active(&f->mt[b].e->ext, genmask)))
+ 				goto next_match;
+ 
+@@ -601,8 +600,17 @@ out:
+ static void *nft_pipapo_get(const struct net *net, const struct nft_set *set,
+ 			    const struct nft_set_elem *elem, unsigned int flags)
+ {
+-	return pipapo_get(net, set, (const u8 *)elem->key.val.data,
+-			  nft_genmask_cur(net));
++	struct nft_pipapo_elem *ret;
++
++	ret = pipapo_get(net, set, (const u8 *)elem->key.val.data,
++			 nft_genmask_cur(net));
++	if (IS_ERR(ret))
++		return ret;
++
++	if (nft_set_elem_expired(&ret->ext))
++		return ERR_PTR(-ENOENT);
++
++	return ret;
+ }
+ 
+ /**
+@@ -1529,16 +1537,34 @@ static void pipapo_drop(struct nft_pipapo_match *m,
+ 	}
+ }
+ 
++static void nft_pipapo_gc_deactivate(struct net *net, struct nft_set *set,
++				     struct nft_pipapo_elem *e)
++
++{
++	struct nft_set_elem elem = {
++		.priv	= e,
++	};
++
++	nft_setelem_data_deactivate(net, set, &elem);
++}
++
+ /**
+  * pipapo_gc() - Drop expired entries from set, destroy start and end elements
+  * @set:	nftables API set representation
+  * @m:		Matching data
+  */
+-static void pipapo_gc(const struct nft_set *set, struct nft_pipapo_match *m)
++static void pipapo_gc(const struct nft_set *_set, struct nft_pipapo_match *m)
+ {
++	struct nft_set *set = (struct nft_set *) _set;
+ 	struct nft_pipapo *priv = nft_set_priv(set);
++	struct net *net = read_pnet(&set->net);
+ 	int rules_f0, first_rule = 0;
+ 	struct nft_pipapo_elem *e;
++	struct nft_trans_gc *gc;
++
++	gc = nft_trans_gc_alloc(set, 0, GFP_KERNEL);
++	if (!gc)
++		return;
+ 
+ 	while ((rules_f0 = pipapo_rules_same_key(m->f, first_rule))) {
+ 		union nft_pipapo_map_bucket rulemap[NFT_PIPAPO_MAX_FIELDS];
+@@ -1562,13 +1588,20 @@ static void pipapo_gc(const struct nft_set *set, struct nft_pipapo_match *m)
+ 		f--;
+ 		i--;
+ 		e = f->mt[rulemap[i].to].e;
+-		if (nft_set_elem_expired(&e->ext) &&
+-		    !nft_set_elem_mark_busy(&e->ext)) {
++
++		/* synchronous gc never fails, there is no need to set on
++		 * NFT_SET_ELEM_DEAD_BIT.
++		 */
++		if (nft_set_elem_expired(&e->ext)) {
+ 			priv->dirty = true;
+-			pipapo_drop(m, rulemap);
+ 
+-			rcu_barrier();
+-			nft_set_elem_destroy(set, e, true);
++			gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC);
++			if (!gc)
++				break;
++
++			nft_pipapo_gc_deactivate(net, set, e);
++			pipapo_drop(m, rulemap);
++			nft_trans_gc_elem_add(gc, e);
+ 
+ 			/* And check again current first rule, which is now the
+ 			 * first we haven't checked.
+@@ -1578,11 +1611,11 @@ static void pipapo_gc(const struct nft_set *set, struct nft_pipapo_match *m)
+ 		}
+ 	}
+ 
+-	e = nft_set_catchall_gc(set);
+-	if (e)
+-		nft_set_elem_destroy(set, e, true);
+-
+-	priv->last_gc = jiffies;
++	gc = nft_trans_gc_catchall(gc, 0);
++	if (gc) {
++		nft_trans_gc_queue_sync_done(gc);
++		priv->last_gc = jiffies;
++	}
+ }
+ 
+ /**
+@@ -1707,7 +1740,6 @@ static void nft_pipapo_activate(const struct net *net,
+ 		return;
+ 
+ 	nft_set_elem_change_active(net, set, &e->ext);
+-	nft_set_elem_clear_busy(&e->ext);
+ }
+ 
+ /**
+@@ -2006,8 +2038,6 @@ static void nft_pipapo_walk(const struct nft_ctx *ctx, struct nft_set *set,
+ 			goto cont;
+ 
+ 		e = f->mt[r].e;
+-		if (nft_set_elem_expired(&e->ext))
+-			goto cont;
+ 
+ 		elem.priv = e;
+ 
+diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c
+index 8d73fffd2d09d..f9d4c8fcbbf82 100644
+--- a/net/netfilter/nft_set_rbtree.c
++++ b/net/netfilter/nft_set_rbtree.c
+@@ -46,6 +46,12 @@ static int nft_rbtree_cmp(const struct nft_set *set,
+ 		      set->klen);
+ }
+ 
++static bool nft_rbtree_elem_expired(const struct nft_rbtree_elem *rbe)
++{
++	return nft_set_elem_expired(&rbe->ext) ||
++	       nft_set_elem_is_dead(&rbe->ext);
++}
++
+ static bool __nft_rbtree_lookup(const struct net *net, const struct nft_set *set,
+ 				const u32 *key, const struct nft_set_ext **ext,
+ 				unsigned int seq)
+@@ -80,7 +86,7 @@ static bool __nft_rbtree_lookup(const struct net *net, const struct nft_set *set
+ 				continue;
+ 			}
+ 
+-			if (nft_set_elem_expired(&rbe->ext))
++			if (nft_rbtree_elem_expired(rbe))
+ 				return false;
+ 
+ 			if (nft_rbtree_interval_end(rbe)) {
+@@ -98,7 +104,7 @@ static bool __nft_rbtree_lookup(const struct net *net, const struct nft_set *set
+ 
+ 	if (set->flags & NFT_SET_INTERVAL && interval != NULL &&
+ 	    nft_set_elem_active(&interval->ext, genmask) &&
+-	    !nft_set_elem_expired(&interval->ext) &&
++	    !nft_rbtree_elem_expired(interval) &&
+ 	    nft_rbtree_interval_start(interval)) {
+ 		*ext = &interval->ext;
+ 		return true;
+@@ -215,6 +221,18 @@ static void *nft_rbtree_get(const struct net *net, const struct nft_set *set,
+ 	return rbe;
+ }
+ 
++static void nft_rbtree_gc_remove(struct net *net, struct nft_set *set,
++				 struct nft_rbtree *priv,
++				 struct nft_rbtree_elem *rbe)
++{
++	struct nft_set_elem elem = {
++		.priv	= rbe,
++	};
++
++	nft_setelem_data_deactivate(net, set, &elem);
++	rb_erase(&rbe->node, &priv->root);
++}
++
+ static int nft_rbtree_gc_elem(const struct nft_set *__set,
+ 			      struct nft_rbtree *priv,
+ 			      struct nft_rbtree_elem *rbe,
+@@ -222,11 +240,12 @@ static int nft_rbtree_gc_elem(const struct nft_set *__set,
+ {
+ 	struct nft_set *set = (struct nft_set *)__set;
+ 	struct rb_node *prev = rb_prev(&rbe->node);
++	struct net *net = read_pnet(&set->net);
+ 	struct nft_rbtree_elem *rbe_prev;
+-	struct nft_set_gc_batch *gcb;
++	struct nft_trans_gc *gc;
+ 
+-	gcb = nft_set_gc_batch_check(set, NULL, GFP_ATOMIC);
+-	if (!gcb)
++	gc = nft_trans_gc_alloc(set, 0, GFP_ATOMIC);
++	if (!gc)
+ 		return -ENOMEM;
+ 
+ 	/* search for end interval coming before this element.
+@@ -244,17 +263,28 @@ static int nft_rbtree_gc_elem(const struct nft_set *__set,
+ 
+ 	if (prev) {
+ 		rbe_prev = rb_entry(prev, struct nft_rbtree_elem, node);
++		nft_rbtree_gc_remove(net, set, priv, rbe_prev);
+ 
+-		rb_erase(&rbe_prev->node, &priv->root);
+-		atomic_dec(&set->nelems);
+-		nft_set_gc_batch_add(gcb, rbe_prev);
++		/* There is always room in this trans gc for this element,
++		 * memory allocation never actually happens, hence, the warning
++		 * splat in such case. No need to set NFT_SET_ELEM_DEAD_BIT,
++		 * this is synchronous gc which never fails.
++		 */
++		gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC);
++		if (WARN_ON_ONCE(!gc))
++			return -ENOMEM;
++
++		nft_trans_gc_elem_add(gc, rbe_prev);
+ 	}
+ 
+-	rb_erase(&rbe->node, &priv->root);
+-	atomic_dec(&set->nelems);
++	nft_rbtree_gc_remove(net, set, priv, rbe);
++	gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC);
++	if (WARN_ON_ONCE(!gc))
++		return -ENOMEM;
++
++	nft_trans_gc_elem_add(gc, rbe);
+ 
+-	nft_set_gc_batch_add(gcb, rbe);
+-	nft_set_gc_batch_complete(gcb);
++	nft_trans_gc_queue_sync_done(gc);
+ 
+ 	return 0;
+ }
+@@ -482,7 +512,6 @@ static void nft_rbtree_activate(const struct net *net,
+ 	struct nft_rbtree_elem *rbe = elem->priv;
+ 
+ 	nft_set_elem_change_active(net, set, &rbe->ext);
+-	nft_set_elem_clear_busy(&rbe->ext);
+ }
+ 
+ static bool nft_rbtree_flush(const struct net *net,
+@@ -490,12 +519,9 @@ static bool nft_rbtree_flush(const struct net *net,
+ {
+ 	struct nft_rbtree_elem *rbe = priv;
+ 
+-	if (!nft_set_elem_mark_busy(&rbe->ext) ||
+-	    !nft_is_active(net, &rbe->ext)) {
+-		nft_set_elem_change_active(net, set, &rbe->ext);
+-		return true;
+-	}
+-	return false;
++	nft_set_elem_change_active(net, set, &rbe->ext);
++
++	return true;
+ }
+ 
+ static void *nft_rbtree_deactivate(const struct net *net,
+@@ -552,8 +578,6 @@ static void nft_rbtree_walk(const struct nft_ctx *ctx,
+ 
+ 		if (iter->count < iter->skip)
+ 			goto cont;
+-		if (nft_set_elem_expired(&rbe->ext))
+-			goto cont;
+ 		if (!nft_set_elem_active(&rbe->ext, iter->genmask))
+ 			goto cont;
+ 
+@@ -572,26 +596,40 @@ cont:
+ 
+ static void nft_rbtree_gc(struct work_struct *work)
+ {
+-	struct nft_rbtree_elem *rbe, *rbe_end = NULL, *rbe_prev = NULL;
+-	struct nft_set_gc_batch *gcb = NULL;
++	struct nft_rbtree_elem *rbe, *rbe_end = NULL;
++	struct nftables_pernet *nft_net;
+ 	struct nft_rbtree *priv;
++	struct nft_trans_gc *gc;
+ 	struct rb_node *node;
+ 	struct nft_set *set;
++	unsigned int gc_seq;
+ 	struct net *net;
+-	u8 genmask;
+ 
+ 	priv = container_of(work, struct nft_rbtree, gc_work.work);
+ 	set  = nft_set_container_of(priv);
+ 	net  = read_pnet(&set->net);
+-	genmask = nft_genmask_cur(net);
++	nft_net = nft_pernet(net);
++	gc_seq  = READ_ONCE(nft_net->gc_seq);
++
++	gc = nft_trans_gc_alloc(set, gc_seq, GFP_KERNEL);
++	if (!gc)
++		goto done;
+ 
+ 	write_lock_bh(&priv->lock);
+ 	write_seqcount_begin(&priv->count);
+ 	for (node = rb_first(&priv->root); node != NULL; node = rb_next(node)) {
++
++		/* Ruleset has been updated, try later. */
++		if (READ_ONCE(nft_net->gc_seq) != gc_seq) {
++			nft_trans_gc_destroy(gc);
++			gc = NULL;
++			goto try_later;
++		}
++
+ 		rbe = rb_entry(node, struct nft_rbtree_elem, node);
+ 
+-		if (!nft_set_elem_active(&rbe->ext, genmask))
+-			continue;
++		if (nft_set_elem_is_dead(&rbe->ext))
++			goto dead_elem;
+ 
+ 		/* elements are reversed in the rbtree for historical reasons,
+ 		 * from highest to lowest value, that is why end element is
+@@ -604,46 +642,36 @@ static void nft_rbtree_gc(struct work_struct *work)
+ 		if (!nft_set_elem_expired(&rbe->ext))
+ 			continue;
+ 
+-		if (nft_set_elem_mark_busy(&rbe->ext)) {
+-			rbe_end = NULL;
++		nft_set_elem_dead(&rbe->ext);
++
++		if (!rbe_end)
+ 			continue;
+-		}
+ 
+-		if (rbe_prev) {
+-			rb_erase(&rbe_prev->node, &priv->root);
+-			rbe_prev = NULL;
+-		}
+-		gcb = nft_set_gc_batch_check(set, gcb, GFP_ATOMIC);
+-		if (!gcb)
+-			break;
++		nft_set_elem_dead(&rbe_end->ext);
+ 
+-		atomic_dec(&set->nelems);
+-		nft_set_gc_batch_add(gcb, rbe);
+-		rbe_prev = rbe;
++		gc = nft_trans_gc_queue_async(gc, gc_seq, GFP_ATOMIC);
++		if (!gc)
++			goto try_later;
+ 
+-		if (rbe_end) {
+-			atomic_dec(&set->nelems);
+-			nft_set_gc_batch_add(gcb, rbe_end);
+-			rb_erase(&rbe_end->node, &priv->root);
+-			rbe_end = NULL;
+-		}
+-		node = rb_next(node);
+-		if (!node)
+-			break;
++		nft_trans_gc_elem_add(gc, rbe_end);
++		rbe_end = NULL;
++dead_elem:
++		gc = nft_trans_gc_queue_async(gc, gc_seq, GFP_ATOMIC);
++		if (!gc)
++			goto try_later;
++
++		nft_trans_gc_elem_add(gc, rbe);
+ 	}
+-	if (rbe_prev)
+-		rb_erase(&rbe_prev->node, &priv->root);
++
++	gc = nft_trans_gc_catchall(gc, gc_seq);
++
++try_later:
+ 	write_seqcount_end(&priv->count);
+ 	write_unlock_bh(&priv->lock);
+ 
+-	rbe = nft_set_catchall_gc(set);
+-	if (rbe) {
+-		gcb = nft_set_gc_batch_check(set, gcb, GFP_ATOMIC);
+-		if (gcb)
+-			nft_set_gc_batch_add(gcb, rbe);
+-	}
+-	nft_set_gc_batch_complete(gcb);
+-
++	if (gc)
++		nft_trans_gc_queue_async_done(gc);
++done:
+ 	queue_delayed_work(system_power_efficient_wq, &priv->gc_work,
+ 			   nft_set_gc_interval(set));
+ }
+diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
+index a753246ef1657..96a017f78539f 100644
+--- a/net/packet/af_packet.c
++++ b/net/packet/af_packet.c
+@@ -401,18 +401,20 @@ static void __packet_set_status(struct packet_sock *po, void *frame, int status)
+ {
+ 	union tpacket_uhdr h;
+ 
++	/* WRITE_ONCE() are paired with READ_ONCE() in __packet_get_status */
++
+ 	h.raw = frame;
+ 	switch (po->tp_version) {
+ 	case TPACKET_V1:
+-		h.h1->tp_status = status;
++		WRITE_ONCE(h.h1->tp_status, status);
+ 		flush_dcache_page(pgv_to_page(&h.h1->tp_status));
+ 		break;
+ 	case TPACKET_V2:
+-		h.h2->tp_status = status;
++		WRITE_ONCE(h.h2->tp_status, status);
+ 		flush_dcache_page(pgv_to_page(&h.h2->tp_status));
+ 		break;
+ 	case TPACKET_V3:
+-		h.h3->tp_status = status;
++		WRITE_ONCE(h.h3->tp_status, status);
+ 		flush_dcache_page(pgv_to_page(&h.h3->tp_status));
+ 		break;
+ 	default:
+@@ -429,17 +431,19 @@ static int __packet_get_status(const struct packet_sock *po, void *frame)
+ 
+ 	smp_rmb();
+ 
++	/* READ_ONCE() are paired with WRITE_ONCE() in __packet_set_status */
++
+ 	h.raw = frame;
+ 	switch (po->tp_version) {
+ 	case TPACKET_V1:
+ 		flush_dcache_page(pgv_to_page(&h.h1->tp_status));
+-		return h.h1->tp_status;
++		return READ_ONCE(h.h1->tp_status);
+ 	case TPACKET_V2:
+ 		flush_dcache_page(pgv_to_page(&h.h2->tp_status));
+-		return h.h2->tp_status;
++		return READ_ONCE(h.h2->tp_status);
+ 	case TPACKET_V3:
+ 		flush_dcache_page(pgv_to_page(&h.h3->tp_status));
+-		return h.h3->tp_status;
++		return READ_ONCE(h.h3->tp_status);
+ 	default:
+ 		WARN(1, "TPACKET version not supported.\n");
+ 		BUG();
+diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
+index fa6b54c1411cb..f94e7a04e33d0 100644
+--- a/net/smc/af_smc.c
++++ b/net/smc/af_smc.c
+@@ -378,8 +378,8 @@ static struct sock *smc_sock_alloc(struct net *net, struct socket *sock,
+ 	sk->sk_state = SMC_INIT;
+ 	sk->sk_destruct = smc_destruct;
+ 	sk->sk_protocol = protocol;
+-	WRITE_ONCE(sk->sk_sndbuf, READ_ONCE(net->smc.sysctl_wmem));
+-	WRITE_ONCE(sk->sk_rcvbuf, READ_ONCE(net->smc.sysctl_rmem));
++	WRITE_ONCE(sk->sk_sndbuf, 2 * READ_ONCE(net->smc.sysctl_wmem));
++	WRITE_ONCE(sk->sk_rcvbuf, 2 * READ_ONCE(net->smc.sysctl_rmem));
+ 	smc = smc_sk(sk);
+ 	INIT_WORK(&smc->tcp_listen_work, smc_tcp_listen_work);
+ 	INIT_WORK(&smc->connect_work, smc_connect_work);
+@@ -436,13 +436,60 @@ out:
+ 	return rc;
+ }
+ 
++/* copy only relevant settings and flags of SOL_SOCKET level from smc to
++ * clc socket (since smc is not called for these options from net/core)
++ */
++
++#define SK_FLAGS_SMC_TO_CLC ((1UL << SOCK_URGINLINE) | \
++			     (1UL << SOCK_KEEPOPEN) | \
++			     (1UL << SOCK_LINGER) | \
++			     (1UL << SOCK_BROADCAST) | \
++			     (1UL << SOCK_TIMESTAMP) | \
++			     (1UL << SOCK_DBG) | \
++			     (1UL << SOCK_RCVTSTAMP) | \
++			     (1UL << SOCK_RCVTSTAMPNS) | \
++			     (1UL << SOCK_LOCALROUTE) | \
++			     (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE) | \
++			     (1UL << SOCK_RXQ_OVFL) | \
++			     (1UL << SOCK_WIFI_STATUS) | \
++			     (1UL << SOCK_NOFCS) | \
++			     (1UL << SOCK_FILTER_LOCKED) | \
++			     (1UL << SOCK_TSTAMP_NEW))
++
++/* if set, use value set by setsockopt() - else use IPv4 or SMC sysctl value */
++static void smc_adjust_sock_bufsizes(struct sock *nsk, struct sock *osk,
++				     unsigned long mask)
++{
++	struct net *nnet = sock_net(nsk);
++
++	nsk->sk_userlocks = osk->sk_userlocks;
++	if (osk->sk_userlocks & SOCK_SNDBUF_LOCK) {
++		nsk->sk_sndbuf = osk->sk_sndbuf;
++	} else {
++		if (mask == SK_FLAGS_SMC_TO_CLC)
++			WRITE_ONCE(nsk->sk_sndbuf,
++				   READ_ONCE(nnet->ipv4.sysctl_tcp_wmem[1]));
++		else
++			WRITE_ONCE(nsk->sk_sndbuf,
++				   2 * READ_ONCE(nnet->smc.sysctl_wmem));
++	}
++	if (osk->sk_userlocks & SOCK_RCVBUF_LOCK) {
++		nsk->sk_rcvbuf = osk->sk_rcvbuf;
++	} else {
++		if (mask == SK_FLAGS_SMC_TO_CLC)
++			WRITE_ONCE(nsk->sk_rcvbuf,
++				   READ_ONCE(nnet->ipv4.sysctl_tcp_rmem[1]));
++		else
++			WRITE_ONCE(nsk->sk_rcvbuf,
++				   2 * READ_ONCE(nnet->smc.sysctl_rmem));
++	}
++}
++
+ static void smc_copy_sock_settings(struct sock *nsk, struct sock *osk,
+ 				   unsigned long mask)
+ {
+ 	/* options we don't get control via setsockopt for */
+ 	nsk->sk_type = osk->sk_type;
+-	nsk->sk_sndbuf = osk->sk_sndbuf;
+-	nsk->sk_rcvbuf = osk->sk_rcvbuf;
+ 	nsk->sk_sndtimeo = osk->sk_sndtimeo;
+ 	nsk->sk_rcvtimeo = osk->sk_rcvtimeo;
+ 	nsk->sk_mark = READ_ONCE(osk->sk_mark);
+@@ -453,26 +500,10 @@ static void smc_copy_sock_settings(struct sock *nsk, struct sock *osk,
+ 
+ 	nsk->sk_flags &= ~mask;
+ 	nsk->sk_flags |= osk->sk_flags & mask;
++
++	smc_adjust_sock_bufsizes(nsk, osk, mask);
+ }
+ 
+-#define SK_FLAGS_SMC_TO_CLC ((1UL << SOCK_URGINLINE) | \
+-			     (1UL << SOCK_KEEPOPEN) | \
+-			     (1UL << SOCK_LINGER) | \
+-			     (1UL << SOCK_BROADCAST) | \
+-			     (1UL << SOCK_TIMESTAMP) | \
+-			     (1UL << SOCK_DBG) | \
+-			     (1UL << SOCK_RCVTSTAMP) | \
+-			     (1UL << SOCK_RCVTSTAMPNS) | \
+-			     (1UL << SOCK_LOCALROUTE) | \
+-			     (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE) | \
+-			     (1UL << SOCK_RXQ_OVFL) | \
+-			     (1UL << SOCK_WIFI_STATUS) | \
+-			     (1UL << SOCK_NOFCS) | \
+-			     (1UL << SOCK_FILTER_LOCKED) | \
+-			     (1UL << SOCK_TSTAMP_NEW))
+-/* copy only relevant settings and flags of SOL_SOCKET level from smc to
+- * clc socket (since smc is not called for these options from net/core)
+- */
+ static void smc_copy_sock_settings_to_clc(struct smc_sock *smc)
+ {
+ 	smc_copy_sock_settings(smc->clcsock->sk, &smc->sk, SK_FLAGS_SMC_TO_CLC);
+@@ -2479,8 +2510,6 @@ static void smc_tcp_listen_work(struct work_struct *work)
+ 		sock_hold(lsk); /* sock_put in smc_listen_work */
+ 		INIT_WORK(&new_smc->smc_listen_work, smc_listen_work);
+ 		smc_copy_sock_settings_to_smc(new_smc);
+-		new_smc->sk.sk_sndbuf = lsmc->sk.sk_sndbuf;
+-		new_smc->sk.sk_rcvbuf = lsmc->sk.sk_rcvbuf;
+ 		sock_hold(&new_smc->sk); /* sock_put in passive closing */
+ 		if (!queue_work(smc_hs_wq, &new_smc->smc_listen_work))
+ 			sock_put(&new_smc->sk);
+diff --git a/net/smc/smc.h b/net/smc/smc.h
+index 2eeea4cdc7187..1f2b912c43d10 100644
+--- a/net/smc/smc.h
++++ b/net/smc/smc.h
+@@ -161,7 +161,7 @@ struct smc_connection {
+ 
+ 	struct smc_buf_desc	*sndbuf_desc;	/* send buffer descriptor */
+ 	struct smc_buf_desc	*rmb_desc;	/* RMBE descriptor */
+-	int			rmbe_size_short;/* compressed notation */
++	int                     rmbe_size_comp; /* compressed notation */
+ 	int			rmbe_update_limit;
+ 						/* lower limit for consumer
+ 						 * cursor update
+diff --git a/net/smc/smc_clc.c b/net/smc/smc_clc.c
+index b9b8b07aa7023..c90d9e5dda540 100644
+--- a/net/smc/smc_clc.c
++++ b/net/smc/smc_clc.c
+@@ -1007,7 +1007,7 @@ static int smc_clc_send_confirm_accept(struct smc_sock *smc,
+ 		clc->d0.gid =
+ 			conn->lgr->smcd->ops->get_local_gid(conn->lgr->smcd);
+ 		clc->d0.token = conn->rmb_desc->token;
+-		clc->d0.dmbe_size = conn->rmbe_size_short;
++		clc->d0.dmbe_size = conn->rmbe_size_comp;
+ 		clc->d0.dmbe_idx = 0;
+ 		memcpy(&clc->d0.linkid, conn->lgr->id, SMC_LGR_ID_SIZE);
+ 		if (version == SMC_V1) {
+@@ -1050,7 +1050,7 @@ static int smc_clc_send_confirm_accept(struct smc_sock *smc,
+ 			clc->r0.qp_mtu = min(link->path_mtu, link->peer_mtu);
+ 			break;
+ 		}
+-		clc->r0.rmbe_size = conn->rmbe_size_short;
++		clc->r0.rmbe_size = conn->rmbe_size_comp;
+ 		clc->r0.rmb_dma_addr = conn->rmb_desc->is_vm ?
+ 			cpu_to_be64((uintptr_t)conn->rmb_desc->cpu_addr) :
+ 			cpu_to_be64((u64)sg_dma_address
+diff --git a/net/smc/smc_core.c b/net/smc/smc_core.c
+index 3f465faf2b681..6b78075404d7d 100644
+--- a/net/smc/smc_core.c
++++ b/net/smc/smc_core.c
+@@ -2309,31 +2309,30 @@ static int __smc_buf_create(struct smc_sock *smc, bool is_smcd, bool is_rmb)
+ 	struct smc_connection *conn = &smc->conn;
+ 	struct smc_link_group *lgr = conn->lgr;
+ 	struct list_head *buf_list;
+-	int bufsize, bufsize_short;
++	int bufsize, bufsize_comp;
+ 	struct rw_semaphore *lock;	/* lock buffer list */
+ 	bool is_dgraded = false;
+-	int sk_buf_size;
+ 
+ 	if (is_rmb)
+ 		/* use socket recv buffer size (w/o overhead) as start value */
+-		sk_buf_size = smc->sk.sk_rcvbuf;
++		bufsize = smc->sk.sk_rcvbuf / 2;
+ 	else
+ 		/* use socket send buffer size (w/o overhead) as start value */
+-		sk_buf_size = smc->sk.sk_sndbuf;
++		bufsize = smc->sk.sk_sndbuf / 2;
+ 
+-	for (bufsize_short = smc_compress_bufsize(sk_buf_size, is_smcd, is_rmb);
+-	     bufsize_short >= 0; bufsize_short--) {
++	for (bufsize_comp = smc_compress_bufsize(bufsize, is_smcd, is_rmb);
++	     bufsize_comp >= 0; bufsize_comp--) {
+ 		if (is_rmb) {
+ 			lock = &lgr->rmbs_lock;
+-			buf_list = &lgr->rmbs[bufsize_short];
++			buf_list = &lgr->rmbs[bufsize_comp];
+ 		} else {
+ 			lock = &lgr->sndbufs_lock;
+-			buf_list = &lgr->sndbufs[bufsize_short];
++			buf_list = &lgr->sndbufs[bufsize_comp];
+ 		}
+-		bufsize = smc_uncompress_bufsize(bufsize_short);
++		bufsize = smc_uncompress_bufsize(bufsize_comp);
+ 
+ 		/* check for reusable slot in the link group */
+-		buf_desc = smc_buf_get_slot(bufsize_short, lock, buf_list);
++		buf_desc = smc_buf_get_slot(bufsize_comp, lock, buf_list);
+ 		if (buf_desc) {
+ 			buf_desc->is_dma_need_sync = 0;
+ 			SMC_STAT_RMB_SIZE(smc, is_smcd, is_rmb, bufsize);
+@@ -2377,8 +2376,8 @@ static int __smc_buf_create(struct smc_sock *smc, bool is_smcd, bool is_rmb)
+ 
+ 	if (is_rmb) {
+ 		conn->rmb_desc = buf_desc;
+-		conn->rmbe_size_short = bufsize_short;
+-		smc->sk.sk_rcvbuf = bufsize;
++		conn->rmbe_size_comp = bufsize_comp;
++		smc->sk.sk_rcvbuf = bufsize * 2;
+ 		atomic_set(&conn->bytes_to_rcv, 0);
+ 		conn->rmbe_update_limit =
+ 			smc_rmb_wnd_update_limit(buf_desc->len);
+@@ -2386,7 +2385,7 @@ static int __smc_buf_create(struct smc_sock *smc, bool is_smcd, bool is_rmb)
+ 			smc_ism_set_conn(conn); /* map RMB/smcd_dev to conn */
+ 	} else {
+ 		conn->sndbuf_desc = buf_desc;
+-		smc->sk.sk_sndbuf = bufsize;
++		smc->sk.sk_sndbuf = bufsize * 2;
+ 		atomic_set(&conn->sndbuf_space, bufsize);
+ 	}
+ 	return 0;
+diff --git a/net/smc/smc_sysctl.c b/net/smc/smc_sysctl.c
+index b6f79fabb9d3f..0b2a957ca5f5f 100644
+--- a/net/smc/smc_sysctl.c
++++ b/net/smc/smc_sysctl.c
+@@ -21,6 +21,10 @@
+ 
+ static int min_sndbuf = SMC_BUF_MIN_SIZE;
+ static int min_rcvbuf = SMC_BUF_MIN_SIZE;
++static int max_sndbuf = INT_MAX / 2;
++static int max_rcvbuf = INT_MAX / 2;
++static const int net_smc_wmem_init = (64 * 1024);
++static const int net_smc_rmem_init = (64 * 1024);
+ 
+ static struct ctl_table smc_table[] = {
+ 	{
+@@ -53,6 +57,7 @@ static struct ctl_table smc_table[] = {
+ 		.mode		= 0644,
+ 		.proc_handler	= proc_dointvec_minmax,
+ 		.extra1		= &min_sndbuf,
++		.extra2		= &max_sndbuf,
+ 	},
+ 	{
+ 		.procname	= "rmem",
+@@ -61,6 +66,7 @@ static struct ctl_table smc_table[] = {
+ 		.mode		= 0644,
+ 		.proc_handler	= proc_dointvec_minmax,
+ 		.extra1		= &min_rcvbuf,
++		.extra2		= &max_rcvbuf,
+ 	},
+ 	{  }
+ };
+@@ -88,8 +94,8 @@ int __net_init smc_sysctl_net_init(struct net *net)
+ 	net->smc.sysctl_autocorking_size = SMC_AUTOCORKING_DEFAULT_SIZE;
+ 	net->smc.sysctl_smcr_buf_type = SMCR_PHYS_CONT_BUFS;
+ 	net->smc.sysctl_smcr_testlink_time = SMC_LLC_TESTLINK_DEFAULT_TIME;
+-	WRITE_ONCE(net->smc.sysctl_wmem, READ_ONCE(net->ipv4.sysctl_tcp_wmem[1]));
+-	WRITE_ONCE(net->smc.sysctl_rmem, READ_ONCE(net->ipv4.sysctl_tcp_rmem[1]));
++	WRITE_ONCE(net->smc.sysctl_wmem, net_smc_wmem_init);
++	WRITE_ONCE(net->smc.sysctl_rmem, net_smc_rmem_init);
+ 
+ 	return 0;
+ 
+diff --git a/net/tls/tls_device.c b/net/tls/tls_device.c
+index bf69c9d6d06c0..1849827884735 100644
+--- a/net/tls/tls_device.c
++++ b/net/tls/tls_device.c
+@@ -52,6 +52,8 @@ static LIST_HEAD(tls_device_list);
+ static LIST_HEAD(tls_device_down_list);
+ static DEFINE_SPINLOCK(tls_device_lock);
+ 
++static struct page *dummy_page;
++
+ static void tls_device_free_ctx(struct tls_context *ctx)
+ {
+ 	if (ctx->tx_conf == TLS_HW) {
+@@ -313,36 +315,33 @@ static int tls_push_record(struct sock *sk,
+ 	return tls_push_sg(sk, ctx, offload_ctx->sg_tx_data, 0, flags);
+ }
+ 
+-static int tls_device_record_close(struct sock *sk,
+-				   struct tls_context *ctx,
+-				   struct tls_record_info *record,
+-				   struct page_frag *pfrag,
+-				   unsigned char record_type)
++static void tls_device_record_close(struct sock *sk,
++				    struct tls_context *ctx,
++				    struct tls_record_info *record,
++				    struct page_frag *pfrag,
++				    unsigned char record_type)
+ {
+ 	struct tls_prot_info *prot = &ctx->prot_info;
+-	int ret;
++	struct page_frag dummy_tag_frag;
+ 
+ 	/* append tag
+ 	 * device will fill in the tag, we just need to append a placeholder
+ 	 * use socket memory to improve coalescing (re-using a single buffer
+ 	 * increases frag count)
+-	 * if we can't allocate memory now, steal some back from data
++	 * if we can't allocate memory now use the dummy page
+ 	 */
+-	if (likely(skb_page_frag_refill(prot->tag_size, pfrag,
+-					sk->sk_allocation))) {
+-		ret = 0;
+-		tls_append_frag(record, pfrag, prot->tag_size);
+-	} else {
+-		ret = prot->tag_size;
+-		if (record->len <= prot->overhead_size)
+-			return -ENOMEM;
++	if (unlikely(pfrag->size - pfrag->offset < prot->tag_size) &&
++	    !skb_page_frag_refill(prot->tag_size, pfrag, sk->sk_allocation)) {
++		dummy_tag_frag.page = dummy_page;
++		dummy_tag_frag.offset = 0;
++		pfrag = &dummy_tag_frag;
+ 	}
++	tls_append_frag(record, pfrag, prot->tag_size);
+ 
+ 	/* fill prepend */
+ 	tls_fill_prepend(ctx, skb_frag_address(&record->frags[0]),
+ 			 record->len - prot->overhead_size,
+ 			 record_type);
+-	return ret;
+ }
+ 
+ static int tls_create_new_record(struct tls_offload_context_tx *offload_ctx,
+@@ -535,18 +534,8 @@ last_record:
+ 
+ 		if (done || record->len >= max_open_record_len ||
+ 		    (record->num_frags >= MAX_SKB_FRAGS - 1)) {
+-			rc = tls_device_record_close(sk, tls_ctx, record,
+-						     pfrag, record_type);
+-			if (rc) {
+-				if (rc > 0) {
+-					size += rc;
+-				} else {
+-					size = orig_size;
+-					destroy_record(record);
+-					ctx->open_record = NULL;
+-					break;
+-				}
+-			}
++			tls_device_record_close(sk, tls_ctx, record,
++						pfrag, record_type);
+ 
+ 			rc = tls_push_record(sk,
+ 					     tls_ctx,
+@@ -1466,14 +1455,26 @@ int __init tls_device_init(void)
+ {
+ 	int err;
+ 
+-	destruct_wq = alloc_workqueue("ktls_device_destruct", 0, 0);
+-	if (!destruct_wq)
++	dummy_page = alloc_page(GFP_KERNEL);
++	if (!dummy_page)
+ 		return -ENOMEM;
+ 
++	destruct_wq = alloc_workqueue("ktls_device_destruct", 0, 0);
++	if (!destruct_wq) {
++		err = -ENOMEM;
++		goto err_free_dummy;
++	}
++
+ 	err = register_netdevice_notifier(&tls_dev_notifier);
+ 	if (err)
+-		destroy_workqueue(destruct_wq);
++		goto err_destroy_wq;
+ 
++	return 0;
++
++err_destroy_wq:
++	destroy_workqueue(destruct_wq);
++err_free_dummy:
++	put_page(dummy_page);
+ 	return err;
+ }
+ 
+@@ -1482,4 +1483,5 @@ void __exit tls_device_cleanup(void)
+ 	unregister_netdevice_notifier(&tls_dev_notifier);
+ 	destroy_workqueue(destruct_wq);
+ 	clean_acked_data_flush();
++	put_page(dummy_page);
+ }
+diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
+index 087d60c0f6e4f..1b688745ce0a1 100644
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -5426,8 +5426,11 @@ nl80211_parse_mbssid_elems(struct wiphy *wiphy, struct nlattr *attrs)
+ 	if (!wiphy->mbssid_max_interfaces)
+ 		return ERR_PTR(-EINVAL);
+ 
+-	nla_for_each_nested(nl_elems, attrs, rem_elems)
++	nla_for_each_nested(nl_elems, attrs, rem_elems) {
++		if (num_elems >= 255)
++			return ERR_PTR(-EINVAL);
+ 		num_elems++;
++	}
+ 
+ 	elems = kzalloc(struct_size(elems, elem, num_elems), GFP_KERNEL);
+ 	if (!elems)
+diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c
+index 35e518eaaebae..5f249fa969985 100644
+--- a/net/xdp/xsk.c
++++ b/net/xdp/xsk.c
+@@ -994,6 +994,7 @@ static int xsk_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
+ 				err = xp_alloc_tx_descs(xs->pool, xs);
+ 				if (err) {
+ 					xp_put_pool(xs->pool);
++					xs->pool = NULL;
+ 					sockfd_put(sock);
+ 					goto out_unlock;
+ 				}
+diff --git a/tools/testing/radix-tree/regression1.c b/tools/testing/radix-tree/regression1.c
+index a61c7bcbc72da..63f468bf8245c 100644
+--- a/tools/testing/radix-tree/regression1.c
++++ b/tools/testing/radix-tree/regression1.c
+@@ -177,7 +177,7 @@ void regression1_test(void)
+ 	nr_threads = 2;
+ 	pthread_barrier_init(&worker_barrier, NULL, nr_threads);
+ 
+-	threads = malloc(nr_threads * sizeof(pthread_t *));
++	threads = malloc(nr_threads * sizeof(*threads));
+ 
+ 	for (i = 0; i < nr_threads; i++) {
+ 		arg = i;
+diff --git a/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c b/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c
+index b4f6f3a50ae58..ba35bcc66e7e9 100644
+--- a/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c
++++ b/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c
+@@ -1432,7 +1432,7 @@ static void vsock_unix_redir_connectible(int sock_mapfd, int verd_mapfd,
+ 	if (n < 1)
+ 		goto out;
+ 
+-	n = recv(mode == REDIR_INGRESS ? u0 : u1, &b, sizeof(b), MSG_DONTWAIT);
++	n = xrecv_nonblock(mode == REDIR_INGRESS ? u0 : u1, &b, sizeof(b), 0);
+ 	if (n < 0)
+ 		FAIL("%s: recv() err, errno=%d", log_prefix, errno);
+ 	if (n == 0)
+diff --git a/tools/testing/selftests/mm/ksm_tests.c b/tools/testing/selftests/mm/ksm_tests.c
+index 435acebdc325f..380b691d3eb9f 100644
+--- a/tools/testing/selftests/mm/ksm_tests.c
++++ b/tools/testing/selftests/mm/ksm_tests.c
+@@ -831,6 +831,7 @@ int main(int argc, char *argv[])
+ 				printf("Size must be greater than 0\n");
+ 				return KSFT_FAIL;
+ 			}
++			break;
+ 		case 't':
+ 			{
+ 				int tmp = atoi(optarg);
+diff --git a/tools/testing/selftests/net/fib_nexthops.sh b/tools/testing/selftests/net/fib_nexthops.sh
+index 0f5e88c8f4ffe..df8d90b51867a 100755
+--- a/tools/testing/selftests/net/fib_nexthops.sh
++++ b/tools/testing/selftests/net/fib_nexthops.sh
+@@ -1981,6 +1981,11 @@ basic()
+ 
+ 	run_cmd "$IP link set dev lo up"
+ 
++	# Dump should not loop endlessly when maximum nexthop ID is configured.
++	run_cmd "$IP nexthop add id $((2**32-1)) blackhole"
++	run_cmd "timeout 5 $IP nexthop"
++	log_test $? 0 "Maximum nexthop ID dump"
++
+ 	#
+ 	# groups
+ 	#
+@@ -2201,6 +2206,11 @@ basic_res()
+ 	run_cmd "$IP nexthop bucket list fdb"
+ 	log_test $? 255 "Dump all nexthop buckets with invalid 'fdb' keyword"
+ 
++	# Dump should not loop endlessly when maximum nexthop ID is configured.
++	run_cmd "$IP nexthop add id $((2**32-1)) group 1/2 type resilient buckets 4"
++	run_cmd "timeout 5 $IP nexthop bucket"
++	log_test $? 0 "Maximum nexthop ID dump"
++
+ 	#
+ 	# resilient nexthop buckets get requests
+ 	#
+diff --git a/tools/testing/selftests/net/forwarding/bridge_mdb.sh b/tools/testing/selftests/net/forwarding/bridge_mdb.sh
+index ae3f9462a2b61..d0c6c499d5dab 100755
+--- a/tools/testing/selftests/net/forwarding/bridge_mdb.sh
++++ b/tools/testing/selftests/net/forwarding/bridge_mdb.sh
+@@ -617,7 +617,7 @@ __cfg_test_port_ip_sg()
+ 		grep -q "permanent"
+ 	check_err $? "Entry not added as \"permanent\" when should"
+ 	bridge -d -s mdb show dev br0 vid 10 | grep "$grp_key" | \
+-		grep -q "0.00"
++		grep -q " 0.00"
+ 	check_err $? "\"permanent\" entry has a pending group timer"
+ 	bridge mdb del dev br0 port $swp1 $grp_key vid 10
+ 
+@@ -626,7 +626,7 @@ __cfg_test_port_ip_sg()
+ 		grep -q "temp"
+ 	check_err $? "Entry not added as \"temp\" when should"
+ 	bridge -d -s mdb show dev br0 vid 10 | grep "$grp_key" | \
+-		grep -q "0.00"
++		grep -q " 0.00"
+ 	check_fail $? "\"temp\" entry has an unpending group timer"
+ 	bridge mdb del dev br0 port $swp1 $grp_key vid 10
+ 
+@@ -659,7 +659,7 @@ __cfg_test_port_ip_sg()
+ 		grep -q "permanent"
+ 	check_err $? "Entry not marked as \"permanent\" after replace"
+ 	bridge -d -s mdb show dev br0 vid 10 | grep "$grp_key" | \
+-		grep -q "0.00"
++		grep -q " 0.00"
+ 	check_err $? "Entry has a pending group timer after replace"
+ 
+ 	bridge mdb replace dev br0 port $swp1 $grp_key vid 10 temp
+@@ -667,7 +667,7 @@ __cfg_test_port_ip_sg()
+ 		grep -q "temp"
+ 	check_err $? "Entry not marked as \"temp\" after replace"
+ 	bridge -d -s mdb show dev br0 vid 10 | grep "$grp_key" | \
+-		grep -q "0.00"
++		grep -q " 0.00"
+ 	check_fail $? "Entry has an unpending group timer after replace"
+ 	bridge mdb del dev br0 port $swp1 $grp_key vid 10
+ 
+@@ -850,6 +850,7 @@ cfg_test()
+ __fwd_test_host_ip()
+ {
+ 	local grp=$1; shift
++	local dmac=$1; shift
+ 	local src=$1; shift
+ 	local mode=$1; shift
+ 	local name
+@@ -872,27 +873,27 @@ __fwd_test_host_ip()
+ 	# Packet should only be flooded to multicast router ports when there is
+ 	# no matching MDB entry. The bridge is not configured as a multicast
+ 	# router port.
+-	$MZ $mode $h1.10 -c 1 -p 128 -A $src -B $grp -t udp -q
++	$MZ $mode $h1.10 -a own -b $dmac -c 1 -p 128 -A $src -B $grp -t udp -q
+ 	tc_check_packets "dev br0 ingress" 1 0
+ 	check_err $? "Packet locally received after flood"
+ 
+ 	# Install a regular port group entry and expect the packet to not be
+ 	# locally received.
+ 	bridge mdb add dev br0 port $swp2 grp $grp temp vid 10
+-	$MZ $mode $h1.10 -c 1 -p 128 -A $src -B $grp -t udp -q
++	$MZ $mode $h1.10 -a own -b $dmac -c 1 -p 128 -A $src -B $grp -t udp -q
+ 	tc_check_packets "dev br0 ingress" 1 0
+ 	check_err $? "Packet locally received after installing a regular entry"
+ 
+ 	# Add a host entry and expect the packet to be locally received.
+ 	bridge mdb add dev br0 port br0 grp $grp temp vid 10
+-	$MZ $mode $h1.10 -c 1 -p 128 -A $src -B $grp -t udp -q
++	$MZ $mode $h1.10 -a own -b $dmac -c 1 -p 128 -A $src -B $grp -t udp -q
+ 	tc_check_packets "dev br0 ingress" 1 1
+ 	check_err $? "Packet not locally received after adding a host entry"
+ 
+ 	# Remove the host entry and expect the packet to not be locally
+ 	# received.
+ 	bridge mdb del dev br0 port br0 grp $grp vid 10
+-	$MZ $mode $h1.10 -c 1 -p 128 -A $src -B $grp -t udp -q
++	$MZ $mode $h1.10 -a own -b $dmac -c 1 -p 128 -A $src -B $grp -t udp -q
+ 	tc_check_packets "dev br0 ingress" 1 1
+ 	check_err $? "Packet locally received after removing a host entry"
+ 
+@@ -905,8 +906,8 @@ __fwd_test_host_ip()
+ 
+ fwd_test_host_ip()
+ {
+-	__fwd_test_host_ip "239.1.1.1" "192.0.2.1" "-4"
+-	__fwd_test_host_ip "ff0e::1" "2001:db8:1::1" "-6"
++	__fwd_test_host_ip "239.1.1.1" "01:00:5e:01:01:01" "192.0.2.1" "-4"
++	__fwd_test_host_ip "ff0e::1" "33:33:00:00:00:01" "2001:db8:1::1" "-6"
+ }
+ 
+ fwd_test_host_l2()
+@@ -966,6 +967,7 @@ fwd_test_host()
+ __fwd_test_port_ip()
+ {
+ 	local grp=$1; shift
++	local dmac=$1; shift
+ 	local valid_src=$1; shift
+ 	local invalid_src=$1; shift
+ 	local mode=$1; shift
+@@ -999,43 +1001,43 @@ __fwd_test_port_ip()
+ 		vlan_ethtype $eth_type vlan_id 10 dst_ip $grp \
+ 		src_ip $invalid_src action drop
+ 
+-	$MZ $mode $h1.10 -c 1 -p 128 -A $valid_src -B $grp -t udp -q
++	$MZ $mode $h1.10 -a own -b $dmac -c 1 -p 128 -A $valid_src -B $grp -t udp -q
+ 	tc_check_packets "dev $h2 ingress" 1 0
+ 	check_err $? "Packet from valid source received on H2 before adding entry"
+ 
+-	$MZ $mode $h1.10 -c 1 -p 128 -A $invalid_src -B $grp -t udp -q
++	$MZ $mode $h1.10 -a own -b $dmac -c 1 -p 128 -A $invalid_src -B $grp -t udp -q
+ 	tc_check_packets "dev $h2 ingress" 2 0
+ 	check_err $? "Packet from invalid source received on H2 before adding entry"
+ 
+ 	bridge mdb add dev br0 port $swp2 grp $grp vid 10 \
+ 		filter_mode $filter_mode source_list $src_list
+ 
+-	$MZ $mode $h1.10 -c 1 -p 128 -A $valid_src -B $grp -t udp -q
++	$MZ $mode $h1.10 -a own -b $dmac -c 1 -p 128 -A $valid_src -B $grp -t udp -q
+ 	tc_check_packets "dev $h2 ingress" 1 1
+ 	check_err $? "Packet from valid source not received on H2 after adding entry"
+ 
+-	$MZ $mode $h1.10 -c 1 -p 128 -A $invalid_src -B $grp -t udp -q
++	$MZ $mode $h1.10 -a own -b $dmac -c 1 -p 128 -A $invalid_src -B $grp -t udp -q
+ 	tc_check_packets "dev $h2 ingress" 2 0
+ 	check_err $? "Packet from invalid source received on H2 after adding entry"
+ 
+ 	bridge mdb replace dev br0 port $swp2 grp $grp vid 10 \
+ 		filter_mode exclude
+ 
+-	$MZ $mode $h1.10 -c 1 -p 128 -A $valid_src -B $grp -t udp -q
++	$MZ $mode $h1.10 -a own -b $dmac -c 1 -p 128 -A $valid_src -B $grp -t udp -q
+ 	tc_check_packets "dev $h2 ingress" 1 2
+ 	check_err $? "Packet from valid source not received on H2 after allowing all sources"
+ 
+-	$MZ $mode $h1.10 -c 1 -p 128 -A $invalid_src -B $grp -t udp -q
++	$MZ $mode $h1.10 -a own -b $dmac -c 1 -p 128 -A $invalid_src -B $grp -t udp -q
+ 	tc_check_packets "dev $h2 ingress" 2 1
+ 	check_err $? "Packet from invalid source not received on H2 after allowing all sources"
+ 
+ 	bridge mdb del dev br0 port $swp2 grp $grp vid 10
+ 
+-	$MZ $mode $h1.10 -c 1 -p 128 -A $valid_src -B $grp -t udp -q
++	$MZ $mode $h1.10 -a own -b $dmac -c 1 -p 128 -A $valid_src -B $grp -t udp -q
+ 	tc_check_packets "dev $h2 ingress" 1 2
+ 	check_err $? "Packet from valid source received on H2 after deleting entry"
+ 
+-	$MZ $mode $h1.10 -c 1 -p 128 -A $invalid_src -B $grp -t udp -q
++	$MZ $mode $h1.10 -a own -b $dmac -c 1 -p 128 -A $invalid_src -B $grp -t udp -q
+ 	tc_check_packets "dev $h2 ingress" 2 1
+ 	check_err $? "Packet from invalid source received on H2 after deleting entry"
+ 
+@@ -1047,11 +1049,11 @@ __fwd_test_port_ip()
+ 
+ fwd_test_port_ip()
+ {
+-	__fwd_test_port_ip "239.1.1.1" "192.0.2.1" "192.0.2.2" "-4" "exclude"
+-	__fwd_test_port_ip "ff0e::1" "2001:db8:1::1" "2001:db8:1::2" "-6" \
++	__fwd_test_port_ip "239.1.1.1" "01:00:5e:01:01:01" "192.0.2.1" "192.0.2.2" "-4" "exclude"
++	__fwd_test_port_ip "ff0e::1" "33:33:00:00:00:01" "2001:db8:1::1" "2001:db8:1::2" "-6" \
+ 		"exclude"
+-	__fwd_test_port_ip "239.1.1.1" "192.0.2.1" "192.0.2.2" "-4" "include"
+-	__fwd_test_port_ip "ff0e::1" "2001:db8:1::1" "2001:db8:1::2" "-6" \
++	__fwd_test_port_ip "239.1.1.1" "01:00:5e:01:01:01" "192.0.2.1" "192.0.2.2" "-4" "include"
++	__fwd_test_port_ip "ff0e::1" "33:33:00:00:00:01" "2001:db8:1::1" "2001:db8:1::2" "-6" \
+ 		"include"
+ }
+ 
+@@ -1127,7 +1129,7 @@ ctrl_igmpv3_is_in_test()
+ 		filter_mode include source_list 192.0.2.1
+ 
+ 	# IS_IN ( 192.0.2.2 )
+-	$MZ $h1.10 -c 1 -A 192.0.2.1 -B 239.1.1.1 \
++	$MZ $h1.10 -c 1 -a own -b 01:00:5e:01:01:01 -A 192.0.2.1 -B 239.1.1.1 \
+ 		-t ip proto=2,p=$(igmpv3_is_in_get 239.1.1.1 192.0.2.2) -q
+ 
+ 	bridge -d mdb show dev br0 vid 10 | grep 239.1.1.1 | grep -q 192.0.2.2
+@@ -1140,7 +1142,7 @@ ctrl_igmpv3_is_in_test()
+ 		filter_mode include source_list 192.0.2.1
+ 
+ 	# IS_IN ( 192.0.2.2 )
+-	$MZ $h1.10 -c 1 -A 192.0.2.1 -B 239.1.1.1 \
++	$MZ $h1.10 -a own -b 01:00:5e:01:01:01 -c 1 -A 192.0.2.1 -B 239.1.1.1 \
+ 		-t ip proto=2,p=$(igmpv3_is_in_get 239.1.1.1 192.0.2.2) -q
+ 
+ 	bridge -d mdb show dev br0 vid 10 | grep 239.1.1.1 | grep -v "src" | \
+@@ -1167,7 +1169,7 @@ ctrl_mldv2_is_in_test()
+ 
+ 	# IS_IN ( 2001:db8:1::2 )
+ 	local p=$(mldv2_is_in_get fe80::1 ff0e::1 2001:db8:1::2)
+-	$MZ -6 $h1.10 -c 1 -A fe80::1 -B ff0e::1 \
++	$MZ -6 $h1.10 -a own -b 33:33:00:00:00:01 -c 1 -A fe80::1 -B ff0e::1 \
+ 		-t ip hop=1,next=0,p="$p" -q
+ 
+ 	bridge -d mdb show dev br0 vid 10 | grep ff0e::1 | \
+@@ -1181,7 +1183,7 @@ ctrl_mldv2_is_in_test()
+ 		filter_mode include source_list 2001:db8:1::1
+ 
+ 	# IS_IN ( 2001:db8:1::2 )
+-	$MZ -6 $h1.10 -c 1 -A fe80::1 -B ff0e::1 \
++	$MZ -6 $h1.10 -a own -b 33:33:00:00:00:01 -c 1 -A fe80::1 -B ff0e::1 \
+ 		-t ip hop=1,next=0,p="$p" -q
+ 
+ 	bridge -d mdb show dev br0 vid 10 | grep ff0e::1 | grep -v "src" | \
+@@ -1206,6 +1208,11 @@ ctrl_test()
+ 	ctrl_mldv2_is_in_test
+ }
+ 
++if ! bridge mdb help 2>&1 | grep -q "replace"; then
++	echo "SKIP: iproute2 too old, missing bridge mdb replace support"
++	exit $ksft_skip
++fi
++
+ trap cleanup EXIT
+ 
+ setup_prepare
+diff --git a/tools/testing/selftests/net/forwarding/bridge_mdb_max.sh b/tools/testing/selftests/net/forwarding/bridge_mdb_max.sh
+index ae255b662ba38..3da9d93ab36fb 100755
+--- a/tools/testing/selftests/net/forwarding/bridge_mdb_max.sh
++++ b/tools/testing/selftests/net/forwarding/bridge_mdb_max.sh
+@@ -252,7 +252,8 @@ ctl4_entries_add()
+ 	local IPs=$(seq -f 192.0.2.%g 1 $((n - 1)))
+ 	local peer=$(locus_dev_peer $locus)
+ 	local GRP=239.1.1.${grp}
+-	$MZ $peer -c 1 -A 192.0.2.1 -B $GRP \
++	local dmac=01:00:5e:01:01:$(printf "%02x" $grp)
++	$MZ $peer -a own -b $dmac -c 1 -A 192.0.2.1 -B $GRP \
+ 		-t ip proto=2,p=$(igmpv3_is_in_get $GRP $IPs) -q
+ 	sleep 1
+ 
+@@ -272,7 +273,8 @@ ctl4_entries_del()
+ 
+ 	local peer=$(locus_dev_peer $locus)
+ 	local GRP=239.1.1.${grp}
+-	$MZ $peer -c 1 -A 192.0.2.1 -B 224.0.0.2 \
++	local dmac=01:00:5e:00:00:02
++	$MZ $peer -a own -b $dmac -c 1 -A 192.0.2.1 -B 224.0.0.2 \
+ 		-t ip proto=2,p=$(igmpv2_leave_get $GRP) -q
+ 	sleep 1
+ 	! bridge mdb show dev br0 | grep -q $GRP
+@@ -289,8 +291,10 @@ ctl6_entries_add()
+ 	local peer=$(locus_dev_peer $locus)
+ 	local SIP=fe80::1
+ 	local GRP=ff0e::${grp}
++	local dmac=33:33:00:00:00:$(printf "%02x" $grp)
+ 	local p=$(mldv2_is_in_get $SIP $GRP $IPs)
+-	$MZ -6 $peer -c 1 -A $SIP -B $GRP -t ip hop=1,next=0,p="$p" -q
++	$MZ -6 $peer -a own -b $dmac -c 1 -A $SIP -B $GRP \
++		-t ip hop=1,next=0,p="$p" -q
+ 	sleep 1
+ 
+ 	local nn=$(bridge mdb show dev br0 | grep $GRP | wc -l)
+@@ -310,8 +314,10 @@ ctl6_entries_del()
+ 	local peer=$(locus_dev_peer $locus)
+ 	local SIP=fe80::1
+ 	local GRP=ff0e::${grp}
++	local dmac=33:33:00:00:00:$(printf "%02x" $grp)
+ 	local p=$(mldv1_done_get $SIP $GRP)
+-	$MZ -6 $peer -c 1 -A $SIP -B $GRP -t ip hop=1,next=0,p="$p" -q
++	$MZ -6 $peer -a own -b $dmac -c 1 -A $SIP -B $GRP \
++		-t ip hop=1,next=0,p="$p" -q
+ 	sleep 1
+ 	! bridge mdb show dev br0 | grep -q $GRP
+ }
+@@ -1328,6 +1334,11 @@ test_8021qvs()
+ 	switch_destroy
+ }
+ 
++if ! bridge link help 2>&1 | grep -q "mcast_max_groups"; then
++	echo "SKIP: iproute2 too old, missing bridge \"mcast_max_groups\" support"
++	exit $ksft_skip
++fi
++
+ trap cleanup EXIT
+ 
+ setup_prepare
+diff --git a/tools/testing/selftests/net/forwarding/ethtool.sh b/tools/testing/selftests/net/forwarding/ethtool.sh
+index dbb9fcf759e0f..aa2eafb7b2437 100755
+--- a/tools/testing/selftests/net/forwarding/ethtool.sh
++++ b/tools/testing/selftests/net/forwarding/ethtool.sh
+@@ -286,6 +286,8 @@ different_speeds_autoneg_on()
+ 	ethtool -s $h1 autoneg on
+ }
+ 
++skip_on_veth
++
+ trap cleanup EXIT
+ 
+ setup_prepare
+diff --git a/tools/testing/selftests/net/forwarding/ethtool_extended_state.sh b/tools/testing/selftests/net/forwarding/ethtool_extended_state.sh
+index 072faa77f53bd..17f89c3b7c020 100755
+--- a/tools/testing/selftests/net/forwarding/ethtool_extended_state.sh
++++ b/tools/testing/selftests/net/forwarding/ethtool_extended_state.sh
+@@ -108,6 +108,8 @@ no_cable()
+ 	ip link set dev $swp3 down
+ }
+ 
++skip_on_veth
++
+ setup_prepare
+ 
+ tests_run
+diff --git a/tools/testing/selftests/net/forwarding/ethtool_mm.sh b/tools/testing/selftests/net/forwarding/ethtool_mm.sh
+index c580ad6238483..39e736f30322a 100755
+--- a/tools/testing/selftests/net/forwarding/ethtool_mm.sh
++++ b/tools/testing/selftests/net/forwarding/ethtool_mm.sh
+@@ -258,11 +258,6 @@ h2_destroy()
+ 
+ setup_prepare()
+ {
+-	check_ethtool_mm_support
+-	check_tc_fp_support
+-	require_command lldptool
+-	bail_on_lldpad "autoconfigure the MAC Merge layer" "configure it manually"
+-
+ 	h1=${NETIFS[p1]}
+ 	h2=${NETIFS[p2]}
+ 
+@@ -278,6 +273,19 @@ cleanup()
+ 	h1_destroy
+ }
+ 
++check_ethtool_mm_support
++check_tc_fp_support
++require_command lldptool
++bail_on_lldpad "autoconfigure the MAC Merge layer" "configure it manually"
++
++for netif in ${NETIFS[@]}; do
++	ethtool --show-mm $netif 2>&1 &> /dev/null
++	if [[ $? -ne 0 ]]; then
++		echo "SKIP: $netif does not support MAC Merge"
++		exit $ksft_skip
++	fi
++done
++
+ trap cleanup EXIT
+ 
+ setup_prepare
+diff --git a/tools/testing/selftests/net/forwarding/hw_stats_l3_gre.sh b/tools/testing/selftests/net/forwarding/hw_stats_l3_gre.sh
+index eb9ec4a68f84b..7594bbb490292 100755
+--- a/tools/testing/selftests/net/forwarding/hw_stats_l3_gre.sh
++++ b/tools/testing/selftests/net/forwarding/hw_stats_l3_gre.sh
+@@ -99,6 +99,8 @@ test_stats_rx()
+ 	test_stats g2a rx
+ }
+ 
++skip_on_veth
++
+ trap cleanup EXIT
+ 
+ setup_prepare
+diff --git a/tools/testing/selftests/net/forwarding/ip6_forward_instats_vrf.sh b/tools/testing/selftests/net/forwarding/ip6_forward_instats_vrf.sh
+index 9f5b3e2e5e954..49fa94b53a1ca 100755
+--- a/tools/testing/selftests/net/forwarding/ip6_forward_instats_vrf.sh
++++ b/tools/testing/selftests/net/forwarding/ip6_forward_instats_vrf.sh
+@@ -14,6 +14,8 @@ ALL_TESTS="
+ NUM_NETIFS=4
+ source lib.sh
+ 
++require_command $TROUTE6
++
+ h1_create()
+ {
+ 	simple_if_init $h1 2001:1:1::2/64
+diff --git a/tools/testing/selftests/net/forwarding/lib.sh b/tools/testing/selftests/net/forwarding/lib.sh
+index 9ddb68dd6a089..f69015bf2dea9 100755
+--- a/tools/testing/selftests/net/forwarding/lib.sh
++++ b/tools/testing/selftests/net/forwarding/lib.sh
+@@ -30,6 +30,7 @@ REQUIRE_MZ=${REQUIRE_MZ:=yes}
+ REQUIRE_MTOOLS=${REQUIRE_MTOOLS:=no}
+ STABLE_MAC_ADDRS=${STABLE_MAC_ADDRS:=no}
+ TCPDUMP_EXTRA_FLAGS=${TCPDUMP_EXTRA_FLAGS:=}
++TROUTE6=${TROUTE6:=traceroute6}
+ 
+ relative_path="${BASH_SOURCE%/*}"
+ if [[ "$relative_path" == "${BASH_SOURCE}" ]]; then
+@@ -163,6 +164,17 @@ check_port_mab_support()
+ 	fi
+ }
+ 
++skip_on_veth()
++{
++	local kind=$(ip -j -d link show dev ${NETIFS[p1]} |
++		jq -r '.[].linkinfo.info_kind')
++
++	if [[ $kind == veth ]]; then
++		echo "SKIP: Test cannot be run with veth pairs"
++		exit $ksft_skip
++	fi
++}
++
+ if [[ "$(id -u)" -ne 0 ]]; then
+ 	echo "SKIP: need root privileges"
+ 	exit $ksft_skip
+@@ -225,6 +237,11 @@ create_netif_veth()
+ 	for ((i = 1; i <= NUM_NETIFS; ++i)); do
+ 		local j=$((i+1))
+ 
++		if [ -z ${NETIFS[p$i]} ]; then
++			echo "SKIP: Cannot create interface. Name not specified"
++			exit $ksft_skip
++		fi
++
+ 		ip link show dev ${NETIFS[p$i]} &> /dev/null
+ 		if [[ $? -ne 0 ]]; then
+ 			ip link add ${NETIFS[p$i]} type veth \
+diff --git a/tools/testing/selftests/net/forwarding/settings b/tools/testing/selftests/net/forwarding/settings
+new file mode 100644
+index 0000000000000..e7b9417537fbc
+--- /dev/null
++++ b/tools/testing/selftests/net/forwarding/settings
+@@ -0,0 +1 @@
++timeout=0
+diff --git a/tools/testing/selftests/net/forwarding/tc_actions.sh b/tools/testing/selftests/net/forwarding/tc_actions.sh
+index a96cff8e72197..b0f5e55d2d0b2 100755
+--- a/tools/testing/selftests/net/forwarding/tc_actions.sh
++++ b/tools/testing/selftests/net/forwarding/tc_actions.sh
+@@ -9,6 +9,8 @@ NUM_NETIFS=4
+ source tc_common.sh
+ source lib.sh
+ 
++require_command ncat
++
+ tcflags="skip_hw"
+ 
+ h1_create()
+@@ -220,9 +222,9 @@ mirred_egress_to_ingress_tcp_test()
+ 		ip_proto icmp \
+ 			action drop
+ 
+-	ip vrf exec v$h1 nc --recv-only -w10 -l -p 12345 -o $mirred_e2i_tf2  &
++	ip vrf exec v$h1 ncat --recv-only -w10 -l -p 12345 -o $mirred_e2i_tf2 &
+ 	local rpid=$!
+-	ip vrf exec v$h1 nc -w1 --send-only 192.0.2.2 12345 <$mirred_e2i_tf1
++	ip vrf exec v$h1 ncat -w1 --send-only 192.0.2.2 12345 <$mirred_e2i_tf1
+ 	wait -n $rpid
+ 	cmp -s $mirred_e2i_tf1 $mirred_e2i_tf2
+ 	check_err $? "server output check failed"
+diff --git a/tools/testing/selftests/net/forwarding/tc_flower.sh b/tools/testing/selftests/net/forwarding/tc_flower.sh
+index 683711f41aa9b..b1daad19b01ec 100755
+--- a/tools/testing/selftests/net/forwarding/tc_flower.sh
++++ b/tools/testing/selftests/net/forwarding/tc_flower.sh
+@@ -52,8 +52,8 @@ match_dst_mac_test()
+ 	tc_check_packets "dev $h2 ingress" 101 1
+ 	check_fail $? "Matched on a wrong filter"
+ 
+-	tc_check_packets "dev $h2 ingress" 102 1
+-	check_err $? "Did not match on correct filter"
++	tc_check_packets "dev $h2 ingress" 102 0
++	check_fail $? "Did not match on correct filter"
+ 
+ 	tc filter del dev $h2 ingress protocol ip pref 1 handle 101 flower
+ 	tc filter del dev $h2 ingress protocol ip pref 2 handle 102 flower
+@@ -78,8 +78,8 @@ match_src_mac_test()
+ 	tc_check_packets "dev $h2 ingress" 101 1
+ 	check_fail $? "Matched on a wrong filter"
+ 
+-	tc_check_packets "dev $h2 ingress" 102 1
+-	check_err $? "Did not match on correct filter"
++	tc_check_packets "dev $h2 ingress" 102 0
++	check_fail $? "Did not match on correct filter"
+ 
+ 	tc filter del dev $h2 ingress protocol ip pref 1 handle 101 flower
+ 	tc filter del dev $h2 ingress protocol ip pref 2 handle 102 flower
+diff --git a/tools/testing/selftests/net/forwarding/tc_tunnel_key.sh b/tools/testing/selftests/net/forwarding/tc_tunnel_key.sh
+index 5ac184d518099..5a5dd90348195 100755
+--- a/tools/testing/selftests/net/forwarding/tc_tunnel_key.sh
++++ b/tools/testing/selftests/net/forwarding/tc_tunnel_key.sh
+@@ -104,11 +104,14 @@ tunnel_key_nofrag_test()
+ 	local i
+ 
+ 	tc filter add dev $swp1 ingress protocol ip pref 100 handle 100 \
+-		flower ip_flags nofrag action drop
++		flower src_ip 192.0.2.1 dst_ip 192.0.2.2 ip_proto udp \
++		ip_flags nofrag action drop
+ 	tc filter add dev $swp1 ingress protocol ip pref 101 handle 101 \
+-		flower ip_flags firstfrag action drop
++		flower src_ip 192.0.2.1 dst_ip 192.0.2.2 ip_proto udp \
++		ip_flags firstfrag action drop
+ 	tc filter add dev $swp1 ingress protocol ip pref 102 handle 102 \
+-		flower ip_flags nofirstfrag action drop
++		flower src_ip 192.0.2.1 dst_ip 192.0.2.2 ip_proto udp \
++		ip_flags nofirstfrag action drop
+ 
+ 	# test 'nofrag' set
+ 	tc filter add dev h1-et egress protocol all pref 1 handle 1 matchall $tcflags \
+diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh
+index a40c35c90c52b..de0d04b0e2469 100755
+--- a/tools/testing/selftests/net/mptcp/mptcp_join.sh
++++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh
+@@ -676,6 +676,7 @@ pm_nl_del_endpoint()
+ 	local addr=$3
+ 
+ 	if [ $ip_mptcp -eq 1 ]; then
++		[ $id -ne 0 ] && addr=''
+ 		ip -n $ns mptcp endpoint delete id $id $addr
+ 	else
+ 		ip netns exec $ns ./pm_nl_ctl del $id $addr
+@@ -766,10 +767,11 @@ pm_nl_check_endpoint()
+ 	fi
+ 
+ 	if [ $ip_mptcp -eq 1 ]; then
++		# get line and trim trailing whitespace
+ 		line=$(ip -n $ns mptcp endpoint show $id)
++		line="${line% }"
+ 		# the dump order is: address id flags port dev
+-		expected_line="$addr"
+-		[ -n "$addr" ] && expected_line="$expected_line $addr"
++		[ -n "$addr" ] && expected_line="$addr"
+ 		expected_line="$expected_line $id"
+ 		[ -n "$_flags" ] && expected_line="$expected_line ${_flags//","/" "}"
+ 		[ -n "$dev" ] && expected_line="$expected_line $dev"
+diff --git a/tools/testing/selftests/rseq/Makefile b/tools/testing/selftests/rseq/Makefile
+index b357ba24af06f..7a957c7d459ae 100644
+--- a/tools/testing/selftests/rseq/Makefile
++++ b/tools/testing/selftests/rseq/Makefile
+@@ -4,8 +4,10 @@ ifneq ($(shell $(CC) --version 2>&1 | head -n 1 | grep clang),)
+ CLANG_FLAGS += -no-integrated-as
+ endif
+ 
++top_srcdir = ../../../..
++
+ CFLAGS += -O2 -Wall -g -I./ $(KHDR_INCLUDES) -L$(OUTPUT) -Wl,-rpath=./ \
+-	  $(CLANG_FLAGS)
++	  $(CLANG_FLAGS) -I$(top_srcdir)/tools/include
+ LDLIBS += -lpthread -ldl
+ 
+ # Own dependencies because we only want to build against 1st prerequisite, but
+diff --git a/tools/testing/selftests/rseq/rseq.c b/tools/testing/selftests/rseq/rseq.c
+index a723da2532441..96e812bdf8a45 100644
+--- a/tools/testing/selftests/rseq/rseq.c
++++ b/tools/testing/selftests/rseq/rseq.c
+@@ -31,6 +31,8 @@
+ #include <sys/auxv.h>
+ #include <linux/auxvec.h>
+ 
++#include <linux/compiler.h>
++
+ #include "../kselftest.h"
+ #include "rseq.h"
+ 


             reply	other threads:[~2023-08-16 17:28 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-08-16 17:28 Mike Pagano [this message]
  -- strict thread matches above, loose matches on Subject: below --
2023-09-13 11:04 [gentoo-commits] proj/linux-patches:6.4 commit in: / Mike Pagano
2023-09-06 22:15 Mike Pagano
2023-09-02  9:55 Mike Pagano
2023-08-30 13:48 Mike Pagano
2023-08-30 13:45 Mike Pagano
2023-08-23 15:57 Mike Pagano
2023-08-16 20:20 Mike Pagano
2023-08-11 11:53 Mike Pagano
2023-08-08 18:39 Mike Pagano
2023-08-03 11:47 Mike Pagano
2023-08-02 10:35 Mike Pagano
2023-07-29 18:37 Mike Pagano
2023-07-27 11:46 Mike Pagano
2023-07-27 11:41 Mike Pagano
2023-07-24 20:26 Mike Pagano
2023-07-23 15:15 Mike Pagano
2023-07-19 17:20 Mike Pagano
2023-07-19 17:04 Mike Pagano
2023-07-11 11:45 Mike Pagano
2023-07-05 20:40 Mike Pagano
2023-07-05 20:26 Mike Pagano
2023-07-04 12:57 Mike Pagano
2023-07-04 12:57 Mike Pagano
2023-07-03 16:59 Mike Pagano
2023-07-01 18:48 Mike Pagano
2023-07-01 18:19 Mike Pagano
2023-05-09 12:38 Mike Pagano
2023-05-09 12:36 Mike Pagano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1692206904.6ac7d6d91eb0fb742af4fcd5f29cb68433c8a24b.mpagano@gentoo \
    --to=mpagano@gentoo.org \
    --cc=gentoo-commits@lists.gentoo.org \
    --cc=gentoo-dev@lists.gentoo.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox