From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id BDBD315800A for ; Wed, 16 Aug 2023 17:28:38 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id 018962BC020; Wed, 16 Aug 2023 17:28:38 +0000 (UTC) Received: from smtp.gentoo.org (woodpecker.gentoo.org [140.211.166.183]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id 7FFE52BC020 for ; Wed, 16 Aug 2023 17:28:37 +0000 (UTC) Received: from oystercatcher.gentoo.org (oystercatcher.gentoo.org [148.251.78.52]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id A0719340CEF for ; Wed, 16 Aug 2023 17:28:35 +0000 (UTC) Received: from localhost.localdomain (localhost [IPv6:::1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id 10B77E64 for ; Wed, 16 Aug 2023 17:28:34 +0000 (UTC) From: "Mike Pagano" To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Mike Pagano" Message-ID: <1692206904.6ac7d6d91eb0fb742af4fcd5f29cb68433c8a24b.mpagano@gentoo> Subject: [gentoo-commits] proj/linux-patches:6.4 commit in: / X-VCS-Repository: proj/linux-patches X-VCS-Files: 0000_README 1010_linux-6.4.11.patch X-VCS-Directories: / X-VCS-Committer: mpagano X-VCS-Committer-Name: Mike Pagano X-VCS-Revision: 6ac7d6d91eb0fb742af4fcd5f29cb68433c8a24b X-VCS-Branch: 6.4 Date: Wed, 16 Aug 2023 17:28:34 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply X-Archives-Salt: a93e2ad8-7060-46f7-85b1-89be5a449e08 X-Archives-Hash: 109d834ae8316235a2f373032a6d3140 commit: 6ac7d6d91eb0fb742af4fcd5f29cb68433c8a24b Author: Mike Pagano gentoo org> AuthorDate: Wed Aug 16 17:16:44 2023 +0000 Commit: Mike Pagano gentoo 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 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 + #include + +-#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 + + /* +- * 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 + #include + #include ++#include + + #include + +@@ -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 + + #include +-#include +-#include +-#include + #include +-#include + #include ++#include ++#include ++#include ++#include ++#include + + #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 + #include + #include ++#include + + #ifdef CONFIG_ACPI_APEI + # include +@@ -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 + #include + +-#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 + #include + #include ++#include + #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 + #include ++#include + + #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 ++ + #include + #include + #include +@@ -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 + #include ++#include + #include + #include + #include ++#include + #include + #include + #include +@@ -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 + #include + #include ++#include + + #include + #include +@@ -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(¶ms->params_v2_le, ¶ms_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 + #include + #include ++#include + #include + #include + +@@ -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 + #include + +-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 + #include + ++#include ++ + #include "../kselftest.h" + #include "rseq.h" +