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 0B5771581FB for ; Thu, 29 Aug 2024 16:48:29 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id 4D7F5E29B4; Thu, 29 Aug 2024 16:48:28 +0000 (UTC) Received: from smtp.gentoo.org (mail.gentoo.org [IPv6:2001:470:ea4a:1:5054:ff:fec7:86e4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id E5586E29B4 for ; Thu, 29 Aug 2024 16:48:27 +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)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id 6836933BEE8 for ; Thu, 29 Aug 2024 16:48:26 +0000 (UTC) Received: from localhost.localdomain (localhost [IPv6:::1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id 036551744 for ; Thu, 29 Aug 2024 16:48:25 +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: <1724950091.ef27e3d3833a5fc6966eba377d74239c139c169e.mpagano@gentoo> Subject: [gentoo-commits] proj/linux-patches:6.10 commit in: / X-VCS-Repository: proj/linux-patches X-VCS-Files: 0000_README 1006_linux-6.10.7.patch X-VCS-Directories: / X-VCS-Committer: mpagano X-VCS-Committer-Name: Mike Pagano X-VCS-Revision: ef27e3d3833a5fc6966eba377d74239c139c169e X-VCS-Branch: 6.10 Date: Thu, 29 Aug 2024 16:48:25 +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: c10bb462-e10b-4cfc-8a74-e55ba9bc12a4 X-Archives-Hash: 979cc4b7cbdb0f3e709108e85cacf7c5 commit: ef27e3d3833a5fc6966eba377d74239c139c169e Author: Mike Pagano gentoo org> AuthorDate: Thu Aug 29 16:48:11 2024 +0000 Commit: Mike Pagano gentoo org> CommitDate: Thu Aug 29 16:48:11 2024 +0000 URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=ef27e3d3 Linux patch 6.10.7 Signed-off-by: Mike Pagano gentoo.org> 0000_README | 4 + 1006_linux-6.10.7.patch | 12217 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 12221 insertions(+) diff --git a/0000_README b/0000_README index 75bbf8b4..82c9265b 100644 --- a/0000_README +++ b/0000_README @@ -67,6 +67,10 @@ Patch: 1005_linux-6.10.6.patch From: https://www.kernel.org Desc: Linux 6.10.6 +Patch: 1006_linux-6.10.7.patch +From: https://www.kernel.org +Desc: Linux 6.10.7 + Patch: 1510_fs-enable-link-security-restrictions-by-default.patch From: http://sources.debian.net/src/linux/3.16.7-ckt4-3/debian/patches/debian/fs-enable-link-security-restrictions-by-default.patch/ Desc: Enable link security restrictions by default. diff --git a/1006_linux-6.10.7.patch b/1006_linux-6.10.7.patch new file mode 100644 index 00000000..00a04ca2 --- /dev/null +++ b/1006_linux-6.10.7.patch @@ -0,0 +1,12217 @@ +diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu +index e7e160954e798..0579860b55299 100644 +--- a/Documentation/ABI/testing/sysfs-devices-system-cpu ++++ b/Documentation/ABI/testing/sysfs-devices-system-cpu +@@ -562,7 +562,8 @@ Description: Control Symmetric Multi Threading (SMT) + ================ ========================================= + + If control status is "forceoff" or "notsupported" writes +- are rejected. ++ are rejected. Note that enabling SMT on PowerPC skips ++ offline cores. + + What: /sys/devices/system/cpu/cpuX/power/energy_perf_bias + Date: March 2019 +diff --git a/Makefile b/Makefile +index 361a70264e1fb..ab77d171e268d 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 6 + PATCHLEVEL = 10 +-SUBLEVEL = 6 ++SUBLEVEL = 7 + EXTRAVERSION = + NAME = Baby Opossum Posse + +@@ -1986,7 +1986,7 @@ nsdeps: modules + quiet_cmd_gen_compile_commands = GEN $@ + cmd_gen_compile_commands = $(PYTHON3) $< -a $(AR) -o $@ $(filter-out $<, $(real-prereqs)) + +-$(extmod_prefix)compile_commands.json: scripts/clang-tools/gen_compile_commands.py \ ++$(extmod_prefix)compile_commands.json: $(srctree)/scripts/clang-tools/gen_compile_commands.py \ + $(if $(KBUILD_EXTMOD),, vmlinux.a $(KBUILD_VMLINUX_LIBS)) \ + $(if $(CONFIG_MODULES), $(MODORDER)) FORCE + $(call if_changed,gen_compile_commands) +diff --git a/arch/arm64/kernel/acpi_numa.c b/arch/arm64/kernel/acpi_numa.c +index e51535a5f939a..ccbff21ce1faf 100644 +--- a/arch/arm64/kernel/acpi_numa.c ++++ b/arch/arm64/kernel/acpi_numa.c +@@ -27,7 +27,7 @@ + + #include + +-static int acpi_early_node_map[NR_CPUS] __initdata = { NUMA_NO_NODE }; ++static int acpi_early_node_map[NR_CPUS] __initdata = { [0 ... NR_CPUS - 1] = NUMA_NO_NODE }; + + int __init acpi_numa_get_nid(unsigned int cpu) + { +diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c +index a096e2451044d..b22d28ec80284 100644 +--- a/arch/arm64/kernel/setup.c ++++ b/arch/arm64/kernel/setup.c +@@ -355,9 +355,6 @@ void __init __no_sanitize_address setup_arch(char **cmdline_p) + smp_init_cpus(); + smp_build_mpidr_hash(); + +- /* Init percpu seeds for random tags after cpus are set up. */ +- kasan_init_sw_tags(); +- + #ifdef CONFIG_ARM64_SW_TTBR0_PAN + /* + * Make sure init_thread_info.ttbr0 always generates translation +diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c +index 5de85dccc09cd..05688f6a275f1 100644 +--- a/arch/arm64/kernel/smp.c ++++ b/arch/arm64/kernel/smp.c +@@ -469,6 +469,8 @@ void __init smp_prepare_boot_cpu(void) + init_gic_priority_masking(); + + kasan_init_hw_tags(); ++ /* Init percpu seeds for random tags after cpus are set up. */ ++ kasan_init_sw_tags(); + } + + /* +diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c +index 22b45a15d0688..33d866ca8f655 100644 +--- a/arch/arm64/kvm/sys_regs.c ++++ b/arch/arm64/kvm/sys_regs.c +@@ -33,6 +33,7 @@ + #include + + #include "sys_regs.h" ++#include "vgic/vgic.h" + + #include "trace.h" + +@@ -428,6 +429,11 @@ static bool access_gic_sgi(struct kvm_vcpu *vcpu, + { + bool g1; + ++ if (!kvm_has_gicv3(vcpu->kvm)) { ++ kvm_inject_undefined(vcpu); ++ return false; ++ } ++ + if (!p->is_write) + return read_from_write_only(vcpu, p, r); + +diff --git a/arch/arm64/kvm/vgic/vgic-debug.c b/arch/arm64/kvm/vgic/vgic-debug.c +index bcbc8c986b1d6..980fbe4fd82cb 100644 +--- a/arch/arm64/kvm/vgic/vgic-debug.c ++++ b/arch/arm64/kvm/vgic/vgic-debug.c +@@ -84,7 +84,7 @@ static void iter_unmark_lpis(struct kvm *kvm) + struct vgic_irq *irq; + unsigned long intid; + +- xa_for_each(&dist->lpi_xa, intid, irq) { ++ xa_for_each_marked(&dist->lpi_xa, intid, irq, LPI_XA_MARK_DEBUG_ITER) { + xa_clear_mark(&dist->lpi_xa, intid, LPI_XA_MARK_DEBUG_ITER); + vgic_put_irq(kvm, irq); + } +diff --git a/arch/arm64/kvm/vgic/vgic.h b/arch/arm64/kvm/vgic/vgic.h +index 03d356a123771..55e3b7108dc9b 100644 +--- a/arch/arm64/kvm/vgic/vgic.h ++++ b/arch/arm64/kvm/vgic/vgic.h +@@ -346,4 +346,11 @@ void vgic_v4_configure_vsgis(struct kvm *kvm); + void vgic_v4_get_vlpi_state(struct vgic_irq *irq, bool *val); + int vgic_v4_request_vpe_irq(struct kvm_vcpu *vcpu, int irq); + ++static inline bool kvm_has_gicv3(struct kvm *kvm) ++{ ++ return (static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif) && ++ irqchip_in_kernel(kvm) && ++ kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3); ++} ++ + #endif +diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c +index bda7f193baab9..af7412549e6ea 100644 +--- a/arch/mips/kernel/cpu-probe.c ++++ b/arch/mips/kernel/cpu-probe.c +@@ -1724,12 +1724,16 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu) + c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_CAM | + MIPS_ASE_LOONGSON_EXT | MIPS_ASE_LOONGSON_EXT2); + c->ases &= ~MIPS_ASE_VZ; /* VZ of Loongson-3A2000/3000 is incomplete */ ++ change_c0_config6(LOONGSON_CONF6_EXTIMER | LOONGSON_CONF6_INTIMER, ++ LOONGSON_CONF6_INTIMER); + break; + case PRID_IMP_LOONGSON_64G: + __cpu_name[cpu] = "ICT Loongson-3"; + set_elf_platform(cpu, "loongson3a"); + set_isa(c, MIPS_CPU_ISA_M64R2); + decode_cpucfg(c); ++ change_c0_config6(LOONGSON_CONF6_EXTIMER | LOONGSON_CONF6_INTIMER, ++ LOONGSON_CONF6_INTIMER); + break; + default: + panic("Unknown Loongson Processor ID!"); +diff --git a/arch/powerpc/include/asm/topology.h b/arch/powerpc/include/asm/topology.h +index f4e6f2dd04b73..16bacfe8c7a2c 100644 +--- a/arch/powerpc/include/asm/topology.h ++++ b/arch/powerpc/include/asm/topology.h +@@ -145,6 +145,7 @@ static inline int cpu_to_coregroup_id(int cpu) + + #ifdef CONFIG_HOTPLUG_SMT + #include ++#include + #include + + static inline bool topology_is_primary_thread(unsigned int cpu) +@@ -156,6 +157,18 @@ static inline bool topology_smt_thread_allowed(unsigned int cpu) + { + return cpu_thread_in_core(cpu) < cpu_smt_num_threads; + } ++ ++#define topology_is_core_online topology_is_core_online ++static inline bool topology_is_core_online(unsigned int cpu) ++{ ++ int i, first_cpu = cpu_first_thread_sibling(cpu); ++ ++ for (i = first_cpu; i < first_cpu + threads_per_core; ++i) { ++ if (cpu_online(i)) ++ return true; ++ } ++ return false; ++} + #endif + + #endif /* __KERNEL__ */ +diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c +index 05a16b1f0aee8..51ebfd23e0076 100644 +--- a/arch/riscv/kernel/traps.c ++++ b/arch/riscv/kernel/traps.c +@@ -319,6 +319,7 @@ void do_trap_ecall_u(struct pt_regs *regs) + + regs->epc += 4; + regs->orig_a0 = regs->a0; ++ regs->a0 = -ENOSYS; + + riscv_v_vstate_discard(regs); + +@@ -328,8 +329,7 @@ void do_trap_ecall_u(struct pt_regs *regs) + + if (syscall >= 0 && syscall < NR_syscalls) + syscall_handler(regs, syscall); +- else if (syscall != -1) +- regs->a0 = -ENOSYS; ++ + /* + * Ultimately, this value will get limited by KSTACK_OFFSET_MAX(), + * so the maximum stack offset is 1k bytes (10 bits). +diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c +index 7e25606f858aa..c5c66f53971af 100644 +--- a/arch/riscv/mm/init.c ++++ b/arch/riscv/mm/init.c +@@ -931,7 +931,7 @@ static void __init create_kernel_page_table(pgd_t *pgdir, + PMD_SIZE, PAGE_KERNEL_EXEC); + + /* Map the data in RAM */ +- end_va = kernel_map.virt_addr + XIP_OFFSET + kernel_map.size; ++ end_va = kernel_map.virt_addr + kernel_map.size; + for (va = kernel_map.virt_addr + XIP_OFFSET; va < end_va; va += PMD_SIZE) + create_pgd_mapping(pgdir, va, + kernel_map.phys_addr + (va - (kernel_map.virt_addr + XIP_OFFSET)), +@@ -1100,7 +1100,7 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa) + + phys_ram_base = CONFIG_PHYS_RAM_BASE; + kernel_map.phys_addr = (uintptr_t)CONFIG_PHYS_RAM_BASE; +- kernel_map.size = (uintptr_t)(&_end) - (uintptr_t)(&_sdata); ++ kernel_map.size = (uintptr_t)(&_end) - (uintptr_t)(&_start); + + kernel_map.va_kernel_xip_pa_offset = kernel_map.virt_addr - kernel_map.xiprom; + #else +diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c +index 5a36d5538dae8..6d88f241dd43a 100644 +--- a/arch/s390/boot/startup.c ++++ b/arch/s390/boot/startup.c +@@ -161,7 +161,7 @@ static void kaslr_adjust_relocs(unsigned long min_addr, unsigned long max_addr, + loc = (long)*reloc + phys_offset; + if (loc < min_addr || loc > max_addr) + error("64-bit relocation outside of kernel!\n"); +- *(u64 *)loc += offset - __START_KERNEL; ++ *(u64 *)loc += offset; + } + } + +@@ -176,7 +176,7 @@ static void kaslr_adjust_got(unsigned long offset) + */ + for (entry = (u64 *)vmlinux.got_start; entry < (u64 *)vmlinux.got_end; entry++) { + if (*entry) +- *entry += offset - __START_KERNEL; ++ *entry += offset; + } + } + +@@ -251,7 +251,7 @@ static unsigned long setup_kernel_memory_layout(unsigned long kernel_size) + vmemmap_size = SECTION_ALIGN_UP(pages) * sizeof(struct page); + + /* choose kernel address space layout: 4 or 3 levels. */ +- BUILD_BUG_ON(!IS_ALIGNED(__START_KERNEL, THREAD_SIZE)); ++ BUILD_BUG_ON(!IS_ALIGNED(TEXT_OFFSET, THREAD_SIZE)); + BUILD_BUG_ON(!IS_ALIGNED(__NO_KASLR_START_KERNEL, THREAD_SIZE)); + BUILD_BUG_ON(__NO_KASLR_END_KERNEL > _REGION1_SIZE); + vsize = get_vmem_size(ident_map_size, vmemmap_size, vmalloc_size, _REGION3_SIZE); +@@ -378,31 +378,25 @@ static void kaslr_adjust_vmlinux_info(long offset) + #endif + } + +-static void fixup_vmlinux_info(void) +-{ +- vmlinux.entry -= __START_KERNEL; +- kaslr_adjust_vmlinux_info(-__START_KERNEL); +-} +- + void startup_kernel(void) + { +- unsigned long kernel_size = vmlinux.image_size + vmlinux.bss_size; +- unsigned long nokaslr_offset_phys, kaslr_large_page_offset; +- unsigned long amode31_lma = 0; ++ unsigned long vmlinux_size = vmlinux.image_size + vmlinux.bss_size; ++ unsigned long nokaslr_text_lma, text_lma = 0, amode31_lma = 0; ++ unsigned long kernel_size = TEXT_OFFSET + vmlinux_size; ++ unsigned long kaslr_large_page_offset; + unsigned long max_physmem_end; + unsigned long asce_limit; + unsigned long safe_addr; + psw_t psw; + +- fixup_vmlinux_info(); + setup_lpp(); + + /* + * Non-randomized kernel physical start address must be _SEGMENT_SIZE + * aligned (see blow). + */ +- nokaslr_offset_phys = ALIGN(mem_safe_offset(), _SEGMENT_SIZE); +- safe_addr = PAGE_ALIGN(nokaslr_offset_phys + kernel_size); ++ nokaslr_text_lma = ALIGN(mem_safe_offset(), _SEGMENT_SIZE); ++ safe_addr = PAGE_ALIGN(nokaslr_text_lma + vmlinux_size); + + /* + * Reserve decompressor memory together with decompression heap, +@@ -446,16 +440,27 @@ void startup_kernel(void) + */ + kaslr_large_page_offset = __kaslr_offset & ~_SEGMENT_MASK; + if (kaslr_enabled()) { +- unsigned long end = ident_map_size - kaslr_large_page_offset; ++ unsigned long size = vmlinux_size + kaslr_large_page_offset; + +- __kaslr_offset_phys = randomize_within_range(kernel_size, _SEGMENT_SIZE, 0, end); ++ text_lma = randomize_within_range(size, _SEGMENT_SIZE, TEXT_OFFSET, ident_map_size); + } +- if (!__kaslr_offset_phys) +- __kaslr_offset_phys = nokaslr_offset_phys; +- __kaslr_offset_phys |= kaslr_large_page_offset; ++ if (!text_lma) ++ text_lma = nokaslr_text_lma; ++ text_lma |= kaslr_large_page_offset; ++ ++ /* ++ * [__kaslr_offset_phys..__kaslr_offset_phys + TEXT_OFFSET] region is ++ * never accessed via the kernel image mapping as per the linker script: ++ * ++ * . = TEXT_OFFSET; ++ * ++ * Therefore, this region could be used for something else and does ++ * not need to be reserved. See how it is skipped in setup_vmem(). ++ */ ++ __kaslr_offset_phys = text_lma - TEXT_OFFSET; + kaslr_adjust_vmlinux_info(__kaslr_offset_phys); +- physmem_reserve(RR_VMLINUX, __kaslr_offset_phys, kernel_size); +- deploy_kernel((void *)__kaslr_offset_phys); ++ physmem_reserve(RR_VMLINUX, text_lma, vmlinux_size); ++ deploy_kernel((void *)text_lma); + + /* vmlinux decompression is done, shrink reserved low memory */ + physmem_reserve(RR_DECOMPRESSOR, 0, (unsigned long)_decompressor_end); +@@ -474,7 +479,7 @@ void startup_kernel(void) + if (kaslr_enabled()) + amode31_lma = randomize_within_range(vmlinux.amode31_size, PAGE_SIZE, 0, SZ_2G); + if (!amode31_lma) +- amode31_lma = __kaslr_offset_phys - vmlinux.amode31_size; ++ amode31_lma = text_lma - vmlinux.amode31_size; + physmem_reserve(RR_AMODE31, amode31_lma, vmlinux.amode31_size); + + /* +@@ -490,8 +495,8 @@ void startup_kernel(void) + * - copy_bootdata() must follow setup_vmem() to propagate changes + * to bootdata made by setup_vmem() + */ +- clear_bss_section(__kaslr_offset_phys); +- kaslr_adjust_relocs(__kaslr_offset_phys, __kaslr_offset_phys + vmlinux.image_size, ++ clear_bss_section(text_lma); ++ kaslr_adjust_relocs(text_lma, text_lma + vmlinux.image_size, + __kaslr_offset, __kaslr_offset_phys); + kaslr_adjust_got(__kaslr_offset); + setup_vmem(__kaslr_offset, __kaslr_offset + kernel_size, asce_limit); +diff --git a/arch/s390/boot/vmem.c b/arch/s390/boot/vmem.c +index 40cfce2687c43..3d4dae9905cd8 100644 +--- a/arch/s390/boot/vmem.c ++++ b/arch/s390/boot/vmem.c +@@ -89,7 +89,7 @@ static void kasan_populate_shadow(unsigned long kernel_start, unsigned long kern + } + memgap_start = end; + } +- kasan_populate(kernel_start, kernel_end, POPULATE_KASAN_MAP_SHADOW); ++ kasan_populate(kernel_start + TEXT_OFFSET, kernel_end, POPULATE_KASAN_MAP_SHADOW); + kasan_populate(0, (unsigned long)__identity_va(0), POPULATE_KASAN_ZERO_SHADOW); + kasan_populate(AMODE31_START, AMODE31_END, POPULATE_KASAN_ZERO_SHADOW); + if (IS_ENABLED(CONFIG_KASAN_VMALLOC)) { +@@ -466,7 +466,17 @@ void setup_vmem(unsigned long kernel_start, unsigned long kernel_end, unsigned l + (unsigned long)__identity_va(end), + POPULATE_IDENTITY); + } +- pgtable_populate(kernel_start, kernel_end, POPULATE_KERNEL); ++ ++ /* ++ * [kernel_start..kernel_start + TEXT_OFFSET] region is never ++ * accessed as per the linker script: ++ * ++ * . = TEXT_OFFSET; ++ * ++ * Therefore, skip mapping TEXT_OFFSET bytes to prevent access to ++ * [__kaslr_offset_phys..__kaslr_offset_phys + TEXT_OFFSET] region. ++ */ ++ pgtable_populate(kernel_start + TEXT_OFFSET, kernel_end, POPULATE_KERNEL); + pgtable_populate(AMODE31_START, AMODE31_END, POPULATE_DIRECT); + pgtable_populate(__abs_lowcore, __abs_lowcore + sizeof(struct lowcore), + POPULATE_ABS_LOWCORE); +diff --git a/arch/s390/boot/vmlinux.lds.S b/arch/s390/boot/vmlinux.lds.S +index a750711d44c86..66670212a3611 100644 +--- a/arch/s390/boot/vmlinux.lds.S ++++ b/arch/s390/boot/vmlinux.lds.S +@@ -109,7 +109,12 @@ SECTIONS + #ifdef CONFIG_KERNEL_UNCOMPRESSED + . = ALIGN(PAGE_SIZE); + . += AMODE31_SIZE; /* .amode31 section */ +- . = ALIGN(1 << 20); /* _SEGMENT_SIZE */ ++ ++ /* ++ * Make sure the location counter is not less than TEXT_OFFSET. ++ * _SEGMENT_SIZE is not available, use ALIGN(1 << 20) instead. ++ */ ++ . = MAX(TEXT_OFFSET, ALIGN(1 << 20)); + #else + . = ALIGN(8); + #endif +diff --git a/arch/s390/include/asm/page.h b/arch/s390/include/asm/page.h +index 224ff9d433ead..8cac1a737424d 100644 +--- a/arch/s390/include/asm/page.h ++++ b/arch/s390/include/asm/page.h +@@ -276,8 +276,9 @@ static inline unsigned long virt_to_pfn(const void *kaddr) + #define AMODE31_SIZE (3 * PAGE_SIZE) + + #define KERNEL_IMAGE_SIZE (512 * 1024 * 1024) +-#define __START_KERNEL 0x100000 + #define __NO_KASLR_START_KERNEL CONFIG_KERNEL_IMAGE_BASE + #define __NO_KASLR_END_KERNEL (__NO_KASLR_START_KERNEL + KERNEL_IMAGE_SIZE) + ++#define TEXT_OFFSET 0x100000 ++ + #endif /* _S390_PAGE_H */ +diff --git a/arch/s390/include/asm/uv.h b/arch/s390/include/asm/uv.h +index 0e7bd3873907f..b2e2f9a4163c5 100644 +--- a/arch/s390/include/asm/uv.h ++++ b/arch/s390/include/asm/uv.h +@@ -442,7 +442,10 @@ static inline int share(unsigned long addr, u16 cmd) + + if (!uv_call(0, (u64)&uvcb)) + return 0; +- return -EINVAL; ++ pr_err("%s UVC failed (rc: 0x%x, rrc: 0x%x), possible hypervisor bug.\n", ++ uvcb.header.cmd == UVC_CMD_SET_SHARED_ACCESS ? "Share" : "Unshare", ++ uvcb.header.rc, uvcb.header.rrc); ++ panic("System security cannot be guaranteed unless the system panics now.\n"); + } + + /* +diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S +index a1ce3925ec719..52bd969b28283 100644 +--- a/arch/s390/kernel/vmlinux.lds.S ++++ b/arch/s390/kernel/vmlinux.lds.S +@@ -39,7 +39,7 @@ PHDRS { + + SECTIONS + { +- . = __START_KERNEL; ++ . = TEXT_OFFSET; + .text : { + _stext = .; /* Start of text section */ + _text = .; /* Text and read-only data */ +diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h +index bf8534218af3d..e680c6bf0c9d9 100644 +--- a/arch/s390/kvm/kvm-s390.h ++++ b/arch/s390/kvm/kvm-s390.h +@@ -267,7 +267,12 @@ static inline unsigned long kvm_s390_get_gfn_end(struct kvm_memslots *slots) + + static inline u32 kvm_s390_get_gisa_desc(struct kvm *kvm) + { +- u32 gd = virt_to_phys(kvm->arch.gisa_int.origin); ++ u32 gd; ++ ++ if (!kvm->arch.gisa_int.origin) ++ return 0; ++ ++ gd = virt_to_phys(kvm->arch.gisa_int.origin); + + if (gd && sclp.has_gisaf) + gd |= GISA_FORMAT1; +diff --git a/arch/s390/tools/relocs.c b/arch/s390/tools/relocs.c +index a74dbd5c9896a..30a732c808f35 100644 +--- a/arch/s390/tools/relocs.c ++++ b/arch/s390/tools/relocs.c +@@ -280,7 +280,7 @@ static int do_reloc(struct section *sec, Elf_Rel *rel) + case R_390_GOTOFF64: + break; + case R_390_64: +- add_reloc(&relocs64, offset - ehdr.e_entry); ++ add_reloc(&relocs64, offset); + break; + default: + die("Unsupported relocation type: %d\n", r_type); +diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c +index cc57e2dd9a0bb..2cafcf11ee8be 100644 +--- a/block/blk-mq-tag.c ++++ b/block/blk-mq-tag.c +@@ -38,6 +38,7 @@ static void blk_mq_update_wake_batch(struct blk_mq_tags *tags, + void __blk_mq_tag_busy(struct blk_mq_hw_ctx *hctx) + { + unsigned int users; ++ unsigned long flags; + struct blk_mq_tags *tags = hctx->tags; + + /* +@@ -56,11 +57,11 @@ void __blk_mq_tag_busy(struct blk_mq_hw_ctx *hctx) + return; + } + +- spin_lock_irq(&tags->lock); ++ spin_lock_irqsave(&tags->lock, flags); + users = tags->active_queues + 1; + WRITE_ONCE(tags->active_queues, users); + blk_mq_update_wake_batch(tags, users); +- spin_unlock_irq(&tags->lock); ++ spin_unlock_irqrestore(&tags->lock, flags); + } + + /* +diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h +index 2133085deda77..1c5218b79fc2a 100644 +--- a/drivers/acpi/acpica/acevents.h ++++ b/drivers/acpi/acpica/acevents.h +@@ -188,13 +188,9 @@ acpi_ev_detach_region(union acpi_operand_object *region_obj, + u8 acpi_ns_is_locked); + + void +-acpi_ev_execute_reg_methods(struct acpi_namespace_node *node, ++acpi_ev_execute_reg_methods(struct acpi_namespace_node *node, u32 max_depth, + acpi_adr_space_type space_id, u32 function); + +-void +-acpi_ev_execute_orphan_reg_method(struct acpi_namespace_node *node, +- acpi_adr_space_type space_id); +- + acpi_status + acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function); + +diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c +index dc6004daf624b..cf53b9535f18e 100644 +--- a/drivers/acpi/acpica/evregion.c ++++ b/drivers/acpi/acpica/evregion.c +@@ -20,6 +20,10 @@ extern u8 acpi_gbl_default_address_spaces[]; + + /* Local prototypes */ + ++static void ++acpi_ev_execute_orphan_reg_method(struct acpi_namespace_node *device_node, ++ acpi_adr_space_type space_id); ++ + static acpi_status + acpi_ev_reg_run(acpi_handle obj_handle, + u32 level, void *context, void **return_value); +@@ -61,6 +65,7 @@ acpi_status acpi_ev_initialize_op_regions(void) + acpi_gbl_default_address_spaces + [i])) { + acpi_ev_execute_reg_methods(acpi_gbl_root_node, ++ ACPI_UINT32_MAX, + acpi_gbl_default_address_spaces + [i], ACPI_REG_CONNECT); + } +@@ -668,6 +673,7 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) + * FUNCTION: acpi_ev_execute_reg_methods + * + * PARAMETERS: node - Namespace node for the device ++ * max_depth - Depth to which search for _REG + * space_id - The address space ID + * function - Passed to _REG: On (1) or Off (0) + * +@@ -679,7 +685,7 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) + ******************************************************************************/ + + void +-acpi_ev_execute_reg_methods(struct acpi_namespace_node *node, ++acpi_ev_execute_reg_methods(struct acpi_namespace_node *node, u32 max_depth, + acpi_adr_space_type space_id, u32 function) + { + struct acpi_reg_walk_info info; +@@ -713,7 +719,7 @@ acpi_ev_execute_reg_methods(struct acpi_namespace_node *node, + * regions and _REG methods. (i.e. handlers must be installed for all + * regions of this Space ID before we can run any _REG methods) + */ +- (void)acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX, ++ (void)acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, max_depth, + ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run, NULL, + &info, NULL); + +@@ -814,7 +820,7 @@ acpi_ev_reg_run(acpi_handle obj_handle, + * + ******************************************************************************/ + +-void ++static void + acpi_ev_execute_orphan_reg_method(struct acpi_namespace_node *device_node, + acpi_adr_space_type space_id) + { +diff --git a/drivers/acpi/acpica/evxfregn.c b/drivers/acpi/acpica/evxfregn.c +index 624361a5f34d8..95f78383bbdba 100644 +--- a/drivers/acpi/acpica/evxfregn.c ++++ b/drivers/acpi/acpica/evxfregn.c +@@ -85,7 +85,8 @@ acpi_install_address_space_handler_internal(acpi_handle device, + /* Run all _REG methods for this address space */ + + if (run_reg) { +- acpi_ev_execute_reg_methods(node, space_id, ACPI_REG_CONNECT); ++ acpi_ev_execute_reg_methods(node, ACPI_UINT32_MAX, space_id, ++ ACPI_REG_CONNECT); + } + + unlock_and_exit: +@@ -263,6 +264,7 @@ ACPI_EXPORT_SYMBOL(acpi_remove_address_space_handler) + * FUNCTION: acpi_execute_reg_methods + * + * PARAMETERS: device - Handle for the device ++ * max_depth - Depth to which search for _REG + * space_id - The address space ID + * + * RETURN: Status +@@ -271,7 +273,8 @@ ACPI_EXPORT_SYMBOL(acpi_remove_address_space_handler) + * + ******************************************************************************/ + acpi_status +-acpi_execute_reg_methods(acpi_handle device, acpi_adr_space_type space_id) ++acpi_execute_reg_methods(acpi_handle device, u32 max_depth, ++ acpi_adr_space_type space_id) + { + struct acpi_namespace_node *node; + acpi_status status; +@@ -296,7 +299,8 @@ acpi_execute_reg_methods(acpi_handle device, acpi_adr_space_type space_id) + + /* Run all _REG methods for this address space */ + +- acpi_ev_execute_reg_methods(node, space_id, ACPI_REG_CONNECT); ++ acpi_ev_execute_reg_methods(node, max_depth, space_id, ++ ACPI_REG_CONNECT); + } else { + status = AE_BAD_PARAMETER; + } +@@ -306,57 +310,3 @@ acpi_execute_reg_methods(acpi_handle device, acpi_adr_space_type space_id) + } + + ACPI_EXPORT_SYMBOL(acpi_execute_reg_methods) +- +-/******************************************************************************* +- * +- * FUNCTION: acpi_execute_orphan_reg_method +- * +- * PARAMETERS: device - Handle for the device +- * space_id - The address space ID +- * +- * RETURN: Status +- * +- * DESCRIPTION: Execute an "orphan" _REG method that appears under an ACPI +- * device. This is a _REG method that has no corresponding region +- * within the device's scope. +- * +- ******************************************************************************/ +-acpi_status +-acpi_execute_orphan_reg_method(acpi_handle device, acpi_adr_space_type space_id) +-{ +- struct acpi_namespace_node *node; +- acpi_status status; +- +- ACPI_FUNCTION_TRACE(acpi_execute_orphan_reg_method); +- +- /* Parameter validation */ +- +- if (!device) { +- return_ACPI_STATUS(AE_BAD_PARAMETER); +- } +- +- status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); +- if (ACPI_FAILURE(status)) { +- return_ACPI_STATUS(status); +- } +- +- /* Convert and validate the device handle */ +- +- node = acpi_ns_validate_handle(device); +- if (node) { +- +- /* +- * If an "orphan" _REG method is present in the device's scope +- * for the given address space ID, run it. +- */ +- +- acpi_ev_execute_orphan_reg_method(node, space_id); +- } else { +- status = AE_BAD_PARAMETER; +- } +- +- (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); +- return_ACPI_STATUS(status); +-} +- +-ACPI_EXPORT_SYMBOL(acpi_execute_orphan_reg_method) +diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c +index 299ec653388ce..38d2f6e6b12b4 100644 +--- a/drivers/acpi/ec.c ++++ b/drivers/acpi/ec.c +@@ -1487,12 +1487,13 @@ static bool install_gpio_irq_event_handler(struct acpi_ec *ec) + static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device, + bool call_reg) + { +- acpi_handle scope_handle = ec == first_ec ? ACPI_ROOT_OBJECT : ec->handle; + acpi_status status; + + acpi_ec_start(ec, false); + + if (!test_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags)) { ++ acpi_handle scope_handle = ec == first_ec ? ACPI_ROOT_OBJECT : ec->handle; ++ + acpi_ec_enter_noirq(ec); + status = acpi_install_address_space_handler_no_reg(scope_handle, + ACPI_ADR_SPACE_EC, +@@ -1506,10 +1507,7 @@ static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device, + } + + if (call_reg && !test_bit(EC_FLAGS_EC_REG_CALLED, &ec->flags)) { +- acpi_execute_reg_methods(scope_handle, ACPI_ADR_SPACE_EC); +- if (scope_handle != ec->handle) +- acpi_execute_orphan_reg_method(ec->handle, ACPI_ADR_SPACE_EC); +- ++ acpi_execute_reg_methods(ec->handle, ACPI_UINT32_MAX, ACPI_ADR_SPACE_EC); + set_bit(EC_FLAGS_EC_REG_CALLED, &ec->flags); + } + +@@ -1724,6 +1722,12 @@ static void acpi_ec_remove(struct acpi_device *device) + } + } + ++void acpi_ec_register_opregions(struct acpi_device *adev) ++{ ++ if (first_ec && first_ec->handle != adev->handle) ++ acpi_execute_reg_methods(adev->handle, 1, ACPI_ADR_SPACE_EC); ++} ++ + static acpi_status + ec_parse_io_ports(struct acpi_resource *resource, void *context) + { +diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h +index 601b670356e50..aadd4c218b320 100644 +--- a/drivers/acpi/internal.h ++++ b/drivers/acpi/internal.h +@@ -223,6 +223,7 @@ int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit, + acpi_handle handle, acpi_ec_query_func func, + void *data); + void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit); ++void acpi_ec_register_opregions(struct acpi_device *adev); + + #ifdef CONFIG_PM_SLEEP + void acpi_ec_flush_work(void); +diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c +index 503773707e012..cdc5a74092c77 100644 +--- a/drivers/acpi/scan.c ++++ b/drivers/acpi/scan.c +@@ -2264,6 +2264,8 @@ static int acpi_bus_attach(struct acpi_device *device, void *first_pass) + if (device->handler) + goto ok; + ++ acpi_ec_register_opregions(device); ++ + if (!device->flags.initialized) { + device->flags.power_manageable = + device->power.states[ACPI_STATE_D0].flags.valid; +diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c +index 2cc3821b2b16e..ff6f260433a11 100644 +--- a/drivers/acpi/video_detect.c ++++ b/drivers/acpi/video_detect.c +@@ -54,6 +54,8 @@ static void acpi_video_parse_cmdline(void) + acpi_backlight_cmdline = acpi_backlight_nvidia_wmi_ec; + if (!strcmp("apple_gmux", acpi_video_backlight_string)) + acpi_backlight_cmdline = acpi_backlight_apple_gmux; ++ if (!strcmp("dell_uart", acpi_video_backlight_string)) ++ acpi_backlight_cmdline = acpi_backlight_dell_uart; + if (!strcmp("none", acpi_video_backlight_string)) + acpi_backlight_cmdline = acpi_backlight_none; + } +@@ -805,6 +807,21 @@ static const struct dmi_system_id video_detect_dmi_table[] = { + }, + }, + ++ /* ++ * Dell AIO (All in Ones) which advertise an UART attached backlight ++ * controller board in their ACPI tables (and may even have one), but ++ * which need native backlight control nevertheless. ++ */ ++ { ++ /* https://bugzilla.redhat.com/show_bug.cgi?id=2303936 */ ++ .callback = video_detect_force_native, ++ /* Dell OptiPlex 7760 AIO */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 7760 AIO"), ++ }, ++ }, ++ + /* + * Models which have nvidia-ec-wmi support, but should not use it. + * Note this indicates a likely firmware bug on these models and should +@@ -902,6 +919,7 @@ enum acpi_backlight_type __acpi_video_get_backlight_type(bool native, bool *auto + static DEFINE_MUTEX(init_mutex); + static bool nvidia_wmi_ec_present; + static bool apple_gmux_present; ++ static bool dell_uart_present; + static bool native_available; + static bool init_done; + static long video_caps; +@@ -916,6 +934,7 @@ enum acpi_backlight_type __acpi_video_get_backlight_type(bool native, bool *auto + &video_caps, NULL); + nvidia_wmi_ec_present = nvidia_wmi_ec_supported(); + apple_gmux_present = apple_gmux_detect(NULL, NULL); ++ dell_uart_present = acpi_dev_present("DELL0501", NULL, -1); + init_done = true; + } + if (native) +@@ -946,6 +965,9 @@ enum acpi_backlight_type __acpi_video_get_backlight_type(bool native, bool *auto + if (apple_gmux_present) + return acpi_backlight_apple_gmux; + ++ if (dell_uart_present) ++ return acpi_backlight_dell_uart; ++ + /* Use ACPI video if available, except when native should be preferred. */ + if ((video_caps & ACPI_VIDEO_BACKLIGHT) && + !(native_available && prefer_native_over_acpi_video())) +diff --git a/drivers/ata/pata_macio.c b/drivers/ata/pata_macio.c +index 3cb455a32d926..99fc5d9d95d7a 100644 +--- a/drivers/ata/pata_macio.c ++++ b/drivers/ata/pata_macio.c +@@ -208,6 +208,19 @@ static const char* macio_ata_names[] = { + /* Don't let a DMA segment go all the way to 64K */ + #define MAX_DBDMA_SEG 0xff00 + ++#ifdef CONFIG_PAGE_SIZE_64KB ++/* ++ * The SCSI core requires the segment size to cover at least a page, so ++ * for 64K page size kernels it must be at least 64K. However the ++ * hardware can't handle 64K, so pata_macio_qc_prep() will split large ++ * requests. To handle the split requests the tablesize must be halved. ++ */ ++#define PATA_MACIO_MAX_SEGMENT_SIZE SZ_64K ++#define PATA_MACIO_SG_TABLESIZE (MAX_DCMDS / 2) ++#else ++#define PATA_MACIO_MAX_SEGMENT_SIZE MAX_DBDMA_SEG ++#define PATA_MACIO_SG_TABLESIZE MAX_DCMDS ++#endif + + /* + * Wait 1s for disk to answer on IDE bus after a hard reset +@@ -912,16 +925,10 @@ static int pata_macio_do_resume(struct pata_macio_priv *priv) + + static const struct scsi_host_template pata_macio_sht = { + __ATA_BASE_SHT(DRV_NAME), +- .sg_tablesize = MAX_DCMDS, ++ .sg_tablesize = PATA_MACIO_SG_TABLESIZE, + /* We may not need that strict one */ + .dma_boundary = ATA_DMA_BOUNDARY, +- /* +- * The SCSI core requires the segment size to cover at least a page, so +- * for 64K page size kernels this must be at least 64K. However the +- * hardware can't handle 64K, so pata_macio_qc_prep() will split large +- * requests. +- */ +- .max_segment_size = SZ_64K, ++ .max_segment_size = PATA_MACIO_MAX_SEGMENT_SIZE, + .device_configure = pata_macio_device_configure, + .sdev_groups = ata_common_sdev_groups, + .can_queue = ATA_DEF_QUEUE, +diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c +index e7f713cd70d3f..a876024d8a05f 100644 +--- a/drivers/atm/idt77252.c ++++ b/drivers/atm/idt77252.c +@@ -1118,8 +1118,8 @@ dequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe) + rpp->len += skb->len; + + if (stat & SAR_RSQE_EPDU) { ++ unsigned int len, truesize; + unsigned char *l1l2; +- unsigned int len; + + l1l2 = (unsigned char *) ((unsigned long) skb->data + skb->len - 6); + +@@ -1189,14 +1189,15 @@ dequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe) + ATM_SKB(skb)->vcc = vcc; + __net_timestamp(skb); + ++ truesize = skb->truesize; + vcc->push(vcc, skb); + atomic_inc(&vcc->stats->rx); + +- if (skb->truesize > SAR_FB_SIZE_3) ++ if (truesize > SAR_FB_SIZE_3) + add_rx_skb(card, 3, SAR_FB_SIZE_3, 1); +- else if (skb->truesize > SAR_FB_SIZE_2) ++ else if (truesize > SAR_FB_SIZE_2) + add_rx_skb(card, 2, SAR_FB_SIZE_2, 1); +- else if (skb->truesize > SAR_FB_SIZE_1) ++ else if (truesize > SAR_FB_SIZE_1) + add_rx_skb(card, 1, SAR_FB_SIZE_1, 1); + else + add_rx_skb(card, 0, SAR_FB_SIZE_0, 1); +diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c +index 93900c37349c1..c084dc88d3d91 100644 +--- a/drivers/bluetooth/btintel.c ++++ b/drivers/bluetooth/btintel.c +@@ -2876,9 +2876,6 @@ static int btintel_setup_combined(struct hci_dev *hdev) + INTEL_ROM_LEGACY_NO_WBS_SUPPORT)) + set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, + &hdev->quirks); +- if (ver.hw_variant == 0x08 && ver.fw_variant == 0x22) +- set_bit(HCI_QUIRK_VALID_LE_STATES, +- &hdev->quirks); + + err = btintel_legacy_rom_setup(hdev, &ver); + break; +@@ -2887,7 +2884,6 @@ static int btintel_setup_combined(struct hci_dev *hdev) + case 0x12: /* ThP */ + case 0x13: /* HrP */ + case 0x14: /* CcP */ +- set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks); + fallthrough; + case 0x0c: /* WsP */ + /* Apply the device specific HCI quirks +@@ -2979,9 +2975,6 @@ static int btintel_setup_combined(struct hci_dev *hdev) + /* These variants don't seem to support LE Coded PHY */ + set_bit(HCI_QUIRK_BROKEN_LE_CODED, &hdev->quirks); + +- /* Set Valid LE States quirk */ +- set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks); +- + /* Setup MSFT Extension support */ + btintel_set_msft_opcode(hdev, ver.hw_variant); + +@@ -3003,9 +2996,6 @@ static int btintel_setup_combined(struct hci_dev *hdev) + */ + set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); + +- /* Apply LE States quirk from solar onwards */ +- set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks); +- + /* Setup MSFT Extension support */ + btintel_set_msft_opcode(hdev, + INTEL_HW_VARIANT(ver_tlv.cnvi_bt)); +diff --git a/drivers/bluetooth/btintel_pcie.c b/drivers/bluetooth/btintel_pcie.c +index b8120b98a2395..1fd3b7073ab90 100644 +--- a/drivers/bluetooth/btintel_pcie.c ++++ b/drivers/bluetooth/btintel_pcie.c +@@ -1182,9 +1182,6 @@ static int btintel_pcie_setup(struct hci_dev *hdev) + */ + set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); + +- /* Apply LE States quirk from solar onwards */ +- set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks); +- + /* Setup MSFT Extension support */ + btintel_set_msft_opcode(hdev, + INTEL_HW_VARIANT(ver_tlv.cnvi_bt)); +diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c +index 8ded9ef8089a2..bc4700ed3b782 100644 +--- a/drivers/bluetooth/btmtksdio.c ++++ b/drivers/bluetooth/btmtksdio.c +@@ -1144,9 +1144,6 @@ static int btmtksdio_setup(struct hci_dev *hdev) + } + } + +- /* Valid LE States quirk for MediaTek 7921 */ +- set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks); +- + break; + case 0x7663: + case 0x7668: +diff --git a/drivers/bluetooth/btrtl.c b/drivers/bluetooth/btrtl.c +index 4f1e37b4f7802..bfcb41a57655f 100644 +--- a/drivers/bluetooth/btrtl.c ++++ b/drivers/bluetooth/btrtl.c +@@ -1287,7 +1287,6 @@ void btrtl_set_quirks(struct hci_dev *hdev, struct btrtl_device_info *btrtl_dev) + case CHIP_ID_8852C: + case CHIP_ID_8851B: + case CHIP_ID_8852BT: +- set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks); + set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); + + /* RTL8852C needs to transmit mSBC data continuously without +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index 789c492df6fa2..0927f51867c26 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -4545,8 +4545,8 @@ static int btusb_probe(struct usb_interface *intf, + if (id->driver_info & BTUSB_WIDEBAND_SPEECH) + set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); + +- if (id->driver_info & BTUSB_VALID_LE_STATES) +- set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks); ++ if (!(id->driver_info & BTUSB_VALID_LE_STATES)) ++ set_bit(HCI_QUIRK_BROKEN_LE_STATES, &hdev->quirks); + + if (id->driver_info & BTUSB_DIGIANSWER) { + data->cmdreq_type = USB_TYPE_VENDOR; +diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c +index 9a0bc86f9aace..34c36f0f781ea 100644 +--- a/drivers/bluetooth/hci_qca.c ++++ b/drivers/bluetooth/hci_qca.c +@@ -2408,8 +2408,8 @@ static int qca_serdev_probe(struct serdev_device *serdev) + set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, + &hdev->quirks); + +- if (data->capabilities & QCA_CAP_VALID_LE_STATES) +- set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks); ++ if (!(data->capabilities & QCA_CAP_VALID_LE_STATES)) ++ set_bit(HCI_QUIRK_BROKEN_LE_STATES, &hdev->quirks); + } + + return 0; +diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c +index 28750a40f0ed5..b652d68f0ee14 100644 +--- a/drivers/bluetooth/hci_vhci.c ++++ b/drivers/bluetooth/hci_vhci.c +@@ -425,8 +425,6 @@ static int __vhci_create_device(struct vhci_data *data, __u8 opcode) + if (opcode & 0x80) + set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); + +- set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks); +- + if (hci_register_dev(hdev) < 0) { + BT_ERR("Can't register HCI device"); + hci_free_dev(hdev); +diff --git a/drivers/char/xillybus/xillyusb.c b/drivers/char/xillybus/xillyusb.c +index 5a5afa14ca8cb..45771b1a3716a 100644 +--- a/drivers/char/xillybus/xillyusb.c ++++ b/drivers/char/xillybus/xillyusb.c +@@ -50,6 +50,7 @@ MODULE_LICENSE("GPL v2"); + static const char xillyname[] = "xillyusb"; + + static unsigned int fifo_buf_order; ++static struct workqueue_struct *wakeup_wq; + + #define USB_VENDOR_ID_XILINX 0x03fd + #define USB_VENDOR_ID_ALTERA 0x09fb +@@ -569,10 +570,6 @@ static void cleanup_dev(struct kref *kref) + * errors if executed. The mechanism relies on that xdev->error is assigned + * a non-zero value by report_io_error() prior to queueing wakeup_all(), + * which prevents bulk_in_work() from calling process_bulk_in(). +- * +- * The fact that wakeup_all() and bulk_in_work() are queued on the same +- * workqueue makes their concurrent execution very unlikely, however the +- * kernel's API doesn't seem to ensure this strictly. + */ + + static void wakeup_all(struct work_struct *work) +@@ -627,7 +624,7 @@ static void report_io_error(struct xillyusb_dev *xdev, + + if (do_once) { + kref_get(&xdev->kref); /* xdev is used by work item */ +- queue_work(xdev->workq, &xdev->wakeup_workitem); ++ queue_work(wakeup_wq, &xdev->wakeup_workitem); + } + } + +@@ -1906,6 +1903,13 @@ static const struct file_operations xillyusb_fops = { + + static int xillyusb_setup_base_eps(struct xillyusb_dev *xdev) + { ++ struct usb_device *udev = xdev->udev; ++ ++ /* Verify that device has the two fundamental bulk in/out endpoints */ ++ if (usb_pipe_type_check(udev, usb_sndbulkpipe(udev, MSG_EP_NUM)) || ++ usb_pipe_type_check(udev, usb_rcvbulkpipe(udev, IN_EP_NUM))) ++ return -ENODEV; ++ + xdev->msg_ep = endpoint_alloc(xdev, MSG_EP_NUM | USB_DIR_OUT, + bulk_out_work, 1, 2); + if (!xdev->msg_ep) +@@ -1935,14 +1939,15 @@ static int setup_channels(struct xillyusb_dev *xdev, + __le16 *chandesc, + int num_channels) + { +- struct xillyusb_channel *chan; ++ struct usb_device *udev = xdev->udev; ++ struct xillyusb_channel *chan, *new_channels; + int i; + + chan = kcalloc(num_channels, sizeof(*chan), GFP_KERNEL); + if (!chan) + return -ENOMEM; + +- xdev->channels = chan; ++ new_channels = chan; + + for (i = 0; i < num_channels; i++, chan++) { + unsigned int in_desc = le16_to_cpu(*chandesc++); +@@ -1971,6 +1976,15 @@ static int setup_channels(struct xillyusb_dev *xdev, + */ + + if ((out_desc & 0x80) && i < 14) { /* Entry is valid */ ++ if (usb_pipe_type_check(udev, ++ usb_sndbulkpipe(udev, i + 2))) { ++ dev_err(xdev->dev, ++ "Missing BULK OUT endpoint %d\n", ++ i + 2); ++ kfree(new_channels); ++ return -ENODEV; ++ } ++ + chan->writable = 1; + chan->out_synchronous = !!(out_desc & 0x40); + chan->out_seekable = !!(out_desc & 0x20); +@@ -1980,6 +1994,7 @@ static int setup_channels(struct xillyusb_dev *xdev, + } + } + ++ xdev->channels = new_channels; + return 0; + } + +@@ -2096,9 +2111,11 @@ static int xillyusb_discovery(struct usb_interface *interface) + * just after responding with the IDT, there is no reason for any + * work item to be running now. To be sure that xdev->channels + * is updated on anything that might run in parallel, flush the +- * workqueue, which rarely does anything. ++ * device's workqueue and the wakeup work item. This rarely ++ * does anything. + */ + flush_workqueue(xdev->workq); ++ flush_work(&xdev->wakeup_workitem); + + xdev->num_channels = num_channels; + +@@ -2258,6 +2275,10 @@ static int __init xillyusb_init(void) + { + int rc = 0; + ++ wakeup_wq = alloc_workqueue(xillyname, 0, 0); ++ if (!wakeup_wq) ++ return -ENOMEM; ++ + if (LOG2_INITIAL_FIFO_BUF_SIZE > PAGE_SHIFT) + fifo_buf_order = LOG2_INITIAL_FIFO_BUF_SIZE - PAGE_SHIFT; + else +@@ -2265,12 +2286,17 @@ static int __init xillyusb_init(void) + + rc = usb_register(&xillyusb_driver); + ++ if (rc) ++ destroy_workqueue(wakeup_wq); ++ + return rc; + } + + static void __exit xillyusb_exit(void) + { + usb_deregister(&xillyusb_driver); ++ ++ destroy_workqueue(wakeup_wq); + } + + module_init(xillyusb_init); +diff --git a/drivers/gpio/gpio-mlxbf3.c b/drivers/gpio/gpio-mlxbf3.c +index d5906d419b0ab..10ea71273c891 100644 +--- a/drivers/gpio/gpio-mlxbf3.c ++++ b/drivers/gpio/gpio-mlxbf3.c +@@ -39,6 +39,8 @@ + #define MLXBF_GPIO_CAUSE_OR_EVTEN0 0x14 + #define MLXBF_GPIO_CAUSE_OR_CLRCAUSE 0x18 + ++#define MLXBF_GPIO_CLR_ALL_INTS GENMASK(31, 0) ++ + struct mlxbf3_gpio_context { + struct gpio_chip gc; + +@@ -82,6 +84,8 @@ static void mlxbf3_gpio_irq_disable(struct irq_data *irqd) + val = readl(gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_EVTEN0); + val &= ~BIT(offset); + writel(val, gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_EVTEN0); ++ ++ writel(BIT(offset), gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_CLRCAUSE); + raw_spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); + + gpiochip_disable_irq(gc, offset); +@@ -253,6 +257,15 @@ static int mlxbf3_gpio_probe(struct platform_device *pdev) + return 0; + } + ++static void mlxbf3_gpio_shutdown(struct platform_device *pdev) ++{ ++ struct mlxbf3_gpio_context *gs = platform_get_drvdata(pdev); ++ ++ /* Disable and clear all interrupts */ ++ writel(0, gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_EVTEN0); ++ writel(MLXBF_GPIO_CLR_ALL_INTS, gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_CLRCAUSE); ++} ++ + static const struct acpi_device_id mlxbf3_gpio_acpi_match[] = { + { "MLNXBF33", 0 }, + {} +@@ -265,6 +278,7 @@ static struct platform_driver mlxbf3_gpio_driver = { + .acpi_match_table = mlxbf3_gpio_acpi_match, + }, + .probe = mlxbf3_gpio_probe, ++ .shutdown = mlxbf3_gpio_shutdown, + }; + module_platform_driver(mlxbf3_gpio_driver); + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +index 13eb2bc69e342..936c98a13a240 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +@@ -1057,6 +1057,9 @@ static int amdgpu_cs_patch_ibs(struct amdgpu_cs_parser *p, + r = amdgpu_ring_parse_cs(ring, p, job, ib); + if (r) + return r; ++ ++ if (ib->sa_bo) ++ ib->gpu_addr = amdgpu_sa_bo_gpu_addr(ib->sa_bo); + } else { + ib->ptr = (uint32_t *)kptr; + r = amdgpu_ring_patch_cs_in_place(ring, p, job, ib); +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +index 5cb33ac99f708..c43d1b6e5d66b 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +@@ -685,16 +685,24 @@ int amdgpu_ctx_ioctl(struct drm_device *dev, void *data, + + switch (args->in.op) { + case AMDGPU_CTX_OP_ALLOC_CTX: ++ if (args->in.flags) ++ return -EINVAL; + r = amdgpu_ctx_alloc(adev, fpriv, filp, priority, &id); + args->out.alloc.ctx_id = id; + break; + case AMDGPU_CTX_OP_FREE_CTX: ++ if (args->in.flags) ++ return -EINVAL; + r = amdgpu_ctx_free(fpriv, id); + break; + case AMDGPU_CTX_OP_QUERY_STATE: ++ if (args->in.flags) ++ return -EINVAL; + r = amdgpu_ctx_query(adev, fpriv, id, &args->out); + break; + case AMDGPU_CTX_OP_QUERY_STATE2: ++ if (args->in.flags) ++ return -EINVAL; + r = amdgpu_ctx_query2(adev, fpriv, id, &args->out); + break; + case AMDGPU_CTX_OP_GET_STABLE_PSTATE: +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c +index 8e8afbd237bcd..9aff579c6abf5 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c +@@ -166,6 +166,9 @@ static ssize_t ta_if_load_debugfs_write(struct file *fp, const char *buf, size_t + if (ret) + return -EFAULT; + ++ if (ta_bin_len > PSP_1_MEG) ++ return -EINVAL; ++ + copy_pos += sizeof(uint32_t); + + ta_bin = kzalloc(ta_bin_len, GFP_KERNEL); +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c +index 677eb141554e0..ceb3f1e4ed1dc 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c +@@ -151,6 +151,10 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev) + } + } + ++ /* from vcn4 and above, only unified queue is used */ ++ adev->vcn.using_unified_queue = ++ amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0); ++ + hdr = (const struct common_firmware_header *)adev->vcn.fw[0]->data; + adev->vcn.fw_version = le32_to_cpu(hdr->ucode_version); + +@@ -279,18 +283,6 @@ int amdgpu_vcn_sw_fini(struct amdgpu_device *adev) + return 0; + } + +-/* from vcn4 and above, only unified queue is used */ +-static bool amdgpu_vcn_using_unified_queue(struct amdgpu_ring *ring) +-{ +- struct amdgpu_device *adev = ring->adev; +- bool ret = false; +- +- if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0)) +- ret = true; +- +- return ret; +-} +- + bool amdgpu_vcn_is_disabled_vcn(struct amdgpu_device *adev, enum vcn_ring_type type, uint32_t vcn_instance) + { + bool ret = false; +@@ -401,7 +393,9 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work) + for (i = 0; i < adev->vcn.num_enc_rings; ++i) + fence[j] += amdgpu_fence_count_emitted(&adev->vcn.inst[j].ring_enc[i]); + +- if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) { ++ /* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */ ++ if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG && ++ !adev->vcn.using_unified_queue) { + struct dpg_pause_state new_state; + + if (fence[j] || +@@ -447,7 +441,9 @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring) + amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN, + AMD_PG_STATE_UNGATE); + +- if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) { ++ /* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */ ++ if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG && ++ !adev->vcn.using_unified_queue) { + struct dpg_pause_state new_state; + + if (ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC) { +@@ -473,8 +469,12 @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring) + + void amdgpu_vcn_ring_end_use(struct amdgpu_ring *ring) + { ++ struct amdgpu_device *adev = ring->adev; ++ ++ /* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */ + if (ring->adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG && +- ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC) ++ ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC && ++ !adev->vcn.using_unified_queue) + atomic_dec(&ring->adev->vcn.inst[ring->me].dpg_enc_submission_cnt); + + atomic_dec(&ring->adev->vcn.total_submission_cnt); +@@ -728,12 +728,11 @@ static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring, + struct amdgpu_job *job; + struct amdgpu_ib *ib; + uint64_t addr = AMDGPU_GPU_PAGE_ALIGN(ib_msg->gpu_addr); +- bool sq = amdgpu_vcn_using_unified_queue(ring); + uint32_t *ib_checksum; + uint32_t ib_pack_in_dw; + int i, r; + +- if (sq) ++ if (adev->vcn.using_unified_queue) + ib_size_dw += 8; + + r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL, +@@ -746,7 +745,7 @@ static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring, + ib->length_dw = 0; + + /* single queue headers */ +- if (sq) { ++ if (adev->vcn.using_unified_queue) { + ib_pack_in_dw = sizeof(struct amdgpu_vcn_decode_buffer) / sizeof(uint32_t) + + 4 + 2; /* engine info + decoding ib in dw */ + ib_checksum = amdgpu_vcn_unified_ring_ib_header(ib, ib_pack_in_dw, false); +@@ -765,7 +764,7 @@ static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring, + for (i = ib->length_dw; i < ib_size_dw; ++i) + ib->ptr[i] = 0x0; + +- if (sq) ++ if (adev->vcn.using_unified_queue) + amdgpu_vcn_unified_ring_ib_checksum(&ib_checksum, ib_pack_in_dw); + + r = amdgpu_job_submit_direct(job, ring, &f); +@@ -855,15 +854,15 @@ static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t hand + struct dma_fence **fence) + { + unsigned int ib_size_dw = 16; ++ struct amdgpu_device *adev = ring->adev; + struct amdgpu_job *job; + struct amdgpu_ib *ib; + struct dma_fence *f = NULL; + uint32_t *ib_checksum = NULL; + uint64_t addr; +- bool sq = amdgpu_vcn_using_unified_queue(ring); + int i, r; + +- if (sq) ++ if (adev->vcn.using_unified_queue) + ib_size_dw += 8; + + r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL, +@@ -877,7 +876,7 @@ static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t hand + + ib->length_dw = 0; + +- if (sq) ++ if (adev->vcn.using_unified_queue) + ib_checksum = amdgpu_vcn_unified_ring_ib_header(ib, 0x11, true); + + ib->ptr[ib->length_dw++] = 0x00000018; +@@ -899,7 +898,7 @@ static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t hand + for (i = ib->length_dw; i < ib_size_dw; ++i) + ib->ptr[i] = 0x0; + +- if (sq) ++ if (adev->vcn.using_unified_queue) + amdgpu_vcn_unified_ring_ib_checksum(&ib_checksum, 0x11); + + r = amdgpu_job_submit_direct(job, ring, &f); +@@ -922,15 +921,15 @@ static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han + struct dma_fence **fence) + { + unsigned int ib_size_dw = 16; ++ struct amdgpu_device *adev = ring->adev; + struct amdgpu_job *job; + struct amdgpu_ib *ib; + struct dma_fence *f = NULL; + uint32_t *ib_checksum = NULL; + uint64_t addr; +- bool sq = amdgpu_vcn_using_unified_queue(ring); + int i, r; + +- if (sq) ++ if (adev->vcn.using_unified_queue) + ib_size_dw += 8; + + r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL, +@@ -944,7 +943,7 @@ static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han + + ib->length_dw = 0; + +- if (sq) ++ if (adev->vcn.using_unified_queue) + ib_checksum = amdgpu_vcn_unified_ring_ib_header(ib, 0x11, true); + + ib->ptr[ib->length_dw++] = 0x00000018; +@@ -966,7 +965,7 @@ static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han + for (i = ib->length_dw; i < ib_size_dw; ++i) + ib->ptr[i] = 0x0; + +- if (sq) ++ if (adev->vcn.using_unified_queue) + amdgpu_vcn_unified_ring_ib_checksum(&ib_checksum, 0x11); + + r = amdgpu_job_submit_direct(job, ring, &f); +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h +index 9f06def236fdc..1a5439abd1a04 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h +@@ -329,6 +329,7 @@ struct amdgpu_vcn { + + uint16_t inst_mask; + uint8_t num_inst_per_aid; ++ bool using_unified_queue; + }; + + struct amdgpu_fw_shared_rb_ptrs_struct { +diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c +index ef3e42f6b8411..63f84ef6dfcf2 100644 +--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c +@@ -543,11 +543,11 @@ void jpeg_v2_0_dec_ring_emit_ib(struct amdgpu_ring *ring, + + amdgpu_ring_write(ring, PACKETJ(mmUVD_LMI_JRBC_IB_VMID_INTERNAL_OFFSET, + 0, 0, PACKETJ_TYPE0)); +- amdgpu_ring_write(ring, (vmid | (vmid << 4))); ++ amdgpu_ring_write(ring, (vmid | (vmid << 4) | (vmid << 8))); + + amdgpu_ring_write(ring, PACKETJ(mmUVD_LMI_JPEG_VMID_INTERNAL_OFFSET, + 0, 0, PACKETJ_TYPE0)); +- amdgpu_ring_write(ring, (vmid | (vmid << 4))); ++ amdgpu_ring_write(ring, (vmid | (vmid << 4) | (vmid << 8))); + + amdgpu_ring_write(ring, PACKETJ(mmUVD_LMI_JRBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET, + 0, 0, PACKETJ_TYPE0)); +diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c +index d66af11aa66c7..d24d06f6d682a 100644 +--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c ++++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c +@@ -23,6 +23,7 @@ + + #include "amdgpu.h" + #include "amdgpu_jpeg.h" ++#include "amdgpu_cs.h" + #include "soc15.h" + #include "soc15d.h" + #include "jpeg_v4_0_3.h" +@@ -773,11 +774,15 @@ void jpeg_v4_0_3_dec_ring_emit_ib(struct amdgpu_ring *ring, + + amdgpu_ring_write(ring, PACKETJ(regUVD_LMI_JRBC_IB_VMID_INTERNAL_OFFSET, + 0, 0, PACKETJ_TYPE0)); +- amdgpu_ring_write(ring, (vmid | (vmid << 4))); ++ ++ if (ring->funcs->parse_cs) ++ amdgpu_ring_write(ring, 0); ++ else ++ amdgpu_ring_write(ring, (vmid | (vmid << 4) | (vmid << 8))); + + amdgpu_ring_write(ring, PACKETJ(regUVD_LMI_JPEG_VMID_INTERNAL_OFFSET, + 0, 0, PACKETJ_TYPE0)); +- amdgpu_ring_write(ring, (vmid | (vmid << 4))); ++ amdgpu_ring_write(ring, (vmid | (vmid << 4) | (vmid << 8))); + + amdgpu_ring_write(ring, PACKETJ(regUVD_LMI_JRBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET, + 0, 0, PACKETJ_TYPE0)); +@@ -1063,6 +1068,7 @@ static const struct amdgpu_ring_funcs jpeg_v4_0_3_dec_ring_vm_funcs = { + .get_rptr = jpeg_v4_0_3_dec_ring_get_rptr, + .get_wptr = jpeg_v4_0_3_dec_ring_get_wptr, + .set_wptr = jpeg_v4_0_3_dec_ring_set_wptr, ++ .parse_cs = jpeg_v4_0_3_dec_ring_parse_cs, + .emit_frame_size = + SOC15_FLUSH_GPU_TLB_NUM_WREG * 6 + + SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 8 + +@@ -1227,3 +1233,56 @@ static void jpeg_v4_0_3_set_ras_funcs(struct amdgpu_device *adev) + { + adev->jpeg.ras = &jpeg_v4_0_3_ras; + } ++ ++/** ++ * jpeg_v4_0_3_dec_ring_parse_cs - command submission parser ++ * ++ * @parser: Command submission parser context ++ * @job: the job to parse ++ * @ib: the IB to parse ++ * ++ * Parse the command stream, return -EINVAL for invalid packet, ++ * 0 otherwise ++ */ ++int jpeg_v4_0_3_dec_ring_parse_cs(struct amdgpu_cs_parser *parser, ++ struct amdgpu_job *job, ++ struct amdgpu_ib *ib) ++{ ++ uint32_t i, reg, res, cond, type; ++ struct amdgpu_device *adev = parser->adev; ++ ++ for (i = 0; i < ib->length_dw ; i += 2) { ++ reg = CP_PACKETJ_GET_REG(ib->ptr[i]); ++ res = CP_PACKETJ_GET_RES(ib->ptr[i]); ++ cond = CP_PACKETJ_GET_COND(ib->ptr[i]); ++ type = CP_PACKETJ_GET_TYPE(ib->ptr[i]); ++ ++ if (res) /* only support 0 at the moment */ ++ return -EINVAL; ++ ++ switch (type) { ++ case PACKETJ_TYPE0: ++ if (cond != PACKETJ_CONDITION_CHECK0 || reg < JPEG_REG_RANGE_START || reg > JPEG_REG_RANGE_END) { ++ dev_err(adev->dev, "Invalid packet [0x%08x]!\n", ib->ptr[i]); ++ return -EINVAL; ++ } ++ break; ++ case PACKETJ_TYPE3: ++ if (cond != PACKETJ_CONDITION_CHECK3 || reg < JPEG_REG_RANGE_START || reg > JPEG_REG_RANGE_END) { ++ dev_err(adev->dev, "Invalid packet [0x%08x]!\n", ib->ptr[i]); ++ return -EINVAL; ++ } ++ break; ++ case PACKETJ_TYPE6: ++ if (ib->ptr[i] == CP_PACKETJ_NOP) ++ continue; ++ dev_err(adev->dev, "Invalid packet [0x%08x]!\n", ib->ptr[i]); ++ return -EINVAL; ++ default: ++ dev_err(adev->dev, "Unknown packet type %d !\n", type); ++ return -EINVAL; ++ } ++ } ++ ++ return 0; ++} +diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.h b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.h +index 747a3e5f68564..71c54b294e157 100644 +--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.h ++++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.h +@@ -46,6 +46,9 @@ + + #define JRBC_DEC_EXTERNAL_REG_WRITE_ADDR 0x18000 + ++#define JPEG_REG_RANGE_START 0x4000 ++#define JPEG_REG_RANGE_END 0x41c2 ++ + extern const struct amdgpu_ip_block_version jpeg_v4_0_3_ip_block; + + void jpeg_v4_0_3_dec_ring_emit_ib(struct amdgpu_ring *ring, +@@ -62,5 +65,7 @@ void jpeg_v4_0_3_dec_ring_insert_end(struct amdgpu_ring *ring); + void jpeg_v4_0_3_dec_ring_emit_wreg(struct amdgpu_ring *ring, uint32_t reg, uint32_t val); + void jpeg_v4_0_3_dec_ring_emit_reg_wait(struct amdgpu_ring *ring, uint32_t reg, + uint32_t val, uint32_t mask); +- ++int jpeg_v4_0_3_dec_ring_parse_cs(struct amdgpu_cs_parser *parser, ++ struct amdgpu_job *job, ++ struct amdgpu_ib *ib); + #endif /* __JPEG_V4_0_3_H__ */ +diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c +index 64c856bfe0cbb..90299f66a4445 100644 +--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c +@@ -523,6 +523,7 @@ static const struct amdgpu_ring_funcs jpeg_v5_0_0_dec_ring_vm_funcs = { + .get_rptr = jpeg_v5_0_0_dec_ring_get_rptr, + .get_wptr = jpeg_v5_0_0_dec_ring_get_wptr, + .set_wptr = jpeg_v5_0_0_dec_ring_set_wptr, ++ .parse_cs = jpeg_v4_0_3_dec_ring_parse_cs, + .emit_frame_size = + SOC15_FLUSH_GPU_TLB_NUM_WREG * 6 + + SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 8 + +diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c +index af1e90159ce36..2e72d445415f9 100644 +--- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c ++++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c +@@ -176,14 +176,16 @@ static void sdma_v5_2_ring_set_wptr(struct amdgpu_ring *ring) + DRM_DEBUG("calling WDOORBELL64(0x%08x, 0x%016llx)\n", + ring->doorbell_index, ring->wptr << 2); + WDOORBELL64(ring->doorbell_index, ring->wptr << 2); +- /* SDMA seems to miss doorbells sometimes when powergating kicks in. +- * Updating the wptr directly will wake it. This is only safe because +- * we disallow gfxoff in begin_use() and then allow it again in end_use(). +- */ +- WREG32(sdma_v5_2_get_reg_offset(adev, ring->me, mmSDMA0_GFX_RB_WPTR), +- lower_32_bits(ring->wptr << 2)); +- WREG32(sdma_v5_2_get_reg_offset(adev, ring->me, mmSDMA0_GFX_RB_WPTR_HI), +- upper_32_bits(ring->wptr << 2)); ++ if (amdgpu_ip_version(adev, SDMA0_HWIP, 0) == IP_VERSION(5, 2, 1)) { ++ /* SDMA seems to miss doorbells sometimes when powergating kicks in. ++ * Updating the wptr directly will wake it. This is only safe because ++ * we disallow gfxoff in begin_use() and then allow it again in end_use(). ++ */ ++ WREG32(sdma_v5_2_get_reg_offset(adev, ring->me, mmSDMA0_GFX_RB_WPTR), ++ lower_32_bits(ring->wptr << 2)); ++ WREG32(sdma_v5_2_get_reg_offset(adev, ring->me, mmSDMA0_GFX_RB_WPTR_HI), ++ upper_32_bits(ring->wptr << 2)); ++ } + } else { + DRM_DEBUG("Not using doorbell -- " + "mmSDMA%i_GFX_RB_WPTR == 0x%08x " +diff --git a/drivers/gpu/drm/amd/amdgpu/soc15d.h b/drivers/gpu/drm/amd/amdgpu/soc15d.h +index 2357ff39323f0..e74e1983da53a 100644 +--- a/drivers/gpu/drm/amd/amdgpu/soc15d.h ++++ b/drivers/gpu/drm/amd/amdgpu/soc15d.h +@@ -76,6 +76,12 @@ + ((cond & 0xF) << 24) | \ + ((type & 0xF) << 28)) + ++#define CP_PACKETJ_NOP 0x60000000 ++#define CP_PACKETJ_GET_REG(x) ((x) & 0x3FFFF) ++#define CP_PACKETJ_GET_RES(x) (((x) >> 18) & 0x3F) ++#define CP_PACKETJ_GET_COND(x) (((x) >> 24) & 0xF) ++#define CP_PACKETJ_GET_TYPE(x) (((x) >> 28) & 0xF) ++ + /* Packet 3 types */ + #define PACKET3_NOP 0x10 + #define PACKET3_SET_BASE 0x11 +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 836bf9ba620d1..8d4ad15b8e171 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -2724,6 +2724,9 @@ static int dm_suspend(void *handle) + + hpd_rx_irq_work_suspend(dm); + ++ if (adev->dm.dc->caps.ips_support) ++ dc_allow_idle_optimizations(adev->dm.dc, true); ++ + dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D3); + dc_dmub_srv_set_power_state(dm->dc->ctx->dmub_srv, DC_ACPI_CM_POWER_STATE_D3); + +@@ -6559,12 +6562,34 @@ static const struct attribute_group amdgpu_group = { + .attrs = amdgpu_attrs + }; + ++static bool ++amdgpu_dm_should_create_sysfs(struct amdgpu_dm_connector *amdgpu_dm_connector) ++{ ++ if (amdgpu_dm_abm_level >= 0) ++ return false; ++ ++ if (amdgpu_dm_connector->base.connector_type != DRM_MODE_CONNECTOR_eDP) ++ return false; ++ ++ /* check for OLED panels */ ++ if (amdgpu_dm_connector->bl_idx >= 0) { ++ struct drm_device *drm = amdgpu_dm_connector->base.dev; ++ struct amdgpu_display_manager *dm = &drm_to_adev(drm)->dm; ++ struct amdgpu_dm_backlight_caps *caps; ++ ++ caps = &dm->backlight_caps[amdgpu_dm_connector->bl_idx]; ++ if (caps->aux_support) ++ return false; ++ } ++ ++ return true; ++} ++ + static void amdgpu_dm_connector_unregister(struct drm_connector *connector) + { + struct amdgpu_dm_connector *amdgpu_dm_connector = to_amdgpu_dm_connector(connector); + +- if (connector->connector_type == DRM_MODE_CONNECTOR_eDP && +- amdgpu_dm_abm_level < 0) ++ if (amdgpu_dm_should_create_sysfs(amdgpu_dm_connector)) + sysfs_remove_group(&connector->kdev->kobj, &amdgpu_group); + + drm_dp_aux_unregister(&amdgpu_dm_connector->dm_dp_aux.aux); +@@ -6671,8 +6696,7 @@ amdgpu_dm_connector_late_register(struct drm_connector *connector) + to_amdgpu_dm_connector(connector); + int r; + +- if (connector->connector_type == DRM_MODE_CONNECTOR_eDP && +- amdgpu_dm_abm_level < 0) { ++ if (amdgpu_dm_should_create_sysfs(amdgpu_dm_connector)) { + r = sysfs_create_group(&connector->kdev->kobj, + &amdgpu_group); + if (r) +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c +index 3306684e805ac..872f994dd356e 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c +@@ -3605,7 +3605,7 @@ void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx) + (int)hubp->curs_attr.width || pos_cpy.x + <= (int)hubp->curs_attr.width + + pipe_ctx->plane_state->src_rect.x) { +- pos_cpy.x = temp_x + viewport_width; ++ pos_cpy.x = 2 * viewport_width - temp_x; + } + } + } else { +@@ -3698,7 +3698,7 @@ void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx) + (int)hubp->curs_attr.width || pos_cpy.x + <= (int)hubp->curs_attr.width + + pipe_ctx->plane_state->src_rect.x) { +- pos_cpy.x = 2 * viewport_width - temp_x; ++ pos_cpy.x = temp_x + viewport_width; + } + } + } else { +diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c +index 9a3cc0514a36e..8e0588b1cf305 100644 +--- a/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c +@@ -1778,6 +1778,9 @@ static bool dcn321_resource_construct( + dc->caps.color.mpc.ogam_rom_caps.hlg = 0; + dc->caps.color.mpc.ocsc = 1; + ++ /* Use pipe context based otg sync logic */ ++ dc->config.use_pipe_ctx_sync_logic = true; ++ + dc->config.dc_mode_clk_limit_support = true; + dc->config.enable_windowed_mpo_odm = true; + /* read VBIOS LTTPR caps */ +diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c +index 92b03073acdd5..555428606e127 100644 +--- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c ++++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c +@@ -39,7 +39,9 @@ static u32 transcoder_to_stream_enc_status(enum transcoder cpu_transcoder) + static void intel_dp_hdcp_wait_for_cp_irq(struct intel_connector *connector, + int timeout) + { +- struct intel_hdcp *hdcp = &connector->hdcp; ++ struct intel_digital_port *dig_port = intel_attached_dig_port(connector); ++ struct intel_dp *dp = &dig_port->dp; ++ struct intel_hdcp *hdcp = &dp->attached_connector->hdcp; + long ret; + + #define C (hdcp->cp_irq_count_cached != atomic_read(&hdcp->cp_irq_count)) +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +index 697ad4a640516..a6c5e3bc9bf15 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +@@ -1179,8 +1179,6 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc, + + cstate->num_mixers = num_lm; + +- dpu_enc->connector = conn_state->connector; +- + for (i = 0; i < dpu_enc->num_phys_encs; i++) { + struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i]; + +@@ -1277,6 +1275,8 @@ static void dpu_encoder_virt_atomic_enable(struct drm_encoder *drm_enc, + + dpu_enc->commit_done_timedout = false; + ++ dpu_enc->connector = drm_atomic_get_new_connector_for_encoder(state, drm_enc); ++ + cur_mode = &dpu_enc->base.crtc->state->adjusted_mode; + + dpu_enc->wide_bus_en = dpu_encoder_is_widebus_enabled(drm_enc); +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +index 9b72977feafa4..e61b5681f3bbd 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +@@ -308,8 +308,8 @@ static const u32 wb2_formats_rgb_yuv[] = { + { \ + .maxdwnscale = SSPP_UNITY_SCALE, \ + .maxupscale = SSPP_UNITY_SCALE, \ +- .format_list = plane_formats_yuv, \ +- .num_formats = ARRAY_SIZE(plane_formats_yuv), \ ++ .format_list = plane_formats, \ ++ .num_formats = ARRAY_SIZE(plane_formats), \ + .virt_format_list = plane_formats, \ + .virt_num_formats = ARRAY_SIZE(plane_formats), \ + } +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h +index e2adc937ea63b..935ff6fd172c4 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h +@@ -31,24 +31,14 @@ + * @fmt: Pointer to format string + */ + #define DPU_DEBUG(fmt, ...) \ +- do { \ +- if (drm_debug_enabled(DRM_UT_KMS)) \ +- DRM_DEBUG(fmt, ##__VA_ARGS__); \ +- else \ +- pr_debug(fmt, ##__VA_ARGS__); \ +- } while (0) ++ DRM_DEBUG_DRIVER(fmt, ##__VA_ARGS__) + + /** + * DPU_DEBUG_DRIVER - macro for hardware driver logging + * @fmt: Pointer to format string + */ + #define DPU_DEBUG_DRIVER(fmt, ...) \ +- do { \ +- if (drm_debug_enabled(DRM_UT_DRIVER)) \ +- DRM_ERROR(fmt, ##__VA_ARGS__); \ +- else \ +- pr_debug(fmt, ##__VA_ARGS__); \ +- } while (0) ++ DRM_DEBUG_DRIVER(fmt, ##__VA_ARGS__) + + #define DPU_ERROR(fmt, ...) pr_err("[dpu error]" fmt, ##__VA_ARGS__) + #define DPU_ERROR_RATELIMITED(fmt, ...) pr_err_ratelimited("[dpu error]" fmt, ##__VA_ARGS__) +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +index 1c3a2657450c6..c31d283d1c6c1 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +@@ -680,6 +680,9 @@ static int dpu_plane_prepare_fb(struct drm_plane *plane, + new_state->fb, &layout); + if (ret) { + DPU_ERROR_PLANE(pdpu, "failed to get format layout, %d\n", ret); ++ if (pstate->aspace) ++ msm_framebuffer_cleanup(new_state->fb, pstate->aspace, ++ pstate->needs_dirtyfb); + return ret; + } + +@@ -743,10 +746,9 @@ static int dpu_plane_atomic_check_pipe(struct dpu_plane *pdpu, + min_src_size = MSM_FORMAT_IS_YUV(fmt) ? 2 : 1; + + if (MSM_FORMAT_IS_YUV(fmt) && +- (!pipe->sspp->cap->sblk->scaler_blk.len || +- !pipe->sspp->cap->sblk->csc_blk.len)) { ++ !pipe->sspp->cap->sblk->csc_blk.len) { + DPU_DEBUG_PLANE(pdpu, +- "plane doesn't have scaler/csc for yuv\n"); ++ "plane doesn't have csc for yuv\n"); + return -EINVAL; + } + +@@ -863,6 +865,10 @@ static int dpu_plane_atomic_check(struct drm_plane *plane, + + max_linewidth = pdpu->catalog->caps->max_linewidth; + ++ drm_rect_rotate(&pipe_cfg->src_rect, ++ new_plane_state->fb->width, new_plane_state->fb->height, ++ new_plane_state->rotation); ++ + if ((drm_rect_width(&pipe_cfg->src_rect) > max_linewidth) || + _dpu_plane_calc_clk(&crtc_state->adjusted_mode, pipe_cfg) > max_mdp_clk_rate) { + /* +@@ -912,6 +918,14 @@ static int dpu_plane_atomic_check(struct drm_plane *plane, + r_pipe_cfg->dst_rect.x1 = pipe_cfg->dst_rect.x2; + } + ++ drm_rect_rotate_inv(&pipe_cfg->src_rect, ++ new_plane_state->fb->width, new_plane_state->fb->height, ++ new_plane_state->rotation); ++ if (r_pipe->sspp) ++ drm_rect_rotate_inv(&r_pipe_cfg->src_rect, ++ new_plane_state->fb->width, new_plane_state->fb->height, ++ new_plane_state->rotation); ++ + ret = dpu_plane_atomic_check_pipe(pdpu, pipe, pipe_cfg, fmt, &crtc_state->adjusted_mode); + if (ret) + return ret; +diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c +index 7bc8a9f0657a9..f342fc5ae41ec 100644 +--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c ++++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c +@@ -1286,6 +1286,8 @@ static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl, + link_info.rate = ctrl->link->link_params.rate; + link_info.capabilities = DP_LINK_CAP_ENHANCED_FRAMING; + ++ dp_link_reset_phy_params_vx_px(ctrl->link); ++ + dp_aux_link_configure(ctrl->aux, &link_info); + + if (drm_dp_max_downspread(dpcd)) +diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c +index 07db8f37cd06a..017fb8cc8ab67 100644 +--- a/drivers/gpu/drm/msm/dp/dp_panel.c ++++ b/drivers/gpu/drm/msm/dp/dp_panel.c +@@ -90,22 +90,22 @@ static int dp_panel_read_dpcd(struct dp_panel *dp_panel) + static u32 dp_panel_get_supported_bpp(struct dp_panel *dp_panel, + u32 mode_edid_bpp, u32 mode_pclk_khz) + { +- struct dp_link_info *link_info; ++ const struct dp_link_info *link_info; + const u32 max_supported_bpp = 30, min_supported_bpp = 18; +- u32 bpp = 0, data_rate_khz = 0; ++ u32 bpp, data_rate_khz; + +- bpp = min_t(u32, mode_edid_bpp, max_supported_bpp); ++ bpp = min(mode_edid_bpp, max_supported_bpp); + + link_info = &dp_panel->link_info; + data_rate_khz = link_info->num_lanes * link_info->rate * 8; + +- while (bpp > min_supported_bpp) { ++ do { + if (mode_pclk_khz * bpp <= data_rate_khz) +- break; ++ return bpp; + bpp -= 6; +- } ++ } while (bpp > min_supported_bpp); + +- return bpp; ++ return min_supported_bpp; + } + + static int dp_panel_update_modes(struct drm_connector *connector, +@@ -442,8 +442,9 @@ int dp_panel_init_panel_info(struct dp_panel *dp_panel) + drm_mode->clock); + drm_dbg_dp(panel->drm_dev, "bpp = %d\n", dp_panel->dp_mode.bpp); + +- dp_panel->dp_mode.bpp = max_t(u32, 18, +- min_t(u32, dp_panel->dp_mode.bpp, 30)); ++ dp_panel->dp_mode.bpp = dp_panel_get_mode_bpp(dp_panel, dp_panel->dp_mode.bpp, ++ dp_panel->dp_mode.drm_mode.clock); ++ + drm_dbg_dp(panel->drm_dev, "updated bpp = %d\n", + dp_panel->dp_mode.bpp); + +diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c +index fab6ad4e5107c..ec75274178028 100644 +--- a/drivers/gpu/drm/msm/msm_mdss.c ++++ b/drivers/gpu/drm/msm/msm_mdss.c +@@ -577,7 +577,7 @@ static const struct msm_mdss_data sc7180_data = { + .ubwc_enc_version = UBWC_2_0, + .ubwc_dec_version = UBWC_2_0, + .ubwc_static = 0x1e, +- .highest_bank_bit = 0x3, ++ .highest_bank_bit = 0x1, + .reg_bus_bw = 76800, + }; + +diff --git a/drivers/gpu/drm/nouveau/nvkm/core/firmware.c b/drivers/gpu/drm/nouveau/nvkm/core/firmware.c +index adc60b25f8e6c..0af01a0ec6016 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/core/firmware.c ++++ b/drivers/gpu/drm/nouveau/nvkm/core/firmware.c +@@ -205,7 +205,8 @@ nvkm_firmware_dtor(struct nvkm_firmware *fw) + break; + case NVKM_FIRMWARE_IMG_DMA: + nvkm_memory_unref(&memory); +- dma_free_coherent(fw->device->dev, sg_dma_len(&fw->mem.sgl), fw->img, fw->phys); ++ dma_free_noncoherent(fw->device->dev, sg_dma_len(&fw->mem.sgl), ++ fw->img, fw->phys, DMA_TO_DEVICE); + break; + case NVKM_FIRMWARE_IMG_SGT: + nvkm_memory_unref(&memory); +@@ -236,10 +237,12 @@ nvkm_firmware_ctor(const struct nvkm_firmware_func *func, const char *name, + break; + case NVKM_FIRMWARE_IMG_DMA: { + dma_addr_t addr; +- + len = ALIGN(fw->len, PAGE_SIZE); + +- fw->img = dma_alloc_coherent(fw->device->dev, len, &addr, GFP_KERNEL); ++ fw->img = dma_alloc_noncoherent(fw->device->dev, ++ len, &addr, ++ DMA_TO_DEVICE, ++ GFP_KERNEL); + if (fw->img) { + memcpy(fw->img, src, fw->len); + fw->phys = addr; +diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/fw.c b/drivers/gpu/drm/nouveau/nvkm/falcon/fw.c +index 80a480b121746..a1c8545f1249a 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/falcon/fw.c ++++ b/drivers/gpu/drm/nouveau/nvkm/falcon/fw.c +@@ -89,6 +89,12 @@ nvkm_falcon_fw_boot(struct nvkm_falcon_fw *fw, struct nvkm_subdev *user, + nvkm_falcon_fw_dtor_sigs(fw); + } + ++ /* after last write to the img, sync dma mappings */ ++ dma_sync_single_for_device(fw->fw.device->dev, ++ fw->fw.phys, ++ sg_dma_len(&fw->fw.mem.sgl), ++ DMA_TO_DEVICE); ++ + FLCNFW_DBG(fw, "resetting"); + fw->func->reset(fw); + +diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c +index 30d5366d62883..0132403b8159f 100644 +--- a/drivers/gpu/drm/v3d/v3d_sched.c ++++ b/drivers/gpu/drm/v3d/v3d_sched.c +@@ -315,7 +315,7 @@ v3d_csd_job_run(struct drm_sched_job *sched_job) + struct v3d_dev *v3d = job->base.v3d; + struct drm_device *dev = &v3d->drm; + struct dma_fence *fence; +- int i, csd_cfg0_reg, csd_cfg_reg_count; ++ int i, csd_cfg0_reg; + + v3d->csd_job = job; + +@@ -335,9 +335,17 @@ v3d_csd_job_run(struct drm_sched_job *sched_job) + v3d_switch_perfmon(v3d, &job->base); + + csd_cfg0_reg = V3D_CSD_QUEUED_CFG0(v3d->ver); +- csd_cfg_reg_count = v3d->ver < 71 ? 6 : 7; +- for (i = 1; i <= csd_cfg_reg_count; i++) ++ for (i = 1; i <= 6; i++) + V3D_CORE_WRITE(0, csd_cfg0_reg + 4 * i, job->args.cfg[i]); ++ ++ /* Although V3D 7.1 has an eighth configuration register, we are not ++ * using it. Therefore, make sure it remains unused. ++ * ++ * XXX: Set the CFG7 register ++ */ ++ if (v3d->ver >= 71) ++ V3D_CORE_WRITE(0, V3D_V7_CSD_QUEUED_CFG7, 0); ++ + /* CFG0 write kicks off the job. */ + V3D_CORE_WRITE(0, csd_cfg0_reg, job->args.cfg[0]); + +diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c +index 0de0566e5b394..7cdc03dc40ed9 100644 +--- a/drivers/gpu/drm/xe/display/xe_display.c ++++ b/drivers/gpu/drm/xe/display/xe_display.c +@@ -134,7 +134,7 @@ static void xe_display_fini_noirq(struct drm_device *dev, void *dummy) + return; + + intel_display_driver_remove_noirq(xe); +- intel_power_domains_driver_remove(xe); ++ intel_opregion_cleanup(xe); + } + + int xe_display_init_noirq(struct xe_device *xe) +@@ -160,8 +160,10 @@ int xe_display_init_noirq(struct xe_device *xe) + intel_display_device_info_runtime_init(xe); + + err = intel_display_driver_probe_noirq(xe); +- if (err) ++ if (err) { ++ intel_opregion_cleanup(xe); + return err; ++ } + + return drmm_add_action_or_reset(&xe->drm, xe_display_fini_noirq, NULL); + } +diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c +index 5ef9b50a20d01..a1cbdafbff75e 100644 +--- a/drivers/gpu/drm/xe/xe_device.c ++++ b/drivers/gpu/drm/xe/xe_device.c +@@ -551,7 +551,9 @@ int xe_device_probe(struct xe_device *xe) + if (err) + return err; + +- xe_mmio_probe_tiles(xe); ++ err = xe_mmio_probe_tiles(xe); ++ if (err) ++ return err; + + xe_ttm_sys_mgr_init(xe); + +diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c +index 395de93579fa6..2ae4420e29353 100644 +--- a/drivers/gpu/drm/xe/xe_exec_queue.c ++++ b/drivers/gpu/drm/xe/xe_exec_queue.c +@@ -96,17 +96,11 @@ static struct xe_exec_queue *__xe_exec_queue_alloc(struct xe_device *xe, + } + } + +- if (xe_exec_queue_is_parallel(q)) { +- q->parallel.composite_fence_ctx = dma_fence_context_alloc(1); +- q->parallel.composite_fence_seqno = XE_FENCE_INITIAL_SEQNO; +- } +- + return q; + } + + static int __xe_exec_queue_init(struct xe_exec_queue *q) + { +- struct xe_device *xe = gt_to_xe(q->gt); + int i, err; + + for (i = 0; i < q->width; ++i) { +@@ -119,17 +113,6 @@ static int __xe_exec_queue_init(struct xe_exec_queue *q) + if (err) + goto err_lrc; + +- /* +- * Normally the user vm holds an rpm ref to keep the device +- * awake, and the context holds a ref for the vm, however for +- * some engines we use the kernels migrate vm underneath which offers no +- * such rpm ref, or we lack a vm. Make sure we keep a ref here, so we +- * can perform GuC CT actions when needed. Caller is expected to have +- * already grabbed the rpm ref outside any sensitive locks. +- */ +- if (!(q->flags & EXEC_QUEUE_FLAG_PERMANENT) && (q->flags & EXEC_QUEUE_FLAG_VM || !q->vm)) +- xe_pm_runtime_get_noresume(xe); +- + return 0; + + err_lrc: +@@ -216,8 +199,6 @@ void xe_exec_queue_fini(struct xe_exec_queue *q) + + for (i = 0; i < q->width; ++i) + xe_lrc_finish(q->lrc + i); +- if (!(q->flags & EXEC_QUEUE_FLAG_PERMANENT) && (q->flags & EXEC_QUEUE_FLAG_VM || !q->vm)) +- xe_pm_runtime_put(gt_to_xe(q->gt)); + __xe_exec_queue_free(q); + } + +diff --git a/drivers/gpu/drm/xe/xe_exec_queue_types.h b/drivers/gpu/drm/xe/xe_exec_queue_types.h +index ee78d497d838a..f0c40e8ad80a1 100644 +--- a/drivers/gpu/drm/xe/xe_exec_queue_types.h ++++ b/drivers/gpu/drm/xe/xe_exec_queue_types.h +@@ -103,16 +103,6 @@ struct xe_exec_queue { + struct xe_guc_exec_queue *guc; + }; + +- /** +- * @parallel: parallel submission state +- */ +- struct { +- /** @parallel.composite_fence_ctx: context composite fence */ +- u64 composite_fence_ctx; +- /** @parallel.composite_fence_seqno: seqno for composite fence */ +- u32 composite_fence_seqno; +- } parallel; +- + /** @sched_props: scheduling properties */ + struct { + /** @sched_props.timeslice_us: timeslice period in micro-seconds */ +diff --git a/drivers/gpu/drm/xe/xe_gt_pagefault.c b/drivers/gpu/drm/xe/xe_gt_pagefault.c +index fa9e9853c53ba..67e8efcaa93f1 100644 +--- a/drivers/gpu/drm/xe/xe_gt_pagefault.c ++++ b/drivers/gpu/drm/xe/xe_gt_pagefault.c +@@ -402,6 +402,18 @@ static void pf_queue_work_func(struct work_struct *w) + + static void acc_queue_work_func(struct work_struct *w); + ++static void pagefault_fini(void *arg) ++{ ++ struct xe_gt *gt = arg; ++ struct xe_device *xe = gt_to_xe(gt); ++ ++ if (!xe->info.has_usm) ++ return; ++ ++ destroy_workqueue(gt->usm.acc_wq); ++ destroy_workqueue(gt->usm.pf_wq); ++} ++ + int xe_gt_pagefault_init(struct xe_gt *gt) + { + struct xe_device *xe = gt_to_xe(gt); +@@ -429,10 +441,12 @@ int xe_gt_pagefault_init(struct xe_gt *gt) + gt->usm.acc_wq = alloc_workqueue("xe_gt_access_counter_work_queue", + WQ_UNBOUND | WQ_HIGHPRI, + NUM_ACC_QUEUE); +- if (!gt->usm.acc_wq) ++ if (!gt->usm.acc_wq) { ++ destroy_workqueue(gt->usm.pf_wq); + return -ENOMEM; ++ } + +- return 0; ++ return devm_add_action_or_reset(xe->drm.dev, pagefault_fini, gt); + } + + void xe_gt_pagefault_reset(struct xe_gt *gt) +diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c +index 0f42971ff0a83..e48285c81bf57 100644 +--- a/drivers/gpu/drm/xe/xe_guc_submit.c ++++ b/drivers/gpu/drm/xe/xe_guc_submit.c +@@ -35,6 +35,7 @@ + #include "xe_macros.h" + #include "xe_map.h" + #include "xe_mocs.h" ++#include "xe_pm.h" + #include "xe_ring_ops_types.h" + #include "xe_sched_job.h" + #include "xe_trace.h" +@@ -916,8 +917,9 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job) + return DRM_GPU_SCHED_STAT_NOMINAL; + } + +- drm_notice(&xe->drm, "Timedout job: seqno=%u, guc_id=%d, flags=0x%lx", +- xe_sched_job_seqno(job), q->guc->id, q->flags); ++ drm_notice(&xe->drm, "Timedout job: seqno=%u, lrc_seqno=%u, guc_id=%d, flags=0x%lx", ++ xe_sched_job_seqno(job), xe_sched_job_lrc_seqno(job), ++ q->guc->id, q->flags); + xe_gt_WARN(q->gt, q->flags & EXEC_QUEUE_FLAG_KERNEL, + "Kernel-submitted job timed out\n"); + xe_gt_WARN(q->gt, q->flags & EXEC_QUEUE_FLAG_VM && !exec_queue_killed(q), +@@ -1011,6 +1013,7 @@ static void __guc_exec_queue_fini_async(struct work_struct *w) + struct xe_exec_queue *q = ge->q; + struct xe_guc *guc = exec_queue_to_guc(q); + ++ xe_pm_runtime_get(guc_to_xe(guc)); + trace_xe_exec_queue_destroy(q); + + if (xe_exec_queue_is_lr(q)) +@@ -1021,6 +1024,7 @@ static void __guc_exec_queue_fini_async(struct work_struct *w) + + kfree(ge); + xe_exec_queue_fini(q); ++ xe_pm_runtime_put(guc_to_xe(guc)); + } + + static void guc_exec_queue_fini_async(struct xe_exec_queue *q) +diff --git a/drivers/gpu/drm/xe/xe_hw_fence.c b/drivers/gpu/drm/xe/xe_hw_fence.c +index f872ef1031272..35c0063a831af 100644 +--- a/drivers/gpu/drm/xe/xe_hw_fence.c ++++ b/drivers/gpu/drm/xe/xe_hw_fence.c +@@ -208,23 +208,58 @@ static struct xe_hw_fence *to_xe_hw_fence(struct dma_fence *fence) + return container_of(fence, struct xe_hw_fence, dma); + } + +-struct xe_hw_fence *xe_hw_fence_create(struct xe_hw_fence_ctx *ctx, +- struct iosys_map seqno_map) ++/** ++ * xe_hw_fence_alloc() - Allocate an hw fence. ++ * ++ * Allocate but don't initialize an hw fence. ++ * ++ * Return: Pointer to the allocated fence or ++ * negative error pointer on error. ++ */ ++struct dma_fence *xe_hw_fence_alloc(void) + { +- struct xe_hw_fence *fence; ++ struct xe_hw_fence *hw_fence = fence_alloc(); + +- fence = fence_alloc(); +- if (!fence) ++ if (!hw_fence) + return ERR_PTR(-ENOMEM); + +- fence->ctx = ctx; +- fence->seqno_map = seqno_map; +- INIT_LIST_HEAD(&fence->irq_link); ++ return &hw_fence->dma; ++} + +- dma_fence_init(&fence->dma, &xe_hw_fence_ops, &ctx->irq->lock, +- ctx->dma_fence_ctx, ctx->next_seqno++); ++/** ++ * xe_hw_fence_free() - Free an hw fence. ++ * @fence: Pointer to the fence to free. ++ * ++ * Frees an hw fence that hasn't yet been ++ * initialized. ++ */ ++void xe_hw_fence_free(struct dma_fence *fence) ++{ ++ fence_free(&fence->rcu); ++} + +- trace_xe_hw_fence_create(fence); ++/** ++ * xe_hw_fence_init() - Initialize an hw fence. ++ * @fence: Pointer to the fence to initialize. ++ * @ctx: Pointer to the struct xe_hw_fence_ctx fence context. ++ * @seqno_map: Pointer to the map into where the seqno is blitted. ++ * ++ * Initializes a pre-allocated hw fence. ++ * After initialization, the fence is subject to normal ++ * dma-fence refcounting. ++ */ ++void xe_hw_fence_init(struct dma_fence *fence, struct xe_hw_fence_ctx *ctx, ++ struct iosys_map seqno_map) ++{ ++ struct xe_hw_fence *hw_fence = ++ container_of(fence, typeof(*hw_fence), dma); ++ ++ hw_fence->ctx = ctx; ++ hw_fence->seqno_map = seqno_map; ++ INIT_LIST_HEAD(&hw_fence->irq_link); ++ ++ dma_fence_init(fence, &xe_hw_fence_ops, &ctx->irq->lock, ++ ctx->dma_fence_ctx, ctx->next_seqno++); + +- return fence; ++ trace_xe_hw_fence_create(hw_fence); + } +diff --git a/drivers/gpu/drm/xe/xe_hw_fence.h b/drivers/gpu/drm/xe/xe_hw_fence.h +index cfe5fd603787e..f13a1c4982c73 100644 +--- a/drivers/gpu/drm/xe/xe_hw_fence.h ++++ b/drivers/gpu/drm/xe/xe_hw_fence.h +@@ -24,7 +24,10 @@ void xe_hw_fence_ctx_init(struct xe_hw_fence_ctx *ctx, struct xe_gt *gt, + struct xe_hw_fence_irq *irq, const char *name); + void xe_hw_fence_ctx_finish(struct xe_hw_fence_ctx *ctx); + +-struct xe_hw_fence *xe_hw_fence_create(struct xe_hw_fence_ctx *ctx, +- struct iosys_map seqno_map); ++struct dma_fence *xe_hw_fence_alloc(void); + ++void xe_hw_fence_free(struct dma_fence *fence); ++ ++void xe_hw_fence_init(struct dma_fence *fence, struct xe_hw_fence_ctx *ctx, ++ struct iosys_map seqno_map); + #endif +diff --git a/drivers/gpu/drm/xe/xe_lrc.c b/drivers/gpu/drm/xe/xe_lrc.c +index d7bf7bc9dc145..995f47eb365c3 100644 +--- a/drivers/gpu/drm/xe/xe_lrc.c ++++ b/drivers/gpu/drm/xe/xe_lrc.c +@@ -901,10 +901,54 @@ u32 xe_lrc_seqno_ggtt_addr(struct xe_lrc *lrc) + return __xe_lrc_seqno_ggtt_addr(lrc); + } + ++/** ++ * xe_lrc_alloc_seqno_fence() - Allocate an lrc seqno fence. ++ * ++ * Allocate but don't initialize an lrc seqno fence. ++ * ++ * Return: Pointer to the allocated fence or ++ * negative error pointer on error. ++ */ ++struct dma_fence *xe_lrc_alloc_seqno_fence(void) ++{ ++ return xe_hw_fence_alloc(); ++} ++ ++/** ++ * xe_lrc_free_seqno_fence() - Free an lrc seqno fence. ++ * @fence: Pointer to the fence to free. ++ * ++ * Frees an lrc seqno fence that hasn't yet been ++ * initialized. ++ */ ++void xe_lrc_free_seqno_fence(struct dma_fence *fence) ++{ ++ xe_hw_fence_free(fence); ++} ++ ++/** ++ * xe_lrc_init_seqno_fence() - Initialize an lrc seqno fence. ++ * @lrc: Pointer to the lrc. ++ * @fence: Pointer to the fence to initialize. ++ * ++ * Initializes a pre-allocated lrc seqno fence. ++ * After initialization, the fence is subject to normal ++ * dma-fence refcounting. ++ */ ++void xe_lrc_init_seqno_fence(struct xe_lrc *lrc, struct dma_fence *fence) ++{ ++ xe_hw_fence_init(fence, &lrc->fence_ctx, __xe_lrc_seqno_map(lrc)); ++} ++ + struct dma_fence *xe_lrc_create_seqno_fence(struct xe_lrc *lrc) + { +- return &xe_hw_fence_create(&lrc->fence_ctx, +- __xe_lrc_seqno_map(lrc))->dma; ++ struct dma_fence *fence = xe_lrc_alloc_seqno_fence(); ++ ++ if (IS_ERR(fence)) ++ return fence; ++ ++ xe_lrc_init_seqno_fence(lrc, fence); ++ return fence; + } + + s32 xe_lrc_seqno(struct xe_lrc *lrc) +diff --git a/drivers/gpu/drm/xe/xe_lrc.h b/drivers/gpu/drm/xe/xe_lrc.h +index d32fa31faa2cf..f57c5836dab87 100644 +--- a/drivers/gpu/drm/xe/xe_lrc.h ++++ b/drivers/gpu/drm/xe/xe_lrc.h +@@ -38,6 +38,9 @@ void xe_lrc_write_ctx_reg(struct xe_lrc *lrc, int reg_nr, u32 val); + u64 xe_lrc_descriptor(struct xe_lrc *lrc); + + u32 xe_lrc_seqno_ggtt_addr(struct xe_lrc *lrc); ++struct dma_fence *xe_lrc_alloc_seqno_fence(void); ++void xe_lrc_free_seqno_fence(struct dma_fence *fence); ++void xe_lrc_init_seqno_fence(struct xe_lrc *lrc, struct dma_fence *fence); + struct dma_fence *xe_lrc_create_seqno_fence(struct xe_lrc *lrc); + s32 xe_lrc_seqno(struct xe_lrc *lrc); + +diff --git a/drivers/gpu/drm/xe/xe_mmio.c b/drivers/gpu/drm/xe/xe_mmio.c +index 334637511e750..beb4e276ba845 100644 +--- a/drivers/gpu/drm/xe/xe_mmio.c ++++ b/drivers/gpu/drm/xe/xe_mmio.c +@@ -254,6 +254,21 @@ static int xe_mmio_tile_vram_size(struct xe_tile *tile, u64 *vram_size, + return xe_force_wake_put(gt_to_fw(gt), XE_FW_GT); + } + ++static void vram_fini(void *arg) ++{ ++ struct xe_device *xe = arg; ++ struct xe_tile *tile; ++ int id; ++ ++ if (xe->mem.vram.mapping) ++ iounmap(xe->mem.vram.mapping); ++ ++ xe->mem.vram.mapping = NULL; ++ ++ for_each_tile(tile, xe, id) ++ tile->mem.vram.mapping = NULL; ++} ++ + int xe_mmio_probe_vram(struct xe_device *xe) + { + struct xe_tile *tile; +@@ -330,10 +345,21 @@ int xe_mmio_probe_vram(struct xe_device *xe) + drm_info(&xe->drm, "Available VRAM: %pa, %pa\n", &xe->mem.vram.io_start, + &available_size); + +- return 0; ++ return devm_add_action_or_reset(xe->drm.dev, vram_fini, xe); + } + +-void xe_mmio_probe_tiles(struct xe_device *xe) ++static void tiles_fini(void *arg) ++{ ++ struct xe_device *xe = arg; ++ struct xe_tile *tile; ++ int id; ++ ++ for_each_tile(tile, xe, id) ++ if (tile != xe_device_get_root_tile(xe)) ++ tile->mmio.regs = NULL; ++} ++ ++int xe_mmio_probe_tiles(struct xe_device *xe) + { + size_t tile_mmio_size = SZ_16M, tile_mmio_ext_size = xe->info.tile_mmio_ext_size; + u8 id, tile_count = xe->info.tile_count; +@@ -384,15 +410,18 @@ void xe_mmio_probe_tiles(struct xe_device *xe) + regs += tile_mmio_ext_size; + } + } ++ ++ return devm_add_action_or_reset(xe->drm.dev, tiles_fini, xe); + } + +-static void mmio_fini(struct drm_device *drm, void *arg) ++static void mmio_fini(void *arg) + { + struct xe_device *xe = arg; ++ struct xe_tile *root_tile = xe_device_get_root_tile(xe); + + pci_iounmap(to_pci_dev(xe->drm.dev), xe->mmio.regs); +- if (xe->mem.vram.mapping) +- iounmap(xe->mem.vram.mapping); ++ xe->mmio.regs = NULL; ++ root_tile->mmio.regs = NULL; + } + + int xe_mmio_init(struct xe_device *xe) +@@ -417,7 +446,7 @@ int xe_mmio_init(struct xe_device *xe) + root_tile->mmio.size = SZ_16M; + root_tile->mmio.regs = xe->mmio.regs; + +- return drmm_add_action_or_reset(&xe->drm, mmio_fini, xe); ++ return devm_add_action_or_reset(xe->drm.dev, mmio_fini, xe); + } + + u8 xe_mmio_read8(struct xe_gt *gt, struct xe_reg reg) +diff --git a/drivers/gpu/drm/xe/xe_mmio.h b/drivers/gpu/drm/xe/xe_mmio.h +index a3cd7b3036c73..a929d090bb2f1 100644 +--- a/drivers/gpu/drm/xe/xe_mmio.h ++++ b/drivers/gpu/drm/xe/xe_mmio.h +@@ -21,7 +21,7 @@ struct xe_device; + #define LMEM_BAR 2 + + int xe_mmio_init(struct xe_device *xe); +-void xe_mmio_probe_tiles(struct xe_device *xe); ++int xe_mmio_probe_tiles(struct xe_device *xe); + + u8 xe_mmio_read8(struct xe_gt *gt, struct xe_reg reg); + u16 xe_mmio_read16(struct xe_gt *gt, struct xe_reg reg); +diff --git a/drivers/gpu/drm/xe/xe_ring_ops.c b/drivers/gpu/drm/xe/xe_ring_ops.c +index aca7a9af6e846..c59c4373aefad 100644 +--- a/drivers/gpu/drm/xe/xe_ring_ops.c ++++ b/drivers/gpu/drm/xe/xe_ring_ops.c +@@ -380,7 +380,7 @@ static void emit_migration_job_gen12(struct xe_sched_job *job, + + dw[i++] = MI_ARB_ON_OFF | MI_ARB_DISABLE; /* Enabled again below */ + +- i = emit_bb_start(job->batch_addr[0], BIT(8), dw, i); ++ i = emit_bb_start(job->ptrs[0].batch_addr, BIT(8), dw, i); + + if (!IS_SRIOV_VF(gt_to_xe(job->q->gt))) { + /* XXX: Do we need this? Leaving for now. */ +@@ -389,7 +389,7 @@ static void emit_migration_job_gen12(struct xe_sched_job *job, + dw[i++] = preparser_disable(false); + } + +- i = emit_bb_start(job->batch_addr[1], BIT(8), dw, i); ++ i = emit_bb_start(job->ptrs[1].batch_addr, BIT(8), dw, i); + + dw[i++] = MI_FLUSH_DW | MI_INVALIDATE_TLB | job->migrate_flush_flags | + MI_FLUSH_DW_OP_STOREDW | MI_FLUSH_IMM_DW; +@@ -411,8 +411,8 @@ static void emit_job_gen12_gsc(struct xe_sched_job *job) + xe_gt_assert(gt, job->q->width <= 1); /* no parallel submission for GSCCS */ + + __emit_job_gen12_simple(job, job->q->lrc, +- job->batch_addr[0], +- xe_sched_job_seqno(job)); ++ job->ptrs[0].batch_addr, ++ xe_sched_job_lrc_seqno(job)); + } + + static void emit_job_gen12_copy(struct xe_sched_job *job) +@@ -421,14 +421,14 @@ static void emit_job_gen12_copy(struct xe_sched_job *job) + + if (xe_sched_job_is_migration(job->q)) { + emit_migration_job_gen12(job, job->q->lrc, +- xe_sched_job_seqno(job)); ++ xe_sched_job_lrc_seqno(job)); + return; + } + + for (i = 0; i < job->q->width; ++i) + __emit_job_gen12_simple(job, job->q->lrc + i, +- job->batch_addr[i], +- xe_sched_job_seqno(job)); ++ job->ptrs[i].batch_addr, ++ xe_sched_job_lrc_seqno(job)); + } + + static void emit_job_gen12_video(struct xe_sched_job *job) +@@ -438,8 +438,8 @@ static void emit_job_gen12_video(struct xe_sched_job *job) + /* FIXME: Not doing parallel handshake for now */ + for (i = 0; i < job->q->width; ++i) + __emit_job_gen12_video(job, job->q->lrc + i, +- job->batch_addr[i], +- xe_sched_job_seqno(job)); ++ job->ptrs[i].batch_addr, ++ xe_sched_job_lrc_seqno(job)); + } + + static void emit_job_gen12_render_compute(struct xe_sched_job *job) +@@ -448,8 +448,8 @@ static void emit_job_gen12_render_compute(struct xe_sched_job *job) + + for (i = 0; i < job->q->width; ++i) + __emit_job_gen12_render_compute(job, job->q->lrc + i, +- job->batch_addr[i], +- xe_sched_job_seqno(job)); ++ job->ptrs[i].batch_addr, ++ xe_sched_job_lrc_seqno(job)); + } + + static const struct xe_ring_ops ring_ops_gen12_gsc = { +diff --git a/drivers/gpu/drm/xe/xe_sched_job.c b/drivers/gpu/drm/xe/xe_sched_job.c +index cd8a2fba54389..2b064680abb96 100644 +--- a/drivers/gpu/drm/xe/xe_sched_job.c ++++ b/drivers/gpu/drm/xe/xe_sched_job.c +@@ -6,7 +6,7 @@ + #include "xe_sched_job.h" + + #include +-#include ++#include + #include + + #include "xe_device.h" +@@ -29,7 +29,7 @@ int __init xe_sched_job_module_init(void) + xe_sched_job_slab = + kmem_cache_create("xe_sched_job", + sizeof(struct xe_sched_job) + +- sizeof(u64), 0, ++ sizeof(struct xe_job_ptrs), 0, + SLAB_HWCACHE_ALIGN, NULL); + if (!xe_sched_job_slab) + return -ENOMEM; +@@ -37,7 +37,7 @@ int __init xe_sched_job_module_init(void) + xe_sched_job_parallel_slab = + kmem_cache_create("xe_sched_job_parallel", + sizeof(struct xe_sched_job) + +- sizeof(u64) * ++ sizeof(struct xe_job_ptrs) * + XE_HW_ENGINE_MAX_INSTANCE, 0, + SLAB_HWCACHE_ALIGN, NULL); + if (!xe_sched_job_parallel_slab) { +@@ -79,26 +79,33 @@ static struct xe_device *job_to_xe(struct xe_sched_job *job) + return gt_to_xe(job->q->gt); + } + ++/* Free unused pre-allocated fences */ ++static void xe_sched_job_free_fences(struct xe_sched_job *job) ++{ ++ int i; ++ ++ for (i = 0; i < job->q->width; ++i) { ++ struct xe_job_ptrs *ptrs = &job->ptrs[i]; ++ ++ if (ptrs->lrc_fence) ++ xe_lrc_free_seqno_fence(ptrs->lrc_fence); ++ if (ptrs->chain_fence) ++ dma_fence_chain_free(ptrs->chain_fence); ++ } ++} ++ + struct xe_sched_job *xe_sched_job_create(struct xe_exec_queue *q, + u64 *batch_addr) + { +- struct xe_sched_job *job; +- struct dma_fence **fences; + bool is_migration = xe_sched_job_is_migration(q); ++ struct xe_sched_job *job; + int err; +- int i, j; ++ int i; + u32 width; + + /* only a kernel context can submit a vm-less job */ + XE_WARN_ON(!q->vm && !(q->flags & EXEC_QUEUE_FLAG_KERNEL)); + +- /* Migration and kernel engines have their own locking */ +- if (!(q->flags & (EXEC_QUEUE_FLAG_KERNEL | EXEC_QUEUE_FLAG_VM))) { +- lockdep_assert_held(&q->vm->lock); +- if (!xe_vm_in_lr_mode(q->vm)) +- xe_vm_assert_held(q->vm); +- } +- + job = job_alloc(xe_exec_queue_is_parallel(q) || is_migration); + if (!job) + return ERR_PTR(-ENOMEM); +@@ -111,44 +118,25 @@ struct xe_sched_job *xe_sched_job_create(struct xe_exec_queue *q, + if (err) + goto err_free; + +- if (!xe_exec_queue_is_parallel(q)) { +- job->fence = xe_lrc_create_seqno_fence(q->lrc); +- if (IS_ERR(job->fence)) { +- err = PTR_ERR(job->fence); +- goto err_sched_job; +- } +- } else { +- struct dma_fence_array *cf; ++ for (i = 0; i < q->width; ++i) { ++ struct dma_fence *fence = xe_lrc_alloc_seqno_fence(); ++ struct dma_fence_chain *chain; + +- fences = kmalloc_array(q->width, sizeof(*fences), GFP_KERNEL); +- if (!fences) { +- err = -ENOMEM; ++ if (IS_ERR(fence)) { ++ err = PTR_ERR(fence); + goto err_sched_job; + } ++ job->ptrs[i].lrc_fence = fence; + +- for (j = 0; j < q->width; ++j) { +- fences[j] = xe_lrc_create_seqno_fence(q->lrc + j); +- if (IS_ERR(fences[j])) { +- err = PTR_ERR(fences[j]); +- goto err_fences; +- } +- } ++ if (i + 1 == q->width) ++ continue; + +- cf = dma_fence_array_create(q->width, fences, +- q->parallel.composite_fence_ctx, +- q->parallel.composite_fence_seqno++, +- false); +- if (!cf) { +- --q->parallel.composite_fence_seqno; ++ chain = dma_fence_chain_alloc(); ++ if (!chain) { + err = -ENOMEM; +- goto err_fences; ++ goto err_sched_job; + } +- +- /* Sanity check */ +- for (j = 0; j < q->width; ++j) +- xe_assert(job_to_xe(job), cf->base.seqno == fences[j]->seqno); +- +- job->fence = &cf->base; ++ job->ptrs[i].chain_fence = chain; + } + + width = q->width; +@@ -156,23 +144,14 @@ struct xe_sched_job *xe_sched_job_create(struct xe_exec_queue *q, + width = 2; + + for (i = 0; i < width; ++i) +- job->batch_addr[i] = batch_addr[i]; +- +- /* All other jobs require a VM to be open which has a ref */ +- if (unlikely(q->flags & EXEC_QUEUE_FLAG_KERNEL)) +- xe_pm_runtime_get_noresume(job_to_xe(job)); +- xe_device_assert_mem_access(job_to_xe(job)); ++ job->ptrs[i].batch_addr = batch_addr[i]; + ++ xe_pm_runtime_get_noresume(job_to_xe(job)); + trace_xe_sched_job_create(job); + return job; + +-err_fences: +- for (j = j - 1; j >= 0; --j) { +- --q->lrc[j].fence_ctx.next_seqno; +- dma_fence_put(fences[j]); +- } +- kfree(fences); + err_sched_job: ++ xe_sched_job_free_fences(job); + drm_sched_job_cleanup(&job->drm); + err_free: + xe_exec_queue_put(q); +@@ -191,36 +170,43 @@ void xe_sched_job_destroy(struct kref *ref) + { + struct xe_sched_job *job = + container_of(ref, struct xe_sched_job, refcount); ++ struct xe_device *xe = job_to_xe(job); ++ struct xe_exec_queue *q = job->q; + +- if (unlikely(job->q->flags & EXEC_QUEUE_FLAG_KERNEL)) +- xe_pm_runtime_put(job_to_xe(job)); +- xe_exec_queue_put(job->q); ++ xe_sched_job_free_fences(job); + dma_fence_put(job->fence); + drm_sched_job_cleanup(&job->drm); + job_free(job); ++ xe_exec_queue_put(q); ++ xe_pm_runtime_put(xe); + } + +-void xe_sched_job_set_error(struct xe_sched_job *job, int error) ++/* Set the error status under the fence to avoid racing with signaling */ ++static bool xe_fence_set_error(struct dma_fence *fence, int error) + { +- if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &job->fence->flags)) +- return; ++ unsigned long irq_flags; ++ bool signaled; + +- dma_fence_set_error(job->fence, error); ++ spin_lock_irqsave(fence->lock, irq_flags); ++ signaled = test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags); ++ if (!signaled) ++ dma_fence_set_error(fence, error); ++ spin_unlock_irqrestore(fence->lock, irq_flags); + +- if (dma_fence_is_array(job->fence)) { +- struct dma_fence_array *array = +- to_dma_fence_array(job->fence); +- struct dma_fence **child = array->fences; +- unsigned int nchild = array->num_fences; ++ return signaled; ++} ++ ++void xe_sched_job_set_error(struct xe_sched_job *job, int error) ++{ ++ if (xe_fence_set_error(job->fence, error)) ++ return; + +- do { +- struct dma_fence *current_fence = *child++; ++ if (dma_fence_is_chain(job->fence)) { ++ struct dma_fence *iter; + +- if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, +- ¤t_fence->flags)) +- continue; +- dma_fence_set_error(current_fence, error); +- } while (--nchild); ++ dma_fence_chain_for_each(iter, job->fence) ++ xe_fence_set_error(dma_fence_chain_contained(iter), ++ error); + } + + trace_xe_sched_job_set_error(job); +@@ -233,9 +219,9 @@ bool xe_sched_job_started(struct xe_sched_job *job) + { + struct xe_lrc *lrc = job->q->lrc; + +- return !__dma_fence_is_later(xe_sched_job_seqno(job), ++ return !__dma_fence_is_later(xe_sched_job_lrc_seqno(job), + xe_lrc_start_seqno(lrc), +- job->fence->ops); ++ dma_fence_chain_contained(job->fence)->ops); + } + + bool xe_sched_job_completed(struct xe_sched_job *job) +@@ -247,14 +233,26 @@ bool xe_sched_job_completed(struct xe_sched_job *job) + * parallel handshake is done. + */ + +- return !__dma_fence_is_later(xe_sched_job_seqno(job), xe_lrc_seqno(lrc), +- job->fence->ops); ++ return !__dma_fence_is_later(xe_sched_job_lrc_seqno(job), ++ xe_lrc_seqno(lrc), ++ dma_fence_chain_contained(job->fence)->ops); + } + + void xe_sched_job_arm(struct xe_sched_job *job) + { + struct xe_exec_queue *q = job->q; ++ struct dma_fence *fence, *prev; + struct xe_vm *vm = q->vm; ++ u64 seqno = 0; ++ int i; ++ ++ /* Migration and kernel engines have their own locking */ ++ if (IS_ENABLED(CONFIG_LOCKDEP) && ++ !(q->flags & (EXEC_QUEUE_FLAG_KERNEL | EXEC_QUEUE_FLAG_VM))) { ++ lockdep_assert_held(&q->vm->lock); ++ if (!xe_vm_in_lr_mode(q->vm)) ++ xe_vm_assert_held(q->vm); ++ } + + if (vm && !xe_sched_job_is_migration(q) && !xe_vm_in_lr_mode(vm) && + (vm->batch_invalidate_tlb || vm->tlb_flush_seqno != q->tlb_flush_seqno)) { +@@ -263,6 +261,27 @@ void xe_sched_job_arm(struct xe_sched_job *job) + job->ring_ops_flush_tlb = true; + } + ++ /* Arm the pre-allocated fences */ ++ for (i = 0; i < q->width; prev = fence, ++i) { ++ struct dma_fence_chain *chain; ++ ++ fence = job->ptrs[i].lrc_fence; ++ xe_lrc_init_seqno_fence(&q->lrc[i], fence); ++ job->ptrs[i].lrc_fence = NULL; ++ if (!i) { ++ job->lrc_seqno = fence->seqno; ++ continue; ++ } else { ++ xe_assert(gt_to_xe(q->gt), job->lrc_seqno == fence->seqno); ++ } ++ ++ chain = job->ptrs[i - 1].chain_fence; ++ dma_fence_chain_init(chain, prev, fence, seqno++); ++ job->ptrs[i - 1].chain_fence = NULL; ++ fence = &chain->base; ++ } ++ ++ job->fence = fence; + drm_sched_job_arm(&job->drm); + } + +@@ -322,7 +341,8 @@ xe_sched_job_snapshot_capture(struct xe_sched_job *job) + + snapshot->batch_addr_len = q->width; + for (i = 0; i < q->width; i++) +- snapshot->batch_addr[i] = xe_device_uncanonicalize_addr(xe, job->batch_addr[i]); ++ snapshot->batch_addr[i] = ++ xe_device_uncanonicalize_addr(xe, job->ptrs[i].batch_addr); + + return snapshot; + } +diff --git a/drivers/gpu/drm/xe/xe_sched_job.h b/drivers/gpu/drm/xe/xe_sched_job.h +index c75018f4660dc..f362e28455dbf 100644 +--- a/drivers/gpu/drm/xe/xe_sched_job.h ++++ b/drivers/gpu/drm/xe/xe_sched_job.h +@@ -70,7 +70,12 @@ to_xe_sched_job(struct drm_sched_job *drm) + + static inline u32 xe_sched_job_seqno(struct xe_sched_job *job) + { +- return job->fence->seqno; ++ return job->fence ? job->fence->seqno : 0; ++} ++ ++static inline u32 xe_sched_job_lrc_seqno(struct xe_sched_job *job) ++{ ++ return job->lrc_seqno; + } + + static inline void +diff --git a/drivers/gpu/drm/xe/xe_sched_job_types.h b/drivers/gpu/drm/xe/xe_sched_job_types.h +index 5e12724219fdd..0d3f76fb05cea 100644 +--- a/drivers/gpu/drm/xe/xe_sched_job_types.h ++++ b/drivers/gpu/drm/xe/xe_sched_job_types.h +@@ -11,6 +11,20 @@ + #include + + struct xe_exec_queue; ++struct dma_fence; ++struct dma_fence_chain; ++ ++/** ++ * struct xe_job_ptrs - Per hw engine instance data ++ */ ++struct xe_job_ptrs { ++ /** @lrc_fence: Pre-allocated uinitialized lrc fence.*/ ++ struct dma_fence *lrc_fence; ++ /** @chain_fence: Pre-allocated ninitialized fence chain node. */ ++ struct dma_fence_chain *chain_fence; ++ /** @batch_addr: Batch buffer address. */ ++ u64 batch_addr; ++}; + + /** + * struct xe_sched_job - XE schedule job (batch buffer tracking) +@@ -37,12 +51,14 @@ struct xe_sched_job { + /** @user_fence.value: write back value */ + u64 value; + } user_fence; ++ /** @lrc_seqno: LRC seqno */ ++ u32 lrc_seqno; + /** @migrate_flush_flags: Additional flush flags for migration jobs */ + u32 migrate_flush_flags; + /** @ring_ops_flush_tlb: The ring ops need to flush TLB before payload. */ + bool ring_ops_flush_tlb; +- /** @batch_addr: batch buffer address of job */ +- u64 batch_addr[]; ++ /** @ptrs: per instance pointers. */ ++ struct xe_job_ptrs ptrs[]; + }; + + struct xe_sched_job_snapshot { +diff --git a/drivers/gpu/drm/xe/xe_trace.h b/drivers/gpu/drm/xe/xe_trace.h +index 2d56cfc09e421..e4cba64474e6d 100644 +--- a/drivers/gpu/drm/xe/xe_trace.h ++++ b/drivers/gpu/drm/xe/xe_trace.h +@@ -254,6 +254,7 @@ DECLARE_EVENT_CLASS(xe_sched_job, + + TP_STRUCT__entry( + __field(u32, seqno) ++ __field(u32, lrc_seqno) + __field(u16, guc_id) + __field(u32, guc_state) + __field(u32, flags) +@@ -264,17 +265,19 @@ DECLARE_EVENT_CLASS(xe_sched_job, + + TP_fast_assign( + __entry->seqno = xe_sched_job_seqno(job); ++ __entry->lrc_seqno = xe_sched_job_lrc_seqno(job); + __entry->guc_id = job->q->guc->id; + __entry->guc_state = + atomic_read(&job->q->guc->state); + __entry->flags = job->q->flags; +- __entry->error = job->fence->error; ++ __entry->error = job->fence ? job->fence->error : 0; + __entry->fence = job->fence; +- __entry->batch_addr = (u64)job->batch_addr[0]; ++ __entry->batch_addr = (u64)job->ptrs[0].batch_addr; + ), + +- TP_printk("fence=%p, seqno=%u, guc_id=%d, batch_addr=0x%012llx, guc_state=0x%x, flags=0x%x, error=%d", +- __entry->fence, __entry->seqno, __entry->guc_id, ++ TP_printk("fence=%p, seqno=%u, lrc_seqno=%u, guc_id=%d, batch_addr=0x%012llx, guc_state=0x%x, flags=0x%x, error=%d", ++ __entry->fence, __entry->seqno, ++ __entry->lrc_seqno, __entry->guc_id, + __entry->batch_addr, __entry->guc_state, + __entry->flags, __entry->error) + ); +diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c +index 20de97ce0f5ee..d84740be96426 100644 +--- a/drivers/hid/wacom_wac.c ++++ b/drivers/hid/wacom_wac.c +@@ -1924,12 +1924,14 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage, + int fmax = field->logical_maximum; + unsigned int equivalent_usage = wacom_equivalent_usage(usage->hid); + int resolution_code = code; +- int resolution = hidinput_calc_abs_res(field, resolution_code); ++ int resolution; + + if (equivalent_usage == HID_DG_TWIST) { + resolution_code = ABS_RZ; + } + ++ resolution = hidinput_calc_abs_res(field, resolution_code); ++ + if (equivalent_usage == HID_GD_X) { + fmin += features->offset_left; + fmax -= features->offset_right; +diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c +index 365e37bba0f33..06e836e3e8773 100644 +--- a/drivers/i2c/busses/i2c-qcom-geni.c ++++ b/drivers/i2c/busses/i2c-qcom-geni.c +@@ -986,8 +986,10 @@ static int __maybe_unused geni_i2c_runtime_resume(struct device *dev) + return ret; + + ret = clk_prepare_enable(gi2c->core_clk); +- if (ret) ++ if (ret) { ++ geni_icc_disable(&gi2c->se); + return ret; ++ } + + ret = geni_se_resources_on(&gi2c->se); + if (ret) { +diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c +index 85b31edc558df..1df5b42041427 100644 +--- a/drivers/i2c/busses/i2c-tegra.c ++++ b/drivers/i2c/busses/i2c-tegra.c +@@ -1802,9 +1802,9 @@ static int tegra_i2c_probe(struct platform_device *pdev) + * domain. + * + * VI I2C device shouldn't be marked as IRQ-safe because VI I2C won't +- * be used for atomic transfers. ++ * be used for atomic transfers. ACPI device is not IRQ safe also. + */ +- if (!IS_VI(i2c_dev)) ++ if (!IS_VI(i2c_dev) && !has_acpi_companion(i2c_dev->dev)) + pm_runtime_irq_safe(i2c_dev->dev); + + pm_runtime_enable(i2c_dev->dev); +diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c +index 14b53dac1253b..6b04a674f832a 100644 +--- a/drivers/input/input-mt.c ++++ b/drivers/input/input-mt.c +@@ -46,6 +46,9 @@ int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots, + return 0; + if (mt) + return mt->num_slots != num_slots ? -EINVAL : 0; ++ /* Arbitrary limit for avoiding too large memory allocation. */ ++ if (num_slots > 1024) ++ return -EINVAL; + + mt = kzalloc(struct_size(mt, slots, num_slots), GFP_KERNEL); + if (!mt) +diff --git a/drivers/input/serio/i8042-acpipnpio.h b/drivers/input/serio/i8042-acpipnpio.h +index 5b50475ec4140..e9eb9554dd7bd 100644 +--- a/drivers/input/serio/i8042-acpipnpio.h ++++ b/drivers/input/serio/i8042-acpipnpio.h +@@ -83,6 +83,7 @@ static inline void i8042_write_command(int val) + #define SERIO_QUIRK_KBDRESET BIT(12) + #define SERIO_QUIRK_DRITEK BIT(13) + #define SERIO_QUIRK_NOPNP BIT(14) ++#define SERIO_QUIRK_FORCENORESTORE BIT(15) + + /* Quirk table for different mainboards. Options similar or identical to i8042 + * module parameters. +@@ -1149,18 +1150,10 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { + SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + }, + { +- /* +- * Setting SERIO_QUIRK_NOMUX or SERIO_QUIRK_RESET_ALWAYS makes +- * the keyboard very laggy for ~5 seconds after boot and +- * sometimes also after resume. +- * However both are required for the keyboard to not fail +- * completely sometimes after boot or resume. +- */ + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "N150CU"), + }, +- .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | +- SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) ++ .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) + }, + { + .matches = { +@@ -1685,6 +1678,8 @@ static void __init i8042_check_quirks(void) + if (quirks & SERIO_QUIRK_NOPNP) + i8042_nopnp = true; + #endif ++ if (quirks & SERIO_QUIRK_FORCENORESTORE) ++ i8042_forcenorestore = true; + } + #else + static inline void i8042_check_quirks(void) {} +@@ -1718,7 +1713,7 @@ static int __init i8042_platform_init(void) + + i8042_check_quirks(); + +- pr_debug("Active quirks (empty means none):%s%s%s%s%s%s%s%s%s%s%s%s%s\n", ++ pr_debug("Active quirks (empty means none):%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", + i8042_nokbd ? " nokbd" : "", + i8042_noaux ? " noaux" : "", + i8042_nomux ? " nomux" : "", +@@ -1738,10 +1733,11 @@ static int __init i8042_platform_init(void) + "", + #endif + #ifdef CONFIG_PNP +- i8042_nopnp ? " nopnp" : ""); ++ i8042_nopnp ? " nopnp" : "", + #else +- ""); ++ "", + #endif ++ i8042_forcenorestore ? " forcenorestore" : ""); + + retval = i8042_pnp_init(); + if (retval) +diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c +index 9fbb8d31575ae..2233d93f90e81 100644 +--- a/drivers/input/serio/i8042.c ++++ b/drivers/input/serio/i8042.c +@@ -115,6 +115,10 @@ module_param_named(nopnp, i8042_nopnp, bool, 0); + MODULE_PARM_DESC(nopnp, "Do not use PNP to detect controller settings"); + #endif + ++static bool i8042_forcenorestore; ++module_param_named(forcenorestore, i8042_forcenorestore, bool, 0); ++MODULE_PARM_DESC(forcenorestore, "Force no restore on s3 resume, copying s2idle behaviour"); ++ + #define DEBUG + #ifdef DEBUG + static bool i8042_debug; +@@ -1232,7 +1236,7 @@ static int i8042_pm_suspend(struct device *dev) + { + int i; + +- if (pm_suspend_via_firmware()) ++ if (!i8042_forcenorestore && pm_suspend_via_firmware()) + i8042_controller_reset(true); + + /* Set up serio interrupts for system wakeup. */ +@@ -1248,7 +1252,7 @@ static int i8042_pm_suspend(struct device *dev) + + static int i8042_pm_resume_noirq(struct device *dev) + { +- if (!pm_resume_via_firmware()) ++ if (i8042_forcenorestore || !pm_resume_via_firmware()) + i8042_interrupt(0, NULL); + + return 0; +@@ -1271,7 +1275,7 @@ static int i8042_pm_resume(struct device *dev) + * not restore the controller state to whatever it had been at boot + * time, so we do not need to do anything. + */ +- if (!pm_suspend_via_firmware()) ++ if (i8042_forcenorestore || !pm_suspend_via_firmware()) + return 0; + + /* +diff --git a/drivers/iommu/io-pgfault.c b/drivers/iommu/io-pgfault.c +index 06d78fcc79fdb..f2c87c695a17c 100644 +--- a/drivers/iommu/io-pgfault.c ++++ b/drivers/iommu/io-pgfault.c +@@ -192,6 +192,7 @@ void iommu_report_device_fault(struct device *dev, struct iopf_fault *evt) + report_partial_fault(iopf_param, fault); + iopf_put_dev_fault_param(iopf_param); + /* A request that is not the last does not need to be ack'd */ ++ return; + } + + /* +diff --git a/drivers/iommu/iommufd/device.c b/drivers/iommu/iommufd/device.c +index 873630c111c1f..e333793e88eb7 100644 +--- a/drivers/iommu/iommufd/device.c ++++ b/drivers/iommu/iommufd/device.c +@@ -525,7 +525,7 @@ iommufd_device_do_replace(struct iommufd_device *idev, + err_unresv: + if (hwpt_is_paging(hwpt)) + iommufd_group_remove_reserved_iova(igroup, +- to_hwpt_paging(old_hwpt)); ++ to_hwpt_paging(hwpt)); + err_unlock: + mutex_unlock(&idev->igroup->lock); + return ERR_PTR(rc); +diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c +index c2c07bfa64719..f299ff393a6a2 100644 +--- a/drivers/md/dm-ioctl.c ++++ b/drivers/md/dm-ioctl.c +@@ -1181,8 +1181,26 @@ static int do_resume(struct dm_ioctl *param) + suspend_flags &= ~DM_SUSPEND_LOCKFS_FLAG; + if (param->flags & DM_NOFLUSH_FLAG) + suspend_flags |= DM_SUSPEND_NOFLUSH_FLAG; +- if (!dm_suspended_md(md)) +- dm_suspend(md, suspend_flags); ++ if (!dm_suspended_md(md)) { ++ r = dm_suspend(md, suspend_flags); ++ if (r) { ++ down_write(&_hash_lock); ++ hc = dm_get_mdptr(md); ++ if (hc && !hc->new_map) { ++ hc->new_map = new_map; ++ new_map = NULL; ++ } else { ++ r = -ENXIO; ++ } ++ up_write(&_hash_lock); ++ if (new_map) { ++ dm_sync_table(md); ++ dm_table_destroy(new_map); ++ } ++ dm_put(md); ++ return r; ++ } ++ } + + old_size = dm_get_size(md); + old_map = dm_swap_table(md, new_map); +diff --git a/drivers/md/dm.c b/drivers/md/dm.c +index 13037d6a6f62a..6e15ac4e0845c 100644 +--- a/drivers/md/dm.c ++++ b/drivers/md/dm.c +@@ -2594,7 +2594,7 @@ static int dm_wait_for_bios_completion(struct mapped_device *md, unsigned int ta + break; + + if (signal_pending_state(task_state, current)) { +- r = -EINTR; ++ r = -ERESTARTSYS; + break; + } + +@@ -2619,7 +2619,7 @@ static int dm_wait_for_completion(struct mapped_device *md, unsigned int task_st + break; + + if (signal_pending_state(task_state, current)) { +- r = -EINTR; ++ r = -ERESTARTSYS; + break; + } + +diff --git a/drivers/md/persistent-data/dm-space-map-metadata.c b/drivers/md/persistent-data/dm-space-map-metadata.c +index 04698fd03e606..d48c4fafc7798 100644 +--- a/drivers/md/persistent-data/dm-space-map-metadata.c ++++ b/drivers/md/persistent-data/dm-space-map-metadata.c +@@ -277,7 +277,7 @@ static void sm_metadata_destroy(struct dm_space_map *sm) + { + struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); + +- kfree(smm); ++ kvfree(smm); + } + + static int sm_metadata_get_nr_blocks(struct dm_space_map *sm, dm_block_t *count) +@@ -772,7 +772,7 @@ struct dm_space_map *dm_sm_metadata_init(void) + { + struct sm_metadata *smm; + +- smm = kmalloc(sizeof(*smm), GFP_KERNEL); ++ smm = kvmalloc(sizeof(*smm), GFP_KERNEL); + if (!smm) + return ERR_PTR(-ENOMEM); + +diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c +index 5ea57b6748c53..687bd374cde89 100644 +--- a/drivers/md/raid1.c ++++ b/drivers/md/raid1.c +@@ -617,6 +617,12 @@ static int choose_first_rdev(struct r1conf *conf, struct r1bio *r1_bio, + return -1; + } + ++static bool rdev_in_recovery(struct md_rdev *rdev, struct r1bio *r1_bio) ++{ ++ return !test_bit(In_sync, &rdev->flags) && ++ rdev->recovery_offset < r1_bio->sector + r1_bio->sectors; ++} ++ + static int choose_bb_rdev(struct r1conf *conf, struct r1bio *r1_bio, + int *max_sectors) + { +@@ -635,6 +641,7 @@ static int choose_bb_rdev(struct r1conf *conf, struct r1bio *r1_bio, + + rdev = conf->mirrors[disk].rdev; + if (!rdev || test_bit(Faulty, &rdev->flags) || ++ rdev_in_recovery(rdev, r1_bio) || + test_bit(WriteMostly, &rdev->flags)) + continue; + +@@ -673,7 +680,8 @@ static int choose_slow_rdev(struct r1conf *conf, struct r1bio *r1_bio, + + rdev = conf->mirrors[disk].rdev; + if (!rdev || test_bit(Faulty, &rdev->flags) || +- !test_bit(WriteMostly, &rdev->flags)) ++ !test_bit(WriteMostly, &rdev->flags) || ++ rdev_in_recovery(rdev, r1_bio)) + continue; + + /* there are no bad blocks, we can use this disk */ +@@ -733,9 +741,7 @@ static bool rdev_readable(struct md_rdev *rdev, struct r1bio *r1_bio) + if (!rdev || test_bit(Faulty, &rdev->flags)) + return false; + +- /* still in recovery */ +- if (!test_bit(In_sync, &rdev->flags) && +- rdev->recovery_offset < r1_bio->sector + r1_bio->sectors) ++ if (rdev_in_recovery(rdev, r1_bio)) + return false; + + /* don't read from slow disk unless have to */ +diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c +index a7a2bcedb37e4..5680856c0fb82 100644 +--- a/drivers/misc/fastrpc.c ++++ b/drivers/misc/fastrpc.c +@@ -2087,16 +2087,6 @@ static int fastrpc_req_mem_map(struct fastrpc_user *fl, char __user *argp) + return err; + } + +-static int is_attach_rejected(struct fastrpc_user *fl) +-{ +- /* Check if the device node is non-secure */ +- if (!fl->is_secure_dev) { +- dev_dbg(&fl->cctx->rpdev->dev, "untrusted app trying to attach to privileged DSP PD\n"); +- return -EACCES; +- } +- return 0; +-} +- + static long fastrpc_device_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) + { +@@ -2109,19 +2099,13 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int cmd, + err = fastrpc_invoke(fl, argp); + break; + case FASTRPC_IOCTL_INIT_ATTACH: +- err = is_attach_rejected(fl); +- if (!err) +- err = fastrpc_init_attach(fl, ROOT_PD); ++ err = fastrpc_init_attach(fl, ROOT_PD); + break; + case FASTRPC_IOCTL_INIT_ATTACH_SNS: +- err = is_attach_rejected(fl); +- if (!err) +- err = fastrpc_init_attach(fl, SENSORS_PD); ++ err = fastrpc_init_attach(fl, SENSORS_PD); + break; + case FASTRPC_IOCTL_INIT_CREATE_STATIC: +- err = is_attach_rejected(fl); +- if (!err) +- err = fastrpc_init_create_static_process(fl, argp); ++ err = fastrpc_init_create_static_process(fl, argp); + break; + case FASTRPC_IOCTL_INIT_CREATE: + err = fastrpc_init_create_process(fl, argp); +diff --git a/drivers/mmc/core/mmc_test.c b/drivers/mmc/core/mmc_test.c +index 8f7f587a0025b..b7f627a9fdeab 100644 +--- a/drivers/mmc/core/mmc_test.c ++++ b/drivers/mmc/core/mmc_test.c +@@ -3125,13 +3125,13 @@ static ssize_t mtf_test_write(struct file *file, const char __user *buf, + test->buffer = kzalloc(BUFFER_SIZE, GFP_KERNEL); + #ifdef CONFIG_HIGHMEM + test->highmem = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, BUFFER_ORDER); ++ if (!test->highmem) { ++ count = -ENOMEM; ++ goto free_test_buffer; ++ } + #endif + +-#ifdef CONFIG_HIGHMEM +- if (test->buffer && test->highmem) { +-#else + if (test->buffer) { +-#endif + mutex_lock(&mmc_test_lock); + mmc_test_run(test, testcase); + mutex_unlock(&mmc_test_lock); +@@ -3139,6 +3139,7 @@ static ssize_t mtf_test_write(struct file *file, const char __user *buf, + + #ifdef CONFIG_HIGHMEM + __free_pages(test->highmem, BUFFER_ORDER); ++free_test_buffer: + #endif + kfree(test->buffer); + kfree(test); +diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c +index 8e2d676b92399..a4f813ea177a8 100644 +--- a/drivers/mmc/host/dw_mmc.c ++++ b/drivers/mmc/host/dw_mmc.c +@@ -3293,6 +3293,10 @@ int dw_mci_probe(struct dw_mci *host) + host->biu_clk = devm_clk_get(host->dev, "biu"); + if (IS_ERR(host->biu_clk)) { + dev_dbg(host->dev, "biu clock not available\n"); ++ ret = PTR_ERR(host->biu_clk); ++ if (ret == -EPROBE_DEFER) ++ return ret; ++ + } else { + ret = clk_prepare_enable(host->biu_clk); + if (ret) { +@@ -3304,6 +3308,10 @@ int dw_mci_probe(struct dw_mci *host) + host->ciu_clk = devm_clk_get(host->dev, "ciu"); + if (IS_ERR(host->ciu_clk)) { + dev_dbg(host->dev, "ciu clock not available\n"); ++ ret = PTR_ERR(host->ciu_clk); ++ if (ret == -EPROBE_DEFER) ++ goto err_clk_biu; ++ + host->bus_hz = host->pdata->bus_hz; + } else { + ret = clk_prepare_enable(host->ciu_clk); +diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c +index a94835b8ab939..e386f78e32679 100644 +--- a/drivers/mmc/host/mtk-sd.c ++++ b/drivers/mmc/host/mtk-sd.c +@@ -1230,7 +1230,7 @@ static bool msdc_cmd_done(struct msdc_host *host, int events, + } + + if (!sbc_error && !(events & MSDC_INT_CMDRDY)) { +- if (events & MSDC_INT_CMDTMO || ++ if ((events & MSDC_INT_CMDTMO && !host->hs400_tuning) || + (!mmc_op_tuning(cmd->opcode) && !host->hs400_tuning)) + /* + * should not clear fifo/interrupt as the tune data +@@ -1323,9 +1323,9 @@ static void msdc_start_command(struct msdc_host *host, + static void msdc_cmd_next(struct msdc_host *host, + struct mmc_request *mrq, struct mmc_command *cmd) + { +- if ((cmd->error && +- !(cmd->error == -EILSEQ && +- (mmc_op_tuning(cmd->opcode) || host->hs400_tuning))) || ++ if ((cmd->error && !host->hs400_tuning && ++ !(cmd->error == -EILSEQ && ++ mmc_op_tuning(cmd->opcode))) || + (mrq->sbc && mrq->sbc->error)) + msdc_request_done(host, mrq); + else if (cmd == mrq->sbc) +diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c +index 2ed0da0684906..b257504a85347 100644 +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -582,7 +582,6 @@ static void bond_ipsec_del_sa_all(struct bonding *bond) + } else { + slave->dev->xfrmdev_ops->xdo_dev_state_delete(ipsec->xs); + } +- ipsec->xs->xso.real_dev = NULL; + } + spin_unlock_bh(&bond->ipsec_lock); + rcu_read_unlock(); +@@ -599,34 +598,30 @@ static bool bond_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *xs) + struct net_device *real_dev; + struct slave *curr_active; + struct bonding *bond; +- int err; ++ bool ok = false; + + bond = netdev_priv(bond_dev); + rcu_read_lock(); + curr_active = rcu_dereference(bond->curr_active_slave); ++ if (!curr_active) ++ goto out; + real_dev = curr_active->dev; + +- if (BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP) { +- err = false; ++ if (BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP) + goto out; +- } + +- if (!xs->xso.real_dev) { +- err = false; ++ if (!xs->xso.real_dev) + goto out; +- } + + if (!real_dev->xfrmdev_ops || + !real_dev->xfrmdev_ops->xdo_dev_offload_ok || +- netif_is_bond_master(real_dev)) { +- err = false; ++ netif_is_bond_master(real_dev)) + goto out; +- } + +- err = real_dev->xfrmdev_ops->xdo_dev_offload_ok(skb, xs); ++ ok = real_dev->xfrmdev_ops->xdo_dev_offload_ok(skb, xs); + out: + rcu_read_unlock(); +- return err; ++ return ok; + } + + static const struct xfrmdev_ops bond_xfrmdev_ops = { +diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c +index bc80fb6397dcd..95d59a18c0223 100644 +--- a/drivers/net/bonding/bond_options.c ++++ b/drivers/net/bonding/bond_options.c +@@ -936,7 +936,7 @@ static int bond_option_active_slave_set(struct bonding *bond, + /* check to see if we are clearing active */ + if (!slave_dev) { + netdev_dbg(bond->dev, "Clearing current active slave\n"); +- RCU_INIT_POINTER(bond->curr_active_slave, NULL); ++ bond_change_active_slave(bond, NULL); + bond_select_active_slave(bond); + } else { + struct slave *old_active = rtnl_dereference(bond->curr_active_slave); +diff --git a/drivers/net/dsa/microchip/ksz_ptp.c b/drivers/net/dsa/microchip/ksz_ptp.c +index 1fe105913c758..beb969f391be5 100644 +--- a/drivers/net/dsa/microchip/ksz_ptp.c ++++ b/drivers/net/dsa/microchip/ksz_ptp.c +@@ -266,7 +266,6 @@ static int ksz_ptp_enable_mode(struct ksz_device *dev) + struct ksz_port *prt; + struct dsa_port *dp; + bool tag_en = false; +- int ret; + + dsa_switch_for_each_user_port(dp, dev->ds) { + prt = &dev->ports[dp->index]; +@@ -277,9 +276,7 @@ static int ksz_ptp_enable_mode(struct ksz_device *dev) + } + + if (tag_en) { +- ret = ptp_schedule_worker(ptp_data->clock, 0); +- if (ret) +- return ret; ++ ptp_schedule_worker(ptp_data->clock, 0); + } else { + ptp_cancel_worker_sync(ptp_data->clock); + } +diff --git a/drivers/net/dsa/mv88e6xxx/global1_atu.c b/drivers/net/dsa/mv88e6xxx/global1_atu.c +index ce3b3690c3c05..c47f068f56b32 100644 +--- a/drivers/net/dsa/mv88e6xxx/global1_atu.c ++++ b/drivers/net/dsa/mv88e6xxx/global1_atu.c +@@ -457,7 +457,8 @@ static irqreturn_t mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq, void *dev_id) + trace_mv88e6xxx_atu_full_violation(chip->dev, spid, + entry.portvec, entry.mac, + fid); +- chip->ports[spid].atu_full_violation++; ++ if (spid < ARRAY_SIZE(chip->ports)) ++ chip->ports[spid].atu_full_violation++; + } + + return IRQ_HANDLED; +diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c +index 61e95487732dc..f5d26e724ae65 100644 +--- a/drivers/net/dsa/ocelot/felix.c ++++ b/drivers/net/dsa/ocelot/felix.c +@@ -528,7 +528,9 @@ static int felix_tag_8021q_setup(struct dsa_switch *ds) + * so we need to be careful that there are no extra frames to be + * dequeued over MMIO, since we would never know to discard them. + */ ++ ocelot_lock_xtr_grp_bh(ocelot, 0); + ocelot_drain_cpu_queue(ocelot, 0); ++ ocelot_unlock_xtr_grp_bh(ocelot, 0); + + return 0; + } +@@ -1504,6 +1506,8 @@ static void felix_port_deferred_xmit(struct kthread_work *work) + int port = xmit_work->dp->index; + int retries = 10; + ++ ocelot_lock_inj_grp(ocelot, 0); ++ + do { + if (ocelot_can_inject(ocelot, 0)) + break; +@@ -1512,6 +1516,7 @@ static void felix_port_deferred_xmit(struct kthread_work *work) + } while (--retries); + + if (!retries) { ++ ocelot_unlock_inj_grp(ocelot, 0); + dev_err(ocelot->dev, "port %d failed to inject skb\n", + port); + ocelot_port_purge_txtstamp_skb(ocelot, port, skb); +@@ -1521,6 +1526,8 @@ static void felix_port_deferred_xmit(struct kthread_work *work) + + ocelot_port_inject_frame(ocelot, port, 0, rew_op, skb); + ++ ocelot_unlock_inj_grp(ocelot, 0); ++ + consume_skb(skb); + kfree(xmit_work); + } +@@ -1671,6 +1678,8 @@ static bool felix_check_xtr_pkt(struct ocelot *ocelot) + if (!felix->info->quirk_no_xtr_irq) + return false; + ++ ocelot_lock_xtr_grp(ocelot, grp); ++ + while (ocelot_read(ocelot, QS_XTR_DATA_PRESENT) & BIT(grp)) { + struct sk_buff *skb; + unsigned int type; +@@ -1707,6 +1716,8 @@ static bool felix_check_xtr_pkt(struct ocelot *ocelot) + ocelot_drain_cpu_queue(ocelot, 0); + } + ++ ocelot_unlock_xtr_grp(ocelot, grp); ++ + return true; + } + +diff --git a/drivers/net/dsa/vitesse-vsc73xx-core.c b/drivers/net/dsa/vitesse-vsc73xx-core.c +index 4b031fefcec68..56bb77dbd28a2 100644 +--- a/drivers/net/dsa/vitesse-vsc73xx-core.c ++++ b/drivers/net/dsa/vitesse-vsc73xx-core.c +@@ -38,6 +38,10 @@ + #define VSC73XX_BLOCK_ARBITER 0x5 /* Only subblock 0 */ + #define VSC73XX_BLOCK_SYSTEM 0x7 /* Only subblock 0 */ + ++/* MII Block subblock */ ++#define VSC73XX_BLOCK_MII_INTERNAL 0x0 /* Internal MDIO subblock */ ++#define VSC73XX_BLOCK_MII_EXTERNAL 0x1 /* External MDIO subblock */ ++ + #define CPU_PORT 6 /* CPU port */ + + /* MAC Block registers */ +@@ -196,6 +200,8 @@ + #define VSC73XX_MII_CMD 0x1 + #define VSC73XX_MII_DATA 0x2 + ++#define VSC73XX_MII_STAT_BUSY BIT(3) ++ + /* Arbiter block 5 registers */ + #define VSC73XX_ARBEMPTY 0x0c + #define VSC73XX_ARBDISC 0x0e +@@ -270,6 +276,7 @@ + #define IS_739X(a) (IS_7395(a) || IS_7398(a)) + + #define VSC73XX_POLL_SLEEP_US 1000 ++#define VSC73XX_MDIO_POLL_SLEEP_US 5 + #define VSC73XX_POLL_TIMEOUT_US 10000 + + struct vsc73xx_counter { +@@ -487,6 +494,22 @@ static int vsc73xx_detect(struct vsc73xx *vsc) + return 0; + } + ++static int vsc73xx_mdio_busy_check(struct vsc73xx *vsc) ++{ ++ int ret, err; ++ u32 val; ++ ++ ret = read_poll_timeout(vsc73xx_read, err, ++ err < 0 || !(val & VSC73XX_MII_STAT_BUSY), ++ VSC73XX_MDIO_POLL_SLEEP_US, ++ VSC73XX_POLL_TIMEOUT_US, false, vsc, ++ VSC73XX_BLOCK_MII, VSC73XX_BLOCK_MII_INTERNAL, ++ VSC73XX_MII_STAT, &val); ++ if (ret) ++ return ret; ++ return err; ++} ++ + static int vsc73xx_phy_read(struct dsa_switch *ds, int phy, int regnum) + { + struct vsc73xx *vsc = ds->priv; +@@ -494,12 +517,20 @@ static int vsc73xx_phy_read(struct dsa_switch *ds, int phy, int regnum) + u32 val; + int ret; + ++ ret = vsc73xx_mdio_busy_check(vsc); ++ if (ret) ++ return ret; ++ + /* Setting bit 26 means "read" */ + cmd = BIT(26) | (phy << 21) | (regnum << 16); + ret = vsc73xx_write(vsc, VSC73XX_BLOCK_MII, 0, 1, cmd); + if (ret) + return ret; +- msleep(2); ++ ++ ret = vsc73xx_mdio_busy_check(vsc); ++ if (ret) ++ return ret; ++ + ret = vsc73xx_read(vsc, VSC73XX_BLOCK_MII, 0, 2, &val); + if (ret) + return ret; +@@ -523,6 +554,10 @@ static int vsc73xx_phy_write(struct dsa_switch *ds, int phy, int regnum, + u32 cmd; + int ret; + ++ ret = vsc73xx_mdio_busy_check(vsc); ++ if (ret) ++ return ret; ++ + /* It was found through tedious experiments that this router + * chip really hates to have it's PHYs reset. They + * never recover if that happens: autonegotiation stops +@@ -534,7 +569,7 @@ static int vsc73xx_phy_write(struct dsa_switch *ds, int phy, int regnum, + return 0; + } + +- cmd = (phy << 21) | (regnum << 16); ++ cmd = (phy << 21) | (regnum << 16) | val; + ret = vsc73xx_write(vsc, VSC73XX_BLOCK_MII, 0, 1, cmd); + if (ret) + return ret; +@@ -817,6 +852,11 @@ static void vsc73xx_mac_link_up(struct phylink_config *config, + + if (duplex == DUPLEX_FULL) + val |= VSC73XX_MAC_CFG_FDX; ++ else ++ /* In datasheet description ("Port Mode Procedure" in 5.6.2) ++ * this bit is configured only for half duplex. ++ */ ++ val |= VSC73XX_MAC_CFG_WEXC_DIS; + + /* This routine is described in the datasheet (below ARBDISC register + * description) +@@ -827,7 +867,6 @@ static void vsc73xx_mac_link_up(struct phylink_config *config, + get_random_bytes(&seed, 1); + val |= seed << VSC73XX_MAC_CFG_SEED_OFFSET; + val |= VSC73XX_MAC_CFG_SEED_LOAD; +- val |= VSC73XX_MAC_CFG_WEXC_DIS; + vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, port, VSC73XX_MAC_CFG, val); + + /* Flow control for the PHY facing ports: +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c +index 345681d5007e3..f88b641533fcc 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c +@@ -297,11 +297,6 @@ bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons, + * redirect is coming from a frame received by the + * bnxt_en driver. + */ +- rx_buf = &rxr->rx_buf_ring[cons]; +- mapping = rx_buf->mapping - bp->rx_dma_offset; +- dma_unmap_page_attrs(&pdev->dev, mapping, +- BNXT_RX_PAGE_SIZE, bp->rx_dir, +- DMA_ATTR_WEAK_ORDERING); + + /* if we are unable to allocate a new buffer, abort and reuse */ + if (bnxt_alloc_rx_data(bp, rxr, rxr->rx_prod, GFP_ATOMIC)) { +diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c +index 786ceae344887..dd9e68465e697 100644 +--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c ++++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c +@@ -1244,7 +1244,8 @@ static u64 hash_filter_ntuple(struct ch_filter_specification *fs, + * in the Compressed Filter Tuple. + */ + if (tp->vlan_shift >= 0 && fs->mask.ivlan) +- ntuple |= (FT_VLAN_VLD_F | fs->val.ivlan) << tp->vlan_shift; ++ ntuple |= (u64)(FT_VLAN_VLD_F | ++ fs->val.ivlan) << tp->vlan_shift; + + if (tp->port_shift >= 0 && fs->mask.iport) + ntuple |= (u64)fs->val.iport << tp->port_shift; +diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c +index a71f848adc054..a293b08f36d46 100644 +--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c ++++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c +@@ -2638,13 +2638,14 @@ static int dpaa2_switch_refill_bp(struct ethsw_core *ethsw) + + static int dpaa2_switch_seed_bp(struct ethsw_core *ethsw) + { +- int *count, i; ++ int *count, ret, i; + + for (i = 0; i < DPAA2_ETHSW_NUM_BUFS; i += BUFS_PER_CMD) { ++ ret = dpaa2_switch_add_bufs(ethsw, ethsw->bpid); + count = ðsw->buf_count; +- *count += dpaa2_switch_add_bufs(ethsw, ethsw->bpid); ++ *count += ret; + +- if (unlikely(*count < BUFS_PER_CMD)) ++ if (unlikely(ret < BUFS_PER_CMD)) + return -ENOMEM; + } + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +index a5fc0209d628e..4cbc4d069a1f3 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +@@ -5724,6 +5724,9 @@ static int hns3_reset_notify_uninit_enet(struct hnae3_handle *handle) + struct net_device *netdev = handle->kinfo.netdev; + struct hns3_nic_priv *priv = netdev_priv(netdev); + ++ if (!test_bit(HNS3_NIC_STATE_DOWN, &priv->state)) ++ hns3_nic_net_stop(netdev); ++ + if (!test_and_clear_bit(HNS3_NIC_STATE_INITED, &priv->state)) { + netdev_warn(netdev, "already uninitialized\n"); + return 0; +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +index 82574ce0194fb..465f0d5822837 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +@@ -2653,8 +2653,17 @@ static int hclge_cfg_mac_speed_dup_h(struct hnae3_handle *handle, int speed, + { + struct hclge_vport *vport = hclge_get_vport(handle); + struct hclge_dev *hdev = vport->back; ++ int ret; ++ ++ ret = hclge_cfg_mac_speed_dup(hdev, speed, duplex, lane_num); ++ ++ if (ret) ++ return ret; + +- return hclge_cfg_mac_speed_dup(hdev, speed, duplex, lane_num); ++ hdev->hw.mac.req_speed = speed; ++ hdev->hw.mac.req_duplex = duplex; ++ ++ return 0; + } + + static int hclge_set_autoneg_en(struct hclge_dev *hdev, bool enable) +@@ -2956,17 +2965,20 @@ static int hclge_mac_init(struct hclge_dev *hdev) + if (!test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state)) + hdev->hw.mac.duplex = HCLGE_MAC_FULL; + +- ret = hclge_cfg_mac_speed_dup_hw(hdev, hdev->hw.mac.speed, +- hdev->hw.mac.duplex, hdev->hw.mac.lane_num); +- if (ret) +- return ret; +- + if (hdev->hw.mac.support_autoneg) { + ret = hclge_set_autoneg_en(hdev, hdev->hw.mac.autoneg); + if (ret) + return ret; + } + ++ if (!hdev->hw.mac.autoneg) { ++ ret = hclge_cfg_mac_speed_dup_hw(hdev, hdev->hw.mac.req_speed, ++ hdev->hw.mac.req_duplex, ++ hdev->hw.mac.lane_num); ++ if (ret) ++ return ret; ++ } ++ + mac->link = 0; + + if (mac->user_fec_mode & BIT(HNAE3_FEC_USER_DEF)) { +@@ -11516,8 +11528,8 @@ static void hclge_reset_done(struct hnae3_ae_dev *ae_dev) + dev_err(&hdev->pdev->dev, "fail to rebuild, ret=%d\n", ret); + + hdev->reset_type = HNAE3_NONE_RESET; +- clear_bit(HCLGE_STATE_RST_HANDLING, &hdev->state); +- up(&hdev->reset_sem); ++ if (test_and_clear_bit(HCLGE_STATE_RST_HANDLING, &hdev->state)) ++ up(&hdev->reset_sem); + } + + static void hclge_clear_resetting_state(struct hclge_dev *hdev) +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c +index 85fb11de43a12..80079657afebe 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c +@@ -191,6 +191,9 @@ static void hclge_mac_adjust_link(struct net_device *netdev) + if (ret) + netdev_err(netdev, "failed to adjust link.\n"); + ++ hdev->hw.mac.req_speed = (u32)speed; ++ hdev->hw.mac.req_duplex = (u8)duplex; ++ + ret = hclge_cfg_flowctrl(hdev); + if (ret) + netdev_err(netdev, "failed to configure flow control.\n"); +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +index 3735d2fed11f7..094a7c7b55921 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +@@ -1747,8 +1747,8 @@ static void hclgevf_reset_done(struct hnae3_ae_dev *ae_dev) + ret); + + hdev->reset_type = HNAE3_NONE_RESET; +- clear_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state); +- up(&hdev->reset_sem); ++ if (test_and_clear_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state)) ++ up(&hdev->reset_sem); + } + + static u32 hclgevf_get_fw_version(struct hnae3_handle *handle) +diff --git a/drivers/net/ethernet/intel/ice/devlink/devlink_port.c b/drivers/net/ethernet/intel/ice/devlink/devlink_port.c +index 13e6790d3cae7..afcf64dab48a1 100644 +--- a/drivers/net/ethernet/intel/ice/devlink/devlink_port.c ++++ b/drivers/net/ethernet/intel/ice/devlink/devlink_port.c +@@ -337,7 +337,7 @@ int ice_devlink_create_pf_port(struct ice_pf *pf) + return -EIO; + + attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL; +- attrs.phys.port_number = pf->hw.bus.func; ++ attrs.phys.port_number = pf->hw.pf_id; + + /* As FW supports only port split options for whole device, + * set port split options only for first PF. +@@ -399,7 +399,7 @@ int ice_devlink_create_vf_port(struct ice_vf *vf) + return -EINVAL; + + attrs.flavour = DEVLINK_PORT_FLAVOUR_PCI_VF; +- attrs.pci_vf.pf = pf->hw.bus.func; ++ attrs.pci_vf.pf = pf->hw.pf_id; + attrs.pci_vf.vf = vf->vf_id; + + ice_devlink_set_switch_id(pf, &attrs.switch_id); +diff --git a/drivers/net/ethernet/intel/ice/ice_base.c b/drivers/net/ethernet/intel/ice/ice_base.c +index 1facf179a96fd..f448d3a845642 100644 +--- a/drivers/net/ethernet/intel/ice/ice_base.c ++++ b/drivers/net/ethernet/intel/ice/ice_base.c +@@ -512,6 +512,25 @@ static void ice_xsk_pool_fill_cb(struct ice_rx_ring *ring) + xsk_pool_fill_cb(ring->xsk_pool, &desc); + } + ++/** ++ * ice_get_frame_sz - calculate xdp_buff::frame_sz ++ * @rx_ring: the ring being configured ++ * ++ * Return frame size based on underlying PAGE_SIZE ++ */ ++static unsigned int ice_get_frame_sz(struct ice_rx_ring *rx_ring) ++{ ++ unsigned int frame_sz; ++ ++#if (PAGE_SIZE >= 8192) ++ frame_sz = rx_ring->rx_buf_len; ++#else ++ frame_sz = ice_rx_pg_size(rx_ring) / 2; ++#endif ++ ++ return frame_sz; ++} ++ + /** + * ice_vsi_cfg_rxq - Configure an Rx queue + * @ring: the ring being configured +@@ -576,7 +595,7 @@ static int ice_vsi_cfg_rxq(struct ice_rx_ring *ring) + } + } + +- xdp_init_buff(&ring->xdp, ice_rx_pg_size(ring) / 2, &ring->xdp_rxq); ++ xdp_init_buff(&ring->xdp, ice_get_frame_sz(ring), &ring->xdp_rxq); + ring->xdp.data = NULL; + ring->xdp_ext.pkt_ctx = &ring->pkt_ctx; + err = ice_setup_rx_ctx(ring); +diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c +index 8d25b69812698..c9bc3f1add5d3 100644 +--- a/drivers/net/ethernet/intel/ice/ice_txrx.c ++++ b/drivers/net/ethernet/intel/ice/ice_txrx.c +@@ -521,30 +521,6 @@ int ice_setup_rx_ring(struct ice_rx_ring *rx_ring) + return -ENOMEM; + } + +-/** +- * ice_rx_frame_truesize +- * @rx_ring: ptr to Rx ring +- * @size: size +- * +- * calculate the truesize with taking into the account PAGE_SIZE of +- * underlying arch +- */ +-static unsigned int +-ice_rx_frame_truesize(struct ice_rx_ring *rx_ring, const unsigned int size) +-{ +- unsigned int truesize; +- +-#if (PAGE_SIZE < 8192) +- truesize = ice_rx_pg_size(rx_ring) / 2; /* Must be power-of-2 */ +-#else +- truesize = rx_ring->rx_offset ? +- SKB_DATA_ALIGN(rx_ring->rx_offset + size) + +- SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) : +- SKB_DATA_ALIGN(size); +-#endif +- return truesize; +-} +- + /** + * ice_run_xdp - Executes an XDP program on initialized xdp_buff + * @rx_ring: Rx ring +@@ -837,16 +813,15 @@ ice_can_reuse_rx_page(struct ice_rx_buf *rx_buf) + if (!dev_page_is_reusable(page)) + return false; + +-#if (PAGE_SIZE < 8192) + /* if we are only owner of page we can reuse it */ + if (unlikely(rx_buf->pgcnt - pagecnt_bias > 1)) + return false; +-#else ++#if (PAGE_SIZE >= 8192) + #define ICE_LAST_OFFSET \ +- (SKB_WITH_OVERHEAD(PAGE_SIZE) - ICE_RXBUF_2048) ++ (SKB_WITH_OVERHEAD(PAGE_SIZE) - ICE_RXBUF_3072) + if (rx_buf->page_offset > ICE_LAST_OFFSET) + return false; +-#endif /* PAGE_SIZE < 8192) */ ++#endif /* PAGE_SIZE >= 8192) */ + + /* If we have drained the page fragment pool we need to update + * the pagecnt_bias and page count so that we fully restock the +@@ -949,12 +924,7 @@ ice_get_rx_buf(struct ice_rx_ring *rx_ring, const unsigned int size, + struct ice_rx_buf *rx_buf; + + rx_buf = &rx_ring->rx_buf[ntc]; +- rx_buf->pgcnt = +-#if (PAGE_SIZE < 8192) +- page_count(rx_buf->page); +-#else +- 0; +-#endif ++ rx_buf->pgcnt = page_count(rx_buf->page); + prefetchw(rx_buf->page); + + if (!size) +@@ -1160,11 +1130,6 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget) + bool failure; + u32 first; + +- /* Frame size depend on rx_ring setup when PAGE_SIZE=4K */ +-#if (PAGE_SIZE < 8192) +- xdp->frame_sz = ice_rx_frame_truesize(rx_ring, 0); +-#endif +- + xdp_prog = READ_ONCE(rx_ring->xdp_prog); + if (xdp_prog) { + xdp_ring = rx_ring->xdp_ring; +@@ -1223,10 +1188,6 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget) + hard_start = page_address(rx_buf->page) + rx_buf->page_offset - + offset; + xdp_prepare_buff(xdp, hard_start, offset, size, !!offset); +-#if (PAGE_SIZE > 4096) +- /* At larger PAGE_SIZE, frame_sz depend on len size */ +- xdp->frame_sz = ice_rx_frame_truesize(rx_ring, size); +-#endif + xdp_buff_clear_frags_flag(xdp); + } else if (ice_add_xdp_frag(rx_ring, xdp, rx_buf, size)) { + break; +diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c +index fce2930ae6af7..b6aa449aa56af 100644 +--- a/drivers/net/ethernet/intel/igb/igb_main.c ++++ b/drivers/net/ethernet/intel/igb/igb_main.c +@@ -4809,6 +4809,7 @@ static void igb_set_rx_buffer_len(struct igb_adapter *adapter, + + #if (PAGE_SIZE < 8192) + if (adapter->max_frame_size > IGB_MAX_FRAME_BUILD_SKB || ++ IGB_2K_TOO_SMALL_WITH_PADDING || + rd32(E1000_RCTL) & E1000_RCTL_SBP) + set_ring_uses_large_buffer(rx_ring); + #endif +diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h +index 5f92b3c7c3d4a..511384f3ec5cb 100644 +--- a/drivers/net/ethernet/intel/igc/igc_defines.h ++++ b/drivers/net/ethernet/intel/igc/igc_defines.h +@@ -404,6 +404,12 @@ + #define IGC_DTXMXPKTSZ_TSN 0x19 /* 1600 bytes of max TX DMA packet size */ + #define IGC_DTXMXPKTSZ_DEFAULT 0x98 /* 9728-byte Jumbo frames */ + ++/* Retry Buffer Control */ ++#define IGC_RETX_CTL 0x041C ++#define IGC_RETX_CTL_WATERMARK_MASK 0xF ++#define IGC_RETX_CTL_QBVFULLTH_SHIFT 8 /* QBV Retry Buffer Full Threshold */ ++#define IGC_RETX_CTL_QBVFULLEN 0x1000 /* Enable QBV Retry Buffer Full Threshold */ ++ + /* Transmit Scheduling Latency */ + /* Latency between transmission scheduling (LaunchTime) and the time + * the packet is transmitted to the network in nanosecond. +diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c +index 33069880c86c0..3041f8142324f 100644 +--- a/drivers/net/ethernet/intel/igc/igc_main.c ++++ b/drivers/net/ethernet/intel/igc/igc_main.c +@@ -6319,12 +6319,16 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter, + if (!validate_schedule(adapter, qopt)) + return -EINVAL; + ++ igc_ptp_read(adapter, &now); ++ ++ if (igc_tsn_is_taprio_activated_by_user(adapter) && ++ is_base_time_past(qopt->base_time, &now)) ++ adapter->qbv_config_change_errors++; ++ + adapter->cycle_time = qopt->cycle_time; + adapter->base_time = qopt->base_time; + adapter->taprio_offload_enable = true; + +- igc_ptp_read(adapter, &now); +- + for (n = 0; n < qopt->num_entries; n++) { + struct tc_taprio_sched_entry *e = &qopt->entries[n]; + +diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.c b/drivers/net/ethernet/intel/igc/igc_tsn.c +index 22cefb1eeedfa..d68fa7f3d5f07 100644 +--- a/drivers/net/ethernet/intel/igc/igc_tsn.c ++++ b/drivers/net/ethernet/intel/igc/igc_tsn.c +@@ -49,12 +49,19 @@ static unsigned int igc_tsn_new_flags(struct igc_adapter *adapter) + return new_flags; + } + ++static bool igc_tsn_is_tx_mode_in_tsn(struct igc_adapter *adapter) ++{ ++ struct igc_hw *hw = &adapter->hw; ++ ++ return !!(rd32(IGC_TQAVCTRL) & IGC_TQAVCTRL_TRANSMIT_MODE_TSN); ++} ++ + void igc_tsn_adjust_txtime_offset(struct igc_adapter *adapter) + { + struct igc_hw *hw = &adapter->hw; + u16 txoffset; + +- if (!is_any_launchtime(adapter)) ++ if (!igc_tsn_is_tx_mode_in_tsn(adapter)) + return; + + switch (adapter->link_speed) { +@@ -78,6 +85,23 @@ void igc_tsn_adjust_txtime_offset(struct igc_adapter *adapter) + wr32(IGC_GTXOFFSET, txoffset); + } + ++static void igc_tsn_restore_retx_default(struct igc_adapter *adapter) ++{ ++ struct igc_hw *hw = &adapter->hw; ++ u32 retxctl; ++ ++ retxctl = rd32(IGC_RETX_CTL) & IGC_RETX_CTL_WATERMARK_MASK; ++ wr32(IGC_RETX_CTL, retxctl); ++} ++ ++bool igc_tsn_is_taprio_activated_by_user(struct igc_adapter *adapter) ++{ ++ struct igc_hw *hw = &adapter->hw; ++ ++ return (rd32(IGC_BASET_H) || rd32(IGC_BASET_L)) && ++ adapter->taprio_offload_enable; ++} ++ + /* Returns the TSN specific registers to their default values after + * the adapter is reset. + */ +@@ -91,6 +115,9 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter) + wr32(IGC_TXPBS, I225_TXPBSIZE_DEFAULT); + wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_DEFAULT); + ++ if (igc_is_device_id_i226(hw)) ++ igc_tsn_restore_retx_default(adapter); ++ + tqavctrl = rd32(IGC_TQAVCTRL); + tqavctrl &= ~(IGC_TQAVCTRL_TRANSMIT_MODE_TSN | + IGC_TQAVCTRL_ENHANCED_QAV | IGC_TQAVCTRL_FUTSCDDIS); +@@ -111,6 +138,25 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter) + return 0; + } + ++/* To partially fix i226 HW errata, reduce MAC internal buffering from 192 Bytes ++ * to 88 Bytes by setting RETX_CTL register using the recommendation from: ++ * a) Ethernet Controller I225/I226 Specification Update Rev 2.1 ++ * Item 9: TSN: Packet Transmission Might Cross the Qbv Window ++ * b) I225/6 SW User Manual Rev 1.2.4: Section 8.11.5 Retry Buffer Control ++ */ ++static void igc_tsn_set_retx_qbvfullthreshold(struct igc_adapter *adapter) ++{ ++ struct igc_hw *hw = &adapter->hw; ++ u32 retxctl, watermark; ++ ++ retxctl = rd32(IGC_RETX_CTL); ++ watermark = retxctl & IGC_RETX_CTL_WATERMARK_MASK; ++ /* Set QBVFULLTH value using watermark and set QBVFULLEN */ ++ retxctl |= (watermark << IGC_RETX_CTL_QBVFULLTH_SHIFT) | ++ IGC_RETX_CTL_QBVFULLEN; ++ wr32(IGC_RETX_CTL, retxctl); ++} ++ + static int igc_tsn_enable_offload(struct igc_adapter *adapter) + { + struct igc_hw *hw = &adapter->hw; +@@ -123,6 +169,9 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter) + wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_TSN); + wr32(IGC_TXPBS, IGC_TXPBSIZE_TSN); + ++ if (igc_is_device_id_i226(hw)) ++ igc_tsn_set_retx_qbvfullthreshold(adapter); ++ + for (i = 0; i < adapter->num_tx_queues; i++) { + struct igc_ring *ring = adapter->tx_ring[i]; + u32 txqctl = 0; +@@ -262,14 +311,6 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter) + s64 n = div64_s64(ktime_sub_ns(systim, base_time), cycle); + + base_time = ktime_add_ns(base_time, (n + 1) * cycle); +- +- /* Increase the counter if scheduling into the past while +- * Gate Control List (GCL) is running. +- */ +- if ((rd32(IGC_BASET_H) || rd32(IGC_BASET_L)) && +- (adapter->tc_setup_type == TC_SETUP_QDISC_TAPRIO) && +- (adapter->qbv_count > 1)) +- adapter->qbv_config_change_errors++; + } else { + if (igc_is_device_id_i226(hw)) { + ktime_t adjust_time, expires_time; +@@ -331,15 +372,22 @@ int igc_tsn_reset(struct igc_adapter *adapter) + return err; + } + +-int igc_tsn_offload_apply(struct igc_adapter *adapter) ++static bool igc_tsn_will_tx_mode_change(struct igc_adapter *adapter) + { +- struct igc_hw *hw = &adapter->hw; ++ bool any_tsn_enabled = !!(igc_tsn_new_flags(adapter) & ++ IGC_FLAG_TSN_ANY_ENABLED); + +- /* Per I225/6 HW Design Section 7.5.2.1, transmit mode +- * cannot be changed dynamically. Require reset the adapter. ++ return (any_tsn_enabled && !igc_tsn_is_tx_mode_in_tsn(adapter)) || ++ (!any_tsn_enabled && igc_tsn_is_tx_mode_in_tsn(adapter)); ++} ++ ++int igc_tsn_offload_apply(struct igc_adapter *adapter) ++{ ++ /* Per I225/6 HW Design Section 7.5.2.1 guideline, if tx mode change ++ * from legacy->tsn or tsn->legacy, then reset adapter is needed. + */ + if (netif_running(adapter->netdev) && +- (igc_is_device_id_i225(hw) || !adapter->qbv_count)) { ++ igc_tsn_will_tx_mode_change(adapter)) { + schedule_work(&adapter->reset_task); + return 0; + } +diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.h b/drivers/net/ethernet/intel/igc/igc_tsn.h +index b53e6af560b73..98ec845a86bf0 100644 +--- a/drivers/net/ethernet/intel/igc/igc_tsn.h ++++ b/drivers/net/ethernet/intel/igc/igc_tsn.h +@@ -7,5 +7,6 @@ + int igc_tsn_offload_apply(struct igc_adapter *adapter); + int igc_tsn_reset(struct igc_adapter *adapter); + void igc_tsn_adjust_txtime_offset(struct igc_adapter *adapter); ++bool igc_tsn_is_taprio_activated_by_user(struct igc_adapter *adapter); + + #endif /* _IGC_BASE_H */ +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c +index 3e09d22858147..daf4b951e9059 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c +@@ -632,7 +632,9 @@ int rvu_mbox_handler_cpt_inline_ipsec_cfg(struct rvu *rvu, + return ret; + } + +-static bool is_valid_offset(struct rvu *rvu, struct cpt_rd_wr_reg_msg *req) ++static bool validate_and_update_reg_offset(struct rvu *rvu, ++ struct cpt_rd_wr_reg_msg *req, ++ u64 *reg_offset) + { + u64 offset = req->reg_offset; + int blkaddr, num_lfs, lf; +@@ -663,6 +665,11 @@ static bool is_valid_offset(struct rvu *rvu, struct cpt_rd_wr_reg_msg *req) + if (lf < 0) + return false; + ++ /* Translate local LF's offset to global CPT LF's offset to ++ * access LFX register. ++ */ ++ *reg_offset = (req->reg_offset & 0xFF000) + (lf << 3); ++ + return true; + } else if (!(req->hdr.pcifunc & RVU_PFVF_FUNC_MASK)) { + /* Registers that can be accessed from PF */ +@@ -697,7 +704,7 @@ int rvu_mbox_handler_cpt_rd_wr_register(struct rvu *rvu, + struct cpt_rd_wr_reg_msg *rsp) + { + u64 offset = req->reg_offset; +- int blkaddr, lf; ++ int blkaddr; + + blkaddr = validate_and_get_cpt_blkaddr(req->blkaddr); + if (blkaddr < 0) +@@ -708,18 +715,10 @@ int rvu_mbox_handler_cpt_rd_wr_register(struct rvu *rvu, + !is_cpt_vf(rvu, req->hdr.pcifunc)) + return CPT_AF_ERR_ACCESS_DENIED; + +- if (!is_valid_offset(rvu, req)) ++ if (!validate_and_update_reg_offset(rvu, req, &offset)) + return CPT_AF_ERR_ACCESS_DENIED; + +- /* Translate local LF used by VFs to global CPT LF */ +- lf = rvu_get_lf(rvu, &rvu->hw->block[blkaddr], req->hdr.pcifunc, +- (offset & 0xFFF) >> 3); +- +- /* Translate local LF's offset to global CPT LF's offset */ +- offset &= 0xFF000; +- offset += lf << 3; +- +- rsp->reg_offset = offset; ++ rsp->reg_offset = req->reg_offset; + rsp->ret_val = req->ret_val; + rsp->is_write = req->is_write; + +diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c +index 61334a71058c7..e212a4ba92751 100644 +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -2666,14 +2666,15 @@ mtk_wed_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_pri + { + struct mtk_wed_flow_block_priv *priv = cb_priv; + struct flow_cls_offload *cls = type_data; +- struct mtk_wed_hw *hw = priv->hw; ++ struct mtk_wed_hw *hw = NULL; + +- if (!tc_can_offload(priv->dev)) ++ if (!priv || !tc_can_offload(priv->dev)) + return -EOPNOTSUPP; + + if (type != TC_SETUP_CLSFLOWER) + return -EOPNOTSUPP; + ++ hw = priv->hw; + return mtk_flow_offload_cmd(hw->eth, cls, hw->index); + } + +@@ -2729,6 +2730,7 @@ mtk_wed_setup_tc_block(struct mtk_wed_hw *hw, struct net_device *dev, + flow_block_cb_remove(block_cb, f); + list_del(&block_cb->driver_list); + kfree(block_cb->cb_priv); ++ block_cb->cb_priv = NULL; + } + return 0; + default: +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c +index 22918b2ef7f12..09433b91be176 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c +@@ -146,7 +146,9 @@ static int mlx5e_tx_reporter_timeout_recover(void *ctx) + return err; + } + ++ mutex_lock(&priv->state_lock); + err = mlx5e_safe_reopen_channels(priv); ++ mutex_unlock(&priv->state_lock); + if (!err) { + to_ctx->status = 1; /* all channels recovered */ + return err; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c +index 3eccdadc03578..773624bb2c5d5 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c +@@ -734,7 +734,7 @@ mlx5e_ethtool_flow_replace(struct mlx5e_priv *priv, + if (num_tuples <= 0) { + netdev_warn(priv->netdev, "%s: flow is not valid %d\n", + __func__, num_tuples); +- return num_tuples; ++ return num_tuples < 0 ? num_tuples : -EINVAL; + } + + eth_ft = get_flow_table(priv, fs, num_tuples); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +index eedbcba226894..409f525f1703c 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -3005,15 +3005,18 @@ int mlx5e_update_tx_netdev_queues(struct mlx5e_priv *priv) + static void mlx5e_set_default_xps_cpumasks(struct mlx5e_priv *priv, + struct mlx5e_params *params) + { +- struct mlx5_core_dev *mdev = priv->mdev; +- int num_comp_vectors, ix, irq; +- +- num_comp_vectors = mlx5_comp_vectors_max(mdev); ++ int ix; + + for (ix = 0; ix < params->num_channels; ix++) { ++ int num_comp_vectors, irq, vec_ix; ++ struct mlx5_core_dev *mdev; ++ ++ mdev = mlx5_sd_ch_ix_get_dev(priv->mdev, ix); ++ num_comp_vectors = mlx5_comp_vectors_max(mdev); + cpumask_clear(priv->scratchpad.cpumask); ++ vec_ix = mlx5_sd_ch_ix_get_vec_ix(mdev, ix); + +- for (irq = ix; irq < num_comp_vectors; irq += params->num_channels) { ++ for (irq = vec_ix; irq < num_comp_vectors; irq += params->num_channels) { + int cpu = mlx5_comp_vector_get_cpu(mdev, irq); + + cpumask_set_cpu(cpu, priv->scratchpad.cpumask); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/ipsec_fs_roce.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/ipsec_fs_roce.c +index 234cd00f71a1c..b7d4b1a2baf2e 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/ipsec_fs_roce.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/ipsec_fs_roce.c +@@ -386,7 +386,8 @@ static int ipsec_fs_roce_tx_mpv_create(struct mlx5_core_dev *mdev, + return -EOPNOTSUPP; + + peer_priv = mlx5_devcom_get_next_peer_data(*ipsec_roce->devcom, &tmp); +- if (!peer_priv) { ++ if (!peer_priv || !peer_priv->ipsec) { ++ mlx5_core_err(mdev, "IPsec not supported on master device\n"); + err = -EOPNOTSUPP; + goto release_peer; + } +@@ -455,7 +456,8 @@ static int ipsec_fs_roce_rx_mpv_create(struct mlx5_core_dev *mdev, + return -EOPNOTSUPP; + + peer_priv = mlx5_devcom_get_next_peer_data(*ipsec_roce->devcom, &tmp); +- if (!peer_priv) { ++ if (!peer_priv || !peer_priv->ipsec) { ++ mlx5_core_err(mdev, "IPsec not supported on master device\n"); + err = -EOPNOTSUPP; + goto release_peer; + } +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/sd.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/sd.c +index f6deb5a3f8202..eeb0b7ea05f12 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/sd.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/sd.c +@@ -126,7 +126,7 @@ static bool mlx5_sd_is_supported(struct mlx5_core_dev *dev, u8 host_buses) + } + + static int mlx5_query_sd(struct mlx5_core_dev *dev, bool *sdm, +- u8 *host_buses, u8 *sd_group) ++ u8 *host_buses) + { + u32 out[MLX5_ST_SZ_DW(mpir_reg)]; + int err; +@@ -135,10 +135,6 @@ static int mlx5_query_sd(struct mlx5_core_dev *dev, bool *sdm, + if (err) + return err; + +- err = mlx5_query_nic_vport_sd_group(dev, sd_group); +- if (err) +- return err; +- + *sdm = MLX5_GET(mpir_reg, out, sdm); + *host_buses = MLX5_GET(mpir_reg, out, host_buses); + +@@ -166,19 +162,23 @@ static int sd_init(struct mlx5_core_dev *dev) + if (mlx5_core_is_ecpf(dev)) + return 0; + ++ err = mlx5_query_nic_vport_sd_group(dev, &sd_group); ++ if (err) ++ return err; ++ ++ if (!sd_group) ++ return 0; ++ + if (!MLX5_CAP_MCAM_REG(dev, mpir)) + return 0; + +- err = mlx5_query_sd(dev, &sdm, &host_buses, &sd_group); ++ err = mlx5_query_sd(dev, &sdm, &host_buses); + if (err) + return err; + + if (!sdm) + return 0; + +- if (!sd_group) +- return 0; +- + group_id = mlx5_sd_group_id(dev, sd_group); + + if (!mlx5_sd_is_supported(dev, host_buses)) { +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h +index bc94e75a7aebd..e7777700ee18a 100644 +--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h +@@ -40,6 +40,7 @@ + */ + #define MLXBF_GIGE_BCAST_MAC_FILTER_IDX 0 + #define MLXBF_GIGE_LOCAL_MAC_FILTER_IDX 1 ++#define MLXBF_GIGE_MAX_FILTER_IDX 3 + + /* Define for broadcast MAC literal */ + #define BCAST_MAC_ADDR 0xFFFFFFFFFFFF +@@ -175,6 +176,13 @@ enum mlxbf_gige_res { + int mlxbf_gige_mdio_probe(struct platform_device *pdev, + struct mlxbf_gige *priv); + void mlxbf_gige_mdio_remove(struct mlxbf_gige *priv); ++ ++void mlxbf_gige_enable_multicast_rx(struct mlxbf_gige *priv); ++void mlxbf_gige_disable_multicast_rx(struct mlxbf_gige *priv); ++void mlxbf_gige_enable_mac_rx_filter(struct mlxbf_gige *priv, ++ unsigned int index); ++void mlxbf_gige_disable_mac_rx_filter(struct mlxbf_gige *priv, ++ unsigned int index); + void mlxbf_gige_set_mac_rx_filter(struct mlxbf_gige *priv, + unsigned int index, u64 dmac); + void mlxbf_gige_get_mac_rx_filter(struct mlxbf_gige *priv, +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c +index b157f0f1c5a88..385a56ac73481 100644 +--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c +@@ -168,6 +168,10 @@ static int mlxbf_gige_open(struct net_device *netdev) + if (err) + goto napi_deinit; + ++ mlxbf_gige_enable_mac_rx_filter(priv, MLXBF_GIGE_BCAST_MAC_FILTER_IDX); ++ mlxbf_gige_enable_mac_rx_filter(priv, MLXBF_GIGE_LOCAL_MAC_FILTER_IDX); ++ mlxbf_gige_enable_multicast_rx(priv); ++ + /* Set bits in INT_EN that we care about */ + int_en = MLXBF_GIGE_INT_EN_HW_ACCESS_ERROR | + MLXBF_GIGE_INT_EN_TX_CHECKSUM_INPUTS | +@@ -379,6 +383,7 @@ static int mlxbf_gige_probe(struct platform_device *pdev) + void __iomem *plu_base; + void __iomem *base; + int addr, phy_irq; ++ unsigned int i; + int err; + + base = devm_platform_ioremap_resource(pdev, MLXBF_GIGE_RES_MAC); +@@ -423,6 +428,11 @@ static int mlxbf_gige_probe(struct platform_device *pdev) + priv->rx_q_entries = MLXBF_GIGE_DEFAULT_RXQ_SZ; + priv->tx_q_entries = MLXBF_GIGE_DEFAULT_TXQ_SZ; + ++ for (i = 0; i <= MLXBF_GIGE_MAX_FILTER_IDX; i++) ++ mlxbf_gige_disable_mac_rx_filter(priv, i); ++ mlxbf_gige_disable_multicast_rx(priv); ++ mlxbf_gige_disable_promisc(priv); ++ + /* Write initial MAC address to hardware */ + mlxbf_gige_initial_mac(priv); + +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h +index 98a8681c21b9c..4d14cb13fd64e 100644 +--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h +@@ -62,6 +62,8 @@ + #define MLXBF_GIGE_TX_STATUS_DATA_FIFO_FULL BIT(1) + #define MLXBF_GIGE_RX_MAC_FILTER_DMAC_RANGE_START 0x0520 + #define MLXBF_GIGE_RX_MAC_FILTER_DMAC_RANGE_END 0x0528 ++#define MLXBF_GIGE_RX_MAC_FILTER_GENERAL 0x0530 ++#define MLXBF_GIGE_RX_MAC_FILTER_EN_MULTICAST BIT(1) + #define MLXBF_GIGE_RX_MAC_FILTER_COUNT_DISC 0x0540 + #define MLXBF_GIGE_RX_MAC_FILTER_COUNT_DISC_EN BIT(0) + #define MLXBF_GIGE_RX_MAC_FILTER_COUNT_PASS 0x0548 +diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_rx.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_rx.c +index 6999843584934..eb62620b63c7f 100644 +--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_rx.c ++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_rx.c +@@ -11,15 +11,31 @@ + #include "mlxbf_gige.h" + #include "mlxbf_gige_regs.h" + +-void mlxbf_gige_set_mac_rx_filter(struct mlxbf_gige *priv, +- unsigned int index, u64 dmac) ++void mlxbf_gige_enable_multicast_rx(struct mlxbf_gige *priv) + { + void __iomem *base = priv->base; +- u64 control; ++ u64 data; + +- /* Write destination MAC to specified MAC RX filter */ +- writeq(dmac, base + MLXBF_GIGE_RX_MAC_FILTER + +- (index * MLXBF_GIGE_RX_MAC_FILTER_STRIDE)); ++ data = readq(base + MLXBF_GIGE_RX_MAC_FILTER_GENERAL); ++ data |= MLXBF_GIGE_RX_MAC_FILTER_EN_MULTICAST; ++ writeq(data, base + MLXBF_GIGE_RX_MAC_FILTER_GENERAL); ++} ++ ++void mlxbf_gige_disable_multicast_rx(struct mlxbf_gige *priv) ++{ ++ void __iomem *base = priv->base; ++ u64 data; ++ ++ data = readq(base + MLXBF_GIGE_RX_MAC_FILTER_GENERAL); ++ data &= ~MLXBF_GIGE_RX_MAC_FILTER_EN_MULTICAST; ++ writeq(data, base + MLXBF_GIGE_RX_MAC_FILTER_GENERAL); ++} ++ ++void mlxbf_gige_enable_mac_rx_filter(struct mlxbf_gige *priv, ++ unsigned int index) ++{ ++ void __iomem *base = priv->base; ++ u64 control; + + /* Enable MAC receive filter mask for specified index */ + control = readq(base + MLXBF_GIGE_CONTROL); +@@ -27,6 +43,28 @@ void mlxbf_gige_set_mac_rx_filter(struct mlxbf_gige *priv, + writeq(control, base + MLXBF_GIGE_CONTROL); + } + ++void mlxbf_gige_disable_mac_rx_filter(struct mlxbf_gige *priv, ++ unsigned int index) ++{ ++ void __iomem *base = priv->base; ++ u64 control; ++ ++ /* Disable MAC receive filter mask for specified index */ ++ control = readq(base + MLXBF_GIGE_CONTROL); ++ control &= ~(MLXBF_GIGE_CONTROL_EN_SPECIFIC_MAC << index); ++ writeq(control, base + MLXBF_GIGE_CONTROL); ++} ++ ++void mlxbf_gige_set_mac_rx_filter(struct mlxbf_gige *priv, ++ unsigned int index, u64 dmac) ++{ ++ void __iomem *base = priv->base; ++ ++ /* Write destination MAC to specified MAC RX filter */ ++ writeq(dmac, base + MLXBF_GIGE_RX_MAC_FILTER + ++ (index * MLXBF_GIGE_RX_MAC_FILTER_STRIDE)); ++} ++ + void mlxbf_gige_get_mac_rx_filter(struct mlxbf_gige *priv, + unsigned int index, u64 *dmac) + { +diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c +index ad7ae7ba2b8fc..482b9cd369508 100644 +--- a/drivers/net/ethernet/microsoft/mana/mana_en.c ++++ b/drivers/net/ethernet/microsoft/mana/mana_en.c +@@ -599,7 +599,11 @@ static void mana_get_rxbuf_cfg(int mtu, u32 *datasize, u32 *alloc_size, + else + *headroom = XDP_PACKET_HEADROOM; + +- *alloc_size = mtu + MANA_RXBUF_PAD + *headroom; ++ *alloc_size = SKB_DATA_ALIGN(mtu + MANA_RXBUF_PAD + *headroom); ++ ++ /* Using page pool in this case, so alloc_size is PAGE_SIZE */ ++ if (*alloc_size < PAGE_SIZE) ++ *alloc_size = PAGE_SIZE; + + *datasize = mtu + ETH_HLEN; + } +@@ -1773,7 +1777,6 @@ static void mana_poll_rx_cq(struct mana_cq *cq) + static int mana_cq_handler(void *context, struct gdma_queue *gdma_queue) + { + struct mana_cq *cq = context; +- u8 arm_bit; + int w; + + WARN_ON_ONCE(cq->gdma_cq != gdma_queue); +@@ -1784,16 +1787,23 @@ static int mana_cq_handler(void *context, struct gdma_queue *gdma_queue) + mana_poll_tx_cq(cq); + + w = cq->work_done; +- +- if (w < cq->budget && +- napi_complete_done(&cq->napi, w)) { +- arm_bit = SET_ARM_BIT; +- } else { +- arm_bit = 0; ++ cq->work_done_since_doorbell += w; ++ ++ if (w < cq->budget) { ++ mana_gd_ring_cq(gdma_queue, SET_ARM_BIT); ++ cq->work_done_since_doorbell = 0; ++ napi_complete_done(&cq->napi, w); ++ } else if (cq->work_done_since_doorbell > ++ cq->gdma_cq->queue_size / COMP_ENTRY_SIZE * 4) { ++ /* MANA hardware requires at least one doorbell ring every 8 ++ * wraparounds of CQ even if there is no need to arm the CQ. ++ * This driver rings the doorbell as soon as we have exceeded ++ * 4 wraparounds. ++ */ ++ mana_gd_ring_cq(gdma_queue, 0); ++ cq->work_done_since_doorbell = 0; + } + +- mana_gd_ring_cq(gdma_queue, arm_bit); +- + return w; + } + +diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c +index ed2fb44500b0c..f4e027a6fe955 100644 +--- a/drivers/net/ethernet/mscc/ocelot.c ++++ b/drivers/net/ethernet/mscc/ocelot.c +@@ -1099,6 +1099,48 @@ void ocelot_ptp_rx_timestamp(struct ocelot *ocelot, struct sk_buff *skb, + } + EXPORT_SYMBOL(ocelot_ptp_rx_timestamp); + ++void ocelot_lock_inj_grp(struct ocelot *ocelot, int grp) ++ __acquires(&ocelot->inj_lock) ++{ ++ spin_lock(&ocelot->inj_lock); ++} ++EXPORT_SYMBOL_GPL(ocelot_lock_inj_grp); ++ ++void ocelot_unlock_inj_grp(struct ocelot *ocelot, int grp) ++ __releases(&ocelot->inj_lock) ++{ ++ spin_unlock(&ocelot->inj_lock); ++} ++EXPORT_SYMBOL_GPL(ocelot_unlock_inj_grp); ++ ++void ocelot_lock_xtr_grp(struct ocelot *ocelot, int grp) ++ __acquires(&ocelot->inj_lock) ++{ ++ spin_lock(&ocelot->inj_lock); ++} ++EXPORT_SYMBOL_GPL(ocelot_lock_xtr_grp); ++ ++void ocelot_unlock_xtr_grp(struct ocelot *ocelot, int grp) ++ __releases(&ocelot->inj_lock) ++{ ++ spin_unlock(&ocelot->inj_lock); ++} ++EXPORT_SYMBOL_GPL(ocelot_unlock_xtr_grp); ++ ++void ocelot_lock_xtr_grp_bh(struct ocelot *ocelot, int grp) ++ __acquires(&ocelot->xtr_lock) ++{ ++ spin_lock_bh(&ocelot->xtr_lock); ++} ++EXPORT_SYMBOL_GPL(ocelot_lock_xtr_grp_bh); ++ ++void ocelot_unlock_xtr_grp_bh(struct ocelot *ocelot, int grp) ++ __releases(&ocelot->xtr_lock) ++{ ++ spin_unlock_bh(&ocelot->xtr_lock); ++} ++EXPORT_SYMBOL_GPL(ocelot_unlock_xtr_grp_bh); ++ + int ocelot_xtr_poll_frame(struct ocelot *ocelot, int grp, struct sk_buff **nskb) + { + u64 timestamp, src_port, len; +@@ -1109,6 +1151,8 @@ int ocelot_xtr_poll_frame(struct ocelot *ocelot, int grp, struct sk_buff **nskb) + u32 val, *buf; + int err; + ++ lockdep_assert_held(&ocelot->xtr_lock); ++ + err = ocelot_xtr_poll_xfh(ocelot, grp, xfh); + if (err) + return err; +@@ -1184,6 +1228,8 @@ bool ocelot_can_inject(struct ocelot *ocelot, int grp) + { + u32 val = ocelot_read(ocelot, QS_INJ_STATUS); + ++ lockdep_assert_held(&ocelot->inj_lock); ++ + if (!(val & QS_INJ_STATUS_FIFO_RDY(BIT(grp)))) + return false; + if (val & QS_INJ_STATUS_WMARK_REACHED(BIT(grp))) +@@ -1193,28 +1239,55 @@ bool ocelot_can_inject(struct ocelot *ocelot, int grp) + } + EXPORT_SYMBOL(ocelot_can_inject); + +-void ocelot_ifh_port_set(void *ifh, int port, u32 rew_op, u32 vlan_tag) ++/** ++ * ocelot_ifh_set_basic - Set basic information in Injection Frame Header ++ * @ifh: Pointer to Injection Frame Header memory ++ * @ocelot: Switch private data structure ++ * @port: Egress port number ++ * @rew_op: Egress rewriter operation for PTP ++ * @skb: Pointer to socket buffer (packet) ++ * ++ * Populate the Injection Frame Header with basic information for this skb: the ++ * analyzer bypass bit, destination port, VLAN info, egress rewriter info. ++ */ ++void ocelot_ifh_set_basic(void *ifh, struct ocelot *ocelot, int port, ++ u32 rew_op, struct sk_buff *skb) + { ++ struct ocelot_port *ocelot_port = ocelot->ports[port]; ++ struct net_device *dev = skb->dev; ++ u64 vlan_tci, tag_type; ++ int qos_class; ++ ++ ocelot_xmit_get_vlan_info(skb, ocelot_port->bridge, &vlan_tci, ++ &tag_type); ++ ++ qos_class = netdev_get_num_tc(dev) ? ++ netdev_get_prio_tc_map(dev, skb->priority) : skb->priority; ++ ++ memset(ifh, 0, OCELOT_TAG_LEN); + ocelot_ifh_set_bypass(ifh, 1); ++ ocelot_ifh_set_src(ifh, BIT_ULL(ocelot->num_phys_ports)); + ocelot_ifh_set_dest(ifh, BIT_ULL(port)); +- ocelot_ifh_set_tag_type(ifh, IFH_TAG_TYPE_C); +- if (vlan_tag) +- ocelot_ifh_set_vlan_tci(ifh, vlan_tag); ++ ocelot_ifh_set_qos_class(ifh, qos_class); ++ ocelot_ifh_set_tag_type(ifh, tag_type); ++ ocelot_ifh_set_vlan_tci(ifh, vlan_tci); + if (rew_op) + ocelot_ifh_set_rew_op(ifh, rew_op); + } +-EXPORT_SYMBOL(ocelot_ifh_port_set); ++EXPORT_SYMBOL(ocelot_ifh_set_basic); + + void ocelot_port_inject_frame(struct ocelot *ocelot, int port, int grp, + u32 rew_op, struct sk_buff *skb) + { +- u32 ifh[OCELOT_TAG_LEN / 4] = {0}; ++ u32 ifh[OCELOT_TAG_LEN / 4]; + unsigned int i, count, last; + ++ lockdep_assert_held(&ocelot->inj_lock); ++ + ocelot_write_rix(ocelot, QS_INJ_CTRL_GAP_SIZE(1) | + QS_INJ_CTRL_SOF, QS_INJ_CTRL, grp); + +- ocelot_ifh_port_set(ifh, port, rew_op, skb_vlan_tag_get(skb)); ++ ocelot_ifh_set_basic(ifh, ocelot, port, rew_op, skb); + + for (i = 0; i < OCELOT_TAG_LEN / 4; i++) + ocelot_write_rix(ocelot, ifh[i], QS_INJ_WR, grp); +@@ -1247,6 +1320,8 @@ EXPORT_SYMBOL(ocelot_port_inject_frame); + + void ocelot_drain_cpu_queue(struct ocelot *ocelot, int grp) + { ++ lockdep_assert_held(&ocelot->xtr_lock); ++ + while (ocelot_read(ocelot, QS_XTR_DATA_PRESENT) & BIT(grp)) + ocelot_read_rix(ocelot, QS_XTR_RD, grp); + } +@@ -2929,6 +3004,8 @@ int ocelot_init(struct ocelot *ocelot) + mutex_init(&ocelot->fwd_domain_lock); + spin_lock_init(&ocelot->ptp_clock_lock); + spin_lock_init(&ocelot->ts_id_lock); ++ spin_lock_init(&ocelot->inj_lock); ++ spin_lock_init(&ocelot->xtr_lock); + + ocelot->owq = alloc_ordered_workqueue("ocelot-owq", 0); + if (!ocelot->owq) +diff --git a/drivers/net/ethernet/mscc/ocelot_fdma.c b/drivers/net/ethernet/mscc/ocelot_fdma.c +index 312a468321544..00326ae8c708b 100644 +--- a/drivers/net/ethernet/mscc/ocelot_fdma.c ++++ b/drivers/net/ethernet/mscc/ocelot_fdma.c +@@ -665,8 +665,7 @@ static int ocelot_fdma_prepare_skb(struct ocelot *ocelot, int port, u32 rew_op, + + ifh = skb_push(skb, OCELOT_TAG_LEN); + skb_put(skb, ETH_FCS_LEN); +- memset(ifh, 0, OCELOT_TAG_LEN); +- ocelot_ifh_port_set(ifh, port, rew_op, skb_vlan_tag_get(skb)); ++ ocelot_ifh_set_basic(ifh, ocelot, port, rew_op, skb); + + return 0; + } +diff --git a/drivers/net/ethernet/mscc/ocelot_vsc7514.c b/drivers/net/ethernet/mscc/ocelot_vsc7514.c +index 993212c3a7da6..c09dd2e3343cb 100644 +--- a/drivers/net/ethernet/mscc/ocelot_vsc7514.c ++++ b/drivers/net/ethernet/mscc/ocelot_vsc7514.c +@@ -51,6 +51,8 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg) + struct ocelot *ocelot = arg; + int grp = 0, err; + ++ ocelot_lock_xtr_grp(ocelot, grp); ++ + while (ocelot_read(ocelot, QS_XTR_DATA_PRESENT) & BIT(grp)) { + struct sk_buff *skb; + +@@ -69,6 +71,8 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg) + if (err < 0) + ocelot_drain_cpu_queue(ocelot, 0); + ++ ocelot_unlock_xtr_grp(ocelot, grp); ++ + return IRQ_HANDLED; + } + +diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c +index ec54b18c5fe73..a5e9b779c44d0 100644 +--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c ++++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_mdio.c +@@ -124,8 +124,12 @@ static int ngbe_phylink_init(struct wx *wx) + MAC_SYM_PAUSE | MAC_ASYM_PAUSE; + config->mac_managed_pm = true; + +- phy_mode = PHY_INTERFACE_MODE_RGMII_ID; +- __set_bit(PHY_INTERFACE_MODE_RGMII_ID, config->supported_interfaces); ++ /* The MAC only has add the Tx delay and it can not be modified. ++ * So just disable TX delay in PHY, and it is does not matter to ++ * internal phy. ++ */ ++ phy_mode = PHY_INTERFACE_MODE_RGMII_RXID; ++ __set_bit(PHY_INTERFACE_MODE_RGMII_RXID, config->supported_interfaces); + + phylink = phylink_create(config, NULL, phy_mode, &ngbe_mac_ops); + if (IS_ERR(phylink)) +diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h b/drivers/net/ethernet/xilinx/xilinx_axienet.h +index fa5500decc960..09c9f9787180b 100644 +--- a/drivers/net/ethernet/xilinx/xilinx_axienet.h ++++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h +@@ -160,16 +160,17 @@ + #define XAE_RCW1_OFFSET 0x00000404 /* Rx Configuration Word 1 */ + #define XAE_TC_OFFSET 0x00000408 /* Tx Configuration */ + #define XAE_FCC_OFFSET 0x0000040C /* Flow Control Configuration */ +-#define XAE_EMMC_OFFSET 0x00000410 /* EMAC mode configuration */ +-#define XAE_PHYC_OFFSET 0x00000414 /* RGMII/SGMII configuration */ ++#define XAE_EMMC_OFFSET 0x00000410 /* MAC speed configuration */ ++#define XAE_PHYC_OFFSET 0x00000414 /* RX Max Frame Configuration */ + #define XAE_ID_OFFSET 0x000004F8 /* Identification register */ +-#define XAE_MDIO_MC_OFFSET 0x00000500 /* MII Management Config */ +-#define XAE_MDIO_MCR_OFFSET 0x00000504 /* MII Management Control */ +-#define XAE_MDIO_MWD_OFFSET 0x00000508 /* MII Management Write Data */ +-#define XAE_MDIO_MRD_OFFSET 0x0000050C /* MII Management Read Data */ ++#define XAE_MDIO_MC_OFFSET 0x00000500 /* MDIO Setup */ ++#define XAE_MDIO_MCR_OFFSET 0x00000504 /* MDIO Control */ ++#define XAE_MDIO_MWD_OFFSET 0x00000508 /* MDIO Write Data */ ++#define XAE_MDIO_MRD_OFFSET 0x0000050C /* MDIO Read Data */ + #define XAE_UAW0_OFFSET 0x00000700 /* Unicast address word 0 */ + #define XAE_UAW1_OFFSET 0x00000704 /* Unicast address word 1 */ +-#define XAE_FMI_OFFSET 0x00000708 /* Filter Mask Index */ ++#define XAE_FMI_OFFSET 0x00000708 /* Frame Filter Control */ ++#define XAE_FFE_OFFSET 0x0000070C /* Frame Filter Enable */ + #define XAE_AF0_OFFSET 0x00000710 /* Address Filter 0 */ + #define XAE_AF1_OFFSET 0x00000714 /* Address Filter 1 */ + +@@ -308,7 +309,7 @@ + */ + #define XAE_UAW1_UNICASTADDR_MASK 0x0000FFFF + +-/* Bit masks for Axi Ethernet FMI register */ ++/* Bit masks for Axi Ethernet FMC register */ + #define XAE_FMI_PM_MASK 0x80000000 /* Promis. mode enable */ + #define XAE_FMI_IND_MASK 0x00000003 /* Index Mask */ + +diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +index fa510f4e26008..559c0d60d9483 100644 +--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c ++++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +@@ -432,7 +432,7 @@ static int netdev_set_mac_address(struct net_device *ndev, void *p) + */ + static void axienet_set_multicast_list(struct net_device *ndev) + { +- int i; ++ int i = 0; + u32 reg, af0reg, af1reg; + struct axienet_local *lp = netdev_priv(ndev); + +@@ -450,7 +450,10 @@ static void axienet_set_multicast_list(struct net_device *ndev) + } else if (!netdev_mc_empty(ndev)) { + struct netdev_hw_addr *ha; + +- i = 0; ++ reg = axienet_ior(lp, XAE_FMI_OFFSET); ++ reg &= ~XAE_FMI_PM_MASK; ++ axienet_iow(lp, XAE_FMI_OFFSET, reg); ++ + netdev_for_each_mc_addr(ha, ndev) { + if (i >= XAE_MULTICAST_CAM_TABLE_NUM) + break; +@@ -469,6 +472,7 @@ static void axienet_set_multicast_list(struct net_device *ndev) + axienet_iow(lp, XAE_FMI_OFFSET, reg); + axienet_iow(lp, XAE_AF0_OFFSET, af0reg); + axienet_iow(lp, XAE_AF1_OFFSET, af1reg); ++ axienet_iow(lp, XAE_FFE_OFFSET, 1); + i++; + } + } else { +@@ -476,18 +480,15 @@ static void axienet_set_multicast_list(struct net_device *ndev) + reg &= ~XAE_FMI_PM_MASK; + + axienet_iow(lp, XAE_FMI_OFFSET, reg); +- +- for (i = 0; i < XAE_MULTICAST_CAM_TABLE_NUM; i++) { +- reg = axienet_ior(lp, XAE_FMI_OFFSET) & 0xFFFFFF00; +- reg |= i; +- +- axienet_iow(lp, XAE_FMI_OFFSET, reg); +- axienet_iow(lp, XAE_AF0_OFFSET, 0); +- axienet_iow(lp, XAE_AF1_OFFSET, 0); +- } +- + dev_info(&ndev->dev, "Promiscuous mode disabled.\n"); + } ++ ++ for (; i < XAE_MULTICAST_CAM_TABLE_NUM; i++) { ++ reg = axienet_ior(lp, XAE_FMI_OFFSET) & 0xFFFFFF00; ++ reg |= i; ++ axienet_iow(lp, XAE_FMI_OFFSET, reg); ++ axienet_iow(lp, XAE_FFE_OFFSET, 0); ++ } + } + + /** +diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c +index 427b91aca50d3..0696faf60013e 100644 +--- a/drivers/net/gtp.c ++++ b/drivers/net/gtp.c +@@ -1269,6 +1269,9 @@ static netdev_tx_t gtp_dev_xmit(struct sk_buff *skb, struct net_device *dev) + if (skb_cow_head(skb, dev->needed_headroom)) + goto tx_err; + ++ if (!pskb_inet_may_pull(skb)) ++ goto tx_err; ++ + skb_reset_inner_headers(skb); + + /* PDP context lookups in gtp_build_skb_*() need rcu read-side lock. */ +diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c +index a7c7a868c14ce..fca9f7e510b41 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_tx.c +@@ -124,6 +124,60 @@ static void ath12k_hal_tx_cmd_ext_desc_setup(struct ath12k_base *ab, + HAL_TX_MSDU_EXT_INFO1_ENCRYPT_TYPE); + } + ++static void ath12k_dp_tx_move_payload(struct sk_buff *skb, ++ unsigned long delta, ++ bool head) ++{ ++ unsigned long len = skb->len; ++ ++ if (head) { ++ skb_push(skb, delta); ++ memmove(skb->data, skb->data + delta, len); ++ skb_trim(skb, len); ++ } else { ++ skb_put(skb, delta); ++ memmove(skb->data + delta, skb->data, len); ++ skb_pull(skb, delta); ++ } ++} ++ ++static int ath12k_dp_tx_align_payload(struct ath12k_base *ab, ++ struct sk_buff **pskb) ++{ ++ u32 iova_mask = ab->hw_params->iova_mask; ++ unsigned long offset, delta1, delta2; ++ struct sk_buff *skb2, *skb = *pskb; ++ unsigned int headroom = skb_headroom(skb); ++ int tailroom = skb_tailroom(skb); ++ int ret = 0; ++ ++ offset = (unsigned long)skb->data & iova_mask; ++ delta1 = offset; ++ delta2 = iova_mask - offset + 1; ++ ++ if (headroom >= delta1) { ++ ath12k_dp_tx_move_payload(skb, delta1, true); ++ } else if (tailroom >= delta2) { ++ ath12k_dp_tx_move_payload(skb, delta2, false); ++ } else { ++ skb2 = skb_realloc_headroom(skb, iova_mask); ++ if (!skb2) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ dev_kfree_skb_any(skb); ++ ++ offset = (unsigned long)skb2->data & iova_mask; ++ if (offset) ++ ath12k_dp_tx_move_payload(skb2, offset, true); ++ *pskb = skb2; ++ } ++ ++out: ++ return ret; ++} ++ + int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif, + struct sk_buff *skb) + { +@@ -145,6 +199,7 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif, + u8 ring_selector, ring_map = 0; + bool tcl_ring_retry; + bool msdu_ext_desc = false; ++ u32 iova_mask = ab->hw_params->iova_mask; + + if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags)) + return -ESHUTDOWN; +@@ -240,6 +295,23 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif, + goto fail_remove_tx_buf; + } + ++ if (iova_mask && ++ (unsigned long)skb->data & iova_mask) { ++ ret = ath12k_dp_tx_align_payload(ab, &skb); ++ if (ret) { ++ ath12k_warn(ab, "failed to align TX buffer %d\n", ret); ++ /* don't bail out, give original buffer ++ * a chance even unaligned. ++ */ ++ goto map; ++ } ++ ++ /* hdr is pointing to a wrong place after alignment, ++ * so refresh it for later use. ++ */ ++ hdr = (void *)skb->data; ++ } ++map: + ti.paddr = dma_map_single(ab->dev, skb->data, skb->len, DMA_TO_DEVICE); + if (dma_mapping_error(ab->dev, ti.paddr)) { + atomic_inc(&ab->soc_stats.tx_err.misc_fail); +diff --git a/drivers/net/wireless/ath/ath12k/hw.c b/drivers/net/wireless/ath/ath12k/hw.c +index bff8cf97a18c6..2a92147d15fa1 100644 +--- a/drivers/net/wireless/ath/ath12k/hw.c ++++ b/drivers/net/wireless/ath/ath12k/hw.c +@@ -922,6 +922,8 @@ static const struct ath12k_hw_params ath12k_hw_params[] = { + .supports_sta_ps = false, + + .acpi_guid = NULL, ++ ++ .iova_mask = 0, + }, + { + .name = "wcn7850 hw2.0", +@@ -997,6 +999,8 @@ static const struct ath12k_hw_params ath12k_hw_params[] = { + .supports_sta_ps = true, + + .acpi_guid = &wcn7850_uuid, ++ ++ .iova_mask = ATH12K_PCIE_MAX_PAYLOAD_SIZE - 1, + }, + { + .name = "qcn9274 hw2.0", +@@ -1067,6 +1071,8 @@ static const struct ath12k_hw_params ath12k_hw_params[] = { + .supports_sta_ps = false, + + .acpi_guid = NULL, ++ ++ .iova_mask = 0, + }, + }; + +diff --git a/drivers/net/wireless/ath/ath12k/hw.h b/drivers/net/wireless/ath/ath12k/hw.h +index 2a314cfc8cb84..400bda17e02f6 100644 +--- a/drivers/net/wireless/ath/ath12k/hw.h ++++ b/drivers/net/wireless/ath/ath12k/hw.h +@@ -96,6 +96,8 @@ + #define ATH12K_M3_FILE "m3.bin" + #define ATH12K_REGDB_FILE_NAME "regdb.bin" + ++#define ATH12K_PCIE_MAX_PAYLOAD_SIZE 128 ++ + enum ath12k_hw_rate_cck { + ATH12K_HW_RATE_CCK_LP_11M = 0, + ATH12K_HW_RATE_CCK_LP_5_5M, +@@ -214,6 +216,8 @@ struct ath12k_hw_params { + bool supports_sta_ps; + + const guid_t *acpi_guid; ++ ++ u32 iova_mask; + }; + + struct ath12k_hw_ops { +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index ead37a4e002a2..8474e25d2ac64 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -8737,6 +8737,7 @@ static int ath12k_mac_hw_register(struct ath12k_hw *ah) + + hw->vif_data_size = sizeof(struct ath12k_vif); + hw->sta_data_size = sizeof(struct ath12k_sta); ++ hw->extra_tx_headroom = ab->hw_params->iova_mask; + + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_STA_TX_PWR); +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +index 5fe0e671ecb36..826b768196e28 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -4320,9 +4320,16 @@ brcmf_pmksa_v3_op(struct brcmf_if *ifp, struct cfg80211_pmksa *pmksa, + /* Single PMK operation */ + pmk_op->count = cpu_to_le16(1); + length += sizeof(struct brcmf_pmksa_v3); +- memcpy(pmk_op->pmk[0].bssid, pmksa->bssid, ETH_ALEN); +- memcpy(pmk_op->pmk[0].pmkid, pmksa->pmkid, WLAN_PMKID_LEN); +- pmk_op->pmk[0].pmkid_len = WLAN_PMKID_LEN; ++ if (pmksa->bssid) ++ memcpy(pmk_op->pmk[0].bssid, pmksa->bssid, ETH_ALEN); ++ if (pmksa->pmkid) { ++ memcpy(pmk_op->pmk[0].pmkid, pmksa->pmkid, WLAN_PMKID_LEN); ++ pmk_op->pmk[0].pmkid_len = WLAN_PMKID_LEN; ++ } ++ if (pmksa->ssid && pmksa->ssid_len) { ++ memcpy(pmk_op->pmk[0].ssid.SSID, pmksa->ssid, pmksa->ssid_len); ++ pmk_op->pmk[0].ssid.SSID_len = pmksa->ssid_len; ++ } + pmk_op->pmk[0].time_left = cpu_to_le32(alive ? BRCMF_PMKSA_NO_EXPIRY : 0); + } + +diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c +index 782090ce0bc10..d973d063bbf50 100644 +--- a/drivers/nvme/host/core.c ++++ b/drivers/nvme/host/core.c +@@ -4522,7 +4522,6 @@ void nvme_stop_ctrl(struct nvme_ctrl *ctrl) + { + nvme_mpath_stop(ctrl); + nvme_auth_stop(ctrl); +- nvme_stop_keep_alive(ctrl); + nvme_stop_failfast_work(ctrl); + flush_work(&ctrl->async_event_work); + cancel_work_sync(&ctrl->fw_act_work); +@@ -4558,6 +4557,7 @@ EXPORT_SYMBOL_GPL(nvme_start_ctrl); + + void nvme_uninit_ctrl(struct nvme_ctrl *ctrl) + { ++ nvme_stop_keep_alive(ctrl); + nvme_hwmon_exit(ctrl); + nvme_fault_inject_fini(&ctrl->fault_inject); + dev_pm_qos_hide_latency_tolerance(ctrl->device); +diff --git a/drivers/platform/surface/aggregator/controller.c b/drivers/platform/surface/aggregator/controller.c +index 7fc602e01487d..7e89f547999b2 100644 +--- a/drivers/platform/surface/aggregator/controller.c ++++ b/drivers/platform/surface/aggregator/controller.c +@@ -1354,7 +1354,8 @@ void ssam_controller_destroy(struct ssam_controller *ctrl) + if (ctrl->state == SSAM_CONTROLLER_UNINITIALIZED) + return; + +- WARN_ON(ctrl->state != SSAM_CONTROLLER_STOPPED); ++ WARN_ON(ctrl->state != SSAM_CONTROLLER_STOPPED && ++ ctrl->state != SSAM_CONTROLLER_INITIALIZED); + + /* + * Note: New events could still have been received after the previous +diff --git a/drivers/platform/x86/dell/Kconfig b/drivers/platform/x86/dell/Kconfig +index 195a8bf532cc6..de0bfd8f4b66e 100644 +--- a/drivers/platform/x86/dell/Kconfig ++++ b/drivers/platform/x86/dell/Kconfig +@@ -148,6 +148,7 @@ config DELL_SMO8800 + config DELL_UART_BACKLIGHT + tristate "Dell AIO UART Backlight driver" + depends on ACPI ++ depends on ACPI_VIDEO + depends on BACKLIGHT_CLASS_DEVICE + depends on SERIAL_DEV_BUS + help +diff --git a/drivers/platform/x86/dell/dell-uart-backlight.c b/drivers/platform/x86/dell/dell-uart-backlight.c +index 87d2a20b4cb3d..3995f90add456 100644 +--- a/drivers/platform/x86/dell/dell-uart-backlight.c ++++ b/drivers/platform/x86/dell/dell-uart-backlight.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + #include "../serdev_helpers.h" + + /* The backlight controller must respond within 1 second */ +@@ -332,10 +333,17 @@ struct serdev_device_driver dell_uart_bl_serdev_driver = { + + static int dell_uart_bl_pdev_probe(struct platform_device *pdev) + { ++ enum acpi_backlight_type bl_type; + struct serdev_device *serdev; + struct device *ctrl_dev; + int ret; + ++ bl_type = acpi_video_get_backlight_type(); ++ if (bl_type != acpi_backlight_dell_uart) { ++ dev_dbg(&pdev->dev, "Not loading (ACPI backlight type = %d)\n", bl_type); ++ return -ENODEV; ++ } ++ + ctrl_dev = get_serdev_controller("DELL0501", NULL, 0, "serial0"); + if (IS_ERR(ctrl_dev)) + return PTR_ERR(ctrl_dev); +diff --git a/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c b/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c +index 7fa360073f6ef..4045823071091 100644 +--- a/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c ++++ b/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c +@@ -1549,8 +1549,7 @@ int tpmi_sst_dev_add(struct auxiliary_device *auxdev) + goto unlock_free; + } + +- ret = sst_main(auxdev, &pd_info[i]); +- if (ret) { ++ if (sst_main(auxdev, &pd_info[i])) { + /* + * This entry is not valid, hardware can partially + * populate dies. In this case MMIO will have 0xFFs. +diff --git a/drivers/pmdomain/imx/imx93-pd.c b/drivers/pmdomain/imx/imx93-pd.c +index 1e94b499c19bc..d750a7dc58d21 100644 +--- a/drivers/pmdomain/imx/imx93-pd.c ++++ b/drivers/pmdomain/imx/imx93-pd.c +@@ -20,6 +20,7 @@ + #define FUNC_STAT_PSW_STAT_MASK BIT(0) + #define FUNC_STAT_RST_STAT_MASK BIT(2) + #define FUNC_STAT_ISO_STAT_MASK BIT(4) ++#define FUNC_STAT_SSAR_STAT_MASK BIT(8) + + struct imx93_power_domain { + struct generic_pm_domain genpd; +@@ -50,7 +51,7 @@ static int imx93_pd_on(struct generic_pm_domain *genpd) + writel(val, addr + MIX_SLICE_SW_CTRL_OFF); + + ret = readl_poll_timeout(addr + MIX_FUNC_STAT_OFF, val, +- !(val & FUNC_STAT_ISO_STAT_MASK), 1, 10000); ++ !(val & FUNC_STAT_SSAR_STAT_MASK), 1, 10000); + if (ret) { + dev_err(domain->dev, "pd_on timeout: name: %s, stat: %x\n", genpd->name, val); + return ret; +@@ -72,7 +73,7 @@ static int imx93_pd_off(struct generic_pm_domain *genpd) + writel(val, addr + MIX_SLICE_SW_CTRL_OFF); + + ret = readl_poll_timeout(addr + MIX_FUNC_STAT_OFF, val, +- val & FUNC_STAT_PSW_STAT_MASK, 1, 1000); ++ val & FUNC_STAT_PSW_STAT_MASK, 1, 10000); + if (ret) { + dev_err(domain->dev, "pd_off timeout: name: %s, stat: %x\n", genpd->name, val); + return ret; +diff --git a/drivers/pmdomain/imx/scu-pd.c b/drivers/pmdomain/imx/scu-pd.c +index 05841b0bf7f30..01d465d88f60d 100644 +--- a/drivers/pmdomain/imx/scu-pd.c ++++ b/drivers/pmdomain/imx/scu-pd.c +@@ -223,11 +223,6 @@ static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = { + { "lvds1-pwm", IMX_SC_R_LVDS_1_PWM_0, 1, false, 0 }, + { "lvds1-lpi2c", IMX_SC_R_LVDS_1_I2C_0, 2, true, 0 }, + +- { "mipi1", IMX_SC_R_MIPI_1, 1, 0 }, +- { "mipi1-pwm0", IMX_SC_R_MIPI_1_PWM_0, 1, 0 }, +- { "mipi1-i2c", IMX_SC_R_MIPI_1_I2C_0, 2, 1 }, +- { "lvds1", IMX_SC_R_LVDS_1, 1, 0 }, +- + /* DC SS */ + { "dc0", IMX_SC_R_DC_0, 1, false, 0 }, + { "dc0-pll", IMX_SC_R_DC_0_PLL_0, 2, true, 0 }, +diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c +index 0a97cfedd7060..42a4a996defbe 100644 +--- a/drivers/s390/block/dasd.c ++++ b/drivers/s390/block/dasd.c +@@ -1601,9 +1601,15 @@ static int dasd_ese_needs_format(struct dasd_block *block, struct irb *irb) + if (!sense) + return 0; + +- return !!(sense[1] & SNS1_NO_REC_FOUND) || +- !!(sense[1] & SNS1_FILE_PROTECTED) || +- scsw_cstat(&irb->scsw) == SCHN_STAT_INCORR_LEN; ++ if (sense[1] & SNS1_NO_REC_FOUND) ++ return 1; ++ ++ if ((sense[1] & SNS1_INV_TRACK_FORMAT) && ++ scsw_is_tm(&irb->scsw) && ++ !(sense[2] & SNS2_ENV_DATA_PRESENT)) ++ return 1; ++ ++ return 0; + } + + static int dasd_ese_oos_cond(u8 *sense) +@@ -1624,7 +1630,7 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, + struct dasd_device *device; + unsigned long now; + int nrf_suppressed = 0; +- int fp_suppressed = 0; ++ int it_suppressed = 0; + struct request *req; + u8 *sense = NULL; + int expires; +@@ -1679,8 +1685,9 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, + */ + sense = dasd_get_sense(irb); + if (sense) { +- fp_suppressed = (sense[1] & SNS1_FILE_PROTECTED) && +- test_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags); ++ it_suppressed = (sense[1] & SNS1_INV_TRACK_FORMAT) && ++ !(sense[2] & SNS2_ENV_DATA_PRESENT) && ++ test_bit(DASD_CQR_SUPPRESS_IT, &cqr->flags); + nrf_suppressed = (sense[1] & SNS1_NO_REC_FOUND) && + test_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags); + +@@ -1695,7 +1702,7 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, + return; + } + } +- if (!(fp_suppressed || nrf_suppressed)) ++ if (!(it_suppressed || nrf_suppressed)) + device->discipline->dump_sense_dbf(device, irb, "int"); + + if (device->features & DASD_FEATURE_ERPLOG) +@@ -2459,14 +2466,17 @@ static int _dasd_sleep_on_queue(struct list_head *ccw_queue, int interruptible) + rc = 0; + list_for_each_entry_safe(cqr, n, ccw_queue, blocklist) { + /* +- * In some cases the 'File Protected' or 'Incorrect Length' +- * error might be expected and error recovery would be +- * unnecessary in these cases. Check if the according suppress +- * bit is set. ++ * In some cases certain errors might be expected and ++ * error recovery would be unnecessary in these cases. ++ * Check if the according suppress bit is set. + */ + sense = dasd_get_sense(&cqr->irb); +- if (sense && sense[1] & SNS1_FILE_PROTECTED && +- test_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags)) ++ if (sense && (sense[1] & SNS1_INV_TRACK_FORMAT) && ++ !(sense[2] & SNS2_ENV_DATA_PRESENT) && ++ test_bit(DASD_CQR_SUPPRESS_IT, &cqr->flags)) ++ continue; ++ if (sense && (sense[1] & SNS1_NO_REC_FOUND) && ++ test_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags)) + continue; + if (scsw_cstat(&cqr->irb.scsw) == 0x40 && + test_bit(DASD_CQR_SUPPRESS_IL, &cqr->flags)) +diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c +index bbbacfc386f28..d0aa267462c50 100644 +--- a/drivers/s390/block/dasd_3990_erp.c ++++ b/drivers/s390/block/dasd_3990_erp.c +@@ -1386,14 +1386,8 @@ dasd_3990_erp_file_prot(struct dasd_ccw_req * erp) + + struct dasd_device *device = erp->startdev; + +- /* +- * In some cases the 'File Protected' error might be expected and +- * log messages shouldn't be written then. +- * Check if the according suppress bit is set. +- */ +- if (!test_bit(DASD_CQR_SUPPRESS_FP, &erp->flags)) +- dev_err(&device->cdev->dev, +- "Accessing the DASD failed because of a hardware error\n"); ++ dev_err(&device->cdev->dev, ++ "Accessing the DASD failed because of a hardware error\n"); + + return dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED); + +diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c +index a76c6af9ea638..a47443d3cc366 100644 +--- a/drivers/s390/block/dasd_eckd.c ++++ b/drivers/s390/block/dasd_eckd.c +@@ -2274,6 +2274,7 @@ dasd_eckd_analysis_ccw(struct dasd_device *device) + cqr->status = DASD_CQR_FILLED; + /* Set flags to suppress output for expected errors */ + set_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags); ++ set_bit(DASD_CQR_SUPPRESS_IT, &cqr->flags); + + return cqr; + } +@@ -2555,7 +2556,6 @@ dasd_eckd_build_check_tcw(struct dasd_device *base, struct format_data_t *fdata, + cqr->buildclk = get_tod_clock(); + cqr->status = DASD_CQR_FILLED; + /* Set flags to suppress output for expected errors */ +- set_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags); + set_bit(DASD_CQR_SUPPRESS_IL, &cqr->flags); + + return cqr; +@@ -4129,8 +4129,6 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_single( + + /* Set flags to suppress output for expected errors */ + if (dasd_eckd_is_ese(basedev)) { +- set_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags); +- set_bit(DASD_CQR_SUPPRESS_IL, &cqr->flags); + set_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags); + } + +@@ -4632,9 +4630,8 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track( + + /* Set flags to suppress output for expected errors */ + if (dasd_eckd_is_ese(basedev)) { +- set_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags); +- set_bit(DASD_CQR_SUPPRESS_IL, &cqr->flags); + set_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags); ++ set_bit(DASD_CQR_SUPPRESS_IT, &cqr->flags); + } + + return cqr; +@@ -5779,36 +5776,32 @@ static void dasd_eckd_dump_sense(struct dasd_device *device, + { + u8 *sense = dasd_get_sense(irb); + +- if (scsw_is_tm(&irb->scsw)) { +- /* +- * In some cases the 'File Protected' or 'Incorrect Length' +- * error might be expected and log messages shouldn't be written +- * then. Check if the according suppress bit is set. +- */ +- if (sense && (sense[1] & SNS1_FILE_PROTECTED) && +- test_bit(DASD_CQR_SUPPRESS_FP, &req->flags)) +- return; +- if (scsw_cstat(&irb->scsw) == 0x40 && +- test_bit(DASD_CQR_SUPPRESS_IL, &req->flags)) +- return; ++ /* ++ * In some cases certain errors might be expected and ++ * log messages shouldn't be written then. ++ * Check if the according suppress bit is set. ++ */ ++ if (sense && (sense[1] & SNS1_INV_TRACK_FORMAT) && ++ !(sense[2] & SNS2_ENV_DATA_PRESENT) && ++ test_bit(DASD_CQR_SUPPRESS_IT, &req->flags)) ++ return; + +- dasd_eckd_dump_sense_tcw(device, req, irb); +- } else { +- /* +- * In some cases the 'Command Reject' or 'No Record Found' +- * error might be expected and log messages shouldn't be +- * written then. Check if the according suppress bit is set. +- */ +- if (sense && sense[0] & SNS0_CMD_REJECT && +- test_bit(DASD_CQR_SUPPRESS_CR, &req->flags)) +- return; ++ if (sense && sense[0] & SNS0_CMD_REJECT && ++ test_bit(DASD_CQR_SUPPRESS_CR, &req->flags)) ++ return; + +- if (sense && sense[1] & SNS1_NO_REC_FOUND && +- test_bit(DASD_CQR_SUPPRESS_NRF, &req->flags)) +- return; ++ if (sense && sense[1] & SNS1_NO_REC_FOUND && ++ test_bit(DASD_CQR_SUPPRESS_NRF, &req->flags)) ++ return; + ++ if (scsw_cstat(&irb->scsw) == 0x40 && ++ test_bit(DASD_CQR_SUPPRESS_IL, &req->flags)) ++ return; ++ ++ if (scsw_is_tm(&irb->scsw)) ++ dasd_eckd_dump_sense_tcw(device, req, irb); ++ else + dasd_eckd_dump_sense_ccw(device, req, irb); +- } + } + + static int dasd_eckd_reload_device(struct dasd_device *device) +diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c +index 4533dd055ca8e..23d6e638f381d 100644 +--- a/drivers/s390/block/dasd_genhd.c ++++ b/drivers/s390/block/dasd_genhd.c +@@ -41,7 +41,6 @@ int dasd_gendisk_alloc(struct dasd_block *block) + */ + .max_segment_size = PAGE_SIZE, + .seg_boundary_mask = PAGE_SIZE - 1, +- .dma_alignment = PAGE_SIZE - 1, + .max_segments = USHRT_MAX, + }; + struct gendisk *gdp; +diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h +index e5f40536b4254..81cfb5c89681b 100644 +--- a/drivers/s390/block/dasd_int.h ++++ b/drivers/s390/block/dasd_int.h +@@ -196,7 +196,7 @@ struct dasd_ccw_req { + * The following flags are used to suppress output of certain errors. + */ + #define DASD_CQR_SUPPRESS_NRF 4 /* Suppress 'No Record Found' error */ +-#define DASD_CQR_SUPPRESS_FP 5 /* Suppress 'File Protected' error*/ ++#define DASD_CQR_SUPPRESS_IT 5 /* Suppress 'Invalid Track' error*/ + #define DASD_CQR_SUPPRESS_IL 6 /* Suppress 'Incorrect Length' error */ + #define DASD_CQR_SUPPRESS_CR 7 /* Suppress 'Command Reject' error */ + +diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c +index 898865be0dad9..99fadfb4cd9f2 100644 +--- a/drivers/s390/crypto/ap_bus.c ++++ b/drivers/s390/crypto/ap_bus.c +@@ -971,11 +971,16 @@ int ap_driver_register(struct ap_driver *ap_drv, struct module *owner, + char *name) + { + struct device_driver *drv = &ap_drv->driver; ++ int rc; + + drv->bus = &ap_bus_type; + drv->owner = owner; + drv->name = name; +- return driver_register(drv); ++ rc = driver_register(drv); ++ ++ ap_check_bindings_complete(); ++ ++ return rc; + } + EXPORT_SYMBOL(ap_driver_register); + +diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c +index 05ebb03d319fc..d4607cb89c484 100644 +--- a/drivers/spi/spi-cadence-quadspi.c ++++ b/drivers/spi/spi-cadence-quadspi.c +@@ -2000,13 +2000,25 @@ static int cqspi_runtime_resume(struct device *dev) + static int cqspi_suspend(struct device *dev) + { + struct cqspi_st *cqspi = dev_get_drvdata(dev); ++ int ret; + +- return spi_controller_suspend(cqspi->host); ++ ret = spi_controller_suspend(cqspi->host); ++ if (ret) ++ return ret; ++ ++ return pm_runtime_force_suspend(dev); + } + + static int cqspi_resume(struct device *dev) + { + struct cqspi_st *cqspi = dev_get_drvdata(dev); ++ int ret; ++ ++ ret = pm_runtime_force_resume(dev); ++ if (ret) { ++ dev_err(dev, "pm_runtime_force_resume failed on resume\n"); ++ return ret; ++ } + + return spi_controller_resume(cqspi->host); + } +diff --git a/drivers/staging/media/atomisp/pci/ia_css_stream_public.h b/drivers/staging/media/atomisp/pci/ia_css_stream_public.h +index 961c612880833..aad860e54d3a7 100644 +--- a/drivers/staging/media/atomisp/pci/ia_css_stream_public.h ++++ b/drivers/staging/media/atomisp/pci/ia_css_stream_public.h +@@ -27,12 +27,16 @@ + #include "ia_css_prbs.h" + #include "ia_css_input_port.h" + +-/* Input modes, these enumerate all supported input modes. +- * Note that not all ISP modes support all input modes. ++/* ++ * Input modes, these enumerate all supported input modes. ++ * This enum is part of the atomisp firmware ABI and must ++ * NOT be changed! ++ * Note that not all ISP modes support all input modes. + */ + enum ia_css_input_mode { + IA_CSS_INPUT_MODE_SENSOR, /** data from sensor */ + IA_CSS_INPUT_MODE_FIFO, /** data from input-fifo */ ++ IA_CSS_INPUT_MODE_TPG, /** data from test-pattern generator */ + IA_CSS_INPUT_MODE_PRBS, /** data from pseudo-random bit stream */ + IA_CSS_INPUT_MODE_MEMORY, /** data from a frame in memory */ + IA_CSS_INPUT_MODE_BUFFERED_SENSOR /** data is sent through mipi buffer */ +diff --git a/drivers/staging/media/atomisp/pci/sh_css_internal.h b/drivers/staging/media/atomisp/pci/sh_css_internal.h +index bef2b8c5132ba..419aba9b0e49e 100644 +--- a/drivers/staging/media/atomisp/pci/sh_css_internal.h ++++ b/drivers/staging/media/atomisp/pci/sh_css_internal.h +@@ -341,7 +341,14 @@ struct sh_css_sp_input_formatter_set { + + #define IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT (3) + +-/* SP configuration information */ ++/* ++ * SP configuration information ++ * ++ * This struct is part of the atomisp firmware ABI and is directly copied ++ * to ISP DRAM by sh_css_store_sp_group_to_ddr() ++ * ++ * Do NOT change this struct's layout or remove seemingly unused fields! ++ */ + struct sh_css_sp_config { + u8 no_isp_sync; /* Signal host immediately after start */ + u8 enable_raw_pool_locking; /** Enable Raw Buffer Locking for HALv3 Support */ +@@ -351,6 +358,10 @@ struct sh_css_sp_config { + host (true) or when they are passed to the preview/video pipe + (false). */ + ++ /* ++ * Note the fields below are only used on the ISP2400 not on the ISP2401, ++ * sh_css_store_sp_group_to_ddr() skip copying these when run on the ISP2401. ++ */ + struct { + u8 a_changed; + u8 b_changed; +@@ -360,11 +371,13 @@ struct sh_css_sp_config { + } input_formatter; + + sync_generator_cfg_t sync_gen; ++ tpg_cfg_t tpg; + prbs_cfg_t prbs; + input_system_cfg_t input_circuit; + u8 input_circuit_cfg_changed; +- u32 mipi_sizes_for_check[N_CSI_PORTS][IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT]; +- u8 enable_isys_event_queue; ++ u32 mipi_sizes_for_check[N_CSI_PORTS][IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT]; ++ /* These last 2 fields are used on both the ISP2400 and the ISP2401 */ ++ u8 enable_isys_event_queue; + u8 disable_cont_vf; + }; + +diff --git a/drivers/thermal/gov_bang_bang.c b/drivers/thermal/gov_bang_bang.c +index acb52c9ee10f1..daed67d19efb8 100644 +--- a/drivers/thermal/gov_bang_bang.c ++++ b/drivers/thermal/gov_bang_bang.c +@@ -13,6 +13,28 @@ + + #include "thermal_core.h" + ++static void bang_bang_set_instance_target(struct thermal_instance *instance, ++ unsigned int target) ++{ ++ if (instance->target != 0 && instance->target != 1 && ++ instance->target != THERMAL_NO_TARGET) ++ pr_debug("Unexpected state %ld of thermal instance %s in bang-bang\n", ++ instance->target, instance->name); ++ ++ /* ++ * Enable the fan when the trip is crossed on the way up and disable it ++ * when the trip is crossed on the way down. ++ */ ++ instance->target = target; ++ instance->initialized = true; ++ ++ dev_dbg(&instance->cdev->device, "target=%ld\n", instance->target); ++ ++ mutex_lock(&instance->cdev->lock); ++ __thermal_cdev_update(instance->cdev); ++ mutex_unlock(&instance->cdev->lock); ++} ++ + /** + * bang_bang_control - controls devices associated with the given zone + * @tz: thermal_zone_device +@@ -54,41 +76,60 @@ static void bang_bang_control(struct thermal_zone_device *tz, + tz->temperature, trip->hysteresis); + + list_for_each_entry(instance, &tz->thermal_instances, tz_node) { +- if (instance->trip != trip) +- continue; ++ if (instance->trip == trip) ++ bang_bang_set_instance_target(instance, crossed_up); ++ } ++} ++ ++static void bang_bang_manage(struct thermal_zone_device *tz) ++{ ++ const struct thermal_trip_desc *td; ++ struct thermal_instance *instance; + +- if (instance->target == THERMAL_NO_TARGET) +- instance->target = 0; ++ /* If the code below has run already, nothing needs to be done. */ ++ if (tz->governor_data) ++ return; + +- if (instance->target != 0 && instance->target != 1) { +- pr_debug("Unexpected state %ld of thermal instance %s in bang-bang\n", +- instance->target, instance->name); ++ for_each_trip_desc(tz, td) { ++ const struct thermal_trip *trip = &td->trip; + +- instance->target = 1; +- } ++ if (tz->temperature >= td->threshold || ++ trip->temperature == THERMAL_TEMP_INVALID || ++ trip->type == THERMAL_TRIP_CRITICAL || ++ trip->type == THERMAL_TRIP_HOT) ++ continue; + + /* +- * Enable the fan when the trip is crossed on the way up and +- * disable it when the trip is crossed on the way down. ++ * If the initial cooling device state is "on", but the zone ++ * temperature is not above the trip point, the core will not ++ * call bang_bang_control() until the zone temperature reaches ++ * the trip point temperature which may be never. In those ++ * cases, set the initial state of the cooling device to 0. + */ +- if (instance->target == 0 && crossed_up) +- instance->target = 1; +- else if (instance->target == 1 && !crossed_up) +- instance->target = 0; +- +- dev_dbg(&instance->cdev->device, "target=%ld\n", instance->target); +- +- mutex_lock(&instance->cdev->lock); +- instance->cdev->updated = false; /* cdev needs update */ +- mutex_unlock(&instance->cdev->lock); ++ list_for_each_entry(instance, &tz->thermal_instances, tz_node) { ++ if (!instance->initialized && instance->trip == trip) ++ bang_bang_set_instance_target(instance, 0); ++ } + } + +- list_for_each_entry(instance, &tz->thermal_instances, tz_node) +- thermal_cdev_update(instance->cdev); ++ tz->governor_data = (void *)true; ++} ++ ++static void bang_bang_update_tz(struct thermal_zone_device *tz, ++ enum thermal_notify_event reason) ++{ ++ /* ++ * Let bang_bang_manage() know that it needs to walk trips after binding ++ * a new cdev and after system resume. ++ */ ++ if (reason == THERMAL_TZ_BIND_CDEV || reason == THERMAL_TZ_RESUME) ++ tz->governor_data = NULL; + } + + static struct thermal_governor thermal_gov_bang_bang = { + .name = "bang_bang", + .trip_crossed = bang_bang_control, ++ .manage = bang_bang_manage, ++ .update_tz = bang_bang_update_tz, + }; + THERMAL_GOVERNOR_DECLARE(thermal_gov_bang_bang); +diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c +index f2d31bc48f529..b8d889ef4fa5e 100644 +--- a/drivers/thermal/thermal_core.c ++++ b/drivers/thermal/thermal_core.c +@@ -1715,7 +1715,8 @@ static void thermal_zone_device_resume(struct work_struct *work) + tz->suspended = false; + + thermal_zone_device_init(tz); +- __thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); ++ thermal_governor_update_tz(tz, THERMAL_TZ_RESUME); ++ __thermal_zone_device_update(tz, THERMAL_TZ_RESUME); + + complete(&tz->resume); + tz->resuming = false; +diff --git a/drivers/thermal/thermal_debugfs.c b/drivers/thermal/thermal_debugfs.c +index 9424472291570..6d55f5fc4ca0f 100644 +--- a/drivers/thermal/thermal_debugfs.c ++++ b/drivers/thermal/thermal_debugfs.c +@@ -178,11 +178,11 @@ struct thermal_debugfs { + void thermal_debug_init(void) + { + d_root = debugfs_create_dir("thermal", NULL); +- if (!d_root) ++ if (IS_ERR(d_root)) + return; + + d_cdev = debugfs_create_dir("cooling_devices", d_root); +- if (!d_cdev) ++ if (IS_ERR(d_cdev)) + return; + + d_tz = debugfs_create_dir("thermal_zones", d_root); +@@ -202,7 +202,7 @@ static struct thermal_debugfs *thermal_debugfs_add_id(struct dentry *d, int id) + snprintf(ids, IDSLENGTH, "%d", id); + + thermal_dbg->d_top = debugfs_create_dir(ids, d); +- if (!thermal_dbg->d_top) { ++ if (IS_ERR(thermal_dbg->d_top)) { + kfree(thermal_dbg); + return NULL; + } +diff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c +index aa34b6e82e268..1f252692815a1 100644 +--- a/drivers/thermal/thermal_of.c ++++ b/drivers/thermal/thermal_of.c +@@ -125,7 +125,7 @@ static int thermal_of_populate_trip(struct device_node *np, + static struct thermal_trip *thermal_of_trips_init(struct device_node *np, int *ntrips) + { + struct thermal_trip *tt; +- struct device_node *trips, *trip; ++ struct device_node *trips; + int ret, count; + + trips = of_get_child_by_name(np, "trips"); +@@ -150,7 +150,7 @@ static struct thermal_trip *thermal_of_trips_init(struct device_node *np, int *n + *ntrips = count; + + count = 0; +- for_each_child_of_node(trips, trip) { ++ for_each_child_of_node_scoped(trips, trip) { + ret = thermal_of_populate_trip(trip, &tt[count++]); + if (ret) + goto out_kfree; +@@ -184,14 +184,14 @@ static struct device_node *of_thermal_zone_find(struct device_node *sensor, int + * Search for each thermal zone, a defined sensor + * corresponding to the one passed as parameter + */ +- for_each_available_child_of_node(np, tz) { ++ for_each_available_child_of_node_scoped(np, child) { + + int count, i; + +- count = of_count_phandle_with_args(tz, "thermal-sensors", ++ count = of_count_phandle_with_args(child, "thermal-sensors", + "#thermal-sensor-cells"); + if (count <= 0) { +- pr_err("%pOFn: missing thermal sensor\n", tz); ++ pr_err("%pOFn: missing thermal sensor\n", child); + tz = ERR_PTR(-EINVAL); + goto out; + } +@@ -200,18 +200,19 @@ static struct device_node *of_thermal_zone_find(struct device_node *sensor, int + + int ret; + +- ret = of_parse_phandle_with_args(tz, "thermal-sensors", ++ ret = of_parse_phandle_with_args(child, "thermal-sensors", + "#thermal-sensor-cells", + i, &sensor_specs); + if (ret < 0) { +- pr_err("%pOFn: Failed to read thermal-sensors cells: %d\n", tz, ret); ++ pr_err("%pOFn: Failed to read thermal-sensors cells: %d\n", child, ret); + tz = ERR_PTR(ret); + goto out; + } + + if ((sensor == sensor_specs.np) && id == (sensor_specs.args_count ? + sensor_specs.args[0] : 0)) { +- pr_debug("sensor %pOFn id=%d belongs to %pOFn\n", sensor, id, tz); ++ pr_debug("sensor %pOFn id=%d belongs to %pOFn\n", sensor, id, child); ++ tz = no_free_ptr(child); + goto out; + } + } +@@ -491,7 +492,8 @@ static struct thermal_zone_device *thermal_of_zone_register(struct device_node * + trips = thermal_of_trips_init(np, &ntrips); + if (IS_ERR(trips)) { + pr_err("Failed to find trip points for %pOFn id=%d\n", sensor, id); +- return ERR_CAST(trips); ++ ret = PTR_ERR(trips); ++ goto out_of_node_put; + } + + ret = thermal_of_monitor_init(np, &delay, &pdelay); +@@ -519,6 +521,7 @@ static struct thermal_zone_device *thermal_of_zone_register(struct device_node * + goto out_kfree_trips; + } + ++ of_node_put(np); + kfree(trips); + + ret = thermal_zone_device_enable(tz); +@@ -533,6 +536,8 @@ static struct thermal_zone_device *thermal_of_zone_register(struct device_node * + + out_kfree_trips: + kfree(trips); ++out_of_node_put: ++ of_node_put(np); + + return ERR_PTR(ret); + } +diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c +index 326433df5880e..6a2116cbb06f9 100644 +--- a/drivers/thunderbolt/switch.c ++++ b/drivers/thunderbolt/switch.c +@@ -3392,6 +3392,7 @@ void tb_switch_remove(struct tb_switch *sw) + tb_switch_remove(port->remote->sw); + port->remote = NULL; + } else if (port->xdomain) { ++ port->xdomain->is_unplugged = true; + tb_xdomain_remove(port->xdomain); + port->xdomain = NULL; + } +diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c +index 1af9aed99c651..afef1dd4ddf49 100644 +--- a/drivers/tty/serial/8250/8250_omap.c ++++ b/drivers/tty/serial/8250/8250_omap.c +@@ -27,7 +27,6 @@ + #include + #include + #include +-#include + + #include "8250.h" + +@@ -119,12 +118,6 @@ + #define UART_OMAP_TO_L 0x26 + #define UART_OMAP_TO_H 0x27 + +-/* +- * Copy of the genpd flags for the console. +- * Only used if console suspend is disabled +- */ +-static unsigned int genpd_flags_console; +- + struct omap8250_priv { + void __iomem *membase; + int line; +@@ -1655,7 +1648,6 @@ static int omap8250_suspend(struct device *dev) + { + struct omap8250_priv *priv = dev_get_drvdata(dev); + struct uart_8250_port *up = serial8250_get_port(priv->line); +- struct generic_pm_domain *genpd = pd_to_genpd(dev->pm_domain); + int err = 0; + + serial8250_suspend_port(priv->line); +@@ -1666,19 +1658,8 @@ static int omap8250_suspend(struct device *dev) + if (!device_may_wakeup(dev)) + priv->wer = 0; + serial_out(up, UART_OMAP_WER, priv->wer); +- if (uart_console(&up->port)) { +- if (console_suspend_enabled) +- err = pm_runtime_force_suspend(dev); +- else { +- /* +- * The pd shall not be powered-off (no console suspend). +- * Make copy of genpd flags before to set it always on. +- * The original value is restored during the resume. +- */ +- genpd_flags_console = genpd->flags; +- genpd->flags |= GENPD_FLAG_ALWAYS_ON; +- } +- } ++ if (uart_console(&up->port) && console_suspend_enabled) ++ err = pm_runtime_force_suspend(dev); + flush_work(&priv->qos_work); + + return err; +@@ -1688,16 +1669,12 @@ static int omap8250_resume(struct device *dev) + { + struct omap8250_priv *priv = dev_get_drvdata(dev); + struct uart_8250_port *up = serial8250_get_port(priv->line); +- struct generic_pm_domain *genpd = pd_to_genpd(dev->pm_domain); + int err; + + if (uart_console(&up->port) && console_suspend_enabled) { +- if (console_suspend_enabled) { +- err = pm_runtime_force_resume(dev); +- if (err) +- return err; +- } else +- genpd->flags = genpd_flags_console; ++ err = pm_runtime_force_resume(dev); ++ if (err) ++ return err; + } + + serial8250_resume_port(priv->line); +diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c +index 0a90964d6d107..09b246c9e389e 100644 +--- a/drivers/tty/serial/atmel_serial.c ++++ b/drivers/tty/serial/atmel_serial.c +@@ -2514,7 +2514,7 @@ static const struct uart_ops atmel_pops = { + }; + + static const struct serial_rs485 atmel_rs485_supported = { +- .flags = SER_RS485_ENABLED | SER_RS485_RTS_AFTER_SEND | SER_RS485_RX_DURING_TX, ++ .flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND | SER_RS485_RX_DURING_TX, + .delay_rts_before_send = 1, + .delay_rts_after_send = 1, + }; +diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c +index 615291ea9b5e9..77efa7ee6eda2 100644 +--- a/drivers/tty/serial/fsl_lpuart.c ++++ b/drivers/tty/serial/fsl_lpuart.c +@@ -2923,6 +2923,7 @@ static int lpuart_probe(struct platform_device *pdev) + pm_runtime_set_autosuspend_delay(&pdev->dev, UART_AUTOSUSPEND_TIMEOUT); + pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(&pdev->dev); ++ pm_runtime_mark_last_busy(&pdev->dev); + + ret = lpuart_global_reset(sport); + if (ret) +diff --git a/drivers/tty/vt/conmakehash.c b/drivers/tty/vt/conmakehash.c +index 82d9db68b2ce8..a931fcde7ad98 100644 +--- a/drivers/tty/vt/conmakehash.c ++++ b/drivers/tty/vt/conmakehash.c +@@ -11,8 +11,6 @@ + * Copyright (C) 1995-1997 H. Peter Anvin + */ + +-#include +-#include + #include + #include + #include +@@ -79,7 +77,6 @@ int main(int argc, char *argv[]) + { + FILE *ctbl; + const char *tblname; +- char base_tblname[PATH_MAX]; + char buffer[65536]; + int fontlen; + int i, nuni, nent; +@@ -245,20 +242,15 @@ int main(int argc, char *argv[]) + for ( i = 0 ; i < fontlen ; i++ ) + nuni += unicount[i]; + +- strncpy(base_tblname, tblname, PATH_MAX); +- base_tblname[PATH_MAX - 1] = 0; + printf("\ + /*\n\ +- * Do not edit this file; it was automatically generated by\n\ +- *\n\ +- * conmakehash %s > [this file]\n\ +- *\n\ ++ * Automatically generated file; Do not edit.\n\ + */\n\ + \n\ + #include \n\ + \n\ + u8 dfont_unicount[%d] = \n\ +-{\n\t", basename(base_tblname), fontlen); ++{\n\t", fontlen); + + for ( i = 0 ; i < fontlen ; i++ ) + { +diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c +index 3100219d6496d..f591ddd086627 100644 +--- a/drivers/usb/host/xhci-mem.c ++++ b/drivers/usb/host/xhci-mem.c +@@ -1877,7 +1877,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) + + cancel_delayed_work_sync(&xhci->cmd_timer); + +- for (i = 0; i < xhci->max_interrupters; i++) { ++ for (i = 0; xhci->interrupters && i < xhci->max_interrupters; i++) { + if (xhci->interrupters[i]) { + xhci_remove_interrupter(xhci, xhci->interrupters[i]); + xhci_free_interrupter(xhci, xhci->interrupters[i]); +diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c +index 0a8cf6c17f827..efdf4c228b8c0 100644 +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -2837,7 +2837,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci, + xhci->num_active_eps); + return -ENOMEM; + } +- if ((xhci->quirks & XHCI_SW_BW_CHECKING) && ++ if ((xhci->quirks & XHCI_SW_BW_CHECKING) && !ctx_change && + xhci_reserve_bandwidth(xhci, virt_dev, command->in_ctx)) { + if ((xhci->quirks & XHCI_EP_LIMIT_QUIRK)) + xhci_free_host_resources(xhci, ctrl_ctx); +@@ -4200,8 +4200,10 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev, + mutex_unlock(&xhci->mutex); + ret = xhci_disable_slot(xhci, udev->slot_id); + xhci_free_virt_device(xhci, udev->slot_id); +- if (!ret) +- xhci_alloc_dev(hcd, udev); ++ if (!ret) { ++ if (xhci_alloc_dev(hcd, udev) == 1) ++ xhci_setup_addressable_virt_dev(xhci, udev); ++ } + kfree(command->completion); + kfree(command); + return -EPROTO; +diff --git a/drivers/usb/misc/usb-ljca.c b/drivers/usb/misc/usb-ljca.c +index 2d30fc1be3066..1a8d5e80b9aec 100644 +--- a/drivers/usb/misc/usb-ljca.c ++++ b/drivers/usb/misc/usb-ljca.c +@@ -169,6 +169,7 @@ static const struct acpi_device_id ljca_gpio_hids[] = { + { "INTC1096" }, + { "INTC100B" }, + { "INTC10D1" }, ++ { "INTC10B5" }, + {}, + }; + +diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c +index 5d4da962acc87..ea388e793f882 100644 +--- a/drivers/usb/typec/tcpm/tcpm.c ++++ b/drivers/usb/typec/tcpm/tcpm.c +@@ -5630,7 +5630,6 @@ static void run_state_machine(struct tcpm_port *port) + break; + case PORT_RESET: + tcpm_reset_port(port); +- port->pd_events = 0; + if (port->self_powered) + tcpm_set_cc(port, TYPEC_CC_OPEN); + else +diff --git a/fs/btrfs/delayed-ref.c b/fs/btrfs/delayed-ref.c +index 6cc80fb10da23..5eb06fccc32e5 100644 +--- a/fs/btrfs/delayed-ref.c ++++ b/fs/btrfs/delayed-ref.c +@@ -1169,6 +1169,73 @@ btrfs_find_delayed_ref_head(struct btrfs_delayed_ref_root *delayed_refs, u64 byt + return find_ref_head(delayed_refs, bytenr, false); + } + ++static int find_comp(struct btrfs_delayed_ref_node *entry, u64 root, u64 parent) ++{ ++ int type = parent ? BTRFS_SHARED_BLOCK_REF_KEY : BTRFS_TREE_BLOCK_REF_KEY; ++ ++ if (type < entry->type) ++ return -1; ++ if (type > entry->type) ++ return 1; ++ ++ if (type == BTRFS_TREE_BLOCK_REF_KEY) { ++ if (root < entry->ref_root) ++ return -1; ++ if (root > entry->ref_root) ++ return 1; ++ } else { ++ if (parent < entry->parent) ++ return -1; ++ if (parent > entry->parent) ++ return 1; ++ } ++ return 0; ++} ++ ++/* ++ * Check to see if a given root/parent reference is attached to the head. This ++ * only checks for BTRFS_ADD_DELAYED_REF references that match, as that ++ * indicates the reference exists for the given root or parent. This is for ++ * tree blocks only. ++ * ++ * @head: the head of the bytenr we're searching. ++ * @root: the root objectid of the reference if it is a normal reference. ++ * @parent: the parent if this is a shared backref. ++ */ ++bool btrfs_find_delayed_tree_ref(struct btrfs_delayed_ref_head *head, ++ u64 root, u64 parent) ++{ ++ struct rb_node *node; ++ bool found = false; ++ ++ lockdep_assert_held(&head->mutex); ++ ++ spin_lock(&head->lock); ++ node = head->ref_tree.rb_root.rb_node; ++ while (node) { ++ struct btrfs_delayed_ref_node *entry; ++ int ret; ++ ++ entry = rb_entry(node, struct btrfs_delayed_ref_node, ref_node); ++ ret = find_comp(entry, root, parent); ++ if (ret < 0) { ++ node = node->rb_left; ++ } else if (ret > 0) { ++ node = node->rb_right; ++ } else { ++ /* ++ * We only want to count ADD actions, as drops mean the ++ * ref doesn't exist. ++ */ ++ if (entry->action == BTRFS_ADD_DELAYED_REF) ++ found = true; ++ break; ++ } ++ } ++ spin_unlock(&head->lock); ++ return found; ++} ++ + void __cold btrfs_delayed_ref_exit(void) + { + kmem_cache_destroy(btrfs_delayed_ref_head_cachep); +diff --git a/fs/btrfs/delayed-ref.h b/fs/btrfs/delayed-ref.h +index 04b180ebe1fe0..1d11a1a6f9cb1 100644 +--- a/fs/btrfs/delayed-ref.h ++++ b/fs/btrfs/delayed-ref.h +@@ -389,6 +389,8 @@ int btrfs_delayed_refs_rsv_refill(struct btrfs_fs_info *fs_info, + void btrfs_migrate_to_delayed_refs_rsv(struct btrfs_fs_info *fs_info, + u64 num_bytes); + bool btrfs_check_space_for_delayed_refs(struct btrfs_fs_info *fs_info); ++bool btrfs_find_delayed_tree_ref(struct btrfs_delayed_ref_head *head, ++ u64 root, u64 parent); + + static inline u64 btrfs_delayed_ref_owner(struct btrfs_delayed_ref_node *node) + { +diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c +index 844b677d054ec..8bf980123c5c5 100644 +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -5387,23 +5387,62 @@ static int check_ref_exists(struct btrfs_trans_handle *trans, + struct btrfs_root *root, u64 bytenr, u64 parent, + int level) + { ++ struct btrfs_delayed_ref_root *delayed_refs; ++ struct btrfs_delayed_ref_head *head; + struct btrfs_path *path; + struct btrfs_extent_inline_ref *iref; + int ret; ++ bool exists = false; + + path = btrfs_alloc_path(); + if (!path) + return -ENOMEM; +- ++again: + ret = lookup_extent_backref(trans, path, &iref, bytenr, + root->fs_info->nodesize, parent, + btrfs_root_id(root), level, 0); ++ if (ret != -ENOENT) { ++ /* ++ * If we get 0 then we found our reference, return 1, else ++ * return the error if it's not -ENOENT; ++ */ ++ btrfs_free_path(path); ++ return (ret < 0 ) ? ret : 1; ++ } ++ ++ /* ++ * We could have a delayed ref with this reference, so look it up while ++ * we're holding the path open to make sure we don't race with the ++ * delayed ref running. ++ */ ++ delayed_refs = &trans->transaction->delayed_refs; ++ spin_lock(&delayed_refs->lock); ++ head = btrfs_find_delayed_ref_head(delayed_refs, bytenr); ++ if (!head) ++ goto out; ++ if (!mutex_trylock(&head->mutex)) { ++ /* ++ * We're contended, means that the delayed ref is running, get a ++ * reference and wait for the ref head to be complete and then ++ * try again. ++ */ ++ refcount_inc(&head->refs); ++ spin_unlock(&delayed_refs->lock); ++ ++ btrfs_release_path(path); ++ ++ mutex_lock(&head->mutex); ++ mutex_unlock(&head->mutex); ++ btrfs_put_delayed_ref_head(head); ++ goto again; ++ } ++ ++ exists = btrfs_find_delayed_tree_ref(head, root->root_key.objectid, parent); ++ mutex_unlock(&head->mutex); ++out: ++ spin_unlock(&delayed_refs->lock); + btrfs_free_path(path); +- if (ret == -ENOENT) +- return 0; +- if (ret < 0) +- return ret; +- return 1; ++ return exists ? 1 : 0; + } + + /* +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index 0486b1f911248..3bad7c0be1f10 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -1420,6 +1420,13 @@ static noinline_for_stack int __extent_writepage_io(struct btrfs_inode *inode, + free_extent_map(em); + em = NULL; + ++ /* ++ * Although the PageDirty bit might be cleared before entering ++ * this function, subpage dirty bit is not cleared. ++ * So clear subpage dirty bit here so next time we won't submit ++ * page for range already written to disk. ++ */ ++ btrfs_folio_clear_dirty(fs_info, page_folio(page), cur, iosize); + btrfs_set_range_writeback(inode, cur, cur + iosize - 1); + if (!PageWriteback(page)) { + btrfs_err(inode->root->fs_info, +@@ -1427,13 +1434,6 @@ static noinline_for_stack int __extent_writepage_io(struct btrfs_inode *inode, + page->index, cur, end); + } + +- /* +- * Although the PageDirty bit is cleared before entering this +- * function, subpage dirty bit is not cleared. +- * So clear subpage dirty bit here so next time we won't submit +- * page for range already written to disk. +- */ +- btrfs_folio_clear_dirty(fs_info, page_folio(page), cur, iosize); + + submit_extent_page(bio_ctrl, disk_bytenr, page, iosize, + cur - page_offset(page)); +diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c +index b4c9a6aa118cd..6853f043c2c14 100644 +--- a/fs/btrfs/extent_map.c ++++ b/fs/btrfs/extent_map.c +@@ -1065,8 +1065,7 @@ static long btrfs_scan_inode(struct btrfs_inode *inode, struct btrfs_em_shrink_c + return 0; + + /* +- * We want to be fast because we can be called from any path trying to +- * allocate memory, so if the lock is busy we don't want to spend time ++ * We want to be fast so if the lock is busy we don't want to spend time + * waiting for it - either some task is about to do IO for the inode or + * we may have another task shrinking extent maps, here in this code, so + * skip this inode. +@@ -1109,9 +1108,7 @@ static long btrfs_scan_inode(struct btrfs_inode *inode, struct btrfs_em_shrink_c + /* + * Stop if we need to reschedule or there's contention on the + * lock. This is to avoid slowing other tasks trying to take the +- * lock and because the shrinker might be called during a memory +- * allocation path and we want to avoid taking a very long time +- * and slowing down all sorts of tasks. ++ * lock. + */ + if (need_resched() || rwlock_needbreak(&tree->lock)) + break; +@@ -1139,12 +1136,7 @@ static long btrfs_scan_root(struct btrfs_root *root, struct btrfs_em_shrink_ctx + if (ctx->scanned >= ctx->nr_to_scan) + break; + +- /* +- * We may be called from memory allocation paths, so we don't +- * want to take too much time and slowdown tasks. +- */ +- if (need_resched()) +- break; ++ cond_resched(); + + inode = btrfs_find_first_inode(root, min_ino); + } +@@ -1202,14 +1194,12 @@ long btrfs_free_extent_maps(struct btrfs_fs_info *fs_info, long nr_to_scan) + ctx.last_ino); + } + +- /* +- * We may be called from memory allocation paths, so we don't want to +- * take too much time and slowdown tasks, so stop if we need reschedule. +- */ +- while (ctx.scanned < ctx.nr_to_scan && !need_resched()) { ++ while (ctx.scanned < ctx.nr_to_scan) { + struct btrfs_root *root; + unsigned long count; + ++ cond_resched(); ++ + spin_lock(&fs_info->fs_roots_radix_lock); + count = radix_tree_gang_lookup(&fs_info->fs_roots_radix, + (void **)&root, +diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c +index 62c3dea9572ab..1926a228d0ba0 100644 +--- a/fs/btrfs/free-space-cache.c ++++ b/fs/btrfs/free-space-cache.c +@@ -2698,15 +2698,16 @@ static int __btrfs_add_free_space_zoned(struct btrfs_block_group *block_group, + u64 offset = bytenr - block_group->start; + u64 to_free, to_unusable; + int bg_reclaim_threshold = 0; +- bool initial = ((size == block_group->length) && (block_group->alloc_offset == 0)); ++ bool initial; + u64 reclaimable_unusable; + +- WARN_ON(!initial && offset + size > block_group->zone_capacity); ++ spin_lock(&block_group->lock); + ++ initial = ((size == block_group->length) && (block_group->alloc_offset == 0)); ++ WARN_ON(!initial && offset + size > block_group->zone_capacity); + if (!initial) + bg_reclaim_threshold = READ_ONCE(sinfo->bg_reclaim_threshold); + +- spin_lock(&ctl->tree_lock); + if (!used) + to_free = size; + else if (initial) +@@ -2719,7 +2720,9 @@ static int __btrfs_add_free_space_zoned(struct btrfs_block_group *block_group, + to_free = offset + size - block_group->alloc_offset; + to_unusable = size - to_free; + ++ spin_lock(&ctl->tree_lock); + ctl->free_space += to_free; ++ spin_unlock(&ctl->tree_lock); + /* + * If the block group is read-only, we should account freed space into + * bytes_readonly. +@@ -2728,11 +2731,8 @@ static int __btrfs_add_free_space_zoned(struct btrfs_block_group *block_group, + block_group->zone_unusable += to_unusable; + WARN_ON(block_group->zone_unusable > block_group->length); + } +- spin_unlock(&ctl->tree_lock); + if (!used) { +- spin_lock(&block_group->lock); + block_group->alloc_offset -= size; +- spin_unlock(&block_group->lock); + } + + reclaimable_unusable = block_group->zone_unusable - +@@ -2746,6 +2746,8 @@ static int __btrfs_add_free_space_zoned(struct btrfs_block_group *block_group, + btrfs_mark_bg_to_reclaim(block_group); + } + ++ spin_unlock(&block_group->lock); ++ + return 0; + } + +diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c +index 3dd4a48479a9e..d1a04c0c576ed 100644 +--- a/fs/btrfs/send.c ++++ b/fs/btrfs/send.c +@@ -6158,25 +6158,51 @@ static int send_write_or_clone(struct send_ctx *sctx, + u64 offset = key->offset; + u64 end; + u64 bs = sctx->send_root->fs_info->sectorsize; ++ struct btrfs_file_extent_item *ei; ++ u64 disk_byte; ++ u64 data_offset; ++ u64 num_bytes; ++ struct btrfs_inode_info info = { 0 }; + + end = min_t(u64, btrfs_file_extent_end(path), sctx->cur_inode_size); + if (offset >= end) + return 0; + +- if (clone_root && IS_ALIGNED(end, bs)) { +- struct btrfs_file_extent_item *ei; +- u64 disk_byte; +- u64 data_offset; ++ num_bytes = end - offset; + +- ei = btrfs_item_ptr(path->nodes[0], path->slots[0], +- struct btrfs_file_extent_item); +- disk_byte = btrfs_file_extent_disk_bytenr(path->nodes[0], ei); +- data_offset = btrfs_file_extent_offset(path->nodes[0], ei); +- ret = clone_range(sctx, path, clone_root, disk_byte, +- data_offset, offset, end - offset); +- } else { +- ret = send_extent_data(sctx, path, offset, end - offset); +- } ++ if (!clone_root) ++ goto write_data; ++ ++ if (IS_ALIGNED(end, bs)) ++ goto clone_data; ++ ++ /* ++ * If the extent end is not aligned, we can clone if the extent ends at ++ * the i_size of the inode and the clone range ends at the i_size of the ++ * source inode, otherwise the clone operation fails with -EINVAL. ++ */ ++ if (end != sctx->cur_inode_size) ++ goto write_data; ++ ++ ret = get_inode_info(clone_root->root, clone_root->ino, &info); ++ if (ret < 0) ++ return ret; ++ ++ if (clone_root->offset + num_bytes == info.size) ++ goto clone_data; ++ ++write_data: ++ ret = send_extent_data(sctx, path, offset, num_bytes); ++ sctx->cur_inode_next_write_offset = end; ++ return ret; ++ ++clone_data: ++ ei = btrfs_item_ptr(path->nodes[0], path->slots[0], ++ struct btrfs_file_extent_item); ++ disk_byte = btrfs_file_extent_disk_bytenr(path->nodes[0], ei); ++ data_offset = btrfs_file_extent_offset(path->nodes[0], ei); ++ ret = clone_range(sctx, path, clone_root, disk_byte, data_offset, offset, ++ num_bytes); + sctx->cur_inode_next_write_offset = end; + return ret; + } +diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c +index f05cce7c8b8d1..03107c01b2875 100644 +--- a/fs/btrfs/super.c ++++ b/fs/btrfs/super.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + #include "messages.h" + #include "delayed-inode.h" + #include "ctree.h" +@@ -2386,7 +2387,13 @@ static long btrfs_nr_cached_objects(struct super_block *sb, struct shrink_contro + + trace_btrfs_extent_map_shrinker_count(fs_info, nr); + +- return nr; ++ /* ++ * Only report the real number for DEBUG builds, as there are reports of ++ * serious performance degradation caused by too frequent shrinks. ++ */ ++ if (IS_ENABLED(CONFIG_BTRFS_DEBUG)) ++ return nr; ++ return 0; + } + + static long btrfs_free_cached_objects(struct super_block *sb, struct shrink_control *sc) +@@ -2394,6 +2401,15 @@ static long btrfs_free_cached_objects(struct super_block *sb, struct shrink_cont + const long nr_to_scan = min_t(unsigned long, LONG_MAX, sc->nr_to_scan); + struct btrfs_fs_info *fs_info = btrfs_sb(sb); + ++ /* ++ * We may be called from any task trying to allocate memory and we don't ++ * want to slow it down with scanning and dropping extent maps. It would ++ * also cause heavy lock contention if many tasks concurrently enter ++ * here. Therefore only allow kswapd tasks to scan and drop extent maps. ++ */ ++ if (!current_is_kswapd()) ++ return 0; ++ + return btrfs_free_extent_maps(fs_info, nr_to_scan); + } + +diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c +index a2c3651a3d8fc..897e19790522d 100644 +--- a/fs/btrfs/tree-checker.c ++++ b/fs/btrfs/tree-checker.c +@@ -551,9 +551,10 @@ static int check_dir_item(struct extent_buffer *leaf, + + /* dir type check */ + dir_type = btrfs_dir_ftype(leaf, di); +- if (unlikely(dir_type >= BTRFS_FT_MAX)) { ++ if (unlikely(dir_type <= BTRFS_FT_UNKNOWN || ++ dir_type >= BTRFS_FT_MAX)) { + dir_item_err(leaf, slot, +- "invalid dir item type, have %u expect [0, %u)", ++ "invalid dir item type, have %u expect (0, %u)", + dir_type, BTRFS_FT_MAX); + return -EUCLEAN; + } +@@ -1717,6 +1718,72 @@ static int check_raid_stripe_extent(const struct extent_buffer *leaf, + return 0; + } + ++static int check_dev_extent_item(const struct extent_buffer *leaf, ++ const struct btrfs_key *key, ++ int slot, ++ struct btrfs_key *prev_key) ++{ ++ struct btrfs_dev_extent *de; ++ const u32 sectorsize = leaf->fs_info->sectorsize; ++ ++ de = btrfs_item_ptr(leaf, slot, struct btrfs_dev_extent); ++ /* Basic fixed member checks. */ ++ if (unlikely(btrfs_dev_extent_chunk_tree(leaf, de) != ++ BTRFS_CHUNK_TREE_OBJECTID)) { ++ generic_err(leaf, slot, ++ "invalid dev extent chunk tree id, has %llu expect %llu", ++ btrfs_dev_extent_chunk_tree(leaf, de), ++ BTRFS_CHUNK_TREE_OBJECTID); ++ return -EUCLEAN; ++ } ++ if (unlikely(btrfs_dev_extent_chunk_objectid(leaf, de) != ++ BTRFS_FIRST_CHUNK_TREE_OBJECTID)) { ++ generic_err(leaf, slot, ++ "invalid dev extent chunk objectid, has %llu expect %llu", ++ btrfs_dev_extent_chunk_objectid(leaf, de), ++ BTRFS_FIRST_CHUNK_TREE_OBJECTID); ++ return -EUCLEAN; ++ } ++ /* Alignment check. */ ++ if (unlikely(!IS_ALIGNED(key->offset, sectorsize))) { ++ generic_err(leaf, slot, ++ "invalid dev extent key.offset, has %llu not aligned to %u", ++ key->offset, sectorsize); ++ return -EUCLEAN; ++ } ++ if (unlikely(!IS_ALIGNED(btrfs_dev_extent_chunk_offset(leaf, de), ++ sectorsize))) { ++ generic_err(leaf, slot, ++ "invalid dev extent chunk offset, has %llu not aligned to %u", ++ btrfs_dev_extent_chunk_objectid(leaf, de), ++ sectorsize); ++ return -EUCLEAN; ++ } ++ if (unlikely(!IS_ALIGNED(btrfs_dev_extent_length(leaf, de), ++ sectorsize))) { ++ generic_err(leaf, slot, ++ "invalid dev extent length, has %llu not aligned to %u", ++ btrfs_dev_extent_length(leaf, de), sectorsize); ++ return -EUCLEAN; ++ } ++ /* Overlap check with previous dev extent. */ ++ if (slot && prev_key->objectid == key->objectid && ++ prev_key->type == key->type) { ++ struct btrfs_dev_extent *prev_de; ++ u64 prev_len; ++ ++ prev_de = btrfs_item_ptr(leaf, slot - 1, struct btrfs_dev_extent); ++ prev_len = btrfs_dev_extent_length(leaf, prev_de); ++ if (unlikely(prev_key->offset + prev_len > key->offset)) { ++ generic_err(leaf, slot, ++ "dev extent overlap, prev offset %llu len %llu current offset %llu", ++ prev_key->objectid, prev_len, key->offset); ++ return -EUCLEAN; ++ } ++ } ++ return 0; ++} ++ + /* + * Common point to switch the item-specific validation. + */ +@@ -1753,6 +1820,9 @@ static enum btrfs_tree_block_status check_leaf_item(struct extent_buffer *leaf, + case BTRFS_DEV_ITEM_KEY: + ret = check_dev_item(leaf, key, slot); + break; ++ case BTRFS_DEV_EXTENT_KEY: ++ ret = check_dev_extent_item(leaf, key, slot, prev_key); ++ break; + case BTRFS_INODE_ITEM_KEY: + ret = check_inode_item(leaf, key, slot); + break; +diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c +index 8c16bc5250ef5..73b5a07bf94de 100644 +--- a/fs/ceph/addr.c ++++ b/fs/ceph/addr.c +@@ -498,6 +498,11 @@ const struct netfs_request_ops ceph_netfs_ops = { + }; + + #ifdef CONFIG_CEPH_FSCACHE ++static void ceph_set_page_fscache(struct page *page) ++{ ++ folio_start_private_2(page_folio(page)); /* [DEPRECATED] */ ++} ++ + static void ceph_fscache_write_terminated(void *priv, ssize_t error, bool was_async) + { + struct inode *inode = priv; +@@ -515,6 +520,10 @@ static void ceph_fscache_write_to_cache(struct inode *inode, u64 off, u64 len, b + ceph_fscache_write_terminated, inode, true, caching); + } + #else ++static inline void ceph_set_page_fscache(struct page *page) ++{ ++} ++ + static inline void ceph_fscache_write_to_cache(struct inode *inode, u64 off, u64 len, bool caching) + { + } +@@ -706,6 +715,8 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc) + len = wlen; + + set_page_writeback(page); ++ if (caching) ++ ceph_set_page_fscache(page); + ceph_fscache_write_to_cache(inode, page_off, len, caching); + + if (IS_ENCRYPTED(inode)) { +@@ -789,6 +800,8 @@ static int ceph_writepage(struct page *page, struct writeback_control *wbc) + return AOP_WRITEPAGE_ACTIVATE; + } + ++ folio_wait_private_2(page_folio(page)); /* [DEPRECATED] */ ++ + err = writepage_nounlock(page, wbc); + if (err == -ERESTARTSYS) { + /* direct memory reclaimer was killed by SIGKILL. return 0 +@@ -1062,7 +1075,8 @@ static int ceph_writepages_start(struct address_space *mapping, + unlock_page(page); + break; + } +- if (PageWriteback(page)) { ++ if (PageWriteback(page) || ++ PagePrivate2(page) /* [DEPRECATED] */) { + if (wbc->sync_mode == WB_SYNC_NONE) { + doutc(cl, "%p under writeback\n", page); + unlock_page(page); +@@ -1070,6 +1084,7 @@ static int ceph_writepages_start(struct address_space *mapping, + } + doutc(cl, "waiting on writeback %p\n", page); + wait_on_page_writeback(page); ++ folio_wait_private_2(page_folio(page)); /* [DEPRECATED] */ + } + + if (!clear_page_dirty_for_io(page)) { +@@ -1254,6 +1269,8 @@ static int ceph_writepages_start(struct address_space *mapping, + } + + set_page_writeback(page); ++ if (caching) ++ ceph_set_page_fscache(page); + len += thp_size(page); + } + ceph_fscache_write_to_cache(inode, offset, len, caching); +diff --git a/fs/file.c b/fs/file.c +index a11e59b5d6026..655338effe9c7 100644 +--- a/fs/file.c ++++ b/fs/file.c +@@ -46,27 +46,23 @@ static void free_fdtable_rcu(struct rcu_head *rcu) + #define BITBIT_NR(nr) BITS_TO_LONGS(BITS_TO_LONGS(nr)) + #define BITBIT_SIZE(nr) (BITBIT_NR(nr) * sizeof(long)) + ++#define fdt_words(fdt) ((fdt)->max_fds / BITS_PER_LONG) // words in ->open_fds + /* + * Copy 'count' fd bits from the old table to the new table and clear the extra + * space if any. This does not copy the file pointers. Called with the files + * spinlock held for write. + */ +-static void copy_fd_bitmaps(struct fdtable *nfdt, struct fdtable *ofdt, +- unsigned int count) ++static inline void copy_fd_bitmaps(struct fdtable *nfdt, struct fdtable *ofdt, ++ unsigned int copy_words) + { +- unsigned int cpy, set; +- +- cpy = count / BITS_PER_BYTE; +- set = (nfdt->max_fds - count) / BITS_PER_BYTE; +- memcpy(nfdt->open_fds, ofdt->open_fds, cpy); +- memset((char *)nfdt->open_fds + cpy, 0, set); +- memcpy(nfdt->close_on_exec, ofdt->close_on_exec, cpy); +- memset((char *)nfdt->close_on_exec + cpy, 0, set); +- +- cpy = BITBIT_SIZE(count); +- set = BITBIT_SIZE(nfdt->max_fds) - cpy; +- memcpy(nfdt->full_fds_bits, ofdt->full_fds_bits, cpy); +- memset((char *)nfdt->full_fds_bits + cpy, 0, set); ++ unsigned int nwords = fdt_words(nfdt); ++ ++ bitmap_copy_and_extend(nfdt->open_fds, ofdt->open_fds, ++ copy_words * BITS_PER_LONG, nwords * BITS_PER_LONG); ++ bitmap_copy_and_extend(nfdt->close_on_exec, ofdt->close_on_exec, ++ copy_words * BITS_PER_LONG, nwords * BITS_PER_LONG); ++ bitmap_copy_and_extend(nfdt->full_fds_bits, ofdt->full_fds_bits, ++ copy_words, nwords); + } + + /* +@@ -84,7 +80,7 @@ static void copy_fdtable(struct fdtable *nfdt, struct fdtable *ofdt) + memcpy(nfdt->fd, ofdt->fd, cpy); + memset((char *)nfdt->fd + cpy, 0, set); + +- copy_fd_bitmaps(nfdt, ofdt, ofdt->max_fds); ++ copy_fd_bitmaps(nfdt, ofdt, fdt_words(ofdt)); + } + + /* +@@ -379,7 +375,7 @@ struct files_struct *dup_fd(struct files_struct *oldf, unsigned int max_fds, int + open_files = sane_fdtable_size(old_fdt, max_fds); + } + +- copy_fd_bitmaps(new_fdt, old_fdt, open_files); ++ copy_fd_bitmaps(new_fdt, old_fdt, open_files / BITS_PER_LONG); + + old_fds = old_fdt->fd; + new_fds = new_fdt->fd; +diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c +index 9eb191b5c4de1..7146038b2fe7d 100644 +--- a/fs/fuse/dev.c ++++ b/fs/fuse/dev.c +@@ -1618,9 +1618,11 @@ static int fuse_notify_store(struct fuse_conn *fc, unsigned int size, + + this_num = min_t(unsigned, num, PAGE_SIZE - offset); + err = fuse_copy_page(cs, &page, offset, this_num, 0); +- if (!err && offset == 0 && +- (this_num == PAGE_SIZE || file_size == end)) ++ if (!PageUptodate(page) && !err && offset == 0 && ++ (this_num == PAGE_SIZE || file_size == end)) { ++ zero_user_segment(page, this_num, PAGE_SIZE); + SetPageUptodate(page); ++ } + unlock_page(page); + put_page(page); + +diff --git a/fs/inode.c b/fs/inode.c +index 3a41f83a4ba55..f5add7222c98e 100644 +--- a/fs/inode.c ++++ b/fs/inode.c +@@ -486,6 +486,39 @@ static void inode_lru_list_del(struct inode *inode) + this_cpu_dec(nr_unused); + } + ++static void inode_pin_lru_isolating(struct inode *inode) ++{ ++ lockdep_assert_held(&inode->i_lock); ++ WARN_ON(inode->i_state & (I_LRU_ISOLATING | I_FREEING | I_WILL_FREE)); ++ inode->i_state |= I_LRU_ISOLATING; ++} ++ ++static void inode_unpin_lru_isolating(struct inode *inode) ++{ ++ spin_lock(&inode->i_lock); ++ WARN_ON(!(inode->i_state & I_LRU_ISOLATING)); ++ inode->i_state &= ~I_LRU_ISOLATING; ++ smp_mb(); ++ wake_up_bit(&inode->i_state, __I_LRU_ISOLATING); ++ spin_unlock(&inode->i_lock); ++} ++ ++static void inode_wait_for_lru_isolating(struct inode *inode) ++{ ++ spin_lock(&inode->i_lock); ++ if (inode->i_state & I_LRU_ISOLATING) { ++ DEFINE_WAIT_BIT(wq, &inode->i_state, __I_LRU_ISOLATING); ++ wait_queue_head_t *wqh; ++ ++ wqh = bit_waitqueue(&inode->i_state, __I_LRU_ISOLATING); ++ spin_unlock(&inode->i_lock); ++ __wait_on_bit(wqh, &wq, bit_wait, TASK_UNINTERRUPTIBLE); ++ spin_lock(&inode->i_lock); ++ WARN_ON(inode->i_state & I_LRU_ISOLATING); ++ } ++ spin_unlock(&inode->i_lock); ++} ++ + /** + * inode_sb_list_add - add inode to the superblock list of inodes + * @inode: inode to add +@@ -655,6 +688,8 @@ static void evict(struct inode *inode) + + inode_sb_list_del(inode); + ++ inode_wait_for_lru_isolating(inode); ++ + /* + * Wait for flusher thread to be done with the inode so that filesystem + * does not start destroying it while writeback is still running. Since +@@ -843,7 +878,7 @@ static enum lru_status inode_lru_isolate(struct list_head *item, + * be under pressure before the cache inside the highmem zone. + */ + if (inode_has_buffers(inode) || !mapping_empty(&inode->i_data)) { +- __iget(inode); ++ inode_pin_lru_isolating(inode); + spin_unlock(&inode->i_lock); + spin_unlock(lru_lock); + if (remove_inode_buffers(inode)) { +@@ -855,7 +890,7 @@ static enum lru_status inode_lru_isolate(struct list_head *item, + __count_vm_events(PGINODESTEAL, reap); + mm_account_reclaimed_pages(reap); + } +- iput(inode); ++ inode_unpin_lru_isolating(inode); + spin_lock(lru_lock); + return LRU_RETRY; + } +diff --git a/fs/libfs.c b/fs/libfs.c +index b635ee5adbcce..65279e53fbf27 100644 +--- a/fs/libfs.c ++++ b/fs/libfs.c +@@ -450,6 +450,14 @@ void simple_offset_destroy(struct offset_ctx *octx) + mtree_destroy(&octx->mt); + } + ++static int offset_dir_open(struct inode *inode, struct file *file) ++{ ++ struct offset_ctx *ctx = inode->i_op->get_offset_ctx(inode); ++ ++ file->private_data = (void *)ctx->next_offset; ++ return 0; ++} ++ + /** + * offset_dir_llseek - Advance the read position of a directory descriptor + * @file: an open directory whose position is to be updated +@@ -463,6 +471,9 @@ void simple_offset_destroy(struct offset_ctx *octx) + */ + static loff_t offset_dir_llseek(struct file *file, loff_t offset, int whence) + { ++ struct inode *inode = file->f_inode; ++ struct offset_ctx *ctx = inode->i_op->get_offset_ctx(inode); ++ + switch (whence) { + case SEEK_CUR: + offset += file->f_pos; +@@ -476,7 +487,8 @@ static loff_t offset_dir_llseek(struct file *file, loff_t offset, int whence) + } + + /* In this case, ->private_data is protected by f_pos_lock */ +- file->private_data = NULL; ++ if (!offset) ++ file->private_data = (void *)ctx->next_offset; + return vfs_setpos(file, offset, LONG_MAX); + } + +@@ -507,7 +519,7 @@ static bool offset_dir_emit(struct dir_context *ctx, struct dentry *dentry) + inode->i_ino, fs_umode_to_dtype(inode->i_mode)); + } + +-static void *offset_iterate_dir(struct inode *inode, struct dir_context *ctx) ++static void offset_iterate_dir(struct inode *inode, struct dir_context *ctx, long last_index) + { + struct offset_ctx *octx = inode->i_op->get_offset_ctx(inode); + struct dentry *dentry; +@@ -515,17 +527,21 @@ static void *offset_iterate_dir(struct inode *inode, struct dir_context *ctx) + while (true) { + dentry = offset_find_next(octx, ctx->pos); + if (!dentry) +- return ERR_PTR(-ENOENT); ++ return; ++ ++ if (dentry2offset(dentry) >= last_index) { ++ dput(dentry); ++ return; ++ } + + if (!offset_dir_emit(ctx, dentry)) { + dput(dentry); +- break; ++ return; + } + + ctx->pos = dentry2offset(dentry) + 1; + dput(dentry); + } +- return NULL; + } + + /** +@@ -552,22 +568,19 @@ static void *offset_iterate_dir(struct inode *inode, struct dir_context *ctx) + static int offset_readdir(struct file *file, struct dir_context *ctx) + { + struct dentry *dir = file->f_path.dentry; ++ long last_index = (long)file->private_data; + + lockdep_assert_held(&d_inode(dir)->i_rwsem); + + if (!dir_emit_dots(file, ctx)) + return 0; + +- /* In this case, ->private_data is protected by f_pos_lock */ +- if (ctx->pos == DIR_OFFSET_MIN) +- file->private_data = NULL; +- else if (file->private_data == ERR_PTR(-ENOENT)) +- return 0; +- file->private_data = offset_iterate_dir(d_inode(dir), ctx); ++ offset_iterate_dir(d_inode(dir), ctx, last_index); + return 0; + } + + const struct file_operations simple_offset_dir_operations = { ++ .open = offset_dir_open, + .llseek = offset_dir_llseek, + .iterate_shared = offset_readdir, + .read = generic_read_dir, +diff --git a/fs/locks.c b/fs/locks.c +index 9afb16e0683ff..e45cad40f8b6b 100644 +--- a/fs/locks.c ++++ b/fs/locks.c +@@ -2984,7 +2984,7 @@ static int __init filelock_init(void) + filelock_cache = kmem_cache_create("file_lock_cache", + sizeof(struct file_lock), 0, SLAB_PANIC, NULL); + +- filelease_cache = kmem_cache_create("file_lock_cache", ++ filelease_cache = kmem_cache_create("file_lease_cache", + sizeof(struct file_lease), 0, SLAB_PANIC, NULL); + + for_each_possible_cpu(i) { +diff --git a/fs/netfs/buffered_read.c b/fs/netfs/buffered_read.c +index 4c0401dbbfcfa..9aa045e2ab0ae 100644 +--- a/fs/netfs/buffered_read.c ++++ b/fs/netfs/buffered_read.c +@@ -466,7 +466,7 @@ int netfs_write_begin(struct netfs_inode *ctx, + if (!netfs_is_cache_enabled(ctx) && + netfs_skip_folio_read(folio, pos, len, false)) { + netfs_stat(&netfs_n_rh_write_zskip); +- goto have_folio; ++ goto have_folio_no_wait; + } + + rreq = netfs_alloc_request(mapping, file, +@@ -507,6 +507,12 @@ int netfs_write_begin(struct netfs_inode *ctx, + netfs_put_request(rreq, false, netfs_rreq_trace_put_return); + + have_folio: ++ if (test_bit(NETFS_ICTX_USE_PGPRIV2, &ctx->flags)) { ++ ret = folio_wait_private_2_killable(folio); ++ if (ret < 0) ++ goto error; ++ } ++have_folio_no_wait: + *_folio = folio; + kleave(" = 0"); + return 0; +diff --git a/fs/netfs/buffered_write.c b/fs/netfs/buffered_write.c +index ecbc99ec7d367..18055c1e01835 100644 +--- a/fs/netfs/buffered_write.c ++++ b/fs/netfs/buffered_write.c +@@ -184,7 +184,7 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct iov_iter *iter, + unsigned int bdp_flags = (iocb->ki_flags & IOCB_NOWAIT) ? BDP_ASYNC : 0; + ssize_t written = 0, ret, ret2; + loff_t i_size, pos = iocb->ki_pos, from, to; +- size_t max_chunk = PAGE_SIZE << MAX_PAGECACHE_ORDER; ++ size_t max_chunk = mapping_max_folio_size(mapping); + bool maybe_trouble = false; + + if (unlikely(test_bit(NETFS_ICTX_WRITETHROUGH, &ctx->flags) || +diff --git a/fs/netfs/fscache_cookie.c b/fs/netfs/fscache_cookie.c +index 4d1e8bf4c615f..431a1905fcb4c 100644 +--- a/fs/netfs/fscache_cookie.c ++++ b/fs/netfs/fscache_cookie.c +@@ -741,6 +741,10 @@ static void fscache_cookie_state_machine(struct fscache_cookie *cookie) + spin_lock(&cookie->lock); + } + if (test_bit(FSCACHE_COOKIE_DO_LRU_DISCARD, &cookie->flags)) { ++ if (atomic_read(&cookie->n_accesses) != 0) ++ /* still being accessed: postpone it */ ++ break; ++ + __fscache_set_cookie_state(cookie, + FSCACHE_COOKIE_STATE_LRU_DISCARDING); + wake = true; +diff --git a/fs/netfs/io.c b/fs/netfs/io.c +index c7576481c321d..f3abc5dfdbc0c 100644 +--- a/fs/netfs/io.c ++++ b/fs/netfs/io.c +@@ -98,6 +98,146 @@ static void netfs_rreq_completed(struct netfs_io_request *rreq, bool was_async) + netfs_put_request(rreq, was_async, netfs_rreq_trace_put_complete); + } + ++/* ++ * [DEPRECATED] Deal with the completion of writing the data to the cache. We ++ * have to clear the PG_fscache bits on the folios involved and release the ++ * caller's ref. ++ * ++ * May be called in softirq mode and we inherit a ref from the caller. ++ */ ++static void netfs_rreq_unmark_after_write(struct netfs_io_request *rreq, ++ bool was_async) ++{ ++ struct netfs_io_subrequest *subreq; ++ struct folio *folio; ++ pgoff_t unlocked = 0; ++ bool have_unlocked = false; ++ ++ rcu_read_lock(); ++ ++ list_for_each_entry(subreq, &rreq->subrequests, rreq_link) { ++ XA_STATE(xas, &rreq->mapping->i_pages, subreq->start / PAGE_SIZE); ++ ++ xas_for_each(&xas, folio, (subreq->start + subreq->len - 1) / PAGE_SIZE) { ++ if (xas_retry(&xas, folio)) ++ continue; ++ ++ /* We might have multiple writes from the same huge ++ * folio, but we mustn't unlock a folio more than once. ++ */ ++ if (have_unlocked && folio->index <= unlocked) ++ continue; ++ unlocked = folio_next_index(folio) - 1; ++ trace_netfs_folio(folio, netfs_folio_trace_end_copy); ++ folio_end_private_2(folio); ++ have_unlocked = true; ++ } ++ } ++ ++ rcu_read_unlock(); ++ netfs_rreq_completed(rreq, was_async); ++} ++ ++static void netfs_rreq_copy_terminated(void *priv, ssize_t transferred_or_error, ++ bool was_async) /* [DEPRECATED] */ ++{ ++ struct netfs_io_subrequest *subreq = priv; ++ struct netfs_io_request *rreq = subreq->rreq; ++ ++ if (IS_ERR_VALUE(transferred_or_error)) { ++ netfs_stat(&netfs_n_rh_write_failed); ++ trace_netfs_failure(rreq, subreq, transferred_or_error, ++ netfs_fail_copy_to_cache); ++ } else { ++ netfs_stat(&netfs_n_rh_write_done); ++ } ++ ++ trace_netfs_sreq(subreq, netfs_sreq_trace_write_term); ++ ++ /* If we decrement nr_copy_ops to 0, the ref belongs to us. */ ++ if (atomic_dec_and_test(&rreq->nr_copy_ops)) ++ netfs_rreq_unmark_after_write(rreq, was_async); ++ ++ netfs_put_subrequest(subreq, was_async, netfs_sreq_trace_put_terminated); ++} ++ ++/* ++ * [DEPRECATED] Perform any outstanding writes to the cache. We inherit a ref ++ * from the caller. ++ */ ++static void netfs_rreq_do_write_to_cache(struct netfs_io_request *rreq) ++{ ++ struct netfs_cache_resources *cres = &rreq->cache_resources; ++ struct netfs_io_subrequest *subreq, *next, *p; ++ struct iov_iter iter; ++ int ret; ++ ++ trace_netfs_rreq(rreq, netfs_rreq_trace_copy); ++ ++ /* We don't want terminating writes trying to wake us up whilst we're ++ * still going through the list. ++ */ ++ atomic_inc(&rreq->nr_copy_ops); ++ ++ list_for_each_entry_safe(subreq, p, &rreq->subrequests, rreq_link) { ++ if (!test_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags)) { ++ list_del_init(&subreq->rreq_link); ++ netfs_put_subrequest(subreq, false, ++ netfs_sreq_trace_put_no_copy); ++ } ++ } ++ ++ list_for_each_entry(subreq, &rreq->subrequests, rreq_link) { ++ /* Amalgamate adjacent writes */ ++ while (!list_is_last(&subreq->rreq_link, &rreq->subrequests)) { ++ next = list_next_entry(subreq, rreq_link); ++ if (next->start != subreq->start + subreq->len) ++ break; ++ subreq->len += next->len; ++ list_del_init(&next->rreq_link); ++ netfs_put_subrequest(next, false, ++ netfs_sreq_trace_put_merged); ++ } ++ ++ ret = cres->ops->prepare_write(cres, &subreq->start, &subreq->len, ++ subreq->len, rreq->i_size, true); ++ if (ret < 0) { ++ trace_netfs_failure(rreq, subreq, ret, netfs_fail_prepare_write); ++ trace_netfs_sreq(subreq, netfs_sreq_trace_write_skip); ++ continue; ++ } ++ ++ iov_iter_xarray(&iter, ITER_SOURCE, &rreq->mapping->i_pages, ++ subreq->start, subreq->len); ++ ++ atomic_inc(&rreq->nr_copy_ops); ++ netfs_stat(&netfs_n_rh_write); ++ netfs_get_subrequest(subreq, netfs_sreq_trace_get_copy_to_cache); ++ trace_netfs_sreq(subreq, netfs_sreq_trace_write); ++ cres->ops->write(cres, subreq->start, &iter, ++ netfs_rreq_copy_terminated, subreq); ++ } ++ ++ /* If we decrement nr_copy_ops to 0, the usage ref belongs to us. */ ++ if (atomic_dec_and_test(&rreq->nr_copy_ops)) ++ netfs_rreq_unmark_after_write(rreq, false); ++} ++ ++static void netfs_rreq_write_to_cache_work(struct work_struct *work) /* [DEPRECATED] */ ++{ ++ struct netfs_io_request *rreq = ++ container_of(work, struct netfs_io_request, work); ++ ++ netfs_rreq_do_write_to_cache(rreq); ++} ++ ++static void netfs_rreq_write_to_cache(struct netfs_io_request *rreq) /* [DEPRECATED] */ ++{ ++ rreq->work.func = netfs_rreq_write_to_cache_work; ++ if (!queue_work(system_unbound_wq, &rreq->work)) ++ BUG(); ++} ++ + /* + * Handle a short read. + */ +@@ -275,6 +415,10 @@ static void netfs_rreq_assess(struct netfs_io_request *rreq, bool was_async) + clear_bit_unlock(NETFS_RREQ_IN_PROGRESS, &rreq->flags); + wake_up_bit(&rreq->flags, NETFS_RREQ_IN_PROGRESS); + ++ if (test_bit(NETFS_RREQ_COPY_TO_CACHE, &rreq->flags) && ++ test_bit(NETFS_RREQ_USE_PGPRIV2, &rreq->flags)) ++ return netfs_rreq_write_to_cache(rreq); ++ + netfs_rreq_completed(rreq, was_async); + } + +diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h +index d4bcc7da700c6..0a271b9fbc622 100644 +--- a/fs/smb/client/cifsglob.h ++++ b/fs/smb/client/cifsglob.h +@@ -290,7 +290,7 @@ struct smb_version_operations { + int (*check_receive)(struct mid_q_entry *, struct TCP_Server_Info *, + bool); + void (*add_credits)(struct TCP_Server_Info *server, +- const struct cifs_credits *credits, ++ struct cifs_credits *credits, + const int optype); + void (*set_credits)(struct TCP_Server_Info *, const int); + int * (*get_credits_field)(struct TCP_Server_Info *, const int); +@@ -550,8 +550,8 @@ struct smb_version_operations { + size_t *, struct cifs_credits *); + /* adjust previously taken mtu credits to request size */ + int (*adjust_credits)(struct TCP_Server_Info *server, +- struct cifs_credits *credits, +- const unsigned int payload_size); ++ struct cifs_io_subrequest *subreq, ++ unsigned int /*enum smb3_rw_credits_trace*/ trace); + /* check if we need to issue closedir */ + bool (*dir_needs_close)(struct cifsFileInfo *); + long (*fallocate)(struct file *, struct cifs_tcon *, int, loff_t, +@@ -848,6 +848,9 @@ static inline void cifs_server_unlock(struct TCP_Server_Info *server) + struct cifs_credits { + unsigned int value; + unsigned int instance; ++ unsigned int in_flight_check; ++ unsigned int rreq_debug_id; ++ unsigned int rreq_debug_index; + }; + + static inline unsigned int +@@ -873,7 +876,7 @@ has_credits(struct TCP_Server_Info *server, int *credits, int num_credits) + } + + static inline void +-add_credits(struct TCP_Server_Info *server, const struct cifs_credits *credits, ++add_credits(struct TCP_Server_Info *server, struct cifs_credits *credits, + const int optype) + { + server->ops->add_credits(server, credits, optype); +@@ -897,11 +900,11 @@ set_credits(struct TCP_Server_Info *server, const int val) + } + + static inline int +-adjust_credits(struct TCP_Server_Info *server, struct cifs_credits *credits, +- const unsigned int payload_size) ++adjust_credits(struct TCP_Server_Info *server, struct cifs_io_subrequest *subreq, ++ unsigned int /* enum smb3_rw_credits_trace */ trace) + { + return server->ops->adjust_credits ? +- server->ops->adjust_credits(server, credits, payload_size) : 0; ++ server->ops->adjust_credits(server, subreq, trace) : 0; + } + + static inline __le64 +diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c +index 04ec1b9737a89..b202eac6584e1 100644 +--- a/fs/smb/client/file.c ++++ b/fs/smb/client/file.c +@@ -80,6 +80,16 @@ static void cifs_prepare_write(struct netfs_io_subrequest *subreq) + return netfs_prepare_write_failed(subreq); + } + ++ wdata->credits.rreq_debug_id = subreq->rreq->debug_id; ++ wdata->credits.rreq_debug_index = subreq->debug_index; ++ wdata->credits.in_flight_check = 1; ++ trace_smb3_rw_credits(wdata->rreq->debug_id, ++ wdata->subreq.debug_index, ++ wdata->credits.value, ++ server->credits, server->in_flight, ++ wdata->credits.value, ++ cifs_trace_rw_credits_write_prepare); ++ + #ifdef CONFIG_CIFS_SMB_DIRECT + if (server->smbd_conn) + subreq->max_nr_segs = server->smbd_conn->max_frmr_depth; +@@ -101,7 +111,7 @@ static void cifs_issue_write(struct netfs_io_subrequest *subreq) + goto fail; + } + +- rc = adjust_credits(wdata->server, &wdata->credits, wdata->subreq.len); ++ rc = adjust_credits(wdata->server, wdata, cifs_trace_rw_credits_issue_write_adjust); + if (rc) + goto fail; + +@@ -163,7 +173,18 @@ static bool cifs_clamp_length(struct netfs_io_subrequest *subreq) + return false; + } + ++ rdata->credits.in_flight_check = 1; ++ rdata->credits.rreq_debug_id = rreq->debug_id; ++ rdata->credits.rreq_debug_index = subreq->debug_index; ++ ++ trace_smb3_rw_credits(rdata->rreq->debug_id, ++ rdata->subreq.debug_index, ++ rdata->credits.value, ++ server->credits, server->in_flight, 0, ++ cifs_trace_rw_credits_read_submit); ++ + subreq->len = min_t(size_t, subreq->len, rsize); ++ + #ifdef CONFIG_CIFS_SMB_DIRECT + if (server->smbd_conn) + subreq->max_nr_segs = server->smbd_conn->max_frmr_depth; +@@ -294,7 +315,20 @@ static void cifs_free_subrequest(struct netfs_io_subrequest *subreq) + #endif + } + +- add_credits_and_wake_if(rdata->server, &rdata->credits, 0); ++ if (rdata->credits.value != 0) { ++ trace_smb3_rw_credits(rdata->rreq->debug_id, ++ rdata->subreq.debug_index, ++ rdata->credits.value, ++ rdata->server ? rdata->server->credits : 0, ++ rdata->server ? rdata->server->in_flight : 0, ++ -rdata->credits.value, ++ cifs_trace_rw_credits_free_subreq); ++ if (rdata->server) ++ add_credits_and_wake_if(rdata->server, &rdata->credits, 0); ++ else ++ rdata->credits.value = 0; ++ } ++ + if (rdata->have_xid) + free_xid(rdata->xid); + } +@@ -2719,6 +2753,7 @@ cifs_writev(struct kiocb *iocb, struct iov_iter *from) + struct inode *inode = file->f_mapping->host; + struct cifsInodeInfo *cinode = CIFS_I(inode); + struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server; ++ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); + ssize_t rc; + + rc = netfs_start_io_write(inode); +@@ -2735,12 +2770,16 @@ cifs_writev(struct kiocb *iocb, struct iov_iter *from) + if (rc <= 0) + goto out; + +- if (!cifs_find_lock_conflict(cfile, iocb->ki_pos, iov_iter_count(from), ++ if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) && ++ (cifs_find_lock_conflict(cfile, iocb->ki_pos, iov_iter_count(from), + server->vals->exclusive_lock_type, 0, +- NULL, CIFS_WRITE_OP)) +- rc = netfs_buffered_write_iter_locked(iocb, from, NULL); +- else ++ NULL, CIFS_WRITE_OP))) { + rc = -EACCES; ++ goto out; ++ } ++ ++ rc = netfs_buffered_write_iter_locked(iocb, from, NULL); ++ + out: + up_read(&cinode->lock_sem); + netfs_end_io_write(inode); +@@ -2872,9 +2911,7 @@ cifs_strict_readv(struct kiocb *iocb, struct iov_iter *to) + if (!CIFS_CACHE_READ(cinode)) + return netfs_unbuffered_read_iter(iocb, to); + +- if (cap_unix(tcon->ses) && +- (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) && +- ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) { ++ if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0) { + if (iocb->ki_flags & IOCB_DIRECT) + return netfs_unbuffered_read_iter(iocb, to); + return netfs_buffered_read_iter(iocb, to); +diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c +index 689d8a506d459..48c27581ec511 100644 +--- a/fs/smb/client/reparse.c ++++ b/fs/smb/client/reparse.c +@@ -378,6 +378,8 @@ int parse_reparse_point(struct reparse_data_buffer *buf, + u32 plen, struct cifs_sb_info *cifs_sb, + bool unicode, struct cifs_open_info_data *data) + { ++ struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); ++ + data->reparse.buf = buf; + + /* See MS-FSCC 2.1.2 */ +@@ -394,12 +396,13 @@ int parse_reparse_point(struct reparse_data_buffer *buf, + case IO_REPARSE_TAG_LX_FIFO: + case IO_REPARSE_TAG_LX_CHR: + case IO_REPARSE_TAG_LX_BLK: +- return 0; ++ break; + default: +- cifs_dbg(VFS, "%s: unhandled reparse tag: 0x%08x\n", +- __func__, le32_to_cpu(buf->ReparseTag)); +- return -EOPNOTSUPP; ++ cifs_tcon_dbg(VFS | ONCE, "unhandled reparse tag: 0x%08x\n", ++ le32_to_cpu(buf->ReparseTag)); ++ break; + } ++ return 0; + } + + int smb2_parse_reparse_point(struct cifs_sb_info *cifs_sb, +diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c +index 212ec6f66ec65..e1f2feb56f45f 100644 +--- a/fs/smb/client/smb1ops.c ++++ b/fs/smb/client/smb1ops.c +@@ -108,7 +108,7 @@ cifs_find_mid(struct TCP_Server_Info *server, char *buffer) + + static void + cifs_add_credits(struct TCP_Server_Info *server, +- const struct cifs_credits *credits, const int optype) ++ struct cifs_credits *credits, const int optype) + { + spin_lock(&server->req_lock); + server->credits += credits->value; +diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c +index c8e536540895a..7fe59235f0901 100644 +--- a/fs/smb/client/smb2ops.c ++++ b/fs/smb/client/smb2ops.c +@@ -66,7 +66,7 @@ change_conf(struct TCP_Server_Info *server) + + static void + smb2_add_credits(struct TCP_Server_Info *server, +- const struct cifs_credits *credits, const int optype) ++ struct cifs_credits *credits, const int optype) + { + int *val, rc = -1; + int scredits, in_flight; +@@ -94,7 +94,21 @@ smb2_add_credits(struct TCP_Server_Info *server, + server->conn_id, server->hostname, *val, + add, server->in_flight); + } +- WARN_ON_ONCE(server->in_flight == 0); ++ if (credits->in_flight_check > 1) { ++ pr_warn_once("rreq R=%08x[%x] Credits not in flight\n", ++ credits->rreq_debug_id, credits->rreq_debug_index); ++ } else { ++ credits->in_flight_check = 2; ++ } ++ if (WARN_ON_ONCE(server->in_flight == 0)) { ++ pr_warn_once("rreq R=%08x[%x] Zero in_flight\n", ++ credits->rreq_debug_id, credits->rreq_debug_index); ++ trace_smb3_rw_credits(credits->rreq_debug_id, ++ credits->rreq_debug_index, ++ credits->value, ++ server->credits, server->in_flight, 0, ++ cifs_trace_rw_credits_zero_in_flight); ++ } + server->in_flight--; + if (server->in_flight == 0 && + ((optype & CIFS_OP_MASK) != CIFS_NEG_OP) && +@@ -283,16 +297,23 @@ smb2_wait_mtu_credits(struct TCP_Server_Info *server, size_t size, + + static int + smb2_adjust_credits(struct TCP_Server_Info *server, +- struct cifs_credits *credits, +- const unsigned int payload_size) ++ struct cifs_io_subrequest *subreq, ++ unsigned int /*enum smb3_rw_credits_trace*/ trace) + { +- int new_val = DIV_ROUND_UP(payload_size, SMB2_MAX_BUFFER_SIZE); ++ struct cifs_credits *credits = &subreq->credits; ++ int new_val = DIV_ROUND_UP(subreq->subreq.len, SMB2_MAX_BUFFER_SIZE); + int scredits, in_flight; + + if (!credits->value || credits->value == new_val) + return 0; + + if (credits->value < new_val) { ++ trace_smb3_rw_credits(subreq->rreq->debug_id, ++ subreq->subreq.debug_index, ++ credits->value, ++ server->credits, server->in_flight, ++ new_val - credits->value, ++ cifs_trace_rw_credits_no_adjust_up); + trace_smb3_too_many_credits(server->CurrentMid, + server->conn_id, server->hostname, 0, credits->value - new_val, 0); + cifs_server_dbg(VFS, "request has less credits (%d) than required (%d)", +@@ -308,6 +329,12 @@ smb2_adjust_credits(struct TCP_Server_Info *server, + in_flight = server->in_flight; + spin_unlock(&server->req_lock); + ++ trace_smb3_rw_credits(subreq->rreq->debug_id, ++ subreq->subreq.debug_index, ++ credits->value, ++ server->credits, server->in_flight, ++ new_val - credits->value, ++ cifs_trace_rw_credits_old_session); + trace_smb3_reconnect_detected(server->CurrentMid, + server->conn_id, server->hostname, scredits, + credits->value - new_val, in_flight); +@@ -316,6 +343,11 @@ smb2_adjust_credits(struct TCP_Server_Info *server, + return -EAGAIN; + } + ++ trace_smb3_rw_credits(subreq->rreq->debug_id, ++ subreq->subreq.debug_index, ++ credits->value, ++ server->credits, server->in_flight, ++ new_val - credits->value, trace); + server->credits += credits->value - new_val; + scredits = server->credits; + in_flight = server->in_flight; +diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c +index 896147ba6660e..4cd5c33be2a1a 100644 +--- a/fs/smb/client/smb2pdu.c ++++ b/fs/smb/client/smb2pdu.c +@@ -4505,8 +4505,15 @@ smb2_readv_callback(struct mid_q_entry *mid) + struct TCP_Server_Info *server = rdata->server; + struct smb2_hdr *shdr = + (struct smb2_hdr *)rdata->iov[0].iov_base; +- struct cifs_credits credits = { .value = 0, .instance = 0 }; ++ struct cifs_credits credits = { ++ .value = 0, ++ .instance = 0, ++ .rreq_debug_id = rdata->rreq->debug_id, ++ .rreq_debug_index = rdata->subreq.debug_index, ++ }; + struct smb_rqst rqst = { .rq_iov = &rdata->iov[1], .rq_nvec = 1 }; ++ unsigned int rreq_debug_id = rdata->rreq->debug_id; ++ unsigned int subreq_debug_index = rdata->subreq.debug_index; + + if (rdata->got_bytes) { + rqst.rq_iter = rdata->subreq.io_iter; +@@ -4590,10 +4597,16 @@ smb2_readv_callback(struct mid_q_entry *mid) + if (rdata->subreq.start < rdata->subreq.rreq->i_size) + rdata->result = 0; + } ++ trace_smb3_rw_credits(rreq_debug_id, subreq_debug_index, rdata->credits.value, ++ server->credits, server->in_flight, ++ 0, cifs_trace_rw_credits_read_response_clear); + rdata->credits.value = 0; + INIT_WORK(&rdata->subreq.work, smb2_readv_worker); + queue_work(cifsiod_wq, &rdata->subreq.work); + release_mid(mid); ++ trace_smb3_rw_credits(rreq_debug_id, subreq_debug_index, 0, ++ server->credits, server->in_flight, ++ credits.value, cifs_trace_rw_credits_read_response_add); + add_credits(server, &credits, 0); + } + +@@ -4650,7 +4663,7 @@ smb2_async_readv(struct cifs_io_subrequest *rdata) + min_t(int, server->max_credits - + server->credits, credit_request)); + +- rc = adjust_credits(server, &rdata->credits, rdata->subreq.len); ++ rc = adjust_credits(server, rdata, cifs_trace_rw_credits_call_readv_adjust); + if (rc) + goto async_readv_out; + +@@ -4769,7 +4782,14 @@ smb2_writev_callback(struct mid_q_entry *mid) + struct cifs_tcon *tcon = tlink_tcon(wdata->req->cfile->tlink); + struct TCP_Server_Info *server = wdata->server; + struct smb2_write_rsp *rsp = (struct smb2_write_rsp *)mid->resp_buf; +- struct cifs_credits credits = { .value = 0, .instance = 0 }; ++ struct cifs_credits credits = { ++ .value = 0, ++ .instance = 0, ++ .rreq_debug_id = wdata->rreq->debug_id, ++ .rreq_debug_index = wdata->subreq.debug_index, ++ }; ++ unsigned int rreq_debug_id = wdata->rreq->debug_id; ++ unsigned int subreq_debug_index = wdata->subreq.debug_index; + ssize_t result = 0; + size_t written; + +@@ -4840,9 +4860,15 @@ smb2_writev_callback(struct mid_q_entry *mid) + tcon->tid, tcon->ses->Suid, + wdata->subreq.start, wdata->subreq.len); + ++ trace_smb3_rw_credits(rreq_debug_id, subreq_debug_index, wdata->credits.value, ++ server->credits, server->in_flight, ++ 0, cifs_trace_rw_credits_write_response_clear); + wdata->credits.value = 0; + cifs_write_subrequest_terminated(wdata, result ?: written, true); + release_mid(mid); ++ trace_smb3_rw_credits(rreq_debug_id, subreq_debug_index, 0, ++ server->credits, server->in_flight, ++ credits.value, cifs_trace_rw_credits_write_response_add); + add_credits(server, &credits, 0); + } + +@@ -4972,7 +4998,7 @@ smb2_async_writev(struct cifs_io_subrequest *wdata) + min_t(int, server->max_credits - + server->credits, credit_request)); + +- rc = adjust_credits(server, &wdata->credits, io_parms->length); ++ rc = adjust_credits(server, wdata, cifs_trace_rw_credits_call_writev_adjust); + if (rc) + goto async_writev_out; + +@@ -4997,6 +5023,12 @@ smb2_async_writev(struct cifs_io_subrequest *wdata) + cifs_small_buf_release(req); + out: + if (rc) { ++ trace_smb3_rw_credits(wdata->rreq->debug_id, ++ wdata->subreq.debug_index, ++ wdata->credits.value, ++ server->credits, server->in_flight, ++ -(int)wdata->credits.value, ++ cifs_trace_rw_credits_write_response_clear); + add_credits_and_wake_if(wdata->server, &wdata->credits, 0); + cifs_write_subrequest_terminated(wdata, rc, true); + } +diff --git a/fs/smb/client/trace.h b/fs/smb/client/trace.h +index 36d47ce596317..36d5295c2a6f9 100644 +--- a/fs/smb/client/trace.h ++++ b/fs/smb/client/trace.h +@@ -20,6 +20,22 @@ + /* + * Specify enums for tracing information. + */ ++#define smb3_rw_credits_traces \ ++ EM(cifs_trace_rw_credits_call_readv_adjust, "rd-call-adj") \ ++ EM(cifs_trace_rw_credits_call_writev_adjust, "wr-call-adj") \ ++ EM(cifs_trace_rw_credits_free_subreq, "free-subreq") \ ++ EM(cifs_trace_rw_credits_issue_read_adjust, "rd-issu-adj") \ ++ EM(cifs_trace_rw_credits_issue_write_adjust, "wr-issu-adj") \ ++ EM(cifs_trace_rw_credits_no_adjust_up, "no-adj-up ") \ ++ EM(cifs_trace_rw_credits_old_session, "old-session") \ ++ EM(cifs_trace_rw_credits_read_response_add, "rd-resp-add") \ ++ EM(cifs_trace_rw_credits_read_response_clear, "rd-resp-clr") \ ++ EM(cifs_trace_rw_credits_read_submit, "rd-submit ") \ ++ EM(cifs_trace_rw_credits_write_prepare, "wr-prepare ") \ ++ EM(cifs_trace_rw_credits_write_response_add, "wr-resp-add") \ ++ EM(cifs_trace_rw_credits_write_response_clear, "wr-resp-clr") \ ++ E_(cifs_trace_rw_credits_zero_in_flight, "ZERO-IN-FLT") ++ + #define smb3_tcon_ref_traces \ + EM(netfs_trace_tcon_ref_dec_dfs_refer, "DEC DfsRef") \ + EM(netfs_trace_tcon_ref_free, "FRE ") \ +@@ -59,7 +75,8 @@ + #define EM(a, b) a, + #define E_(a, b) a + +-enum smb3_tcon_ref_trace { smb3_tcon_ref_traces } __mode(byte); ++enum smb3_rw_credits_trace { smb3_rw_credits_traces } __mode(byte); ++enum smb3_tcon_ref_trace { smb3_tcon_ref_traces } __mode(byte); + + #undef EM + #undef E_ +@@ -71,6 +88,7 @@ enum smb3_tcon_ref_trace { smb3_tcon_ref_traces } __mode(byte); + #define EM(a, b) TRACE_DEFINE_ENUM(a); + #define E_(a, b) TRACE_DEFINE_ENUM(a); + ++smb3_rw_credits_traces; + smb3_tcon_ref_traces; + + #undef EM +@@ -1316,6 +1334,41 @@ TRACE_EVENT(smb3_tcon_ref, + __entry->ref) + ); + ++TRACE_EVENT(smb3_rw_credits, ++ TP_PROTO(unsigned int rreq_debug_id, ++ unsigned int subreq_debug_index, ++ unsigned int subreq_credits, ++ unsigned int server_credits, ++ int server_in_flight, ++ int credit_change, ++ enum smb3_rw_credits_trace trace), ++ TP_ARGS(rreq_debug_id, subreq_debug_index, subreq_credits, ++ server_credits, server_in_flight, credit_change, trace), ++ TP_STRUCT__entry( ++ __field(unsigned int, rreq_debug_id) ++ __field(unsigned int, subreq_debug_index) ++ __field(unsigned int, subreq_credits) ++ __field(unsigned int, server_credits) ++ __field(int, in_flight) ++ __field(int, credit_change) ++ __field(enum smb3_rw_credits_trace, trace) ++ ), ++ TP_fast_assign( ++ __entry->rreq_debug_id = rreq_debug_id; ++ __entry->subreq_debug_index = subreq_debug_index; ++ __entry->subreq_credits = subreq_credits; ++ __entry->server_credits = server_credits; ++ __entry->in_flight = server_in_flight; ++ __entry->credit_change = credit_change; ++ __entry->trace = trace; ++ ), ++ TP_printk("R=%08x[%x] %s cred=%u chg=%d pool=%u ifl=%d", ++ __entry->rreq_debug_id, __entry->subreq_debug_index, ++ __print_symbolic(__entry->trace, smb3_rw_credits_traces), ++ __entry->subreq_credits, __entry->credit_change, ++ __entry->server_credits, __entry->in_flight) ++ ); ++ + + #undef EM + #undef E_ +diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c +index 012b9bd069952..adfe0d0587010 100644 +--- a/fs/smb/client/transport.c ++++ b/fs/smb/client/transport.c +@@ -988,10 +988,10 @@ static void + cifs_compound_callback(struct mid_q_entry *mid) + { + struct TCP_Server_Info *server = mid->server; +- struct cifs_credits credits; +- +- credits.value = server->ops->get_credits(mid); +- credits.instance = server->reconnect_instance; ++ struct cifs_credits credits = { ++ .value = server->ops->get_credits(mid), ++ .instance = server->reconnect_instance, ++ }; + + add_credits(server, &credits, mid->optype); + +diff --git a/fs/smb/server/connection.c b/fs/smb/server/connection.c +index 09e1e7771592f..7889df8112b4e 100644 +--- a/fs/smb/server/connection.c ++++ b/fs/smb/server/connection.c +@@ -165,11 +165,43 @@ void ksmbd_all_conn_set_status(u64 sess_id, u32 status) + up_read(&conn_list_lock); + } + +-void ksmbd_conn_wait_idle(struct ksmbd_conn *conn, u64 sess_id) ++void ksmbd_conn_wait_idle(struct ksmbd_conn *conn) + { + wait_event(conn->req_running_q, atomic_read(&conn->req_running) < 2); + } + ++int ksmbd_conn_wait_idle_sess_id(struct ksmbd_conn *curr_conn, u64 sess_id) ++{ ++ struct ksmbd_conn *conn; ++ int rc, retry_count = 0, max_timeout = 120; ++ int rcount = 1; ++ ++retry_idle: ++ if (retry_count >= max_timeout) ++ return -EIO; ++ ++ down_read(&conn_list_lock); ++ list_for_each_entry(conn, &conn_list, conns_list) { ++ if (conn->binding || xa_load(&conn->sessions, sess_id)) { ++ if (conn == curr_conn) ++ rcount = 2; ++ if (atomic_read(&conn->req_running) >= rcount) { ++ rc = wait_event_timeout(conn->req_running_q, ++ atomic_read(&conn->req_running) < rcount, ++ HZ); ++ if (!rc) { ++ up_read(&conn_list_lock); ++ retry_count++; ++ goto retry_idle; ++ } ++ } ++ } ++ } ++ up_read(&conn_list_lock); ++ ++ return 0; ++} ++ + int ksmbd_conn_write(struct ksmbd_work *work) + { + struct ksmbd_conn *conn = work->conn; +diff --git a/fs/smb/server/connection.h b/fs/smb/server/connection.h +index 0e04cf8b1d896..b93e5437793e0 100644 +--- a/fs/smb/server/connection.h ++++ b/fs/smb/server/connection.h +@@ -145,7 +145,8 @@ extern struct list_head conn_list; + extern struct rw_semaphore conn_list_lock; + + bool ksmbd_conn_alive(struct ksmbd_conn *conn); +-void ksmbd_conn_wait_idle(struct ksmbd_conn *conn, u64 sess_id); ++void ksmbd_conn_wait_idle(struct ksmbd_conn *conn); ++int ksmbd_conn_wait_idle_sess_id(struct ksmbd_conn *curr_conn, u64 sess_id); + struct ksmbd_conn *ksmbd_conn_alloc(void); + void ksmbd_conn_free(struct ksmbd_conn *conn); + bool ksmbd_conn_lookup_dialect(struct ksmbd_conn *c); +diff --git a/fs/smb/server/mgmt/user_session.c b/fs/smb/server/mgmt/user_session.c +index aec0a7a124052..dac5f984f1754 100644 +--- a/fs/smb/server/mgmt/user_session.c ++++ b/fs/smb/server/mgmt/user_session.c +@@ -310,6 +310,7 @@ void destroy_previous_session(struct ksmbd_conn *conn, + { + struct ksmbd_session *prev_sess; + struct ksmbd_user *prev_user; ++ int err; + + down_write(&sessions_table_lock); + down_write(&conn->session_lock); +@@ -324,8 +325,15 @@ void destroy_previous_session(struct ksmbd_conn *conn, + memcmp(user->passkey, prev_user->passkey, user->passkey_sz)) + goto out; + ++ ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_RECONNECT); ++ err = ksmbd_conn_wait_idle_sess_id(conn, id); ++ if (err) { ++ ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_NEGOTIATE); ++ goto out; ++ } + ksmbd_destroy_file_table(&prev_sess->file_table); + prev_sess->state = SMB2_SESSION_EXPIRED; ++ ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_NEGOTIATE); + out: + up_write(&conn->session_lock); + up_write(&sessions_table_lock); +diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c +index 840c71c66b30b..8cfdf0d1a186e 100644 +--- a/fs/smb/server/smb2pdu.c ++++ b/fs/smb/server/smb2pdu.c +@@ -2210,7 +2210,7 @@ int smb2_session_logoff(struct ksmbd_work *work) + ksmbd_conn_unlock(conn); + + ksmbd_close_session_fds(work); +- ksmbd_conn_wait_idle(conn, sess_id); ++ ksmbd_conn_wait_idle(conn); + + /* + * Re-lookup session to validate if session is deleted +@@ -4406,7 +4406,8 @@ int smb2_query_dir(struct ksmbd_work *work) + rsp->OutputBufferLength = cpu_to_le32(0); + rsp->Buffer[0] = 0; + rc = ksmbd_iov_pin_rsp(work, (void *)rsp, +- sizeof(struct smb2_query_directory_rsp)); ++ offsetof(struct smb2_query_directory_rsp, Buffer) ++ + 1); + if (rc) + goto err_out; + } else { +diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h +index 80dc36f9d5274..9f1c1d225e32c 100644 +--- a/include/acpi/acpixf.h ++++ b/include/acpi/acpixf.h +@@ -660,12 +660,9 @@ ACPI_EXTERNAL_RETURN_STATUS(acpi_status + void *context)) + ACPI_EXTERNAL_RETURN_STATUS(acpi_status + acpi_execute_reg_methods(acpi_handle device, ++ u32 nax_depth, + acpi_adr_space_type + space_id)) +-ACPI_EXTERNAL_RETURN_STATUS(acpi_status +- acpi_execute_orphan_reg_method(acpi_handle device, +- acpi_adr_space_type +- space_id)) + ACPI_EXTERNAL_RETURN_STATUS(acpi_status + acpi_remove_address_space_handler(acpi_handle + device, +diff --git a/include/acpi/video.h b/include/acpi/video.h +index 3d538d4178abb..044c463138df8 100644 +--- a/include/acpi/video.h ++++ b/include/acpi/video.h +@@ -50,6 +50,7 @@ enum acpi_backlight_type { + acpi_backlight_native, + acpi_backlight_nvidia_wmi_ec, + acpi_backlight_apple_gmux, ++ acpi_backlight_dell_uart, + }; + + #if IS_ENABLED(CONFIG_ACPI_VIDEO) +diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h +index 70bf1004076b2..f00a8e18f389f 100644 +--- a/include/asm-generic/vmlinux.lds.h ++++ b/include/asm-generic/vmlinux.lds.h +@@ -451,30 +451,11 @@ + #endif + #endif + +-/* +- * Some symbol definitions will not exist yet during the first pass of the +- * link, but are guaranteed to exist in the final link. Provide preliminary +- * definitions that will be superseded in the final link to avoid having to +- * rely on weak external linkage, which requires a GOT when used in position +- * independent code. +- */ +-#define PRELIMINARY_SYMBOL_DEFINITIONS \ +- PROVIDE(kallsyms_addresses = .); \ +- PROVIDE(kallsyms_offsets = .); \ +- PROVIDE(kallsyms_names = .); \ +- PROVIDE(kallsyms_num_syms = .); \ +- PROVIDE(kallsyms_relative_base = .); \ +- PROVIDE(kallsyms_token_table = .); \ +- PROVIDE(kallsyms_token_index = .); \ +- PROVIDE(kallsyms_markers = .); \ +- PROVIDE(kallsyms_seqs_of_names = .); +- + /* + * Read only Data + */ + #define RO_DATA(align) \ + . = ALIGN((align)); \ +- PRELIMINARY_SYMBOL_DEFINITIONS \ + .rodata : AT(ADDR(.rodata) - LOAD_OFFSET) { \ + __start_rodata = .; \ + *(.rodata) *(.rodata.*) \ +diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h +index 8c4768c44a01b..d3b66d77df7a3 100644 +--- a/include/linux/bitmap.h ++++ b/include/linux/bitmap.h +@@ -270,6 +270,18 @@ static inline void bitmap_copy_clear_tail(unsigned long *dst, + dst[nbits / BITS_PER_LONG] &= BITMAP_LAST_WORD_MASK(nbits); + } + ++static inline void bitmap_copy_and_extend(unsigned long *to, ++ const unsigned long *from, ++ unsigned int count, unsigned int size) ++{ ++ unsigned int copy = BITS_TO_LONGS(count); ++ ++ memcpy(to, from, copy * sizeof(long)); ++ if (count % BITS_PER_LONG) ++ to[copy - 1] &= BITMAP_LAST_WORD_MASK(count); ++ memset(to + copy, 0, bitmap_size(size) - copy * sizeof(long)); ++} ++ + /* + * On 32-bit systems bitmaps are represented as u32 arrays internally. On LE64 + * machines the order of hi and lo parts of numbers match the bitmap structure. +diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h +index ff2a6cdb1fa3f..5db4a3f354804 100644 +--- a/include/linux/bpf_verifier.h ++++ b/include/linux/bpf_verifier.h +@@ -846,8 +846,8 @@ static inline u32 type_flag(u32 type) + /* only use after check_attach_btf_id() */ + static inline enum bpf_prog_type resolve_prog_type(const struct bpf_prog *prog) + { +- return (prog->type == BPF_PROG_TYPE_EXT && prog->aux->dst_prog) ? +- prog->aux->dst_prog->type : prog->type; ++ return (prog->type == BPF_PROG_TYPE_EXT && prog->aux->saved_dst_prog_type) ? ++ prog->aux->saved_dst_prog_type : prog->type; + } + + static inline bool bpf_prog_check_recur(const struct bpf_prog *prog) +diff --git a/include/linux/dsa/ocelot.h b/include/linux/dsa/ocelot.h +index dca2969015d80..6fbfbde68a37c 100644 +--- a/include/linux/dsa/ocelot.h ++++ b/include/linux/dsa/ocelot.h +@@ -5,6 +5,8 @@ + #ifndef _NET_DSA_TAG_OCELOT_H + #define _NET_DSA_TAG_OCELOT_H + ++#include ++#include + #include + #include + #include +@@ -273,4 +275,49 @@ static inline u32 ocelot_ptp_rew_op(struct sk_buff *skb) + return rew_op; + } + ++/** ++ * ocelot_xmit_get_vlan_info: Determine VLAN_TCI and TAG_TYPE for injected frame ++ * @skb: Pointer to socket buffer ++ * @br: Pointer to bridge device that the port is under, if any ++ * @vlan_tci: ++ * @tag_type: ++ * ++ * If the port is under a VLAN-aware bridge, remove the VLAN header from the ++ * payload and move it into the DSA tag, which will make the switch classify ++ * the packet to the bridge VLAN. Otherwise, leave the classified VLAN at zero, ++ * which is the pvid of standalone ports (OCELOT_STANDALONE_PVID), although not ++ * of VLAN-unaware bridge ports (that would be ocelot_vlan_unaware_pvid()). ++ * Anyway, VID 0 is fine because it is stripped on egress for these port modes, ++ * and source address learning is not performed for packets injected from the ++ * CPU anyway, so it doesn't matter that the VID is "wrong". ++ */ ++static inline void ocelot_xmit_get_vlan_info(struct sk_buff *skb, ++ struct net_device *br, ++ u64 *vlan_tci, u64 *tag_type) ++{ ++ struct vlan_ethhdr *hdr; ++ u16 proto, tci; ++ ++ if (!br || !br_vlan_enabled(br)) { ++ *vlan_tci = 0; ++ *tag_type = IFH_TAG_TYPE_C; ++ return; ++ } ++ ++ hdr = (struct vlan_ethhdr *)skb_mac_header(skb); ++ br_vlan_get_proto(br, &proto); ++ ++ if (ntohs(hdr->h_vlan_proto) == proto) { ++ vlan_remove_tag(skb, &tci); ++ *vlan_tci = tci; ++ } else { ++ rcu_read_lock(); ++ br_vlan_get_pvid_rcu(br, &tci); ++ rcu_read_unlock(); ++ *vlan_tci = tci; ++ } ++ ++ *tag_type = (proto != ETH_P_8021Q) ? IFH_TAG_TYPE_S : IFH_TAG_TYPE_C; ++} ++ + #endif +diff --git a/include/linux/fs.h b/include/linux/fs.h +index 93ac1a859d699..36b9e87439221 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -2370,6 +2370,9 @@ static inline void kiocb_clone(struct kiocb *kiocb, struct kiocb *kiocb_src, + * + * I_PINNING_FSCACHE_WB Inode is pinning an fscache object for writeback. + * ++ * I_LRU_ISOLATING Inode is pinned being isolated from LRU without holding ++ * i_count. ++ * + * Q: What is the difference between I_WILL_FREE and I_FREEING? + */ + #define I_DIRTY_SYNC (1 << 0) +@@ -2393,6 +2396,8 @@ static inline void kiocb_clone(struct kiocb *kiocb, struct kiocb *kiocb_src, + #define I_DONTCACHE (1 << 16) + #define I_SYNC_QUEUED (1 << 17) + #define I_PINNING_NETFS_WB (1 << 18) ++#define __I_LRU_ISOLATING 19 ++#define I_LRU_ISOLATING (1 << __I_LRU_ISOLATING) + + #define I_DIRTY_INODE (I_DIRTY_SYNC | I_DIRTY_DATASYNC) + #define I_DIRTY (I_DIRTY_INODE | I_DIRTY_PAGES) +diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h +index 8120d1976188c..18cf440866d9f 100644 +--- a/include/linux/hugetlb.h ++++ b/include/linux/hugetlb.h +@@ -967,10 +967,37 @@ static inline bool htlb_allow_alloc_fallback(int reason) + static inline spinlock_t *huge_pte_lockptr(struct hstate *h, + struct mm_struct *mm, pte_t *pte) + { +- if (huge_page_size(h) == PMD_SIZE) ++ const unsigned long size = huge_page_size(h); ++ ++ VM_WARN_ON(size == PAGE_SIZE); ++ ++ /* ++ * hugetlb must use the exact same PT locks as core-mm page table ++ * walkers would. When modifying a PTE table, hugetlb must take the ++ * PTE PT lock, when modifying a PMD table, hugetlb must take the PMD ++ * PT lock etc. ++ * ++ * The expectation is that any hugetlb folio smaller than a PMD is ++ * always mapped into a single PTE table and that any hugetlb folio ++ * smaller than a PUD (but at least as big as a PMD) is always mapped ++ * into a single PMD table. ++ * ++ * If that does not hold for an architecture, then that architecture ++ * must disable split PT locks such that all *_lockptr() functions ++ * will give us the same result: the per-MM PT lock. ++ * ++ * Note that with e.g., CONFIG_PGTABLE_LEVELS=2 where ++ * PGDIR_SIZE==P4D_SIZE==PUD_SIZE==PMD_SIZE, we'd use pud_lockptr() ++ * and core-mm would use pmd_lockptr(). However, in such configurations ++ * split PMD locks are disabled -- they don't make sense on a single ++ * PGDIR page table -- and the end result is the same. ++ */ ++ if (size >= PUD_SIZE) ++ return pud_lockptr(mm, (pud_t *) pte); ++ else if (size >= PMD_SIZE || IS_ENABLED(CONFIG_HIGHPTE)) + return pmd_lockptr(mm, (pmd_t *) pte); +- VM_BUG_ON(huge_page_size(h) == PAGE_SIZE); +- return &mm->page_table_lock; ++ /* pte_alloc_huge() only applies with !CONFIG_HIGHPTE */ ++ return ptep_lockptr(mm, pte); + } + + #ifndef hugepages_supported +diff --git a/include/linux/io_uring_types.h b/include/linux/io_uring_types.h +index 7abdc09271245..b18e998c8b887 100644 +--- a/include/linux/io_uring_types.h ++++ b/include/linux/io_uring_types.h +@@ -410,7 +410,7 @@ struct io_ring_ctx { + spinlock_t napi_lock; /* napi_list lock */ + + /* napi busy poll default timeout */ +- unsigned int napi_busy_poll_to; ++ ktime_t napi_busy_poll_dt; + bool napi_prefer_busy_poll; + bool napi_enabled; + +diff --git a/include/linux/mm.h b/include/linux/mm.h +index b58bad248eefd..f32177152921e 100644 +--- a/include/linux/mm.h ++++ b/include/linux/mm.h +@@ -2960,6 +2960,13 @@ static inline spinlock_t *pte_lockptr(struct mm_struct *mm, pmd_t *pmd) + return ptlock_ptr(page_ptdesc(pmd_page(*pmd))); + } + ++static inline spinlock_t *ptep_lockptr(struct mm_struct *mm, pte_t *pte) ++{ ++ BUILD_BUG_ON(IS_ENABLED(CONFIG_HIGHPTE)); ++ BUILD_BUG_ON(MAX_PTRS_PER_PTE * sizeof(pte_t) > PAGE_SIZE); ++ return ptlock_ptr(virt_to_ptdesc(pte)); ++} ++ + static inline bool ptlock_init(struct ptdesc *ptdesc) + { + /* +@@ -2984,6 +2991,10 @@ static inline spinlock_t *pte_lockptr(struct mm_struct *mm, pmd_t *pmd) + { + return &mm->page_table_lock; + } ++static inline spinlock_t *ptep_lockptr(struct mm_struct *mm, pte_t *pte) ++{ ++ return &mm->page_table_lock; ++} + static inline void ptlock_cache_init(void) {} + static inline bool ptlock_init(struct ptdesc *ptdesc) { return true; } + static inline void ptlock_free(struct ptdesc *ptdesc) {} +diff --git a/include/linux/panic.h b/include/linux/panic.h +index 6717b15e798c3..556b4e2ad9aa5 100644 +--- a/include/linux/panic.h ++++ b/include/linux/panic.h +@@ -16,6 +16,7 @@ extern void oops_enter(void); + extern void oops_exit(void); + extern bool oops_may_print(void); + ++extern bool panic_triggering_all_cpu_backtrace; + extern int panic_timeout; + extern unsigned long panic_print; + extern int panic_on_oops; +diff --git a/include/linux/pgalloc_tag.h b/include/linux/pgalloc_tag.h +index 18cd0c0c73d93..207f0c83c8e97 100644 +--- a/include/linux/pgalloc_tag.h ++++ b/include/linux/pgalloc_tag.h +@@ -43,6 +43,18 @@ static inline void put_page_tag_ref(union codetag_ref *ref) + page_ext_put(page_ext_from_codetag_ref(ref)); + } + ++static inline void clear_page_tag_ref(struct page *page) ++{ ++ if (mem_alloc_profiling_enabled()) { ++ union codetag_ref *ref = get_page_tag_ref(page); ++ ++ if (ref) { ++ set_codetag_empty(ref); ++ put_page_tag_ref(ref); ++ } ++ } ++} ++ + static inline void pgalloc_tag_add(struct page *page, struct task_struct *task, + unsigned int nr) + { +@@ -126,6 +138,7 @@ static inline void pgalloc_tag_sub_pages(struct alloc_tag *tag, unsigned int nr) + + static inline union codetag_ref *get_page_tag_ref(struct page *page) { return NULL; } + static inline void put_page_tag_ref(union codetag_ref *ref) {} ++static inline void clear_page_tag_ref(struct page *page) {} + static inline void pgalloc_tag_add(struct page *page, struct task_struct *task, + unsigned int nr) {} + static inline void pgalloc_tag_sub(struct page *page, unsigned int nr) {} +diff --git a/include/linux/thermal.h b/include/linux/thermal.h +index f1155c0439c4b..13f88317b81bf 100644 +--- a/include/linux/thermal.h ++++ b/include/linux/thermal.h +@@ -55,6 +55,7 @@ enum thermal_notify_event { + THERMAL_TZ_BIND_CDEV, /* Cooling dev is bind to the thermal zone */ + THERMAL_TZ_UNBIND_CDEV, /* Cooling dev is unbind from the thermal zone */ + THERMAL_INSTANCE_WEIGHT_CHANGED, /* Thermal instance weight changed */ ++ THERMAL_TZ_RESUME, /* Thermal zone is resuming after system sleep */ + }; + + /** +diff --git a/include/net/af_vsock.h b/include/net/af_vsock.h +index 535701efc1e5c..24d970f7a4fa2 100644 +--- a/include/net/af_vsock.h ++++ b/include/net/af_vsock.h +@@ -230,8 +230,12 @@ struct vsock_tap { + int vsock_add_tap(struct vsock_tap *vt); + int vsock_remove_tap(struct vsock_tap *vt); + void vsock_deliver_tap(struct sk_buff *build_skb(void *opaque), void *opaque); ++int __vsock_connectible_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, ++ int flags); + int vsock_connectible_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, + int flags); ++int __vsock_dgram_recvmsg(struct socket *sock, struct msghdr *msg, ++ size_t len, int flags); + int vsock_dgram_recvmsg(struct socket *sock, struct msghdr *msg, + size_t len, int flags); + +diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h +index e372a88e8c3f6..d1d073089f384 100644 +--- a/include/net/bluetooth/hci.h ++++ b/include/net/bluetooth/hci.h +@@ -206,14 +206,17 @@ enum { + */ + HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, + +- /* When this quirk is set, the controller has validated that +- * LE states reported through the HCI_LE_READ_SUPPORTED_STATES are +- * valid. This mechanism is necessary as many controllers have +- * been seen has having trouble initiating a connectable +- * advertisement despite the state combination being reported as +- * supported. ++ /* When this quirk is set, the LE states reported through the ++ * HCI_LE_READ_SUPPORTED_STATES are invalid/broken. ++ * ++ * This mechanism is necessary as many controllers have been seen has ++ * having trouble initiating a connectable advertisement despite the ++ * state combination being reported as supported. ++ * ++ * This quirk can be set before hci_register_dev is called or ++ * during the hdev->setup vendor callback. + */ +- HCI_QUIRK_VALID_LE_STATES, ++ HCI_QUIRK_BROKEN_LE_STATES, + + /* When this quirk is set, then erroneous data reporting + * is ignored. This is mainly due to the fact that the HCI +diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h +index b15f51ae3bfd9..c97ff64c9189f 100644 +--- a/include/net/bluetooth/hci_core.h ++++ b/include/net/bluetooth/hci_core.h +@@ -826,7 +826,7 @@ extern struct mutex hci_cb_list_lock; + } while (0) + + #define hci_dev_le_state_simultaneous(hdev) \ +- (test_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks) && \ ++ (!test_bit(HCI_QUIRK_BROKEN_LE_STATES, &hdev->quirks) && \ + (hdev->le_states[4] & 0x08) && /* Central */ \ + (hdev->le_states[4] & 0x40) && /* Peripheral */ \ + (hdev->le_states[3] & 0x10)) /* Simultaneous */ +diff --git a/include/net/kcm.h b/include/net/kcm.h +index 90279e5e09a5c..441e993be634c 100644 +--- a/include/net/kcm.h ++++ b/include/net/kcm.h +@@ -70,6 +70,7 @@ struct kcm_sock { + struct work_struct tx_work; + struct list_head wait_psock_list; + struct sk_buff *seq_skb; ++ struct mutex tx_mutex; + u32 tx_stopped : 1; + + /* Don't use bit fields here, these are set under different locks */ +diff --git a/include/net/mana/mana.h b/include/net/mana/mana.h +index f207a6e1042ae..9bdb1fdc7c51b 100644 +--- a/include/net/mana/mana.h ++++ b/include/net/mana/mana.h +@@ -274,6 +274,7 @@ struct mana_cq { + /* NAPI data */ + struct napi_struct napi; + int work_done; ++ int work_done_since_doorbell; + int budget; + }; + +diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h +index 45c40d200154d..8ecfb94049db5 100644 +--- a/include/scsi/scsi_cmnd.h ++++ b/include/scsi/scsi_cmnd.h +@@ -234,7 +234,7 @@ static inline sector_t scsi_get_lba(struct scsi_cmnd *scmd) + + static inline unsigned int scsi_logical_block_count(struct scsi_cmnd *scmd) + { +- unsigned int shift = ilog2(scmd->device->sector_size) - SECTOR_SHIFT; ++ unsigned int shift = ilog2(scmd->device->sector_size); + + return blk_rq_bytes(scsi_cmd_to_rq(scmd)) >> shift; + } +diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h +index 1e1b40f4e664e..846132ca5503d 100644 +--- a/include/soc/mscc/ocelot.h ++++ b/include/soc/mscc/ocelot.h +@@ -813,6 +813,9 @@ struct ocelot { + const u32 *const *map; + struct list_head stats_regions; + ++ spinlock_t inj_lock; ++ spinlock_t xtr_lock; ++ + u32 pool_size[OCELOT_SB_NUM][OCELOT_SB_POOL_NUM]; + int packet_buffer_size; + int num_frame_refs; +@@ -966,10 +969,17 @@ void __ocelot_target_write_ix(struct ocelot *ocelot, enum ocelot_target target, + u32 val, u32 reg, u32 offset); + + /* Packet I/O */ ++void ocelot_lock_inj_grp(struct ocelot *ocelot, int grp); ++void ocelot_unlock_inj_grp(struct ocelot *ocelot, int grp); ++void ocelot_lock_xtr_grp(struct ocelot *ocelot, int grp); ++void ocelot_unlock_xtr_grp(struct ocelot *ocelot, int grp); ++void ocelot_lock_xtr_grp_bh(struct ocelot *ocelot, int grp); ++void ocelot_unlock_xtr_grp_bh(struct ocelot *ocelot, int grp); + bool ocelot_can_inject(struct ocelot *ocelot, int grp); + void ocelot_port_inject_frame(struct ocelot *ocelot, int port, int grp, + u32 rew_op, struct sk_buff *skb); +-void ocelot_ifh_port_set(void *ifh, int port, u32 rew_op, u32 vlan_tag); ++void ocelot_ifh_set_basic(void *ifh, struct ocelot *ocelot, int port, ++ u32 rew_op, struct sk_buff *skb); + int ocelot_xtr_poll_frame(struct ocelot *ocelot, int grp, struct sk_buff **skb); + void ocelot_drain_cpu_queue(struct ocelot *ocelot, int grp); + void ocelot_ptp_rx_timestamp(struct ocelot *ocelot, struct sk_buff *skb, +diff --git a/include/trace/events/netfs.h b/include/trace/events/netfs.h +index da23484268dfc..24ec3434d32ee 100644 +--- a/include/trace/events/netfs.h ++++ b/include/trace/events/netfs.h +@@ -145,6 +145,7 @@ + EM(netfs_folio_trace_clear_g, "clear-g") \ + EM(netfs_folio_trace_clear_s, "clear-s") \ + EM(netfs_folio_trace_copy_to_cache, "mark-copy") \ ++ EM(netfs_folio_trace_end_copy, "end-copy") \ + EM(netfs_folio_trace_filled_gaps, "filled-gaps") \ + EM(netfs_folio_trace_kill, "kill") \ + EM(netfs_folio_trace_kill_cc, "kill-cc") \ +diff --git a/include/uapi/misc/fastrpc.h b/include/uapi/misc/fastrpc.h +index 91583690bddc5..f33d914d8f469 100644 +--- a/include/uapi/misc/fastrpc.h ++++ b/include/uapi/misc/fastrpc.h +@@ -8,14 +8,11 @@ + #define FASTRPC_IOCTL_ALLOC_DMA_BUFF _IOWR('R', 1, struct fastrpc_alloc_dma_buf) + #define FASTRPC_IOCTL_FREE_DMA_BUFF _IOWR('R', 2, __u32) + #define FASTRPC_IOCTL_INVOKE _IOWR('R', 3, struct fastrpc_invoke) +-/* This ioctl is only supported with secure device nodes */ + #define FASTRPC_IOCTL_INIT_ATTACH _IO('R', 4) + #define FASTRPC_IOCTL_INIT_CREATE _IOWR('R', 5, struct fastrpc_init_create) + #define FASTRPC_IOCTL_MMAP _IOWR('R', 6, struct fastrpc_req_mmap) + #define FASTRPC_IOCTL_MUNMAP _IOWR('R', 7, struct fastrpc_req_munmap) +-/* This ioctl is only supported with secure device nodes */ + #define FASTRPC_IOCTL_INIT_ATTACH_SNS _IO('R', 8) +-/* This ioctl is only supported with secure device nodes */ + #define FASTRPC_IOCTL_INIT_CREATE_STATIC _IOWR('R', 9, struct fastrpc_init_create_static) + #define FASTRPC_IOCTL_MEM_MAP _IOWR('R', 10, struct fastrpc_mem_map) + #define FASTRPC_IOCTL_MEM_UNMAP _IOWR('R', 11, struct fastrpc_mem_unmap) +diff --git a/init/Kconfig b/init/Kconfig +index d8a971b804d32..9684e5d2b81c6 100644 +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -1789,24 +1789,6 @@ config KALLSYMS_ABSOLUTE_PERCPU + depends on KALLSYMS + default X86_64 && SMP + +-config KALLSYMS_BASE_RELATIVE +- bool +- depends on KALLSYMS +- default y +- help +- Instead of emitting them as absolute values in the native word size, +- emit the symbol references in the kallsyms table as 32-bit entries, +- each containing a relative value in the range [base, base + U32_MAX] +- or, when KALLSYMS_ABSOLUTE_PERCPU is in effect, each containing either +- an absolute value in the range [0, S32_MAX] or a relative value in the +- range [base, base + S32_MAX], where base is the lowest relative symbol +- address encountered in the image. +- +- On 64-bit builds, this reduces the size of the address table by 50%, +- but more importantly, it results in entries whose values are build +- time constants, and no relocation pass is required at runtime to fix +- up the entries based on the runtime load address of the kernel. +- + # end of the "standard kernel features (expert users)" menu + + config ARCH_HAS_MEMBARRIER_CALLBACKS +@@ -1924,12 +1906,15 @@ config RUST + config RUSTC_VERSION_TEXT + string + depends on RUST +- default $(shell,command -v $(RUSTC) >/dev/null 2>&1 && $(RUSTC) --version || echo n) ++ default "$(shell,$(RUSTC) --version 2>/dev/null)" + + config BINDGEN_VERSION_TEXT + string + depends on RUST +- default $(shell,command -v $(BINDGEN) >/dev/null 2>&1 && $(BINDGEN) --version || echo n) ++ # The dummy parameter `workaround-for-0.69.0` is required to support 0.69.0 ++ # (https://github.com/rust-lang/rust-bindgen/pull/2678). It can be removed when ++ # the minimum version is upgraded past that (0.69.1 already fixed the issue). ++ default "$(shell,$(BINDGEN) --version workaround-for-0.69.0 2>/dev/null)" + + # + # Place an empty function call at each tracepoint site. Can be +diff --git a/io_uring/io_uring.h b/io_uring/io_uring.h +index 726e6367af4d3..af46d03d58847 100644 +--- a/io_uring/io_uring.h ++++ b/io_uring/io_uring.h +@@ -43,7 +43,7 @@ struct io_wait_queue { + ktime_t timeout; + + #ifdef CONFIG_NET_RX_BUSY_POLL +- unsigned int napi_busy_poll_to; ++ ktime_t napi_busy_poll_dt; + bool napi_prefer_busy_poll; + #endif + }; +diff --git a/io_uring/kbuf.c b/io_uring/kbuf.c +index c95dc1736dd93..1af2bd56af44a 100644 +--- a/io_uring/kbuf.c ++++ b/io_uring/kbuf.c +@@ -218,10 +218,13 @@ static int io_ring_buffers_peek(struct io_kiocb *req, struct buf_sel_arg *arg, + + buf = io_ring_head_to_buf(br, head, bl->mask); + if (arg->max_len) { +- int needed; ++ u32 len = READ_ONCE(buf->len); ++ size_t needed; + +- needed = (arg->max_len + buf->len - 1) / buf->len; +- needed = min(needed, PEEK_MAX_IMPORT); ++ if (unlikely(!len)) ++ return -ENOBUFS; ++ needed = (arg->max_len + len - 1) / len; ++ needed = min_not_zero(needed, (size_t) PEEK_MAX_IMPORT); + if (nr_avail > needed) + nr_avail = needed; + } +diff --git a/io_uring/napi.c b/io_uring/napi.c +index 080d10e0e0afd..ab5d68d4440c4 100644 +--- a/io_uring/napi.c ++++ b/io_uring/napi.c +@@ -33,6 +33,12 @@ static struct io_napi_entry *io_napi_hash_find(struct hlist_head *hash_list, + return NULL; + } + ++static inline ktime_t net_to_ktime(unsigned long t) ++{ ++ /* napi approximating usecs, reverse busy_loop_current_time */ ++ return ns_to_ktime(t << 10); ++} ++ + void __io_napi_add(struct io_ring_ctx *ctx, struct socket *sock) + { + struct hlist_head *hash_list; +@@ -102,14 +108,14 @@ static inline void io_napi_remove_stale(struct io_ring_ctx *ctx, bool is_stale) + __io_napi_remove_stale(ctx); + } + +-static inline bool io_napi_busy_loop_timeout(unsigned long start_time, +- unsigned long bp_usec) ++static inline bool io_napi_busy_loop_timeout(ktime_t start_time, ++ ktime_t bp) + { +- if (bp_usec) { +- unsigned long end_time = start_time + bp_usec; +- unsigned long now = busy_loop_current_time(); ++ if (bp) { ++ ktime_t end_time = ktime_add(start_time, bp); ++ ktime_t now = net_to_ktime(busy_loop_current_time()); + +- return time_after(now, end_time); ++ return ktime_after(now, end_time); + } + + return true; +@@ -124,7 +130,8 @@ static bool io_napi_busy_loop_should_end(void *data, + return true; + if (io_should_wake(iowq) || io_has_work(iowq->ctx)) + return true; +- if (io_napi_busy_loop_timeout(start_time, iowq->napi_busy_poll_to)) ++ if (io_napi_busy_loop_timeout(net_to_ktime(start_time), ++ iowq->napi_busy_poll_dt)) + return true; + + return false; +@@ -181,10 +188,12 @@ static void io_napi_blocking_busy_loop(struct io_ring_ctx *ctx, + */ + void io_napi_init(struct io_ring_ctx *ctx) + { ++ u64 sys_dt = READ_ONCE(sysctl_net_busy_poll) * NSEC_PER_USEC; ++ + INIT_LIST_HEAD(&ctx->napi_list); + spin_lock_init(&ctx->napi_lock); + ctx->napi_prefer_busy_poll = false; +- ctx->napi_busy_poll_to = READ_ONCE(sysctl_net_busy_poll); ++ ctx->napi_busy_poll_dt = ns_to_ktime(sys_dt); + } + + /* +@@ -217,7 +226,7 @@ void io_napi_free(struct io_ring_ctx *ctx) + int io_register_napi(struct io_ring_ctx *ctx, void __user *arg) + { + const struct io_uring_napi curr = { +- .busy_poll_to = ctx->napi_busy_poll_to, ++ .busy_poll_to = ktime_to_us(ctx->napi_busy_poll_dt), + .prefer_busy_poll = ctx->napi_prefer_busy_poll + }; + struct io_uring_napi napi; +@@ -232,7 +241,7 @@ int io_register_napi(struct io_ring_ctx *ctx, void __user *arg) + if (copy_to_user(arg, &curr, sizeof(curr))) + return -EFAULT; + +- WRITE_ONCE(ctx->napi_busy_poll_to, napi.busy_poll_to); ++ WRITE_ONCE(ctx->napi_busy_poll_dt, napi.busy_poll_to * NSEC_PER_USEC); + WRITE_ONCE(ctx->napi_prefer_busy_poll, !!napi.prefer_busy_poll); + WRITE_ONCE(ctx->napi_enabled, true); + return 0; +@@ -249,14 +258,14 @@ int io_register_napi(struct io_ring_ctx *ctx, void __user *arg) + int io_unregister_napi(struct io_ring_ctx *ctx, void __user *arg) + { + const struct io_uring_napi curr = { +- .busy_poll_to = ctx->napi_busy_poll_to, ++ .busy_poll_to = ktime_to_us(ctx->napi_busy_poll_dt), + .prefer_busy_poll = ctx->napi_prefer_busy_poll + }; + + if (arg && copy_to_user(arg, &curr, sizeof(curr))) + return -EFAULT; + +- WRITE_ONCE(ctx->napi_busy_poll_to, 0); ++ WRITE_ONCE(ctx->napi_busy_poll_dt, 0); + WRITE_ONCE(ctx->napi_prefer_busy_poll, false); + WRITE_ONCE(ctx->napi_enabled, false); + return 0; +@@ -275,23 +284,20 @@ int io_unregister_napi(struct io_ring_ctx *ctx, void __user *arg) + void __io_napi_adjust_timeout(struct io_ring_ctx *ctx, struct io_wait_queue *iowq, + struct timespec64 *ts) + { +- unsigned int poll_to = READ_ONCE(ctx->napi_busy_poll_to); ++ ktime_t poll_dt = READ_ONCE(ctx->napi_busy_poll_dt); + + if (ts) { + struct timespec64 poll_to_ts; + +- poll_to_ts = ns_to_timespec64(1000 * (s64)poll_to); ++ poll_to_ts = ns_to_timespec64(ktime_to_ns(poll_dt)); + if (timespec64_compare(ts, &poll_to_ts) < 0) { + s64 poll_to_ns = timespec64_to_ns(ts); +- if (poll_to_ns > 0) { +- u64 val = poll_to_ns + 999; +- do_div(val, (s64) 1000); +- poll_to = val; +- } ++ if (poll_to_ns > 0) ++ poll_dt = ns_to_ktime(poll_to_ns); + } + } + +- iowq->napi_busy_poll_to = poll_to; ++ iowq->napi_busy_poll_dt = poll_dt; + } + + /* +@@ -305,7 +311,7 @@ void __io_napi_busy_loop(struct io_ring_ctx *ctx, struct io_wait_queue *iowq) + { + iowq->napi_prefer_busy_poll = READ_ONCE(ctx->napi_prefer_busy_poll); + +- if (!(ctx->flags & IORING_SETUP_SQPOLL) && ctx->napi_enabled) ++ if (!(ctx->flags & IORING_SETUP_SQPOLL)) + io_napi_blocking_busy_loop(ctx, iowq); + } + +@@ -320,7 +326,7 @@ int io_napi_sqpoll_busy_poll(struct io_ring_ctx *ctx) + LIST_HEAD(napi_list); + bool is_stale = false; + +- if (!READ_ONCE(ctx->napi_busy_poll_to)) ++ if (!READ_ONCE(ctx->napi_busy_poll_dt)) + return 0; + if (list_empty_careful(&ctx->napi_list)) + return 0; +diff --git a/io_uring/napi.h b/io_uring/napi.h +index 6fc0393d0dbef..341d010cf66bc 100644 +--- a/io_uring/napi.h ++++ b/io_uring/napi.h +@@ -55,7 +55,7 @@ static inline void io_napi_add(struct io_kiocb *req) + struct io_ring_ctx *ctx = req->ctx; + struct socket *sock; + +- if (!READ_ONCE(ctx->napi_busy_poll_to)) ++ if (!READ_ONCE(ctx->napi_enabled)) + return; + + sock = sock_from_file(req->file); +diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c +index a8845cc299fec..521bd7efae038 100644 +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -16881,8 +16881,9 @@ static bool stacksafe(struct bpf_verifier_env *env, struct bpf_func_state *old, + spi = i / BPF_REG_SIZE; + + if (exact != NOT_EXACT && +- old->stack[spi].slot_type[i % BPF_REG_SIZE] != +- cur->stack[spi].slot_type[i % BPF_REG_SIZE]) ++ (i >= cur->allocated_stack || ++ old->stack[spi].slot_type[i % BPF_REG_SIZE] != ++ cur->stack[spi].slot_type[i % BPF_REG_SIZE])) + return false; + + if (!(old->stack[spi].spilled_ptr.live & REG_LIVE_READ) +diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c +index 5e468db958104..fc1c6236460d2 100644 +--- a/kernel/cgroup/cpuset.c ++++ b/kernel/cgroup/cpuset.c +@@ -1940,6 +1940,8 @@ static int update_parent_effective_cpumask(struct cpuset *cs, int cmd, + part_error = PERR_CPUSEMPTY; + goto write_error; + } ++ /* Check newmask again, whether cpus are available for parent/cs */ ++ nocpu |= tasks_nocpu_error(parent, cs, newmask); + + /* + * partcmd_update with newmask: +@@ -2472,7 +2474,8 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs, + */ + if (!*buf) { + cpumask_clear(trialcs->cpus_allowed); +- cpumask_clear(trialcs->effective_xcpus); ++ if (cpumask_empty(trialcs->exclusive_cpus)) ++ cpumask_clear(trialcs->effective_xcpus); + } else { + retval = cpulist_parse(buf, trialcs->cpus_allowed); + if (retval < 0) +diff --git a/kernel/cpu.c b/kernel/cpu.c +index 3d2bf1d50a0c4..6dee328bfe6fd 100644 +--- a/kernel/cpu.c ++++ b/kernel/cpu.c +@@ -2679,6 +2679,16 @@ int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval) + return ret; + } + ++/** ++ * Check if the core a CPU belongs to is online ++ */ ++#if !defined(topology_is_core_online) ++static inline bool topology_is_core_online(unsigned int cpu) ++{ ++ return true; ++} ++#endif ++ + int cpuhp_smt_enable(void) + { + int cpu, ret = 0; +@@ -2689,7 +2699,7 @@ int cpuhp_smt_enable(void) + /* Skip online CPUs and CPUs on offline nodes */ + if (cpu_online(cpu) || !node_online(cpu_to_node(cpu))) + continue; +- if (!cpu_smt_thread_allowed(cpu)) ++ if (!cpu_smt_thread_allowed(cpu) || !topology_is_core_online(cpu)) + continue; + ret = _cpu_up(cpu, 0, CPUHP_ONLINE); + if (ret) +diff --git a/kernel/events/core.c b/kernel/events/core.c +index b2a6aec118f3a..7891d5a75526a 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -9708,7 +9708,8 @@ static int __perf_event_overflow(struct perf_event *event, + + ret = __perf_event_account_interrupt(event, throttle); + +- if (event->prog && !bpf_overflow_handler(event, data, regs)) ++ if (event->prog && event->prog->type == BPF_PROG_TYPE_PERF_EVENT && ++ !bpf_overflow_handler(event, data, regs)) + return ret; + + /* +diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c +index 98b9622d372e4..a9a0ca605d4a8 100644 +--- a/kernel/kallsyms.c ++++ b/kernel/kallsyms.c +@@ -148,9 +148,6 @@ static unsigned int get_symbol_offset(unsigned long pos) + + unsigned long kallsyms_sym_address(int idx) + { +- if (!IS_ENABLED(CONFIG_KALLSYMS_BASE_RELATIVE)) +- return kallsyms_addresses[idx]; +- + /* values are unsigned offsets if --absolute-percpu is not in effect */ + if (!IS_ENABLED(CONFIG_KALLSYMS_ABSOLUTE_PERCPU)) + return kallsyms_relative_base + (u32)kallsyms_offsets[idx]; +@@ -163,38 +160,6 @@ unsigned long kallsyms_sym_address(int idx) + return kallsyms_relative_base - 1 - kallsyms_offsets[idx]; + } + +-static void cleanup_symbol_name(char *s) +-{ +- char *res; +- +- if (!IS_ENABLED(CONFIG_LTO_CLANG)) +- return; +- +- /* +- * LLVM appends various suffixes for local functions and variables that +- * must be promoted to global scope as part of LTO. This can break +- * hooking of static functions with kprobes. '.' is not a valid +- * character in an identifier in C. Suffixes only in LLVM LTO observed: +- * - foo.llvm.[0-9a-f]+ +- */ +- res = strstr(s, ".llvm."); +- if (res) +- *res = '\0'; +- +- return; +-} +- +-static int compare_symbol_name(const char *name, char *namebuf) +-{ +- /* The kallsyms_seqs_of_names is sorted based on names after +- * cleanup_symbol_name() (see scripts/kallsyms.c) if clang lto is enabled. +- * To ensure correct bisection in kallsyms_lookup_names(), do +- * cleanup_symbol_name(namebuf) before comparing name and namebuf. +- */ +- cleanup_symbol_name(namebuf); +- return strcmp(name, namebuf); +-} +- + static unsigned int get_symbol_seq(int index) + { + unsigned int i, seq = 0; +@@ -222,7 +187,7 @@ static int kallsyms_lookup_names(const char *name, + seq = get_symbol_seq(mid); + off = get_symbol_offset(seq); + kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf)); +- ret = compare_symbol_name(name, namebuf); ++ ret = strcmp(name, namebuf); + if (ret > 0) + low = mid + 1; + else if (ret < 0) +@@ -239,7 +204,7 @@ static int kallsyms_lookup_names(const char *name, + seq = get_symbol_seq(low - 1); + off = get_symbol_offset(seq); + kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf)); +- if (compare_symbol_name(name, namebuf)) ++ if (strcmp(name, namebuf)) + break; + low--; + } +@@ -251,7 +216,7 @@ static int kallsyms_lookup_names(const char *name, + seq = get_symbol_seq(high + 1); + off = get_symbol_offset(seq); + kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf)); +- if (compare_symbol_name(name, namebuf)) ++ if (strcmp(name, namebuf)) + break; + high++; + } +@@ -325,7 +290,7 @@ static unsigned long get_symbol_pos(unsigned long addr, + unsigned long symbol_start = 0, symbol_end = 0; + unsigned long i, low, high, mid; + +- /* Do a binary search on the sorted kallsyms_addresses array. */ ++ /* Do a binary search on the sorted kallsyms_offsets array. */ + low = 0; + high = kallsyms_num_syms; + +@@ -410,8 +375,7 @@ static int kallsyms_lookup_buildid(unsigned long addr, + if (modbuildid) + *modbuildid = NULL; + +- ret = strlen(namebuf); +- goto found; ++ return strlen(namebuf); + } + + /* See if it's in a module or a BPF JITed image. */ +@@ -425,8 +389,6 @@ static int kallsyms_lookup_buildid(unsigned long addr, + ret = ftrace_mod_address_lookup(addr, symbolsize, + offset, modname, namebuf); + +-found: +- cleanup_symbol_name(namebuf); + return ret; + } + +@@ -453,8 +415,6 @@ const char *kallsyms_lookup(unsigned long addr, + + int lookup_symbol_name(unsigned long addr, char *symname) + { +- int res; +- + symname[0] = '\0'; + symname[KSYM_NAME_LEN - 1] = '\0'; + +@@ -465,16 +425,10 @@ int lookup_symbol_name(unsigned long addr, char *symname) + /* Grab name */ + kallsyms_expand_symbol(get_symbol_offset(pos), + symname, KSYM_NAME_LEN); +- goto found; ++ return 0; + } + /* See if it's in a module. */ +- res = lookup_module_symbol_name(addr, symname); +- if (res) +- return res; +- +-found: +- cleanup_symbol_name(symname); +- return 0; ++ return lookup_module_symbol_name(addr, symname); + } + + /* Look up a kernel symbol and return it in a text buffer. */ +diff --git a/kernel/kallsyms_internal.h b/kernel/kallsyms_internal.h +index 85480274fc8fb..9633782f82500 100644 +--- a/kernel/kallsyms_internal.h ++++ b/kernel/kallsyms_internal.h +@@ -4,12 +4,6 @@ + + #include + +-/* +- * These will be re-linked against their real values during the second link +- * stage. Preliminary values must be provided in the linker script using the +- * PROVIDE() directive so that the first link stage can complete successfully. +- */ +-extern const unsigned long kallsyms_addresses[]; + extern const int kallsyms_offsets[]; + extern const u8 kallsyms_names[]; + +diff --git a/kernel/kallsyms_selftest.c b/kernel/kallsyms_selftest.c +index 2f84896a7bcbd..873f7c445488c 100644 +--- a/kernel/kallsyms_selftest.c ++++ b/kernel/kallsyms_selftest.c +@@ -187,31 +187,11 @@ static void test_perf_kallsyms_lookup_name(void) + stat.min, stat.max, div_u64(stat.sum, stat.real_cnt)); + } + +-static bool match_cleanup_name(const char *s, const char *name) +-{ +- char *p; +- int len; +- +- if (!IS_ENABLED(CONFIG_LTO_CLANG)) +- return false; +- +- p = strstr(s, ".llvm."); +- if (!p) +- return false; +- +- len = strlen(name); +- if (p - s != len) +- return false; +- +- return !strncmp(s, name, len); +-} +- + static int find_symbol(void *data, const char *name, unsigned long addr) + { + struct test_stat *stat = (struct test_stat *)data; + +- if (strcmp(name, stat->name) == 0 || +- (!stat->perf && match_cleanup_name(name, stat->name))) { ++ if (!strcmp(name, stat->name)) { + stat->real_cnt++; + stat->addr = addr; + +diff --git a/kernel/panic.c b/kernel/panic.c +index 8bff183d6180e..30342568e935f 100644 +--- a/kernel/panic.c ++++ b/kernel/panic.c +@@ -63,6 +63,8 @@ unsigned long panic_on_taint; + bool panic_on_taint_nousertaint = false; + static unsigned int warn_limit __read_mostly; + ++bool panic_triggering_all_cpu_backtrace; ++ + int panic_timeout = CONFIG_PANIC_TIMEOUT; + EXPORT_SYMBOL_GPL(panic_timeout); + +@@ -252,8 +254,12 @@ void check_panic_on_warn(const char *origin) + */ + static void panic_other_cpus_shutdown(bool crash_kexec) + { +- if (panic_print & PANIC_PRINT_ALL_CPU_BT) ++ if (panic_print & PANIC_PRINT_ALL_CPU_BT) { ++ /* Temporary allow non-panic CPUs to write their backtraces. */ ++ panic_triggering_all_cpu_backtrace = true; + trigger_all_cpu_backtrace(); ++ panic_triggering_all_cpu_backtrace = false; ++ } + + /* + * Note that smp_send_stop() is the usual SMP shutdown function, +diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c +index dddb15f48d595..c5d844f727f63 100644 +--- a/kernel/printk/printk.c ++++ b/kernel/printk/printk.c +@@ -2316,7 +2316,7 @@ asmlinkage int vprintk_emit(int facility, int level, + * non-panic CPUs are generating any messages, they will be + * silently dropped. + */ +- if (other_cpu_in_panic()) ++ if (other_cpu_in_panic() && !panic_triggering_all_cpu_backtrace) + return 0; + + if (level == LOGLEVEL_SCHED) { +diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c +index 578a49ff5c32e..cb507860163d0 100644 +--- a/kernel/trace/trace.c ++++ b/kernel/trace/trace.c +@@ -7956,7 +7956,7 @@ tracing_buffers_read(struct file *filp, char __user *ubuf, + trace_access_unlock(iter->cpu_file); + + if (ret < 0) { +- if (trace_empty(iter)) { ++ if (trace_empty(iter) && !iter->closed) { + if ((filp->f_flags & O_NONBLOCK)) + return -EAGAIN; + +diff --git a/kernel/vmcore_info.c b/kernel/vmcore_info.c +index 1d5eadd9dd61c..8b4f8cc2e0ec0 100644 +--- a/kernel/vmcore_info.c ++++ b/kernel/vmcore_info.c +@@ -216,12 +216,8 @@ static int __init crash_save_vmcoreinfo_init(void) + VMCOREINFO_SYMBOL(kallsyms_num_syms); + VMCOREINFO_SYMBOL(kallsyms_token_table); + VMCOREINFO_SYMBOL(kallsyms_token_index); +-#ifdef CONFIG_KALLSYMS_BASE_RELATIVE + VMCOREINFO_SYMBOL(kallsyms_offsets); + VMCOREINFO_SYMBOL(kallsyms_relative_base); +-#else +- VMCOREINFO_SYMBOL(kallsyms_addresses); +-#endif /* CONFIG_KALLSYMS_BASE_RELATIVE */ + #endif /* CONFIG_KALLSYMS */ + + arch_crash_save_vmcoreinfo(); +diff --git a/kernel/workqueue.c b/kernel/workqueue.c +index f98247ec99c20..c970eec25c5a0 100644 +--- a/kernel/workqueue.c ++++ b/kernel/workqueue.c +@@ -896,7 +896,7 @@ static struct worker_pool *get_work_pool(struct work_struct *work) + + static unsigned long shift_and_mask(unsigned long v, u32 shift, u32 bits) + { +- return (v >> shift) & ((1 << bits) - 1); ++ return (v >> shift) & ((1U << bits) - 1); + } + + static void work_offqd_unpack(struct work_offq_data *offqd, unsigned long data) +@@ -4190,7 +4190,6 @@ static bool start_flush_work(struct work_struct *work, struct wq_barrier *barr, + static bool __flush_work(struct work_struct *work, bool from_cancel) + { + struct wq_barrier barr; +- unsigned long data; + + if (WARN_ON(!wq_online)) + return false; +@@ -4208,29 +4207,35 @@ static bool __flush_work(struct work_struct *work, bool from_cancel) + * was queued on a BH workqueue, we also know that it was running in the + * BH context and thus can be busy-waited. + */ +- data = *work_data_bits(work); +- if (from_cancel && +- !WARN_ON_ONCE(data & WORK_STRUCT_PWQ) && (data & WORK_OFFQ_BH)) { +- /* +- * On RT, prevent a live lock when %current preempted soft +- * interrupt processing or prevents ksoftirqd from running by +- * keeping flipping BH. If the BH work item runs on a different +- * CPU then this has no effect other than doing the BH +- * disable/enable dance for nothing. This is copied from +- * kernel/softirq.c::tasklet_unlock_spin_wait(). +- */ +- while (!try_wait_for_completion(&barr.done)) { +- if (IS_ENABLED(CONFIG_PREEMPT_RT)) { +- local_bh_disable(); +- local_bh_enable(); +- } else { +- cpu_relax(); ++ if (from_cancel) { ++ unsigned long data = *work_data_bits(work); ++ ++ if (!WARN_ON_ONCE(data & WORK_STRUCT_PWQ) && ++ (data & WORK_OFFQ_BH)) { ++ /* ++ * On RT, prevent a live lock when %current preempted ++ * soft interrupt processing or prevents ksoftirqd from ++ * running by keeping flipping BH. If the BH work item ++ * runs on a different CPU then this has no effect other ++ * than doing the BH disable/enable dance for nothing. ++ * This is copied from ++ * kernel/softirq.c::tasklet_unlock_spin_wait(). ++ */ ++ while (!try_wait_for_completion(&barr.done)) { ++ if (IS_ENABLED(CONFIG_PREEMPT_RT)) { ++ local_bh_disable(); ++ local_bh_enable(); ++ } else { ++ cpu_relax(); ++ } + } ++ goto out_destroy; + } +- } else { +- wait_for_completion(&barr.done); + } + ++ wait_for_completion(&barr.done); ++ ++out_destroy: + destroy_work_on_stack(&barr.work); + return true; + } +diff --git a/mm/huge_memory.c b/mm/huge_memory.c +index 5f32a196a612e..4d9c1277e5e4d 100644 +--- a/mm/huge_memory.c ++++ b/mm/huge_memory.c +@@ -1672,7 +1672,7 @@ vm_fault_t do_huge_pmd_numa_page(struct vm_fault *vmf) + vmf->ptl = pmd_lock(vma->vm_mm, vmf->pmd); + if (unlikely(!pmd_same(oldpmd, *vmf->pmd))) { + spin_unlock(vmf->ptl); +- goto out; ++ return 0; + } + + pmd = pmd_modify(oldpmd, vma->vm_page_prot); +@@ -1715,22 +1715,16 @@ vm_fault_t do_huge_pmd_numa_page(struct vm_fault *vmf) + if (!migrate_misplaced_folio(folio, vma, target_nid)) { + flags |= TNF_MIGRATED; + nid = target_nid; +- } else { +- flags |= TNF_MIGRATE_FAIL; +- vmf->ptl = pmd_lock(vma->vm_mm, vmf->pmd); +- if (unlikely(!pmd_same(oldpmd, *vmf->pmd))) { +- spin_unlock(vmf->ptl); +- goto out; +- } +- goto out_map; +- } +- +-out: +- if (nid != NUMA_NO_NODE) + task_numa_fault(last_cpupid, nid, HPAGE_PMD_NR, flags); ++ return 0; ++ } + +- return 0; +- ++ flags |= TNF_MIGRATE_FAIL; ++ vmf->ptl = pmd_lock(vma->vm_mm, vmf->pmd); ++ if (unlikely(!pmd_same(oldpmd, *vmf->pmd))) { ++ spin_unlock(vmf->ptl); ++ return 0; ++ } + out_map: + /* Restore the PMD */ + pmd = pmd_modify(oldpmd, vma->vm_page_prot); +@@ -1740,7 +1734,10 @@ vm_fault_t do_huge_pmd_numa_page(struct vm_fault *vmf) + set_pmd_at(vma->vm_mm, haddr, vmf->pmd, pmd); + update_mmu_cache_pmd(vma, vmf->address, vmf->pmd); + spin_unlock(vmf->ptl); +- goto out; ++ ++ if (nid != NUMA_NO_NODE) ++ task_numa_fault(last_cpupid, nid, HPAGE_PMD_NR, flags); ++ return 0; + } + + /* +diff --git a/mm/memcontrol.c b/mm/memcontrol.c +index 88c7a0861017c..332f190bf3d6b 100644 +--- a/mm/memcontrol.c ++++ b/mm/memcontrol.c +@@ -5282,9 +5282,12 @@ static ssize_t memcg_write_event_control(struct kernfs_open_file *of, + buf = endp + 1; + + cfd = simple_strtoul(buf, &endp, 10); +- if ((*endp != ' ') && (*endp != '\0')) ++ if (*endp == '\0') ++ buf = endp; ++ else if (*endp == ' ') ++ buf = endp + 1; ++ else + return -EINVAL; +- buf = endp + 1; + + event = kzalloc(sizeof(*event), GFP_KERNEL); + if (!event) +diff --git a/mm/memory-failure.c b/mm/memory-failure.c +index d3c830e817e35..7e2e454142bcd 100644 +--- a/mm/memory-failure.c ++++ b/mm/memory-failure.c +@@ -2406,7 +2406,7 @@ struct memory_failure_entry { + struct memory_failure_cpu { + DECLARE_KFIFO(fifo, struct memory_failure_entry, + MEMORY_FAILURE_FIFO_SIZE); +- spinlock_t lock; ++ raw_spinlock_t lock; + struct work_struct work; + }; + +@@ -2432,20 +2432,22 @@ void memory_failure_queue(unsigned long pfn, int flags) + { + struct memory_failure_cpu *mf_cpu; + unsigned long proc_flags; ++ bool buffer_overflow; + struct memory_failure_entry entry = { + .pfn = pfn, + .flags = flags, + }; + + mf_cpu = &get_cpu_var(memory_failure_cpu); +- spin_lock_irqsave(&mf_cpu->lock, proc_flags); +- if (kfifo_put(&mf_cpu->fifo, entry)) ++ raw_spin_lock_irqsave(&mf_cpu->lock, proc_flags); ++ buffer_overflow = !kfifo_put(&mf_cpu->fifo, entry); ++ if (!buffer_overflow) + schedule_work_on(smp_processor_id(), &mf_cpu->work); +- else ++ raw_spin_unlock_irqrestore(&mf_cpu->lock, proc_flags); ++ put_cpu_var(memory_failure_cpu); ++ if (buffer_overflow) + pr_err("buffer overflow when queuing memory failure at %#lx\n", + pfn); +- spin_unlock_irqrestore(&mf_cpu->lock, proc_flags); +- put_cpu_var(memory_failure_cpu); + } + EXPORT_SYMBOL_GPL(memory_failure_queue); + +@@ -2458,9 +2460,9 @@ static void memory_failure_work_func(struct work_struct *work) + + mf_cpu = container_of(work, struct memory_failure_cpu, work); + for (;;) { +- spin_lock_irqsave(&mf_cpu->lock, proc_flags); ++ raw_spin_lock_irqsave(&mf_cpu->lock, proc_flags); + gotten = kfifo_get(&mf_cpu->fifo, &entry); +- spin_unlock_irqrestore(&mf_cpu->lock, proc_flags); ++ raw_spin_unlock_irqrestore(&mf_cpu->lock, proc_flags); + if (!gotten) + break; + if (entry.flags & MF_SOFT_OFFLINE) +@@ -2490,7 +2492,7 @@ static int __init memory_failure_init(void) + + for_each_possible_cpu(cpu) { + mf_cpu = &per_cpu(memory_failure_cpu, cpu); +- spin_lock_init(&mf_cpu->lock); ++ raw_spin_lock_init(&mf_cpu->lock); + INIT_KFIFO(mf_cpu->fifo); + INIT_WORK(&mf_cpu->work, memory_failure_work_func); + } +diff --git a/mm/memory.c b/mm/memory.c +index 755ffe082e217..72d00a38585d0 100644 +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -5155,7 +5155,7 @@ static vm_fault_t do_numa_page(struct vm_fault *vmf) + + if (unlikely(!pte_same(old_pte, vmf->orig_pte))) { + pte_unmap_unlock(vmf->pte, vmf->ptl); +- goto out; ++ return 0; + } + + pte = pte_modify(old_pte, vma->vm_page_prot); +@@ -5218,23 +5218,19 @@ static vm_fault_t do_numa_page(struct vm_fault *vmf) + if (!migrate_misplaced_folio(folio, vma, target_nid)) { + nid = target_nid; + flags |= TNF_MIGRATED; +- } else { +- flags |= TNF_MIGRATE_FAIL; +- vmf->pte = pte_offset_map_lock(vma->vm_mm, vmf->pmd, +- vmf->address, &vmf->ptl); +- if (unlikely(!vmf->pte)) +- goto out; +- if (unlikely(!pte_same(ptep_get(vmf->pte), vmf->orig_pte))) { +- pte_unmap_unlock(vmf->pte, vmf->ptl); +- goto out; +- } +- goto out_map; ++ task_numa_fault(last_cpupid, nid, nr_pages, flags); ++ return 0; + } + +-out: +- if (nid != NUMA_NO_NODE) +- task_numa_fault(last_cpupid, nid, nr_pages, flags); +- return 0; ++ flags |= TNF_MIGRATE_FAIL; ++ vmf->pte = pte_offset_map_lock(vma->vm_mm, vmf->pmd, ++ vmf->address, &vmf->ptl); ++ if (unlikely(!vmf->pte)) ++ return 0; ++ if (unlikely(!pte_same(ptep_get(vmf->pte), vmf->orig_pte))) { ++ pte_unmap_unlock(vmf->pte, vmf->ptl); ++ return 0; ++ } + out_map: + /* + * Make it present again, depending on how arch implements +@@ -5247,7 +5243,10 @@ static vm_fault_t do_numa_page(struct vm_fault *vmf) + numa_rebuild_single_mapping(vmf, vma, vmf->address, vmf->pte, + writable); + pte_unmap_unlock(vmf->pte, vmf->ptl); +- goto out; ++ ++ if (nid != NUMA_NO_NODE) ++ task_numa_fault(last_cpupid, nid, nr_pages, flags); ++ return 0; + } + + static inline vm_fault_t create_huge_pmd(struct vm_fault *vmf) +diff --git a/mm/mm_init.c b/mm/mm_init.c +index 3ec04933f7fd8..2addc701790ae 100644 +--- a/mm/mm_init.c ++++ b/mm/mm_init.c +@@ -2293,6 +2293,8 @@ void __init init_cma_reserved_pageblock(struct page *page) + + set_pageblock_migratetype(page, MIGRATE_CMA); + set_page_refcounted(page); ++ /* pages were reserved and not allocated */ ++ clear_page_tag_ref(page); + __free_pages(page, pageblock_order); + + adjust_managed_page_count(page, pageblock_nr_pages); +@@ -2505,15 +2507,7 @@ void __init memblock_free_pages(struct page *page, unsigned long pfn, + } + + /* pages were reserved and not allocated */ +- if (mem_alloc_profiling_enabled()) { +- union codetag_ref *ref = get_page_tag_ref(page); +- +- if (ref) { +- set_codetag_empty(ref); +- put_page_tag_ref(ref); +- } +- } +- ++ clear_page_tag_ref(page); + __free_pages_core(page, order); + } + +diff --git a/mm/mseal.c b/mm/mseal.c +index bf783bba8ed0b..15bba28acc005 100644 +--- a/mm/mseal.c ++++ b/mm/mseal.c +@@ -40,9 +40,17 @@ static bool can_modify_vma(struct vm_area_struct *vma) + + static bool is_madv_discard(int behavior) + { +- return behavior & +- (MADV_FREE | MADV_DONTNEED | MADV_DONTNEED_LOCKED | +- MADV_REMOVE | MADV_DONTFORK | MADV_WIPEONFORK); ++ switch (behavior) { ++ case MADV_FREE: ++ case MADV_DONTNEED: ++ case MADV_DONTNEED_LOCKED: ++ case MADV_REMOVE: ++ case MADV_DONTFORK: ++ case MADV_WIPEONFORK: ++ return true; ++ } ++ ++ return false; + } + + static bool is_ro_anon(struct vm_area_struct *vma) +diff --git a/mm/page_alloc.c b/mm/page_alloc.c +index df2c442f1c47b..b50060405d947 100644 +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c +@@ -287,7 +287,7 @@ EXPORT_SYMBOL(nr_online_nodes); + + static bool page_contains_unaccepted(struct page *page, unsigned int order); + static void accept_page(struct page *page, unsigned int order); +-static bool try_to_accept_memory(struct zone *zone, unsigned int order); ++static bool cond_accept_memory(struct zone *zone, unsigned int order); + static inline bool has_unaccepted_memory(void); + static bool __free_unaccepted(struct page *page); + +@@ -3059,9 +3059,6 @@ static inline long __zone_watermark_unusable_free(struct zone *z, + if (!(alloc_flags & ALLOC_CMA)) + unusable_free += zone_page_state(z, NR_FREE_CMA_PAGES); + #endif +-#ifdef CONFIG_UNACCEPTED_MEMORY +- unusable_free += zone_page_state(z, NR_UNACCEPTED); +-#endif + + return unusable_free; + } +@@ -3355,6 +3352,8 @@ get_page_from_freelist(gfp_t gfp_mask, unsigned int order, int alloc_flags, + } + } + ++ cond_accept_memory(zone, order); ++ + /* + * Detect whether the number of free pages is below high + * watermark. If so, we will decrease pcp->high and free +@@ -3380,10 +3379,8 @@ get_page_from_freelist(gfp_t gfp_mask, unsigned int order, int alloc_flags, + gfp_mask)) { + int ret; + +- if (has_unaccepted_memory()) { +- if (try_to_accept_memory(zone, order)) +- goto try_this_zone; +- } ++ if (cond_accept_memory(zone, order)) ++ goto try_this_zone; + + #ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT + /* +@@ -3437,10 +3434,8 @@ get_page_from_freelist(gfp_t gfp_mask, unsigned int order, int alloc_flags, + + return page; + } else { +- if (has_unaccepted_memory()) { +- if (try_to_accept_memory(zone, order)) +- goto try_this_zone; +- } ++ if (cond_accept_memory(zone, order)) ++ goto try_this_zone; + + #ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT + /* Try again if zone has deferred pages */ +@@ -5811,14 +5806,7 @@ unsigned long free_reserved_area(void *start, void *end, int poison, const char + + void free_reserved_page(struct page *page) + { +- if (mem_alloc_profiling_enabled()) { +- union codetag_ref *ref = get_page_tag_ref(page); +- +- if (ref) { +- set_codetag_empty(ref); +- put_page_tag_ref(ref); +- } +- } ++ clear_page_tag_ref(page); + ClearPageReserved(page); + init_page_count(page); + __free_page(page); +@@ -6933,9 +6921,6 @@ static bool try_to_accept_memory_one(struct zone *zone) + struct page *page; + bool last; + +- if (list_empty(&zone->unaccepted_pages)) +- return false; +- + spin_lock_irqsave(&zone->lock, flags); + page = list_first_entry_or_null(&zone->unaccepted_pages, + struct page, lru); +@@ -6961,23 +6946,29 @@ static bool try_to_accept_memory_one(struct zone *zone) + return true; + } + +-static bool try_to_accept_memory(struct zone *zone, unsigned int order) ++static bool cond_accept_memory(struct zone *zone, unsigned int order) + { + long to_accept; +- int ret = false; ++ bool ret = false; ++ ++ if (!has_unaccepted_memory()) ++ return false; ++ ++ if (list_empty(&zone->unaccepted_pages)) ++ return false; + + /* How much to accept to get to high watermark? */ + to_accept = high_wmark_pages(zone) - + (zone_page_state(zone, NR_FREE_PAGES) - +- __zone_watermark_unusable_free(zone, order, 0)); ++ __zone_watermark_unusable_free(zone, order, 0) - ++ zone_page_state(zone, NR_UNACCEPTED)); + +- /* Accept at least one page */ +- do { ++ while (to_accept > 0) { + if (!try_to_accept_memory_one(zone)) + break; + ret = true; + to_accept -= MAX_ORDER_NR_PAGES; +- } while (to_accept > 0); ++ } + + return ret; + } +@@ -7020,7 +7011,7 @@ static void accept_page(struct page *page, unsigned int order) + { + } + +-static bool try_to_accept_memory(struct zone *zone, unsigned int order) ++static bool cond_accept_memory(struct zone *zone, unsigned int order) + { + return false; + } +diff --git a/mm/vmalloc.c b/mm/vmalloc.c +index e34ea860153f2..881e497137e5d 100644 +--- a/mm/vmalloc.c ++++ b/mm/vmalloc.c +@@ -3583,15 +3583,8 @@ vm_area_alloc_pages(gfp_t gfp, int nid, + page = alloc_pages_noprof(alloc_gfp, order); + else + page = alloc_pages_node_noprof(nid, alloc_gfp, order); +- if (unlikely(!page)) { +- if (!nofail) +- break; +- +- /* fall back to the zero order allocations */ +- alloc_gfp |= __GFP_NOFAIL; +- order = 0; +- continue; +- } ++ if (unlikely(!page)) ++ break; + + /* + * Higher order allocations must be able to be treated as +diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c +index 6ecb110bf46bc..b488d0742c966 100644 +--- a/net/bluetooth/hci_core.c ++++ b/net/bluetooth/hci_core.c +@@ -3674,19 +3674,19 @@ static void hci_sched_le(struct hci_dev *hdev) + { + struct hci_chan *chan; + struct sk_buff *skb; +- int quote, cnt, tmp; ++ int quote, *cnt, tmp; + + BT_DBG("%s", hdev->name); + + if (!hci_conn_num(hdev, LE_LINK)) + return; + +- cnt = hdev->le_pkts ? hdev->le_cnt : hdev->acl_cnt; ++ cnt = hdev->le_pkts ? &hdev->le_cnt : &hdev->acl_cnt; + +- __check_timeout(hdev, cnt, LE_LINK); ++ __check_timeout(hdev, *cnt, LE_LINK); + +- tmp = cnt; +- while (cnt && (chan = hci_chan_sent(hdev, LE_LINK, "e))) { ++ tmp = *cnt; ++ while (*cnt && (chan = hci_chan_sent(hdev, LE_LINK, "e))) { + u32 priority = (skb_peek(&chan->data_q))->priority; + while (quote-- && (skb = skb_peek(&chan->data_q))) { + BT_DBG("chan %p skb %p len %d priority %u", chan, skb, +@@ -3701,7 +3701,7 @@ static void hci_sched_le(struct hci_dev *hdev) + hci_send_frame(hdev, skb); + hdev->le_last_tx = jiffies; + +- cnt--; ++ (*cnt)--; + chan->sent++; + chan->conn->sent++; + +@@ -3711,12 +3711,7 @@ static void hci_sched_le(struct hci_dev *hdev) + } + } + +- if (hdev->le_pkts) +- hdev->le_cnt = cnt; +- else +- hdev->acl_cnt = cnt; +- +- if (cnt != tmp) ++ if (*cnt != tmp) + hci_prio_recalculate(hdev, LE_LINK); + } + +diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c +index a78f6d706cd43..59d9086db75fe 100644 +--- a/net/bluetooth/hci_event.c ++++ b/net/bluetooth/hci_event.c +@@ -5921,7 +5921,7 @@ static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev, + * while we have an existing one in peripheral role. + */ + if (hdev->conn_hash.le_num_peripheral > 0 && +- (!test_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks) || ++ (test_bit(HCI_QUIRK_BROKEN_LE_STATES, &hdev->quirks) || + !(hdev->le_states[3] & 0x10))) + return NULL; + +diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c +index 80f220b7e19d5..ad4793ea052df 100644 +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -3457,6 +3457,10 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data, + * will be kept and this function does nothing. + */ + p = hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type); ++ if (!p) { ++ err = -EIO; ++ goto unlock; ++ } + + if (p->auto_connect == HCI_AUTO_CONN_EXPLICIT) + p->auto_connect = HCI_AUTO_CONN_DISABLED; +diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c +index 1e7ea3a4b7ef3..4f9fdf400584e 100644 +--- a/net/bluetooth/smp.c ++++ b/net/bluetooth/smp.c +@@ -914,7 +914,7 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth, + * Confirms and the responder Enters the passkey. + */ + if (smp->method == OVERLAP) { +- if (hcon->role == HCI_ROLE_MASTER) ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) + smp->method = CFM_PASSKEY; + else + smp->method = REQ_PASSKEY; +@@ -964,7 +964,7 @@ static u8 smp_confirm(struct smp_chan *smp) + + smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp); + +- if (conn->hcon->out) ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) + SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM); + else + SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM); +@@ -980,7 +980,8 @@ static u8 smp_random(struct smp_chan *smp) + int ret; + + bt_dev_dbg(conn->hcon->hdev, "conn %p %s", conn, +- conn->hcon->out ? "initiator" : "responder"); ++ test_bit(SMP_FLAG_INITIATOR, &smp->flags) ? "initiator" : ++ "responder"); + + ret = smp_c1(smp->tk, smp->rrnd, smp->preq, smp->prsp, + hcon->init_addr_type, &hcon->init_addr, +@@ -994,7 +995,7 @@ static u8 smp_random(struct smp_chan *smp) + return SMP_CONFIRM_FAILED; + } + +- if (hcon->out) { ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) { + u8 stk[16]; + __le64 rand = 0; + __le16 ediv = 0; +@@ -1256,14 +1257,15 @@ static void smp_distribute_keys(struct smp_chan *smp) + rsp = (void *) &smp->prsp[1]; + + /* The responder sends its keys first */ +- if (hcon->out && (smp->remote_key_dist & KEY_DIST_MASK)) { ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags) && ++ (smp->remote_key_dist & KEY_DIST_MASK)) { + smp_allow_key_dist(smp); + return; + } + + req = (void *) &smp->preq[1]; + +- if (hcon->out) { ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) { + keydist = &rsp->init_key_dist; + *keydist &= req->init_key_dist; + } else { +@@ -1432,7 +1434,7 @@ static int sc_mackey_and_ltk(struct smp_chan *smp, u8 mackey[16], u8 ltk[16]) + struct hci_conn *hcon = smp->conn->hcon; + u8 *na, *nb, a[7], b[7]; + +- if (hcon->out) { ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) { + na = smp->prnd; + nb = smp->rrnd; + } else { +@@ -1460,7 +1462,7 @@ static void sc_dhkey_check(struct smp_chan *smp) + a[6] = hcon->init_addr_type; + b[6] = hcon->resp_addr_type; + +- if (hcon->out) { ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) { + local_addr = a; + remote_addr = b; + memcpy(io_cap, &smp->preq[1], 3); +@@ -1539,7 +1541,7 @@ static u8 sc_passkey_round(struct smp_chan *smp, u8 smp_op) + /* The round is only complete when the initiator + * receives pairing random. + */ +- if (!hcon->out) { ++ if (!test_bit(SMP_FLAG_INITIATOR, &smp->flags)) { + smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, + sizeof(smp->prnd), smp->prnd); + if (smp->passkey_round == 20) +@@ -1567,7 +1569,7 @@ static u8 sc_passkey_round(struct smp_chan *smp, u8 smp_op) + + SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM); + +- if (hcon->out) { ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) { + smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, + sizeof(smp->prnd), smp->prnd); + return 0; +@@ -1578,7 +1580,7 @@ static u8 sc_passkey_round(struct smp_chan *smp, u8 smp_op) + case SMP_CMD_PUBLIC_KEY: + default: + /* Initiating device starts the round */ +- if (!hcon->out) ++ if (!test_bit(SMP_FLAG_INITIATOR, &smp->flags)) + return 0; + + bt_dev_dbg(hdev, "Starting passkey round %u", +@@ -1623,7 +1625,7 @@ static int sc_user_reply(struct smp_chan *smp, u16 mgmt_op, __le32 passkey) + } + + /* Initiator sends DHKey check first */ +- if (hcon->out) { ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) { + sc_dhkey_check(smp); + SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK); + } else if (test_and_clear_bit(SMP_FLAG_DHKEY_PENDING, &smp->flags)) { +@@ -1746,7 +1748,7 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) + struct smp_cmd_pairing rsp, *req = (void *) skb->data; + struct l2cap_chan *chan = conn->smp; + struct hci_dev *hdev = conn->hcon->hdev; +- struct smp_chan *smp; ++ struct smp_chan *smp = chan->data; + u8 key_size, auth, sec_level; + int ret; + +@@ -1755,16 +1757,14 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) + if (skb->len < sizeof(*req)) + return SMP_INVALID_PARAMS; + +- if (conn->hcon->role != HCI_ROLE_SLAVE) ++ if (smp && test_bit(SMP_FLAG_INITIATOR, &smp->flags)) + return SMP_CMD_NOTSUPP; + +- if (!chan->data) ++ if (!smp) { + smp = smp_chan_create(conn); +- else +- smp = chan->data; +- +- if (!smp) +- return SMP_UNSPECIFIED; ++ if (!smp) ++ return SMP_UNSPECIFIED; ++ } + + /* We didn't start the pairing, so match remote */ + auth = req->auth_req & AUTH_REQ_MASK(hdev); +@@ -1946,7 +1946,7 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) + if (skb->len < sizeof(*rsp)) + return SMP_INVALID_PARAMS; + +- if (conn->hcon->role != HCI_ROLE_MASTER) ++ if (!test_bit(SMP_FLAG_INITIATOR, &smp->flags)) + return SMP_CMD_NOTSUPP; + + skb_pull(skb, sizeof(*rsp)); +@@ -2041,7 +2041,7 @@ static u8 sc_check_confirm(struct smp_chan *smp) + if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY) + return sc_passkey_round(smp, SMP_CMD_PAIRING_CONFIRM); + +- if (conn->hcon->out) { ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) { + smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd), + smp->prnd); + SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM); +@@ -2063,7 +2063,7 @@ static int fixup_sc_false_positive(struct smp_chan *smp) + u8 auth; + + /* The issue is only observed when we're in responder role */ +- if (hcon->out) ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) + return SMP_UNSPECIFIED; + + if (hci_dev_test_flag(hdev, HCI_SC_ONLY)) { +@@ -2099,7 +2099,8 @@ static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb) + struct hci_dev *hdev = hcon->hdev; + + bt_dev_dbg(hdev, "conn %p %s", conn, +- hcon->out ? "initiator" : "responder"); ++ test_bit(SMP_FLAG_INITIATOR, &smp->flags) ? "initiator" : ++ "responder"); + + if (skb->len < sizeof(smp->pcnf)) + return SMP_INVALID_PARAMS; +@@ -2121,7 +2122,7 @@ static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb) + return ret; + } + +- if (conn->hcon->out) { ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) { + smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd), + smp->prnd); + SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM); +@@ -2156,7 +2157,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) + if (!test_bit(SMP_FLAG_SC, &smp->flags)) + return smp_random(smp); + +- if (hcon->out) { ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) { + pkax = smp->local_pk; + pkbx = smp->remote_pk; + na = smp->prnd; +@@ -2169,7 +2170,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) + } + + if (smp->method == REQ_OOB) { +- if (!hcon->out) ++ if (!test_bit(SMP_FLAG_INITIATOR, &smp->flags)) + smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, + sizeof(smp->prnd), smp->prnd); + SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK); +@@ -2180,7 +2181,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) + if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY) + return sc_passkey_round(smp, SMP_CMD_PAIRING_RANDOM); + +- if (hcon->out) { ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) { + u8 cfm[16]; + + err = smp_f4(smp->tfm_cmac, smp->remote_pk, smp->local_pk, +@@ -2221,7 +2222,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) + return SMP_UNSPECIFIED; + + if (smp->method == REQ_OOB) { +- if (hcon->out) { ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) { + sc_dhkey_check(smp); + SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK); + } +@@ -2295,10 +2296,27 @@ bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level, + return false; + } + ++static void smp_send_pairing_req(struct smp_chan *smp, __u8 auth) ++{ ++ struct smp_cmd_pairing cp; ++ ++ if (smp->conn->hcon->type == ACL_LINK) ++ build_bredr_pairing_cmd(smp, &cp, NULL); ++ else ++ build_pairing_cmd(smp->conn, &cp, NULL, auth); ++ ++ smp->preq[0] = SMP_CMD_PAIRING_REQ; ++ memcpy(&smp->preq[1], &cp, sizeof(cp)); ++ ++ smp_send_cmd(smp->conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); ++ SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RSP); ++ ++ set_bit(SMP_FLAG_INITIATOR, &smp->flags); ++} ++ + static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) + { + struct smp_cmd_security_req *rp = (void *) skb->data; +- struct smp_cmd_pairing cp; + struct hci_conn *hcon = conn->hcon; + struct hci_dev *hdev = hcon->hdev; + struct smp_chan *smp; +@@ -2347,16 +2365,20 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) + + skb_pull(skb, sizeof(*rp)); + +- memset(&cp, 0, sizeof(cp)); +- build_pairing_cmd(conn, &cp, NULL, auth); ++ smp_send_pairing_req(smp, auth); + +- smp->preq[0] = SMP_CMD_PAIRING_REQ; +- memcpy(&smp->preq[1], &cp, sizeof(cp)); ++ return 0; ++} + +- smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); +- SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RSP); ++static void smp_send_security_req(struct smp_chan *smp, __u8 auth) ++{ ++ struct smp_cmd_security_req cp; + +- return 0; ++ cp.auth_req = auth; ++ smp_send_cmd(smp->conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp); ++ SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_REQ); ++ ++ clear_bit(SMP_FLAG_INITIATOR, &smp->flags); + } + + int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) +@@ -2427,23 +2449,11 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) + authreq |= SMP_AUTH_MITM; + } + +- if (hcon->role == HCI_ROLE_MASTER) { +- struct smp_cmd_pairing cp; +- +- build_pairing_cmd(conn, &cp, NULL, authreq); +- smp->preq[0] = SMP_CMD_PAIRING_REQ; +- memcpy(&smp->preq[1], &cp, sizeof(cp)); +- +- smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); +- SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RSP); +- } else { +- struct smp_cmd_security_req cp; +- cp.auth_req = authreq; +- smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp); +- SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_REQ); +- } ++ if (hcon->role == HCI_ROLE_MASTER) ++ smp_send_pairing_req(smp, authreq); ++ else ++ smp_send_security_req(smp, authreq); + +- set_bit(SMP_FLAG_INITIATOR, &smp->flags); + ret = 0; + + unlock: +@@ -2694,8 +2704,6 @@ static int smp_cmd_sign_info(struct l2cap_conn *conn, struct sk_buff *skb) + + static u8 sc_select_method(struct smp_chan *smp) + { +- struct l2cap_conn *conn = smp->conn; +- struct hci_conn *hcon = conn->hcon; + struct smp_cmd_pairing *local, *remote; + u8 local_mitm, remote_mitm, local_io, remote_io, method; + +@@ -2708,7 +2716,7 @@ static u8 sc_select_method(struct smp_chan *smp) + * the "struct smp_cmd_pairing" from them we need to skip the + * first byte which contains the opcode. + */ +- if (hcon->out) { ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) { + local = (void *) &smp->preq[1]; + remote = (void *) &smp->prsp[1]; + } else { +@@ -2777,7 +2785,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb) + /* Non-initiating device sends its public key after receiving + * the key from the initiating device. + */ +- if (!hcon->out) { ++ if (!test_bit(SMP_FLAG_INITIATOR, &smp->flags)) { + err = sc_send_public_key(smp); + if (err) + return err; +@@ -2839,7 +2847,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb) + } + + if (smp->method == REQ_OOB) { +- if (hcon->out) ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) + smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, + sizeof(smp->prnd), smp->prnd); + +@@ -2848,7 +2856,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb) + return 0; + } + +- if (hcon->out) ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) + SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM); + + if (smp->method == REQ_PASSKEY) { +@@ -2863,7 +2871,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb) + /* The Initiating device waits for the non-initiating device to + * send the confirm value. + */ +- if (conn->hcon->out) ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) + return 0; + + err = smp_f4(smp->tfm_cmac, smp->local_pk, smp->remote_pk, smp->prnd, +@@ -2897,7 +2905,7 @@ static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb) + a[6] = hcon->init_addr_type; + b[6] = hcon->resp_addr_type; + +- if (hcon->out) { ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) { + local_addr = a; + remote_addr = b; + memcpy(io_cap, &smp->prsp[1], 3); +@@ -2922,7 +2930,7 @@ static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb) + if (crypto_memneq(check->e, e, 16)) + return SMP_DHKEY_CHECK_FAILED; + +- if (!hcon->out) { ++ if (!test_bit(SMP_FLAG_INITIATOR, &smp->flags)) { + if (test_bit(SMP_FLAG_WAIT_USER, &smp->flags)) { + set_bit(SMP_FLAG_DHKEY_PENDING, &smp->flags); + return 0; +@@ -2934,7 +2942,7 @@ static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb) + + sc_add_ltk(smp); + +- if (hcon->out) { ++ if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) { + hci_le_start_enc(hcon, 0, 0, smp->tk, smp->enc_key_size); + hcon->enc_key_size = smp->enc_key_size; + } +@@ -3083,7 +3091,6 @@ static void bredr_pairing(struct l2cap_chan *chan) + struct l2cap_conn *conn = chan->conn; + struct hci_conn *hcon = conn->hcon; + struct hci_dev *hdev = hcon->hdev; +- struct smp_cmd_pairing req; + struct smp_chan *smp; + + bt_dev_dbg(hdev, "chan %p", chan); +@@ -3135,14 +3142,7 @@ static void bredr_pairing(struct l2cap_chan *chan) + + bt_dev_dbg(hdev, "starting SMP over BR/EDR"); + +- /* Prepare and send the BR/EDR SMP Pairing Request */ +- build_bredr_pairing_cmd(smp, &req, NULL); +- +- smp->preq[0] = SMP_CMD_PAIRING_REQ; +- memcpy(&smp->preq[1], &req, sizeof(req)); +- +- smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(req), &req); +- SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RSP); ++ smp_send_pairing_req(smp, 0x00); + } + + static void smp_resume_cb(struct l2cap_chan *chan) +diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c +index bf30c50b56895..a9e1b56f854d4 100644 +--- a/net/bridge/br_netfilter_hooks.c ++++ b/net/bridge/br_netfilter_hooks.c +@@ -619,8 +619,12 @@ static unsigned int br_nf_local_in(void *priv, + if (likely(nf_ct_is_confirmed(ct))) + return NF_ACCEPT; + ++ if (WARN_ON_ONCE(refcount_read(&nfct->use) != 1)) { ++ nf_reset_ct(skb); ++ return NF_ACCEPT; ++ } ++ + WARN_ON_ONCE(skb_shared(skb)); +- WARN_ON_ONCE(refcount_read(&nfct->use) != 1); + + /* We can't call nf_confirm here, it would create a dependency + * on nf_conntrack module. +diff --git a/net/dsa/tag_ocelot.c b/net/dsa/tag_ocelot.c +index e0e4300bfbd3f..bf6608fc6be70 100644 +--- a/net/dsa/tag_ocelot.c ++++ b/net/dsa/tag_ocelot.c +@@ -8,40 +8,6 @@ + #define OCELOT_NAME "ocelot" + #define SEVILLE_NAME "seville" + +-/* If the port is under a VLAN-aware bridge, remove the VLAN header from the +- * payload and move it into the DSA tag, which will make the switch classify +- * the packet to the bridge VLAN. Otherwise, leave the classified VLAN at zero, +- * which is the pvid of standalone and VLAN-unaware bridge ports. +- */ +-static void ocelot_xmit_get_vlan_info(struct sk_buff *skb, struct dsa_port *dp, +- u64 *vlan_tci, u64 *tag_type) +-{ +- struct net_device *br = dsa_port_bridge_dev_get(dp); +- struct vlan_ethhdr *hdr; +- u16 proto, tci; +- +- if (!br || !br_vlan_enabled(br)) { +- *vlan_tci = 0; +- *tag_type = IFH_TAG_TYPE_C; +- return; +- } +- +- hdr = skb_vlan_eth_hdr(skb); +- br_vlan_get_proto(br, &proto); +- +- if (ntohs(hdr->h_vlan_proto) == proto) { +- vlan_remove_tag(skb, &tci); +- *vlan_tci = tci; +- } else { +- rcu_read_lock(); +- br_vlan_get_pvid_rcu(br, &tci); +- rcu_read_unlock(); +- *vlan_tci = tci; +- } +- +- *tag_type = (proto != ETH_P_8021Q) ? IFH_TAG_TYPE_S : IFH_TAG_TYPE_C; +-} +- + static void ocelot_xmit_common(struct sk_buff *skb, struct net_device *netdev, + __be32 ifh_prefix, void **ifh) + { +@@ -53,7 +19,8 @@ static void ocelot_xmit_common(struct sk_buff *skb, struct net_device *netdev, + u32 rew_op = 0; + u64 qos_class; + +- ocelot_xmit_get_vlan_info(skb, dp, &vlan_tci, &tag_type); ++ ocelot_xmit_get_vlan_info(skb, dsa_port_bridge_dev_get(dp), &vlan_tci, ++ &tag_type); + + qos_class = netdev_get_num_tc(netdev) ? + netdev_get_prio_tc_map(netdev, skb->priority) : skb->priority; +diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +index ecd521108559f..2c52f6dcbd290 100644 +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -238,9 +238,14 @@ static void tcp_measure_rcv_mss(struct sock *sk, const struct sk_buff *skb) + */ + if (unlikely(len != icsk->icsk_ack.rcv_mss)) { + u64 val = (u64)skb->len << TCP_RMEM_TO_WIN_SCALE; ++ u8 old_ratio = tcp_sk(sk)->scaling_ratio; + + do_div(val, skb->truesize); + tcp_sk(sk)->scaling_ratio = val ? val : 1; ++ ++ if (old_ratio != tcp_sk(sk)->scaling_ratio) ++ WRITE_ONCE(tcp_sk(sk)->window_clamp, ++ tcp_win_from_space(sk, sk->sk_rcvbuf)); + } + icsk->icsk_ack.rcv_mss = min_t(unsigned int, len, + tcp_sk(sk)->advmss); +@@ -754,7 +759,8 @@ void tcp_rcv_space_adjust(struct sock *sk) + * + */ + +- if (READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_moderate_rcvbuf)) { ++ if (READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_moderate_rcvbuf) && ++ !(sk->sk_userlocks & SOCK_RCVBUF_LOCK)) { + u64 rcvwin, grow; + int rcvbuf; + +@@ -770,22 +776,12 @@ void tcp_rcv_space_adjust(struct sock *sk) + + rcvbuf = min_t(u64, tcp_space_from_win(sk, rcvwin), + READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_rmem[2])); +- if (!(sk->sk_userlocks & SOCK_RCVBUF_LOCK)) { +- if (rcvbuf > sk->sk_rcvbuf) { +- WRITE_ONCE(sk->sk_rcvbuf, rcvbuf); +- +- /* Make the window clamp follow along. */ +- WRITE_ONCE(tp->window_clamp, +- tcp_win_from_space(sk, rcvbuf)); +- } +- } else { +- /* Make the window clamp follow along while being bounded +- * by SO_RCVBUF. +- */ +- int clamp = tcp_win_from_space(sk, min(rcvbuf, sk->sk_rcvbuf)); ++ if (rcvbuf > sk->sk_rcvbuf) { ++ WRITE_ONCE(sk->sk_rcvbuf, rcvbuf); + +- if (clamp > tp->window_clamp) +- WRITE_ONCE(tp->window_clamp, clamp); ++ /* Make the window clamp follow along. */ ++ WRITE_ONCE(tp->window_clamp, ++ tcp_win_from_space(sk, rcvbuf)); + } + } + tp->rcvq_space.space = copied; +diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c +index a541659b6562b..8f8f93716ff85 100644 +--- a/net/ipv4/tcp_ipv4.c ++++ b/net/ipv4/tcp_ipv4.c +@@ -95,6 +95,8 @@ EXPORT_SYMBOL(tcp_hashinfo); + + static DEFINE_PER_CPU(struct sock *, ipv4_tcp_sk); + ++static DEFINE_MUTEX(tcp_exit_batch_mutex); ++ + static u32 tcp_v4_init_seq(const struct sk_buff *skb) + { + return secure_tcp_seq(ip_hdr(skb)->daddr, +@@ -3509,6 +3511,16 @@ static void __net_exit tcp_sk_exit_batch(struct list_head *net_exit_list) + { + struct net *net; + ++ /* make sure concurrent calls to tcp_sk_exit_batch from net_cleanup_work ++ * and failed setup_net error unwinding path are serialized. ++ * ++ * tcp_twsk_purge() handles twsk in any dead netns, not just those in ++ * net_exit_list, the thread that dismantles a particular twsk must ++ * do so without other thread progressing to refcount_dec_and_test() of ++ * tcp_death_row.tw_refcount. ++ */ ++ mutex_lock(&tcp_exit_batch_mutex); ++ + tcp_twsk_purge(net_exit_list); + + list_for_each_entry(net, net_exit_list, exit_list) { +@@ -3516,6 +3528,8 @@ static void __net_exit tcp_sk_exit_batch(struct list_head *net_exit_list) + WARN_ON_ONCE(!refcount_dec_and_test(&net->ipv4.tcp_death_row.tw_refcount)); + tcp_fastopen_ctx_destroy(net); + } ++ ++ mutex_unlock(&tcp_exit_batch_mutex); + } + + static struct pernet_operations __net_initdata tcp_sk_ops = { +diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c +index ee9af921556a7..5b54f4f32b1cd 100644 +--- a/net/ipv4/udp_offload.c ++++ b/net/ipv4/udp_offload.c +@@ -279,7 +279,8 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb, + return ERR_PTR(-EINVAL); + + if (unlikely(skb_checksum_start(gso_skb) != +- skb_transport_header(gso_skb))) ++ skb_transport_header(gso_skb) && ++ !(skb_shinfo(gso_skb)->gso_type & SKB_GSO_FRAGLIST))) + return ERR_PTR(-EINVAL); + + if (skb_gso_ok(gso_skb, features | NETIF_F_GSO_ROBUST)) { +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index 784424ac41477..c49344d8311ab 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -70,11 +70,15 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff * + + /* Be paranoid, rather than too clever. */ + if (unlikely(hh_len > skb_headroom(skb)) && dev->header_ops) { ++ /* Make sure idev stays alive */ ++ rcu_read_lock(); + skb = skb_expand_head(skb, hh_len); + if (!skb) { + IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS); ++ rcu_read_unlock(); + return -ENOMEM; + } ++ rcu_read_unlock(); + } + + hdr = ipv6_hdr(skb); +@@ -283,11 +287,15 @@ int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6, + head_room += opt->opt_nflen + opt->opt_flen; + + if (unlikely(head_room > skb_headroom(skb))) { ++ /* Make sure idev stays alive */ ++ rcu_read_lock(); + skb = skb_expand_head(skb, head_room); + if (!skb) { + IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS); ++ rcu_read_unlock(); + return -ENOBUFS; + } ++ rcu_read_unlock(); + } + + if (opt) { +@@ -1953,6 +1961,7 @@ int ip6_send_skb(struct sk_buff *skb) + struct rt6_info *rt = dst_rt6_info(skb_dst(skb)); + int err; + ++ rcu_read_lock(); + err = ip6_local_out(net, skb->sk, skb); + if (err) { + if (err > 0) +@@ -1962,6 +1971,7 @@ int ip6_send_skb(struct sk_buff *skb) + IPSTATS_MIB_OUTDISCARDS); + } + ++ rcu_read_unlock(); + return err; + } + +diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c +index 9dee0c1279554..87dfb565a9f81 100644 +--- a/net/ipv6/ip6_tunnel.c ++++ b/net/ipv6/ip6_tunnel.c +@@ -1507,7 +1507,8 @@ static void ip6_tnl_link_config(struct ip6_tnl *t) + tdev = __dev_get_by_index(t->net, p->link); + + if (tdev) { +- dev->hard_header_len = tdev->hard_header_len + t_hlen; ++ dev->needed_headroom = tdev->hard_header_len + ++ tdev->needed_headroom + t_hlen; + mtu = min_t(unsigned int, tdev->mtu, IP6_MAX_MTU); + + mtu = mtu - t_hlen; +@@ -1731,7 +1732,9 @@ ip6_tnl_siocdevprivate(struct net_device *dev, struct ifreq *ifr, + int ip6_tnl_change_mtu(struct net_device *dev, int new_mtu) + { + struct ip6_tnl *tnl = netdev_priv(dev); ++ int t_hlen; + ++ t_hlen = tnl->hlen + sizeof(struct ipv6hdr); + if (tnl->parms.proto == IPPROTO_IPV6) { + if (new_mtu < IPV6_MIN_MTU) + return -EINVAL; +@@ -1740,10 +1743,10 @@ int ip6_tnl_change_mtu(struct net_device *dev, int new_mtu) + return -EINVAL; + } + if (tnl->parms.proto == IPPROTO_IPV6 || tnl->parms.proto == 0) { +- if (new_mtu > IP6_MAX_MTU - dev->hard_header_len) ++ if (new_mtu > IP6_MAX_MTU - dev->hard_header_len - t_hlen) + return -EINVAL; + } else { +- if (new_mtu > IP_MAX_MTU - dev->hard_header_len) ++ if (new_mtu > IP_MAX_MTU - dev->hard_header_len - t_hlen) + return -EINVAL; + } + WRITE_ONCE(dev->mtu, new_mtu); +@@ -1887,12 +1890,11 @@ ip6_tnl_dev_init_gen(struct net_device *dev) + t_hlen = t->hlen + sizeof(struct ipv6hdr); + + dev->type = ARPHRD_TUNNEL6; +- dev->hard_header_len = LL_MAX_HEADER + t_hlen; + dev->mtu = ETH_DATA_LEN - t_hlen; + if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) + dev->mtu -= 8; + dev->min_mtu = ETH_MIN_MTU; +- dev->max_mtu = IP6_MAX_MTU - dev->hard_header_len; ++ dev->max_mtu = IP6_MAX_MTU - dev->hard_header_len - t_hlen; + + netdev_hold(dev, &t->dev_tracker, GFP_KERNEL); + netdev_lockdep_set_classes(dev); +diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c +index 5e1b50c6a44d2..3e9779ed7daec 100644 +--- a/net/ipv6/netfilter/nf_conntrack_reasm.c ++++ b/net/ipv6/netfilter/nf_conntrack_reasm.c +@@ -154,6 +154,10 @@ static struct frag_queue *fq_find(struct net *net, __be32 id, u32 user, + }; + struct inet_frag_queue *q; + ++ if (!(ipv6_addr_type(&hdr->daddr) & (IPV6_ADDR_MULTICAST | ++ IPV6_ADDR_LINKLOCAL))) ++ key.iif = 0; ++ + q = inet_frag_find(nf_frag->fqdir, &key); + if (!q) + return NULL; +diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c +index b7bf34a5eb37a..1235307020075 100644 +--- a/net/iucv/iucv.c ++++ b/net/iucv/iucv.c +@@ -86,13 +86,15 @@ struct device *iucv_alloc_device(const struct attribute_group **attrs, + { + struct device *dev; + va_list vargs; ++ char buf[20]; + int rc; + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + goto out_error; + va_start(vargs, fmt); +- rc = dev_set_name(dev, fmt, vargs); ++ vsnprintf(buf, sizeof(buf), fmt, vargs); ++ rc = dev_set_name(dev, "%s", buf); + va_end(vargs); + if (rc) + goto out_error; +diff --git a/net/kcm/kcmsock.c b/net/kcm/kcmsock.c +index 2f191e50d4fc9..d4118c796290e 100644 +--- a/net/kcm/kcmsock.c ++++ b/net/kcm/kcmsock.c +@@ -755,6 +755,7 @@ static int kcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) + !(msg->msg_flags & MSG_MORE) : !!(msg->msg_flags & MSG_EOR); + int err = -EPIPE; + ++ mutex_lock(&kcm->tx_mutex); + lock_sock(sk); + + /* Per tcp_sendmsg this should be in poll */ +@@ -926,6 +927,7 @@ static int kcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) + KCM_STATS_ADD(kcm->stats.tx_bytes, copied); + + release_sock(sk); ++ mutex_unlock(&kcm->tx_mutex); + return copied; + + out_error: +@@ -951,6 +953,7 @@ static int kcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) + sk->sk_write_space(sk); + + release_sock(sk); ++ mutex_unlock(&kcm->tx_mutex); + return err; + } + +@@ -1204,6 +1207,7 @@ static void init_kcm_sock(struct kcm_sock *kcm, struct kcm_mux *mux) + spin_unlock_bh(&mux->lock); + + INIT_WORK(&kcm->tx_work, kcm_tx_work); ++ mutex_init(&kcm->tx_mutex); + + spin_lock_bh(&mux->rx_lock); + kcm_rcv_ready(kcm); +diff --git a/net/mctp/test/route-test.c b/net/mctp/test/route-test.c +index 77e5dd4222580..8551dab1d1e69 100644 +--- a/net/mctp/test/route-test.c ++++ b/net/mctp/test/route-test.c +@@ -366,7 +366,7 @@ static void mctp_test_route_input_sk(struct kunit *test) + + skb2 = skb_recv_datagram(sock->sk, MSG_DONTWAIT, &rc); + KUNIT_EXPECT_NOT_ERR_OR_NULL(test, skb2); +- KUNIT_EXPECT_EQ(test, skb->len, 1); ++ KUNIT_EXPECT_EQ(test, skb2->len, 1); + + skb_free_datagram(sock->sk, skb2); + +diff --git a/net/mptcp/diag.c b/net/mptcp/diag.c +index 3ae46b545d2c2..2d3efb405437d 100644 +--- a/net/mptcp/diag.c ++++ b/net/mptcp/diag.c +@@ -94,7 +94,7 @@ static size_t subflow_get_info_size(const struct sock *sk) + nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_RELWRITE_SEQ */ + nla_total_size_64bit(8) + /* MPTCP_SUBFLOW_ATTR_MAP_SEQ */ + nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_MAP_SFSEQ */ +- nla_total_size(2) + /* MPTCP_SUBFLOW_ATTR_SSN_OFFSET */ ++ nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_SSN_OFFSET */ + nla_total_size(2) + /* MPTCP_SUBFLOW_ATTR_MAP_DATALEN */ + nla_total_size(4) + /* MPTCP_SUBFLOW_ATTR_FLAGS */ + nla_total_size(1) + /* MPTCP_SUBFLOW_ATTR_ID_REM */ +diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c +index 23bb89c94e90d..3e6e0f5510bb1 100644 +--- a/net/mptcp/pm.c ++++ b/net/mptcp/pm.c +@@ -60,16 +60,6 @@ int mptcp_pm_remove_addr(struct mptcp_sock *msk, const struct mptcp_rm_list *rm_ + return 0; + } + +-int mptcp_pm_remove_subflow(struct mptcp_sock *msk, const struct mptcp_rm_list *rm_list) +-{ +- pr_debug("msk=%p, rm_list_nr=%d", msk, rm_list->nr); +- +- spin_lock_bh(&msk->pm.lock); +- mptcp_pm_nl_rm_subflow_received(msk, rm_list); +- spin_unlock_bh(&msk->pm.lock); +- return 0; +-} +- + /* path manager event handlers */ + + void mptcp_pm_new_connection(struct mptcp_sock *msk, const struct sock *ssk, int server_side) +@@ -444,9 +434,6 @@ int mptcp_pm_get_flags_and_ifindex_by_id(struct mptcp_sock *msk, unsigned int id + *flags = 0; + *ifindex = 0; + +- if (!id) +- return 0; +- + if (mptcp_pm_is_userspace(msk)) + return mptcp_userspace_pm_get_flags_and_ifindex_by_id(msk, id, flags, ifindex); + return mptcp_pm_nl_get_flags_and_ifindex_by_id(msk, id, flags, ifindex); +diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c +index 4cae2aa7be5cb..3e4ad801786f2 100644 +--- a/net/mptcp/pm_netlink.c ++++ b/net/mptcp/pm_netlink.c +@@ -143,11 +143,13 @@ static bool lookup_subflow_by_daddr(const struct list_head *list, + return false; + } + +-static struct mptcp_pm_addr_entry * ++static bool + select_local_address(const struct pm_nl_pernet *pernet, +- const struct mptcp_sock *msk) ++ const struct mptcp_sock *msk, ++ struct mptcp_pm_addr_entry *new_entry) + { +- struct mptcp_pm_addr_entry *entry, *ret = NULL; ++ struct mptcp_pm_addr_entry *entry; ++ bool found = false; + + msk_owned_by_me(msk); + +@@ -159,17 +161,21 @@ select_local_address(const struct pm_nl_pernet *pernet, + if (!test_bit(entry->addr.id, msk->pm.id_avail_bitmap)) + continue; + +- ret = entry; ++ *new_entry = *entry; ++ found = true; + break; + } + rcu_read_unlock(); +- return ret; ++ ++ return found; + } + +-static struct mptcp_pm_addr_entry * +-select_signal_address(struct pm_nl_pernet *pernet, const struct mptcp_sock *msk) ++static bool ++select_signal_address(struct pm_nl_pernet *pernet, const struct mptcp_sock *msk, ++ struct mptcp_pm_addr_entry *new_entry) + { +- struct mptcp_pm_addr_entry *entry, *ret = NULL; ++ struct mptcp_pm_addr_entry *entry; ++ bool found = false; + + rcu_read_lock(); + /* do not keep any additional per socket state, just signal +@@ -184,11 +190,13 @@ select_signal_address(struct pm_nl_pernet *pernet, const struct mptcp_sock *msk) + if (!(entry->flags & MPTCP_PM_ADDR_FLAG_SIGNAL)) + continue; + +- ret = entry; ++ *new_entry = *entry; ++ found = true; + break; + } + rcu_read_unlock(); +- return ret; ++ ++ return found; + } + + unsigned int mptcp_pm_get_add_addr_signal_max(const struct mptcp_sock *msk) +@@ -512,9 +520,10 @@ __lookup_addr(struct pm_nl_pernet *pernet, const struct mptcp_addr_info *info) + + static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk) + { +- struct mptcp_pm_addr_entry *local, *signal_and_subflow = NULL; + struct sock *sk = (struct sock *)msk; ++ struct mptcp_pm_addr_entry local; + unsigned int add_addr_signal_max; ++ bool signal_and_subflow = false; + unsigned int local_addr_max; + struct pm_nl_pernet *pernet; + unsigned int subflows_max; +@@ -565,23 +574,22 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk) + if (msk->pm.addr_signal & BIT(MPTCP_ADD_ADDR_SIGNAL)) + return; + +- local = select_signal_address(pernet, msk); +- if (!local) ++ if (!select_signal_address(pernet, msk, &local)) + goto subflow; + + /* If the alloc fails, we are on memory pressure, not worth + * continuing, and trying to create subflows. + */ +- if (!mptcp_pm_alloc_anno_list(msk, &local->addr)) ++ if (!mptcp_pm_alloc_anno_list(msk, &local.addr)) + return; + +- __clear_bit(local->addr.id, msk->pm.id_avail_bitmap); ++ __clear_bit(local.addr.id, msk->pm.id_avail_bitmap); + msk->pm.add_addr_signaled++; +- mptcp_pm_announce_addr(msk, &local->addr, false); ++ mptcp_pm_announce_addr(msk, &local.addr, false); + mptcp_pm_nl_addr_send_ack(msk); + +- if (local->flags & MPTCP_PM_ADDR_FLAG_SUBFLOW) +- signal_and_subflow = local; ++ if (local.flags & MPTCP_PM_ADDR_FLAG_SUBFLOW) ++ signal_and_subflow = true; + } + + subflow: +@@ -592,26 +600,22 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk) + bool fullmesh; + int i, nr; + +- if (signal_and_subflow) { +- local = signal_and_subflow; +- signal_and_subflow = NULL; +- } else { +- local = select_local_address(pernet, msk); +- if (!local) +- break; +- } ++ if (signal_and_subflow) ++ signal_and_subflow = false; ++ else if (!select_local_address(pernet, msk, &local)) ++ break; + +- fullmesh = !!(local->flags & MPTCP_PM_ADDR_FLAG_FULLMESH); ++ fullmesh = !!(local.flags & MPTCP_PM_ADDR_FLAG_FULLMESH); + + msk->pm.local_addr_used++; +- __clear_bit(local->addr.id, msk->pm.id_avail_bitmap); +- nr = fill_remote_addresses_vec(msk, &local->addr, fullmesh, addrs); ++ __clear_bit(local.addr.id, msk->pm.id_avail_bitmap); ++ nr = fill_remote_addresses_vec(msk, &local.addr, fullmesh, addrs); + if (nr == 0) + continue; + + spin_unlock_bh(&msk->pm.lock); + for (i = 0; i < nr; i++) +- __mptcp_subflow_connect(sk, &local->addr, &addrs[i]); ++ __mptcp_subflow_connect(sk, &local.addr, &addrs[i]); + spin_lock_bh(&msk->pm.lock); + } + mptcp_pm_nl_check_work_pending(msk); +@@ -636,6 +640,7 @@ static unsigned int fill_local_addresses_vec(struct mptcp_sock *msk, + { + struct sock *sk = (struct sock *)msk; + struct mptcp_pm_addr_entry *entry; ++ struct mptcp_addr_info mpc_addr; + struct pm_nl_pernet *pernet; + unsigned int subflows_max; + int i = 0; +@@ -643,6 +648,8 @@ static unsigned int fill_local_addresses_vec(struct mptcp_sock *msk, + pernet = pm_nl_get_pernet_from_msk(msk); + subflows_max = mptcp_pm_get_subflows_max(msk); + ++ mptcp_local_address((struct sock_common *)msk, &mpc_addr); ++ + rcu_read_lock(); + list_for_each_entry_rcu(entry, &pernet->local_addr_list, list) { + if (!(entry->flags & MPTCP_PM_ADDR_FLAG_FULLMESH)) +@@ -653,7 +660,13 @@ static unsigned int fill_local_addresses_vec(struct mptcp_sock *msk, + + if (msk->pm.subflows < subflows_max) { + msk->pm.subflows++; +- addrs[i++] = entry->addr; ++ addrs[i] = entry->addr; ++ ++ /* Special case for ID0: set the correct ID */ ++ if (mptcp_addresses_equal(&entry->addr, &mpc_addr, entry->addr.port)) ++ addrs[i].id = 0; ++ ++ i++; + } + } + rcu_read_unlock(); +@@ -829,25 +842,27 @@ static void mptcp_pm_nl_rm_addr_or_subflow(struct mptcp_sock *msk, + mptcp_close_ssk(sk, ssk, subflow); + spin_lock_bh(&msk->pm.lock); + +- removed = true; ++ removed |= subflow->request_join; + if (rm_type == MPTCP_MIB_RMSUBFLOW) + __MPTCP_INC_STATS(sock_net(sk), rm_type); + } +- if (rm_type == MPTCP_MIB_RMSUBFLOW) +- __set_bit(rm_id ? rm_id : msk->mpc_endpoint_id, msk->pm.id_avail_bitmap); +- else if (rm_type == MPTCP_MIB_RMADDR) ++ ++ if (rm_type == MPTCP_MIB_RMADDR) + __MPTCP_INC_STATS(sock_net(sk), rm_type); ++ + if (!removed) + continue; + + if (!mptcp_pm_is_kernel(msk)) + continue; + +- if (rm_type == MPTCP_MIB_RMADDR) { +- msk->pm.add_addr_accepted--; +- WRITE_ONCE(msk->pm.accept_addr, true); +- } else if (rm_type == MPTCP_MIB_RMSUBFLOW) { +- msk->pm.local_addr_used--; ++ if (rm_type == MPTCP_MIB_RMADDR && rm_id && ++ !WARN_ON_ONCE(msk->pm.add_addr_accepted == 0)) { ++ /* Note: if the subflow has been closed before, this ++ * add_addr_accepted counter will not be decremented. ++ */ ++ if (--msk->pm.add_addr_accepted < mptcp_pm_get_add_addr_accept_max(msk)) ++ WRITE_ONCE(msk->pm.accept_addr, true); + } + } + } +@@ -857,8 +872,8 @@ static void mptcp_pm_nl_rm_addr_received(struct mptcp_sock *msk) + mptcp_pm_nl_rm_addr_or_subflow(msk, &msk->pm.rm_list_rx, MPTCP_MIB_RMADDR); + } + +-void mptcp_pm_nl_rm_subflow_received(struct mptcp_sock *msk, +- const struct mptcp_rm_list *rm_list) ++static void mptcp_pm_nl_rm_subflow_received(struct mptcp_sock *msk, ++ const struct mptcp_rm_list *rm_list) + { + mptcp_pm_nl_rm_addr_or_subflow(msk, rm_list, MPTCP_MIB_RMSUBFLOW); + } +@@ -1393,6 +1408,10 @@ int mptcp_pm_nl_get_flags_and_ifindex_by_id(struct mptcp_sock *msk, unsigned int + struct sock *sk = (struct sock *)msk; + struct net *net = sock_net(sk); + ++ /* No entries with ID 0 */ ++ if (id == 0) ++ return 0; ++ + rcu_read_lock(); + entry = __lookup_addr_by_id(pm_nl_get_pernet(net), id); + if (entry) { +@@ -1431,13 +1450,24 @@ static bool mptcp_pm_remove_anno_addr(struct mptcp_sock *msk, + ret = remove_anno_list_by_saddr(msk, addr); + if (ret || force) { + spin_lock_bh(&msk->pm.lock); +- msk->pm.add_addr_signaled -= ret; ++ if (ret) { ++ __set_bit(addr->id, msk->pm.id_avail_bitmap); ++ msk->pm.add_addr_signaled--; ++ } + mptcp_pm_remove_addr(msk, &list); + spin_unlock_bh(&msk->pm.lock); + } + return ret; + } + ++static void __mark_subflow_endp_available(struct mptcp_sock *msk, u8 id) ++{ ++ /* If it was marked as used, and not ID 0, decrement local_addr_used */ ++ if (!__test_and_set_bit(id ? : msk->mpc_endpoint_id, msk->pm.id_avail_bitmap) && ++ id && !WARN_ON_ONCE(msk->pm.local_addr_used == 0)) ++ msk->pm.local_addr_used--; ++} ++ + static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net, + const struct mptcp_pm_addr_entry *entry) + { +@@ -1466,8 +1496,19 @@ static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net, + remove_subflow = lookup_subflow_by_saddr(&msk->conn_list, addr); + mptcp_pm_remove_anno_addr(msk, addr, remove_subflow && + !(entry->flags & MPTCP_PM_ADDR_FLAG_IMPLICIT)); +- if (remove_subflow) +- mptcp_pm_remove_subflow(msk, &list); ++ ++ if (remove_subflow) { ++ spin_lock_bh(&msk->pm.lock); ++ mptcp_pm_nl_rm_subflow_received(msk, &list); ++ spin_unlock_bh(&msk->pm.lock); ++ } ++ ++ if (entry->flags & MPTCP_PM_ADDR_FLAG_SUBFLOW) { ++ spin_lock_bh(&msk->pm.lock); ++ __mark_subflow_endp_available(msk, list.ids[0]); ++ spin_unlock_bh(&msk->pm.lock); ++ } ++ + release_sock(sk); + + next: +@@ -1502,6 +1543,7 @@ static int mptcp_nl_remove_id_zero_address(struct net *net, + spin_lock_bh(&msk->pm.lock); + mptcp_pm_remove_addr(msk, &list); + mptcp_pm_nl_rm_subflow_received(msk, &list); ++ __mark_subflow_endp_available(msk, 0); + spin_unlock_bh(&msk->pm.lock); + release_sock(sk); + +@@ -1605,14 +1647,17 @@ static void mptcp_pm_remove_addrs_and_subflows(struct mptcp_sock *msk, + alist.ids[alist.nr++] = entry->addr.id; + } + ++ spin_lock_bh(&msk->pm.lock); + if (alist.nr) { +- spin_lock_bh(&msk->pm.lock); + msk->pm.add_addr_signaled -= alist.nr; + mptcp_pm_remove_addr(msk, &alist); +- spin_unlock_bh(&msk->pm.lock); + } + if (slist.nr) +- mptcp_pm_remove_subflow(msk, &slist); ++ mptcp_pm_nl_rm_subflow_received(msk, &slist); ++ /* Reset counters: maybe some subflows have been removed before */ ++ bitmap_fill(msk->pm.id_avail_bitmap, MPTCP_PM_MAX_ADDR_ID + 1); ++ msk->pm.local_addr_used = 0; ++ spin_unlock_bh(&msk->pm.lock); + } + + static void mptcp_nl_remove_addrs_list(struct net *net, +@@ -1900,6 +1945,7 @@ static void mptcp_pm_nl_fullmesh(struct mptcp_sock *msk, + + spin_lock_bh(&msk->pm.lock); + mptcp_pm_nl_rm_subflow_received(msk, &list); ++ __mark_subflow_endp_available(msk, list.ids[0]); + mptcp_pm_create_subflow_or_signal_addr(msk); + spin_unlock_bh(&msk->pm.lock); + } +diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h +index 8357046732f71..c7c846805c4e1 100644 +--- a/net/mptcp/protocol.h ++++ b/net/mptcp/protocol.h +@@ -1021,7 +1021,6 @@ int mptcp_pm_announce_addr(struct mptcp_sock *msk, + const struct mptcp_addr_info *addr, + bool echo); + int mptcp_pm_remove_addr(struct mptcp_sock *msk, const struct mptcp_rm_list *rm_list); +-int mptcp_pm_remove_subflow(struct mptcp_sock *msk, const struct mptcp_rm_list *rm_list); + void mptcp_pm_remove_addrs(struct mptcp_sock *msk, struct list_head *rm_list); + + void mptcp_free_local_addr_list(struct mptcp_sock *msk); +@@ -1128,8 +1127,6 @@ static inline u8 subflow_get_local_id(const struct mptcp_subflow_context *subflo + + void __init mptcp_pm_nl_init(void); + void mptcp_pm_nl_work(struct mptcp_sock *msk); +-void mptcp_pm_nl_rm_subflow_received(struct mptcp_sock *msk, +- const struct mptcp_rm_list *rm_list); + unsigned int mptcp_pm_get_add_addr_signal_max(const struct mptcp_sock *msk); + unsigned int mptcp_pm_get_add_addr_accept_max(const struct mptcp_sock *msk); + unsigned int mptcp_pm_get_subflows_max(const struct mptcp_sock *msk); +diff --git a/net/netfilter/nf_flow_table_inet.c b/net/netfilter/nf_flow_table_inet.c +index 6eef15648b7b0..b0f1991719324 100644 +--- a/net/netfilter/nf_flow_table_inet.c ++++ b/net/netfilter/nf_flow_table_inet.c +@@ -17,6 +17,9 @@ nf_flow_offload_inet_hook(void *priv, struct sk_buff *skb, + + switch (skb->protocol) { + case htons(ETH_P_8021Q): ++ if (!pskb_may_pull(skb, skb_mac_offset(skb) + sizeof(*veth))) ++ return NF_ACCEPT; ++ + veth = (struct vlan_ethhdr *)skb_mac_header(skb); + proto = veth->h_vlan_encapsulated_proto; + break; +diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c +index c2c005234dcd3..98edcaa37b38d 100644 +--- a/net/netfilter/nf_flow_table_ip.c ++++ b/net/netfilter/nf_flow_table_ip.c +@@ -281,6 +281,9 @@ static bool nf_flow_skb_encap_protocol(struct sk_buff *skb, __be16 proto, + + switch (skb->protocol) { + case htons(ETH_P_8021Q): ++ if (!pskb_may_pull(skb, skb_mac_offset(skb) + sizeof(*veth))) ++ return false; ++ + veth = (struct vlan_ethhdr *)skb_mac_header(skb); + if (veth->h_vlan_encapsulated_proto == proto) { + *offset += VLAN_HLEN; +diff --git a/net/netfilter/nf_flow_table_offload.c b/net/netfilter/nf_flow_table_offload.c +index a010b25076ca0..3d46372b538e5 100644 +--- a/net/netfilter/nf_flow_table_offload.c ++++ b/net/netfilter/nf_flow_table_offload.c +@@ -841,8 +841,8 @@ static int nf_flow_offload_tuple(struct nf_flowtable *flowtable, + struct list_head *block_cb_list) + { + struct flow_cls_offload cls_flow = {}; ++ struct netlink_ext_ack extack = {}; + struct flow_block_cb *block_cb; +- struct netlink_ext_ack extack; + __be16 proto = ETH_P_ALL; + int err, i = 0; + +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index 91cc3a81ba8f1..41d7faeb101cf 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -7977,6 +7977,19 @@ static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb) + return skb->len; + } + ++static int nf_tables_dumpreset_obj(struct sk_buff *skb, ++ struct netlink_callback *cb) ++{ ++ struct nftables_pernet *nft_net = nft_pernet(sock_net(skb->sk)); ++ int ret; ++ ++ mutex_lock(&nft_net->commit_mutex); ++ ret = nf_tables_dump_obj(skb, cb); ++ mutex_unlock(&nft_net->commit_mutex); ++ ++ return ret; ++} ++ + static int nf_tables_dump_obj_start(struct netlink_callback *cb) + { + struct nft_obj_dump_ctx *ctx = (void *)cb->ctx; +@@ -7993,12 +8006,18 @@ static int nf_tables_dump_obj_start(struct netlink_callback *cb) + if (nla[NFTA_OBJ_TYPE]) + ctx->type = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE])); + +- if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) == NFT_MSG_GETOBJ_RESET) +- ctx->reset = true; +- + return 0; + } + ++static int nf_tables_dumpreset_obj_start(struct netlink_callback *cb) ++{ ++ struct nft_obj_dump_ctx *ctx = (void *)cb->ctx; ++ ++ ctx->reset = true; ++ ++ return nf_tables_dump_obj_start(cb); ++} ++ + static int nf_tables_dump_obj_done(struct netlink_callback *cb) + { + struct nft_obj_dump_ctx *ctx = (void *)cb->ctx; +@@ -8009,8 +8028,9 @@ static int nf_tables_dump_obj_done(struct netlink_callback *cb) + } + + /* called with rcu_read_lock held */ +-static int nf_tables_getobj(struct sk_buff *skb, const struct nfnl_info *info, +- const struct nlattr * const nla[]) ++static struct sk_buff * ++nf_tables_getobj_single(u32 portid, const struct nfnl_info *info, ++ const struct nlattr * const nla[], bool reset) + { + struct netlink_ext_ack *extack = info->extack; + u8 genmask = nft_genmask_cur(info->net); +@@ -8019,72 +8039,109 @@ static int nf_tables_getobj(struct sk_buff *skb, const struct nfnl_info *info, + struct net *net = info->net; + struct nft_object *obj; + struct sk_buff *skb2; +- bool reset = false; + u32 objtype; + int err; + +- if (info->nlh->nlmsg_flags & NLM_F_DUMP) { +- struct netlink_dump_control c = { +- .start = nf_tables_dump_obj_start, +- .dump = nf_tables_dump_obj, +- .done = nf_tables_dump_obj_done, +- .module = THIS_MODULE, +- .data = (void *)nla, +- }; +- +- return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c); +- } +- + if (!nla[NFTA_OBJ_NAME] || + !nla[NFTA_OBJ_TYPE]) +- return -EINVAL; ++ return ERR_PTR(-EINVAL); + + table = nft_table_lookup(net, nla[NFTA_OBJ_TABLE], family, genmask, 0); + if (IS_ERR(table)) { + NL_SET_BAD_ATTR(extack, nla[NFTA_OBJ_TABLE]); +- return PTR_ERR(table); ++ return ERR_CAST(table); + } + + objtype = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE])); + obj = nft_obj_lookup(net, table, nla[NFTA_OBJ_NAME], objtype, genmask); + if (IS_ERR(obj)) { + NL_SET_BAD_ATTR(extack, nla[NFTA_OBJ_NAME]); +- return PTR_ERR(obj); ++ return ERR_CAST(obj); + } + + skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC); + if (!skb2) +- return -ENOMEM; ++ return ERR_PTR(-ENOMEM); + +- if (NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_GETOBJ_RESET) +- reset = true; ++ err = nf_tables_fill_obj_info(skb2, net, portid, ++ info->nlh->nlmsg_seq, NFT_MSG_NEWOBJ, 0, ++ family, table, obj, reset); ++ if (err < 0) { ++ kfree_skb(skb2); ++ return ERR_PTR(err); ++ } + +- if (reset) { +- const struct nftables_pernet *nft_net; +- char *buf; ++ return skb2; ++} + +- nft_net = nft_pernet(net); +- buf = kasprintf(GFP_ATOMIC, "%s:%u", table->name, nft_net->base_seq); ++static int nf_tables_getobj(struct sk_buff *skb, const struct nfnl_info *info, ++ const struct nlattr * const nla[]) ++{ ++ u32 portid = NETLINK_CB(skb).portid; ++ struct sk_buff *skb2; + +- audit_log_nfcfg(buf, +- family, +- 1, +- AUDIT_NFT_OP_OBJ_RESET, +- GFP_ATOMIC); +- kfree(buf); ++ if (info->nlh->nlmsg_flags & NLM_F_DUMP) { ++ struct netlink_dump_control c = { ++ .start = nf_tables_dump_obj_start, ++ .dump = nf_tables_dump_obj, ++ .done = nf_tables_dump_obj_done, ++ .module = THIS_MODULE, ++ .data = (void *)nla, ++ }; ++ ++ return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c); + } + +- err = nf_tables_fill_obj_info(skb2, net, NETLINK_CB(skb).portid, +- info->nlh->nlmsg_seq, NFT_MSG_NEWOBJ, 0, +- family, table, obj, reset); +- if (err < 0) +- goto err_fill_obj_info; ++ skb2 = nf_tables_getobj_single(portid, info, nla, false); ++ if (IS_ERR(skb2)) ++ return PTR_ERR(skb2); + +- return nfnetlink_unicast(skb2, net, NETLINK_CB(skb).portid); ++ return nfnetlink_unicast(skb2, info->net, portid); ++} + +-err_fill_obj_info: +- kfree_skb(skb2); +- return err; ++static int nf_tables_getobj_reset(struct sk_buff *skb, ++ const struct nfnl_info *info, ++ const struct nlattr * const nla[]) ++{ ++ struct nftables_pernet *nft_net = nft_pernet(info->net); ++ u32 portid = NETLINK_CB(skb).portid; ++ struct net *net = info->net; ++ struct sk_buff *skb2; ++ char *buf; ++ ++ if (info->nlh->nlmsg_flags & NLM_F_DUMP) { ++ struct netlink_dump_control c = { ++ .start = nf_tables_dumpreset_obj_start, ++ .dump = nf_tables_dumpreset_obj, ++ .done = nf_tables_dump_obj_done, ++ .module = THIS_MODULE, ++ .data = (void *)nla, ++ }; ++ ++ return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c); ++ } ++ ++ if (!try_module_get(THIS_MODULE)) ++ return -EINVAL; ++ rcu_read_unlock(); ++ mutex_lock(&nft_net->commit_mutex); ++ skb2 = nf_tables_getobj_single(portid, info, nla, true); ++ mutex_unlock(&nft_net->commit_mutex); ++ rcu_read_lock(); ++ module_put(THIS_MODULE); ++ ++ if (IS_ERR(skb2)) ++ return PTR_ERR(skb2); ++ ++ buf = kasprintf(GFP_ATOMIC, "%.*s:%u", ++ nla_len(nla[NFTA_OBJ_TABLE]), ++ (char *)nla_data(nla[NFTA_OBJ_TABLE]), ++ nft_net->base_seq); ++ audit_log_nfcfg(buf, info->nfmsg->nfgen_family, 1, ++ AUDIT_NFT_OP_OBJ_RESET, GFP_ATOMIC); ++ kfree(buf); ++ ++ return nfnetlink_unicast(skb2, net, portid); + } + + static void nft_obj_destroy(const struct nft_ctx *ctx, struct nft_object *obj) +@@ -9367,7 +9424,7 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = { + .policy = nft_obj_policy, + }, + [NFT_MSG_GETOBJ_RESET] = { +- .call = nf_tables_getobj, ++ .call = nf_tables_getobj_reset, + .type = NFNL_CB_RCU, + .attr_count = NFTA_OBJ_MAX, + .policy = nft_obj_policy, +diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c +index 4abf660c7baff..932b3ddb34f13 100644 +--- a/net/netfilter/nfnetlink.c ++++ b/net/netfilter/nfnetlink.c +@@ -427,8 +427,10 @@ static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh, + + nfnl_unlock(subsys_id); + +- if (nlh->nlmsg_flags & NLM_F_ACK) ++ if (nlh->nlmsg_flags & NLM_F_ACK) { ++ memset(&extack, 0, sizeof(extack)); + nfnl_err_add(&err_list, nlh, 0, &extack); ++ } + + while (skb->len >= nlmsg_total_size(0)) { + int msglen, type; +@@ -577,6 +579,7 @@ static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh, + ss->abort(net, oskb, NFNL_ABORT_NONE); + netlink_ack(oskb, nlmsg_hdr(oskb), err, NULL); + } else if (nlh->nlmsg_flags & NLM_F_ACK) { ++ memset(&extack, 0, sizeof(extack)); + nfnl_err_add(&err_list, nlh, 0, &extack); + } + } else { +diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c +index 55e28e1da66ec..e0716da256bf5 100644 +--- a/net/netfilter/nfnetlink_queue.c ++++ b/net/netfilter/nfnetlink_queue.c +@@ -820,10 +820,41 @@ static bool nf_ct_drop_unconfirmed(const struct nf_queue_entry *entry) + { + #if IS_ENABLED(CONFIG_NF_CONNTRACK) + static const unsigned long flags = IPS_CONFIRMED | IPS_DYING; +- const struct nf_conn *ct = (void *)skb_nfct(entry->skb); ++ struct nf_conn *ct = (void *)skb_nfct(entry->skb); ++ unsigned long status; ++ unsigned int use; + +- if (ct && ((ct->status & flags) == IPS_DYING)) ++ if (!ct) ++ return false; ++ ++ status = READ_ONCE(ct->status); ++ if ((status & flags) == IPS_DYING) + return true; ++ ++ if (status & IPS_CONFIRMED) ++ return false; ++ ++ /* in some cases skb_clone() can occur after initial conntrack ++ * pickup, but conntrack assumes exclusive skb->_nfct ownership for ++ * unconfirmed entries. ++ * ++ * This happens for br_netfilter and with ip multicast routing. ++ * We can't be solved with serialization here because one clone could ++ * have been queued for local delivery. ++ */ ++ use = refcount_read(&ct->ct_general.use); ++ if (likely(use == 1)) ++ return false; ++ ++ /* Can't decrement further? Exclusive ownership. */ ++ if (!refcount_dec_not_one(&ct->ct_general.use)) ++ return false; ++ ++ skb_set_nfct(entry->skb, 0); ++ /* No nf_ct_put(): we already decremented .use and it cannot ++ * drop down to 0. ++ */ ++ return true; + #endif + return false; + } +diff --git a/net/netfilter/nft_counter.c b/net/netfilter/nft_counter.c +index 291ed2026367e..eab0dc66bee6b 100644 +--- a/net/netfilter/nft_counter.c ++++ b/net/netfilter/nft_counter.c +@@ -107,11 +107,16 @@ static void nft_counter_reset(struct nft_counter_percpu_priv *priv, + struct nft_counter *total) + { + struct nft_counter *this_cpu; ++ seqcount_t *myseq; + + local_bh_disable(); + this_cpu = this_cpu_ptr(priv->counter); ++ myseq = this_cpu_ptr(&nft_counter_seq); ++ ++ write_seqcount_begin(myseq); + this_cpu->packets -= total->packets; + this_cpu->bytes -= total->bytes; ++ write_seqcount_end(myseq); + local_bh_enable(); + } + +@@ -265,7 +270,7 @@ static void nft_counter_offload_stats(struct nft_expr *expr, + struct nft_counter *this_cpu; + seqcount_t *myseq; + +- preempt_disable(); ++ local_bh_disable(); + this_cpu = this_cpu_ptr(priv->counter); + myseq = this_cpu_ptr(&nft_counter_seq); + +@@ -273,7 +278,7 @@ static void nft_counter_offload_stats(struct nft_expr *expr, + this_cpu->packets += stats->pkts; + this_cpu->bytes += stats->bytes; + write_seqcount_end(myseq); +- preempt_enable(); ++ local_bh_enable(); + } + + void nft_counter_init_seqcount(void) +diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c +index 99d72543abd3a..78d9961fcd446 100644 +--- a/net/openvswitch/datapath.c ++++ b/net/openvswitch/datapath.c +@@ -2706,7 +2706,7 @@ static struct pernet_operations ovs_net_ops = { + }; + + static const char * const ovs_drop_reasons[] = { +-#define S(x) (#x), ++#define S(x) [(x) & ~SKB_DROP_REASON_SUBSYS_MASK] = (#x), + OVS_DROP_REASONS(S) + #undef S + }; +diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c +index edc72962ae63a..0f8d581438c39 100644 +--- a/net/sched/sch_netem.c ++++ b/net/sched/sch_netem.c +@@ -446,12 +446,10 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch, + struct netem_sched_data *q = qdisc_priv(sch); + /* We don't fill cb now as skb_unshare() may invalidate it */ + struct netem_skb_cb *cb; +- struct sk_buff *skb2; ++ struct sk_buff *skb2 = NULL; + struct sk_buff *segs = NULL; + unsigned int prev_len = qdisc_pkt_len(skb); + int count = 1; +- int rc = NET_XMIT_SUCCESS; +- int rc_drop = NET_XMIT_DROP; + + /* Do not fool qdisc_drop_all() */ + skb->prev = NULL; +@@ -480,19 +478,11 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch, + skb_orphan_partial(skb); + + /* +- * If we need to duplicate packet, then re-insert at top of the +- * qdisc tree, since parent queuer expects that only one +- * skb will be queued. ++ * If we need to duplicate packet, then clone it before ++ * original is modified. + */ +- if (count > 1 && (skb2 = skb_clone(skb, GFP_ATOMIC)) != NULL) { +- struct Qdisc *rootq = qdisc_root_bh(sch); +- u32 dupsave = q->duplicate; /* prevent duplicating a dup... */ +- +- q->duplicate = 0; +- rootq->enqueue(skb2, rootq, to_free); +- q->duplicate = dupsave; +- rc_drop = NET_XMIT_SUCCESS; +- } ++ if (count > 1) ++ skb2 = skb_clone(skb, GFP_ATOMIC); + + /* + * Randomized packet corruption. +@@ -504,7 +494,8 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch, + if (skb_is_gso(skb)) { + skb = netem_segment(skb, sch, to_free); + if (!skb) +- return rc_drop; ++ goto finish_segs; ++ + segs = skb->next; + skb_mark_not_on_list(skb); + qdisc_skb_cb(skb)->pkt_len = skb->len; +@@ -530,7 +521,24 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch, + /* re-link segs, so that qdisc_drop_all() frees them all */ + skb->next = segs; + qdisc_drop_all(skb, sch, to_free); +- return rc_drop; ++ if (skb2) ++ __qdisc_drop(skb2, to_free); ++ return NET_XMIT_DROP; ++ } ++ ++ /* ++ * If doing duplication then re-insert at top of the ++ * qdisc tree, since parent queuer expects that only one ++ * skb will be queued. ++ */ ++ if (skb2) { ++ struct Qdisc *rootq = qdisc_root_bh(sch); ++ u32 dupsave = q->duplicate; /* prevent duplicating a dup... */ ++ ++ q->duplicate = 0; ++ rootq->enqueue(skb2, rootq, to_free); ++ q->duplicate = dupsave; ++ skb2 = NULL; + } + + qdisc_qstats_backlog_inc(sch, skb); +@@ -601,9 +609,12 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch, + } + + finish_segs: ++ if (skb2) ++ __qdisc_drop(skb2, to_free); ++ + if (segs) { + unsigned int len, last_len; +- int nb; ++ int rc, nb; + + len = skb ? skb->len : 0; + nb = skb ? 1 : 0; +diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c +index 4b040285aa78c..0ff9b2dd86bac 100644 +--- a/net/vmw_vsock/af_vsock.c ++++ b/net/vmw_vsock/af_vsock.c +@@ -1270,25 +1270,28 @@ static int vsock_dgram_connect(struct socket *sock, + return err; + } + ++int __vsock_dgram_recvmsg(struct socket *sock, struct msghdr *msg, ++ size_t len, int flags) ++{ ++ struct sock *sk = sock->sk; ++ struct vsock_sock *vsk = vsock_sk(sk); ++ ++ return vsk->transport->dgram_dequeue(vsk, msg, len, flags); ++} ++ + int vsock_dgram_recvmsg(struct socket *sock, struct msghdr *msg, + size_t len, int flags) + { + #ifdef CONFIG_BPF_SYSCALL ++ struct sock *sk = sock->sk; + const struct proto *prot; +-#endif +- struct vsock_sock *vsk; +- struct sock *sk; + +- sk = sock->sk; +- vsk = vsock_sk(sk); +- +-#ifdef CONFIG_BPF_SYSCALL + prot = READ_ONCE(sk->sk_prot); + if (prot != &vsock_proto) + return prot->recvmsg(sk, msg, len, flags, NULL); + #endif + +- return vsk->transport->dgram_dequeue(vsk, msg, len, flags); ++ return __vsock_dgram_recvmsg(sock, msg, len, flags); + } + EXPORT_SYMBOL_GPL(vsock_dgram_recvmsg); + +@@ -2174,15 +2177,12 @@ static int __vsock_seqpacket_recvmsg(struct sock *sk, struct msghdr *msg, + } + + int +-vsock_connectible_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, +- int flags) ++__vsock_connectible_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, ++ int flags) + { + struct sock *sk; + struct vsock_sock *vsk; + const struct vsock_transport *transport; +-#ifdef CONFIG_BPF_SYSCALL +- const struct proto *prot; +-#endif + int err; + + sk = sock->sk; +@@ -2233,14 +2233,6 @@ vsock_connectible_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, + goto out; + } + +-#ifdef CONFIG_BPF_SYSCALL +- prot = READ_ONCE(sk->sk_prot); +- if (prot != &vsock_proto) { +- release_sock(sk); +- return prot->recvmsg(sk, msg, len, flags, NULL); +- } +-#endif +- + if (sk->sk_type == SOCK_STREAM) + err = __vsock_stream_recvmsg(sk, msg, len, flags); + else +@@ -2250,6 +2242,22 @@ vsock_connectible_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, + release_sock(sk); + return err; + } ++ ++int ++vsock_connectible_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, ++ int flags) ++{ ++#ifdef CONFIG_BPF_SYSCALL ++ struct sock *sk = sock->sk; ++ const struct proto *prot; ++ ++ prot = READ_ONCE(sk->sk_prot); ++ if (prot != &vsock_proto) ++ return prot->recvmsg(sk, msg, len, flags, NULL); ++#endif ++ ++ return __vsock_connectible_recvmsg(sock, msg, len, flags); ++} + EXPORT_SYMBOL_GPL(vsock_connectible_recvmsg); + + static int vsock_set_rcvlowat(struct sock *sk, int val) +diff --git a/net/vmw_vsock/vsock_bpf.c b/net/vmw_vsock/vsock_bpf.c +index a3c97546ab84a..c42c5cc18f324 100644 +--- a/net/vmw_vsock/vsock_bpf.c ++++ b/net/vmw_vsock/vsock_bpf.c +@@ -64,9 +64,9 @@ static int __vsock_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int + int err; + + if (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) +- err = vsock_connectible_recvmsg(sock, msg, len, flags); ++ err = __vsock_connectible_recvmsg(sock, msg, len, flags); + else if (sk->sk_type == SOCK_DGRAM) +- err = vsock_dgram_recvmsg(sock, msg, len, flags); ++ err = __vsock_dgram_recvmsg(sock, msg, len, flags); + else + err = -EPROTOTYPE; + +diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c +index 47978efe4797c..839d9c49f28ce 100644 +--- a/scripts/kallsyms.c ++++ b/scripts/kallsyms.c +@@ -5,8 +5,7 @@ + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + * +- * Usage: kallsyms [--all-symbols] [--absolute-percpu] +- * [--base-relative] [--lto-clang] in.map > out.S ++ * Usage: kallsyms [--all-symbols] [--absolute-percpu] in.map > out.S + * + * Table compression uses all the unused char codes on the symbols and + * maps these to the most used substrings (tokens). For instance, it might +@@ -63,8 +62,6 @@ static struct sym_entry **table; + static unsigned int table_size, table_cnt; + static int all_symbols; + static int absolute_percpu; +-static int base_relative; +-static int lto_clang; + + static int token_profit[0x10000]; + +@@ -75,8 +72,7 @@ static unsigned char best_table_len[256]; + + static void usage(void) + { +- fprintf(stderr, "Usage: kallsyms [--all-symbols] [--absolute-percpu] " +- "[--base-relative] [--lto-clang] in.map > out.S\n"); ++ fprintf(stderr, "Usage: kallsyms [--all-symbols] [--absolute-percpu] in.map > out.S\n"); + exit(1); + } + +@@ -259,12 +255,6 @@ static void shrink_table(void) + } + } + table_cnt = pos; +- +- /* When valid symbol is not registered, exit to error */ +- if (!table_cnt) { +- fprintf(stderr, "No valid symbol.\n"); +- exit(1); +- } + } + + static void read_map(const char *in) +@@ -352,25 +342,6 @@ static int symbol_absolute(const struct sym_entry *s) + return s->percpu_absolute; + } + +-static void cleanup_symbol_name(char *s) +-{ +- char *p; +- +- /* +- * ASCII[.] = 2e +- * ASCII[0-9] = 30,39 +- * ASCII[A-Z] = 41,5a +- * ASCII[_] = 5f +- * ASCII[a-z] = 61,7a +- * +- * As above, replacing the first '.' in ".llvm." with '\0' does not +- * affect the main sorting, but it helps us with subsorting. +- */ +- p = strstr(s, ".llvm."); +- if (p) +- *p = '\0'; +-} +- + static int compare_names(const void *a, const void *b) + { + int ret; +@@ -497,58 +468,43 @@ static void write_src(void) + printf("\t.short\t%d\n", best_idx[i]); + printf("\n"); + +- if (!base_relative) +- output_label("kallsyms_addresses"); +- else +- output_label("kallsyms_offsets"); ++ output_label("kallsyms_offsets"); + + for (i = 0; i < table_cnt; i++) { +- if (base_relative) { +- /* +- * Use the offset relative to the lowest value +- * encountered of all relative symbols, and emit +- * non-relocatable fixed offsets that will be fixed +- * up at runtime. +- */ ++ /* ++ * Use the offset relative to the lowest value ++ * encountered of all relative symbols, and emit ++ * non-relocatable fixed offsets that will be fixed ++ * up at runtime. ++ */ + +- long long offset; +- int overflow; +- +- if (!absolute_percpu) { +- offset = table[i]->addr - relative_base; +- overflow = (offset < 0 || offset > UINT_MAX); +- } else if (symbol_absolute(table[i])) { +- offset = table[i]->addr; +- overflow = (offset < 0 || offset > INT_MAX); +- } else { +- offset = relative_base - table[i]->addr - 1; +- overflow = (offset < INT_MIN || offset >= 0); +- } +- if (overflow) { +- fprintf(stderr, "kallsyms failure: " +- "%s symbol value %#llx out of range in relative mode\n", +- symbol_absolute(table[i]) ? "absolute" : "relative", +- table[i]->addr); +- exit(EXIT_FAILURE); +- } +- printf("\t.long\t%#x /* %s */\n", (int)offset, table[i]->sym); +- } else if (!symbol_absolute(table[i])) { +- output_address(table[i]->addr); ++ long long offset; ++ int overflow; ++ ++ if (!absolute_percpu) { ++ offset = table[i]->addr - relative_base; ++ overflow = (offset < 0 || offset > UINT_MAX); ++ } else if (symbol_absolute(table[i])) { ++ offset = table[i]->addr; ++ overflow = (offset < 0 || offset > INT_MAX); + } else { +- printf("\tPTR\t%#llx\n", table[i]->addr); ++ offset = relative_base - table[i]->addr - 1; ++ overflow = (offset < INT_MIN || offset >= 0); ++ } ++ if (overflow) { ++ fprintf(stderr, "kallsyms failure: " ++ "%s symbol value %#llx out of range in relative mode\n", ++ symbol_absolute(table[i]) ? "absolute" : "relative", ++ table[i]->addr); ++ exit(EXIT_FAILURE); + } ++ printf("\t.long\t%#x /* %s */\n", (int)offset, table[i]->sym); + } + printf("\n"); + +- if (base_relative) { +- output_label("kallsyms_relative_base"); +- output_address(relative_base); +- printf("\n"); +- } +- +- if (lto_clang) +- for (i = 0; i < table_cnt; i++) +- cleanup_symbol_name((char *)table[i]->sym); ++ output_label("kallsyms_relative_base"); ++ output_address(relative_base); ++ printf("\n"); + + sort_symbols_by_name(); + output_label("kallsyms_seqs_of_names"); +@@ -826,8 +782,6 @@ int main(int argc, char **argv) + static const struct option long_options[] = { + {"all-symbols", no_argument, &all_symbols, 1}, + {"absolute-percpu", no_argument, &absolute_percpu, 1}, +- {"base-relative", no_argument, &base_relative, 1}, +- {"lto-clang", no_argument, <o_clang, 1}, + {}, + }; + +@@ -847,8 +801,7 @@ int main(int argc, char **argv) + if (absolute_percpu) + make_percpus_absolute(); + sort_symbols(); +- if (base_relative) +- record_relative_base(); ++ record_relative_base(); + optimize_token_table(); + write_src(); + +diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh +index 518c70b8db507..070a319140e89 100755 +--- a/scripts/link-vmlinux.sh ++++ b/scripts/link-vmlinux.sh +@@ -45,7 +45,6 @@ info() + + # Link of vmlinux + # ${1} - output file +-# ${2}, ${3}, ... - optional extra .o files + vmlinux_link() + { + local output=${1} +@@ -90,7 +89,7 @@ vmlinux_link() + ldflags="${ldflags} ${wl}--script=${objtree}/${KBUILD_LDS}" + + # The kallsyms linking does not need debug symbols included. +- if [ "$output" != "${output#.tmp_vmlinux.kallsyms}" ] ; then ++ if [ -n "${strip_debug}" ] ; then + ldflags="${ldflags} ${wl}--strip-debug" + fi + +@@ -101,15 +100,15 @@ vmlinux_link() + ${ld} ${ldflags} -o ${output} \ + ${wl}--whole-archive ${objs} ${wl}--no-whole-archive \ + ${wl}--start-group ${libs} ${wl}--end-group \ +- $@ ${ldlibs} ++ ${kallsymso} ${btf_vmlinux_bin_o} ${ldlibs} + } + + # generate .BTF typeinfo from DWARF debuginfo + # ${1} - vmlinux image +-# ${2} - file to dump raw BTF data into + gen_btf() + { + local pahole_ver ++ local btf_data=${1}.btf.o + + if ! [ -x "$(command -v ${PAHOLE})" ]; then + echo >&2 "BTF: ${1}: pahole (${PAHOLE}) is not available" +@@ -122,18 +121,16 @@ gen_btf() + return 1 + fi + +- vmlinux_link ${1} +- +- info "BTF" ${2} ++ info BTF "${btf_data}" + LLVM_OBJCOPY="${OBJCOPY}" ${PAHOLE} -J ${PAHOLE_FLAGS} ${1} + +- # Create ${2} which contains just .BTF section but no symbols. Add ++ # Create ${btf_data} which contains just .BTF section but no symbols. Add + # SHF_ALLOC because .BTF will be part of the vmlinux image. --strip-all + # deletes all symbols including __start_BTF and __stop_BTF, which will + # be redefined in the linker script. Add 2>/dev/null to suppress GNU + # objcopy warnings: "empty loadable segment detected at ..." + ${OBJCOPY} --only-section=.BTF --set-section-flags .BTF=alloc,readonly \ +- --strip-all ${1} ${2} 2>/dev/null ++ --strip-all ${1} "${btf_data}" 2>/dev/null + # Change e_type to ET_REL so that it can be used to link final vmlinux. + # GNU ld 2.35+ and lld do not allow an ET_EXEC input. + if is_enabled CONFIG_CPU_BIG_ENDIAN; then +@@ -141,10 +138,12 @@ gen_btf() + else + et_rel='\1\0' + fi +- printf "${et_rel}" | dd of=${2} conv=notrunc bs=1 seek=16 status=none ++ printf "${et_rel}" | dd of="${btf_data}" conv=notrunc bs=1 seek=16 status=none ++ ++ btf_vmlinux_bin_o=${btf_data} + } + +-# Create ${2} .S file with all symbols from the ${1} object file ++# Create ${2}.o file with all symbols from the ${1} object file + kallsyms() + { + local kallsymopt; +@@ -157,35 +156,23 @@ kallsyms() + kallsymopt="${kallsymopt} --absolute-percpu" + fi + +- if is_enabled CONFIG_KALLSYMS_BASE_RELATIVE; then +- kallsymopt="${kallsymopt} --base-relative" +- fi ++ info KSYMS "${2}.S" ++ scripts/kallsyms ${kallsymopt} "${1}" > "${2}.S" + +- if is_enabled CONFIG_LTO_CLANG; then +- kallsymopt="${kallsymopt} --lto-clang" +- fi ++ info AS "${2}.o" ++ ${CC} ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS} \ ++ ${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL} -c -o "${2}.o" "${2}.S" + +- info KSYMS ${2} +- scripts/kallsyms ${kallsymopt} ${1} > ${2} ++ kallsymso=${2}.o + } + +-# Perform one step in kallsyms generation, including temporary linking of +-# vmlinux. +-kallsyms_step() ++# Perform kallsyms for the given temporary vmlinux. ++sysmap_and_kallsyms() + { +- kallsymso_prev=${kallsymso} +- kallsyms_vmlinux=.tmp_vmlinux.kallsyms${1} +- kallsymso=${kallsyms_vmlinux}.o +- kallsyms_S=${kallsyms_vmlinux}.S ++ mksysmap "${1}" "${1}.syms" ++ kallsyms "${1}.syms" "${1}.kallsyms" + +- vmlinux_link ${kallsyms_vmlinux} "${kallsymso_prev}" ${btf_vmlinux_bin_o} +- mksysmap ${kallsyms_vmlinux} ${kallsyms_vmlinux}.syms +- kallsyms ${kallsyms_vmlinux}.syms ${kallsyms_S} +- +- info AS ${kallsymso} +- ${CC} ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS} \ +- ${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL} \ +- -c -o ${kallsymso} ${kallsyms_S} ++ kallsyms_sysmap=${1}.syms + } + + # Create map file with all symbols from ${1} +@@ -223,26 +210,41 @@ fi + + ${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init init/version-timestamp.o + +-btf_vmlinux_bin_o="" ++btf_vmlinux_bin_o= ++kallsymso= ++strip_debug= ++ ++if is_enabled CONFIG_KALLSYMS; then ++ truncate -s0 .tmp_vmlinux.kallsyms0.syms ++ kallsyms .tmp_vmlinux.kallsyms0.syms .tmp_vmlinux0.kallsyms ++fi ++ ++if is_enabled CONFIG_KALLSYMS || is_enabled CONFIG_DEBUG_INFO_BTF; then ++ ++ # The kallsyms linking does not need debug symbols, but the BTF does. ++ if ! is_enabled CONFIG_DEBUG_INFO_BTF; then ++ strip_debug=1 ++ fi ++ ++ vmlinux_link .tmp_vmlinux1 ++fi ++ + if is_enabled CONFIG_DEBUG_INFO_BTF; then +- btf_vmlinux_bin_o=.btf.vmlinux.bin.o +- if ! gen_btf .tmp_vmlinux.btf $btf_vmlinux_bin_o ; then ++ if ! gen_btf .tmp_vmlinux1; then + echo >&2 "Failed to generate BTF for vmlinux" + echo >&2 "Try to disable CONFIG_DEBUG_INFO_BTF" + exit 1 + fi + fi + +-kallsymso="" +-kallsymso_prev="" +-kallsyms_vmlinux="" + if is_enabled CONFIG_KALLSYMS; then + + # kallsyms support + # Generate section listing all symbols and add it into vmlinux +- # It's a three step process: ++ # It's a four step process: ++ # 0) Generate a dummy __kallsyms with empty symbol list. + # 1) Link .tmp_vmlinux.kallsyms1 so it has all symbols and sections, +- # but __kallsyms is empty. ++ # with a dummy __kallsyms. + # Running kallsyms on that gives us .tmp_kallsyms1.o with + # the right size + # 2) Link .tmp_vmlinux.kallsyms2 so it now has a __kallsyms section of +@@ -261,19 +263,25 @@ if is_enabled CONFIG_KALLSYMS; then + # a) Verify that the System.map from vmlinux matches the map from + # ${kallsymso}. + +- kallsyms_step 1 +- kallsyms_step 2 ++ # The kallsyms linking does not need debug symbols included. ++ strip_debug=1 ++ ++ sysmap_and_kallsyms .tmp_vmlinux1 ++ size1=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" ${kallsymso}) + +- # step 3 +- size1=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" ${kallsymso_prev}) ++ vmlinux_link .tmp_vmlinux2 ++ sysmap_and_kallsyms .tmp_vmlinux2 + size2=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" ${kallsymso}) + + if [ $size1 -ne $size2 ] || [ -n "${KALLSYMS_EXTRA_PASS}" ]; then +- kallsyms_step 3 ++ vmlinux_link .tmp_vmlinux3 ++ sysmap_and_kallsyms .tmp_vmlinux3 + fi + fi + +-vmlinux_link vmlinux "${kallsymso}" ${btf_vmlinux_bin_o} ++strip_debug= ++ ++vmlinux_link vmlinux + + # fill in BTF IDs + if is_enabled CONFIG_DEBUG_INFO_BTF && is_enabled CONFIG_BPF; then +@@ -293,7 +301,7 @@ fi + + # step a (see comment above) + if is_enabled CONFIG_KALLSYMS; then +- if ! cmp -s System.map ${kallsyms_vmlinux}.syms; then ++ if ! cmp -s System.map "${kallsyms_sysmap}"; then + echo >&2 Inconsistent kallsyms data + echo >&2 'Try "make KALLSYMS_EXTRA_PASS=1" as a workaround' + exit 1 +diff --git a/scripts/rust_is_available.sh b/scripts/rust_is_available.sh +index 117018946b577..a6fdcf13e0e53 100755 +--- a/scripts/rust_is_available.sh ++++ b/scripts/rust_is_available.sh +@@ -129,8 +129,12 @@ fi + # Check that the Rust bindings generator is suitable. + # + # Non-stable and distributions' versions may have a version suffix, e.g. `-dev`. ++# ++# The dummy parameter `workaround-for-0.69.0` is required to support 0.69.0 ++# (https://github.com/rust-lang/rust-bindgen/pull/2678). It can be removed when ++# the minimum version is upgraded past that (0.69.1 already fixed the issue). + rust_bindings_generator_output=$( \ +- LC_ALL=C "$BINDGEN" --version 2>/dev/null ++ LC_ALL=C "$BINDGEN" --version workaround-for-0.69.0 2>/dev/null + ) || rust_bindings_generator_code=$? + if [ -n "$rust_bindings_generator_code" ]; then + echo >&2 "***" +diff --git a/security/keys/trusted-keys/trusted_dcp.c b/security/keys/trusted-keys/trusted_dcp.c +index b5f81a05be367..4edc5bbbcda3c 100644 +--- a/security/keys/trusted-keys/trusted_dcp.c ++++ b/security/keys/trusted-keys/trusted_dcp.c +@@ -186,20 +186,21 @@ static int do_aead_crypto(u8 *in, u8 *out, size_t len, u8 *key, u8 *nonce, + return ret; + } + +-static int decrypt_blob_key(u8 *key) ++static int decrypt_blob_key(u8 *encrypted_key, u8 *plain_key) + { +- return do_dcp_crypto(key, key, false); ++ return do_dcp_crypto(encrypted_key, plain_key, false); + } + +-static int encrypt_blob_key(u8 *key) ++static int encrypt_blob_key(u8 *plain_key, u8 *encrypted_key) + { +- return do_dcp_crypto(key, key, true); ++ return do_dcp_crypto(plain_key, encrypted_key, true); + } + + static int trusted_dcp_seal(struct trusted_key_payload *p, char *datablob) + { + struct dcp_blob_fmt *b = (struct dcp_blob_fmt *)p->blob; + int blen, ret; ++ u8 plain_blob_key[AES_KEYSIZE_128]; + + blen = calc_blob_len(p->key_len); + if (blen > MAX_BLOB_SIZE) +@@ -207,30 +208,36 @@ static int trusted_dcp_seal(struct trusted_key_payload *p, char *datablob) + + b->fmt_version = DCP_BLOB_VERSION; + get_random_bytes(b->nonce, AES_KEYSIZE_128); +- get_random_bytes(b->blob_key, AES_KEYSIZE_128); ++ get_random_bytes(plain_blob_key, AES_KEYSIZE_128); + +- ret = do_aead_crypto(p->key, b->payload, p->key_len, b->blob_key, ++ ret = do_aead_crypto(p->key, b->payload, p->key_len, plain_blob_key, + b->nonce, true); + if (ret) { + pr_err("Unable to encrypt blob payload: %i\n", ret); +- return ret; ++ goto out; + } + +- ret = encrypt_blob_key(b->blob_key); ++ ret = encrypt_blob_key(plain_blob_key, b->blob_key); + if (ret) { + pr_err("Unable to encrypt blob key: %i\n", ret); +- return ret; ++ goto out; + } + +- b->payload_len = get_unaligned_le32(&p->key_len); ++ put_unaligned_le32(p->key_len, &b->payload_len); + p->blob_len = blen; +- return 0; ++ ret = 0; ++ ++out: ++ memzero_explicit(plain_blob_key, sizeof(plain_blob_key)); ++ ++ return ret; + } + + static int trusted_dcp_unseal(struct trusted_key_payload *p, char *datablob) + { + struct dcp_blob_fmt *b = (struct dcp_blob_fmt *)p->blob; + int blen, ret; ++ u8 plain_blob_key[AES_KEYSIZE_128]; + + if (b->fmt_version != DCP_BLOB_VERSION) { + pr_err("DCP blob has bad version: %i, expected %i\n", +@@ -248,14 +255,14 @@ static int trusted_dcp_unseal(struct trusted_key_payload *p, char *datablob) + goto out; + } + +- ret = decrypt_blob_key(b->blob_key); ++ ret = decrypt_blob_key(b->blob_key, plain_blob_key); + if (ret) { + pr_err("Unable to decrypt blob key: %i\n", ret); + goto out; + } + + ret = do_aead_crypto(b->payload, p->key, p->key_len + DCP_BLOB_AUTHLEN, +- b->blob_key, b->nonce, false); ++ plain_blob_key, b->nonce, false); + if (ret) { + pr_err("Unwrap of DCP payload failed: %i\n", ret); + goto out; +@@ -263,6 +270,8 @@ static int trusted_dcp_unseal(struct trusted_key_payload *p, char *datablob) + + ret = 0; + out: ++ memzero_explicit(plain_blob_key, sizeof(plain_blob_key)); ++ + return ret; + } + +diff --git a/security/selinux/avc.c b/security/selinux/avc.c +index 32eb67fb3e42c..b49c44869dc46 100644 +--- a/security/selinux/avc.c ++++ b/security/selinux/avc.c +@@ -330,12 +330,12 @@ static int avc_add_xperms_decision(struct avc_node *node, + { + struct avc_xperms_decision_node *dest_xpd; + +- node->ae.xp_node->xp.len++; + dest_xpd = avc_xperms_decision_alloc(src->used); + if (!dest_xpd) + return -ENOMEM; + avc_copy_xperms_decision(&dest_xpd->xpd, src); + list_add(&dest_xpd->xpd_list, &node->ae.xp_node->xpd_head); ++ node->ae.xp_node->xp.len++; + return 0; + } + +@@ -907,7 +907,11 @@ static int avc_update_node(u32 event, u32 perms, u8 driver, u8 xperm, u32 ssid, + node->ae.avd.auditdeny &= ~perms; + break; + case AVC_CALLBACK_ADD_XPERMS: +- avc_add_xperms_decision(node, xpd); ++ rc = avc_add_xperms_decision(node, xpd); ++ if (rc) { ++ avc_node_kill(node); ++ goto out_unlock; ++ } + break; + } + avc_node_replace(node, orig); +diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c +index 55c78c318ccd7..bfa61e005aace 100644 +--- a/security/selinux/hooks.c ++++ b/security/selinux/hooks.c +@@ -3852,7 +3852,17 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, + if (default_noexec && + (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) { + int rc = 0; +- if (vma_is_initial_heap(vma)) { ++ /* ++ * We don't use the vma_is_initial_heap() helper as it has ++ * a history of problems and is currently broken on systems ++ * where there is no heap, e.g. brk == start_brk. Before ++ * replacing the conditional below with vma_is_initial_heap(), ++ * or something similar, please ensure that the logic is the ++ * same as what we have below or you have tested every possible ++ * corner case you can think to test. ++ */ ++ if (vma->vm_start >= vma->vm_mm->start_brk && ++ vma->vm_end <= vma->vm_mm->brk) { + rc = avc_has_perm(sid, sid, SECCLASS_PROCESS, + PROCESS__EXECHEAP, NULL); + } else if (!vma->vm_file && (vma_is_initial_stack(vma) || +diff --git a/sound/core/timer.c b/sound/core/timer.c +index d104adc75a8b0..71a07c1662f5c 100644 +--- a/sound/core/timer.c ++++ b/sound/core/timer.c +@@ -547,7 +547,7 @@ static int snd_timer_start1(struct snd_timer_instance *timeri, + /* check the actual time for the start tick; + * bail out as error if it's way too low (< 100us) + */ +- if (start) { ++ if (start && !(timer->hw.flags & SNDRV_TIMER_HW_SLAVE)) { + if ((u64)snd_timer_hw_resolution(timer) * ticks < 100000) + return -EINVAL; + } +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 3840565ef8b02..c9d76bca99232 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -583,7 +583,6 @@ static void alc_shutup_pins(struct hda_codec *codec) + switch (codec->core.vendor_id) { + case 0x10ec0236: + case 0x10ec0256: +- case 0x10ec0257: + case 0x19e58326: + case 0x10ec0283: + case 0x10ec0285: +diff --git a/sound/pci/hda/tas2781_hda_i2c.c b/sound/pci/hda/tas2781_hda_i2c.c +index fdee6592c502d..9e88d39eac1e2 100644 +--- a/sound/pci/hda/tas2781_hda_i2c.c ++++ b/sound/pci/hda/tas2781_hda_i2c.c +@@ -2,10 +2,12 @@ + // + // TAS2781 HDA I2C driver + // +-// Copyright 2023 Texas Instruments, Inc. ++// Copyright 2023 - 2024 Texas Instruments, Inc. + // + // Author: Shenghao Ding ++// Current maintainer: Baojun Xu + ++#include + #include + #include + #include +@@ -519,20 +521,22 @@ static void tas2781_apply_calib(struct tasdevice_priv *tas_priv) + static const unsigned char rgno_array[CALIB_MAX] = { + 0x74, 0x0c, 0x14, 0x70, 0x7c, + }; +- unsigned char *data; ++ int offset = 0; + int i, j, rc; ++ __be32 data; + + for (i = 0; i < tas_priv->ndev; i++) { +- data = tas_priv->cali_data.data + +- i * TASDEVICE_SPEAKER_CALIBRATION_SIZE; + for (j = 0; j < CALIB_MAX; j++) { ++ data = cpu_to_be32( ++ *(uint32_t *)&tas_priv->cali_data.data[offset]); + rc = tasdevice_dev_bulk_write(tas_priv, i, + TASDEVICE_REG(0, page_array[j], rgno_array[j]), +- &(data[4 * j]), 4); ++ (unsigned char *)&data, 4); + if (rc < 0) + dev_err(tas_priv->dev, + "chn %d calib %d bulk_wr err = %d\n", + i, j, rc); ++ offset += 4; + } + } + } +diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h +index f13a8d63a019a..aaa6a515d0f8a 100644 +--- a/sound/usb/quirks-table.h ++++ b/sound/usb/quirks-table.h +@@ -273,6 +273,7 @@ YAMAHA_DEVICE(0x105a, NULL), + YAMAHA_DEVICE(0x105b, NULL), + YAMAHA_DEVICE(0x105c, NULL), + YAMAHA_DEVICE(0x105d, NULL), ++YAMAHA_DEVICE(0x1718, "P-125"), + { + USB_DEVICE(0x0499, 0x1503), + .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { +diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c +index ea063a14cdd8f..e7b68c67852e9 100644 +--- a/sound/usb/quirks.c ++++ b/sound/usb/quirks.c +@@ -2221,6 +2221,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { + QUIRK_FLAG_GENERIC_IMPLICIT_FB), + DEVICE_FLG(0x2b53, 0x0031, /* Fiero SC-01 (firmware v1.1.0) */ + QUIRK_FLAG_GENERIC_IMPLICIT_FB), ++ DEVICE_FLG(0x2d95, 0x8021, /* VIVO USB-C-XE710 HEADSET */ ++ QUIRK_FLAG_CTL_MSG_DELAY_1M), + DEVICE_FLG(0x30be, 0x0101, /* Schiit Hel */ + QUIRK_FLAG_IGNORE_CTL_ERROR), + DEVICE_FLG(0x413c, 0xa506, /* Dell AE515 sound bar */ +diff --git a/tools/perf/tests/vmlinux-kallsyms.c b/tools/perf/tests/vmlinux-kallsyms.c +index e30fd55f8e51d..cd3b480d20bd6 100644 +--- a/tools/perf/tests/vmlinux-kallsyms.c ++++ b/tools/perf/tests/vmlinux-kallsyms.c +@@ -26,7 +26,6 @@ static bool is_ignored_symbol(const char *name, char type) + * when --all-symbols is specified so exclude them to get a + * stable symbol list. + */ +- "kallsyms_addresses", + "kallsyms_offsets", + "kallsyms_relative_base", + "kallsyms_num_syms", +diff --git a/tools/testing/selftests/bpf/progs/iters.c b/tools/testing/selftests/bpf/progs/iters.c +index fe65e0952a1e0..179bfe25dbc61 100644 +--- a/tools/testing/selftests/bpf/progs/iters.c ++++ b/tools/testing/selftests/bpf/progs/iters.c +@@ -1434,4 +1434,58 @@ int iter_arr_with_actual_elem_count(const void *ctx) + return sum; + } + ++__u32 upper, select_n, result; ++__u64 global; ++ ++static __noinline bool nest_2(char *str) ++{ ++ /* some insns (including branch insns) to ensure stacksafe() is triggered ++ * in nest_2(). This way, stacksafe() can compare frame associated with nest_1(). ++ */ ++ if (str[0] == 't') ++ return true; ++ if (str[1] == 'e') ++ return true; ++ if (str[2] == 's') ++ return true; ++ if (str[3] == 't') ++ return true; ++ return false; ++} ++ ++static __noinline bool nest_1(int n) ++{ ++ /* case 0: allocate stack, case 1: no allocate stack */ ++ switch (n) { ++ case 0: { ++ char comm[16]; ++ ++ if (bpf_get_current_comm(comm, 16)) ++ return false; ++ return nest_2(comm); ++ } ++ case 1: ++ return nest_2((char *)&global); ++ default: ++ return false; ++ } ++} ++ ++SEC("raw_tp") ++__success ++int iter_subprog_check_stacksafe(const void *ctx) ++{ ++ long i; ++ ++ bpf_for(i, 0, upper) { ++ if (!nest_1(select_n)) { ++ result = 1; ++ return 0; ++ } ++ } ++ ++ result = 2; ++ return 0; ++} ++ + char _license[] SEC("license") = "GPL"; +diff --git a/tools/testing/selftests/core/close_range_test.c b/tools/testing/selftests/core/close_range_test.c +index 991c473e38593..12b4eb9d04347 100644 +--- a/tools/testing/selftests/core/close_range_test.c ++++ b/tools/testing/selftests/core/close_range_test.c +@@ -589,4 +589,39 @@ TEST(close_range_cloexec_unshare_syzbot) + EXPECT_EQ(close(fd3), 0); + } + ++TEST(close_range_bitmap_corruption) ++{ ++ pid_t pid; ++ int status; ++ struct __clone_args args = { ++ .flags = CLONE_FILES, ++ .exit_signal = SIGCHLD, ++ }; ++ ++ /* get the first 128 descriptors open */ ++ for (int i = 2; i < 128; i++) ++ EXPECT_GE(dup2(0, i), 0); ++ ++ /* get descriptor table shared */ ++ pid = sys_clone3(&args, sizeof(args)); ++ ASSERT_GE(pid, 0); ++ ++ if (pid == 0) { ++ /* unshare and truncate descriptor table down to 64 */ ++ if (sys_close_range(64, ~0U, CLOSE_RANGE_UNSHARE)) ++ exit(EXIT_FAILURE); ++ ++ ASSERT_EQ(fcntl(64, F_GETFD), -1); ++ /* ... and verify that the range 64..127 is not ++ stuck "fully used" according to secondary bitmap */ ++ EXPECT_EQ(dup(0), 64) ++ exit(EXIT_FAILURE); ++ exit(EXIT_SUCCESS); ++ } ++ ++ EXPECT_EQ(waitpid(pid, &status, 0), pid); ++ EXPECT_EQ(true, WIFEXITED(status)); ++ EXPECT_EQ(0, WEXITSTATUS(status)); ++} ++ + TEST_HARNESS_MAIN +diff --git a/tools/testing/selftests/drivers/net/mlxsw/ethtool_lanes.sh b/tools/testing/selftests/drivers/net/mlxsw/ethtool_lanes.sh +index 877cd6df94a10..fe905a7f34b3c 100755 +--- a/tools/testing/selftests/drivers/net/mlxsw/ethtool_lanes.sh ++++ b/tools/testing/selftests/drivers/net/mlxsw/ethtool_lanes.sh +@@ -2,6 +2,7 @@ + # SPDX-License-Identifier: GPL-2.0 + + lib_dir=$(dirname $0)/../../../net/forwarding ++ethtool_lib_dir=$(dirname $0)/../hw + + ALL_TESTS=" + autoneg +@@ -11,7 +12,7 @@ ALL_TESTS=" + NUM_NETIFS=2 + : ${TIMEOUT:=30000} # ms + source $lib_dir/lib.sh +-source $lib_dir/ethtool_lib.sh ++source $ethtool_lib_dir/ethtool_lib.sh + + setup_prepare() + { +diff --git a/tools/testing/selftests/mm/Makefile b/tools/testing/selftests/mm/Makefile +index 478cd26f62fdd..1285b82fbd8a2 100644 +--- a/tools/testing/selftests/mm/Makefile ++++ b/tools/testing/selftests/mm/Makefile +@@ -51,7 +51,9 @@ TEST_GEN_FILES += madv_populate + TEST_GEN_FILES += map_fixed_noreplace + TEST_GEN_FILES += map_hugetlb + TEST_GEN_FILES += map_populate ++ifneq (,$(filter $(ARCH),arm64 riscv riscv64 x86 x86_64)) + TEST_GEN_FILES += memfd_secret ++endif + TEST_GEN_FILES += migration + TEST_GEN_FILES += mkdirty + TEST_GEN_FILES += mlock-random-test +diff --git a/tools/testing/selftests/mm/run_vmtests.sh b/tools/testing/selftests/mm/run_vmtests.sh +index 3157204b90476..1c7cdfd29fcc8 100755 +--- a/tools/testing/selftests/mm/run_vmtests.sh ++++ b/tools/testing/selftests/mm/run_vmtests.sh +@@ -367,8 +367,11 @@ CATEGORY="hmm" run_test bash ./test_hmm.sh smoke + # MADV_POPULATE_READ and MADV_POPULATE_WRITE tests + CATEGORY="madv_populate" run_test ./madv_populate + ++if [ -x ./memfd_secret ] ++then + (echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope 2>&1) | tap_prefix + CATEGORY="memfd_secret" run_test ./memfd_secret ++fi + + # KSM KSM_MERGE_TIME_HUGE_PAGES test with size of 100 + CATEGORY="ksm" run_test ./ksm_tests -H -s 100 +diff --git a/tools/testing/selftests/net/af_unix/msg_oob.c b/tools/testing/selftests/net/af_unix/msg_oob.c +index 16d0c172eaebe..535eb2c3d7d1c 100644 +--- a/tools/testing/selftests/net/af_unix/msg_oob.c ++++ b/tools/testing/selftests/net/af_unix/msg_oob.c +@@ -209,7 +209,7 @@ static void __sendpair(struct __test_metadata *_metadata, + + static void __recvpair(struct __test_metadata *_metadata, + FIXTURE_DATA(msg_oob) *self, +- const void *expected_buf, int expected_len, ++ const char *expected_buf, int expected_len, + int buf_len, int flags) + { + int i, ret[2], recv_errno[2], expected_errno = 0; +diff --git a/tools/testing/selftests/net/lib.sh b/tools/testing/selftests/net/lib.sh +index 9155c914c064f..93de05fedd91a 100644 +--- a/tools/testing/selftests/net/lib.sh ++++ b/tools/testing/selftests/net/lib.sh +@@ -128,25 +128,18 @@ slowwait_for_counter() + cleanup_ns() + { + local ns="" +- local errexit=0 + local ret=0 + +- # disable errexit temporary +- if [[ $- =~ "e" ]]; then +- errexit=1 +- set +e +- fi +- + for ns in "$@"; do + [ -z "${ns}" ] && continue +- ip netns delete "${ns}" &> /dev/null ++ ip netns pids "${ns}" 2> /dev/null | xargs -r kill || true ++ ip netns delete "${ns}" &> /dev/null || true + if ! busywait $BUSYWAIT_TIMEOUT ip netns list \| grep -vq "^$ns$" &> /dev/null; then + echo "Warn: Failed to remove namespace $ns" + ret=1 + fi + done + +- [ $errexit -eq 1 ] && set -e + return $ret + } + +diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh +index a3293043c85dd..ed30c0ed55e7a 100755 +--- a/tools/testing/selftests/net/mptcp/mptcp_join.sh ++++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh +@@ -436,9 +436,10 @@ reset_with_tcp_filter() + local ns="${!1}" + local src="${2}" + local target="${3}" ++ local chain="${4:-INPUT}" + + if ! ip netns exec "${ns}" ${iptables} \ +- -A INPUT \ ++ -A "${chain}" \ + -s "${src}" \ + -p tcp \ + -j "${target}"; then +@@ -3058,6 +3059,7 @@ fullmesh_tests() + pm_nl_set_limits $ns1 1 3 + pm_nl_set_limits $ns2 1 3 + pm_nl_add_endpoint $ns1 10.0.2.1 flags signal ++ pm_nl_add_endpoint $ns2 10.0.1.2 flags subflow,fullmesh + fullmesh=1 speed=slow \ + run_tests $ns1 $ns2 10.0.1.1 + chk_join_nr 3 3 3 +@@ -3571,10 +3573,10 @@ endpoint_tests() + mptcp_lib_kill_wait $tests_pid + fi + +- if reset "delete and re-add" && ++ if reset_with_tcp_filter "delete and re-add" ns2 10.0.3.2 REJECT OUTPUT && + mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then +- pm_nl_set_limits $ns1 1 1 +- pm_nl_set_limits $ns2 1 1 ++ pm_nl_set_limits $ns1 0 2 ++ pm_nl_set_limits $ns2 0 2 + pm_nl_add_endpoint $ns2 10.0.2.2 id 2 dev ns2eth2 flags subflow + test_linkfail=4 speed=20 \ + run_tests $ns1 $ns2 10.0.1.1 & +@@ -3591,11 +3593,27 @@ endpoint_tests() + chk_subflow_nr "after delete" 1 + chk_mptcp_info subflows 0 subflows 0 + +- pm_nl_add_endpoint $ns2 10.0.2.2 dev ns2eth2 flags subflow ++ pm_nl_add_endpoint $ns2 10.0.2.2 id 2 dev ns2eth2 flags subflow + wait_mpj $ns2 + chk_subflow_nr "after re-add" 2 + chk_mptcp_info subflows 1 subflows 1 ++ ++ pm_nl_add_endpoint $ns2 10.0.3.2 id 3 flags subflow ++ wait_attempt_fail $ns2 ++ chk_subflow_nr "after new reject" 2 ++ chk_mptcp_info subflows 1 subflows 1 ++ ++ ip netns exec "${ns2}" ${iptables} -D OUTPUT -s "10.0.3.2" -p tcp -j REJECT ++ pm_nl_del_endpoint $ns2 3 10.0.3.2 ++ pm_nl_add_endpoint $ns2 10.0.3.2 id 3 flags subflow ++ wait_mpj $ns2 ++ chk_subflow_nr "after no reject" 3 ++ chk_mptcp_info subflows 2 subflows 2 ++ + mptcp_lib_kill_wait $tests_pid ++ ++ chk_join_nr 3 3 3 ++ chk_rm_nr 1 1 + fi + } + +diff --git a/tools/testing/selftests/net/udpgro.sh b/tools/testing/selftests/net/udpgro.sh +index 11a1ebda564fd..d5ffd8c9172e1 100755 +--- a/tools/testing/selftests/net/udpgro.sh ++++ b/tools/testing/selftests/net/udpgro.sh +@@ -7,8 +7,6 @@ source net_helper.sh + + readonly PEER_NS="ns-peer-$(mktemp -u XXXXXX)" + +-BPF_FILE="xdp_dummy.bpf.o" +- + # set global exit status, but never reset nonzero one. + check_err() + { +@@ -38,7 +36,7 @@ cfg_veth() { + ip -netns "${PEER_NS}" addr add dev veth1 192.168.1.1/24 + ip -netns "${PEER_NS}" addr add dev veth1 2001:db8::1/64 nodad + ip -netns "${PEER_NS}" link set dev veth1 up +- ip -n "${PEER_NS}" link set veth1 xdp object ${BPF_FILE} section xdp ++ ip netns exec "${PEER_NS}" ethtool -K veth1 gro on + } + + run_one() { +@@ -46,17 +44,19 @@ run_one() { + local -r all="$@" + local -r tx_args=${all%rx*} + local -r rx_args=${all#*rx} ++ local ret=0 + + cfg_veth + +- ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 1000 -R 10 ${rx_args} && \ +- echo "ok" || \ +- echo "failed" & ++ ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 1000 -R 10 ${rx_args} & ++ local PID1=$! + + wait_local_port_listen ${PEER_NS} 8000 udp + ./udpgso_bench_tx ${tx_args} +- ret=$? +- wait $(jobs -p) ++ check_err $? ++ wait ${PID1} ++ check_err $? ++ [ "$ret" -eq 0 ] && echo "ok" || echo "failed" + return $ret + } + +@@ -73,6 +73,7 @@ run_one_nat() { + local -r all="$@" + local -r tx_args=${all%rx*} + local -r rx_args=${all#*rx} ++ local ret=0 + + if [[ ${tx_args} = *-4* ]]; then + ipt_cmd=iptables +@@ -93,16 +94,17 @@ run_one_nat() { + # ... so that GRO will match the UDP_GRO enabled socket, but packets + # will land on the 'plain' one + ip netns exec "${PEER_NS}" ./udpgso_bench_rx -G ${family} -b ${addr1} -n 0 & +- pid=$! +- ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 1000 -R 10 ${family} -b ${addr2%/*} ${rx_args} && \ +- echo "ok" || \ +- echo "failed"& ++ local PID1=$! ++ ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 1000 -R 10 ${family} -b ${addr2%/*} ${rx_args} & ++ local PID2=$! + + wait_local_port_listen "${PEER_NS}" 8000 udp + ./udpgso_bench_tx ${tx_args} +- ret=$? +- kill -INT $pid +- wait $(jobs -p) ++ check_err $? ++ kill -INT ${PID1} ++ wait ${PID2} ++ check_err $? ++ [ "$ret" -eq 0 ] && echo "ok" || echo "failed" + return $ret + } + +@@ -111,20 +113,26 @@ run_one_2sock() { + local -r all="$@" + local -r tx_args=${all%rx*} + local -r rx_args=${all#*rx} ++ local ret=0 + + cfg_veth + + ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 1000 -R 10 ${rx_args} -p 12345 & +- ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 2000 -R 10 ${rx_args} && \ +- echo "ok" || \ +- echo "failed" & ++ local PID1=$! ++ ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 2000 -R 10 ${rx_args} & ++ local PID2=$! + + wait_local_port_listen "${PEER_NS}" 12345 udp + ./udpgso_bench_tx ${tx_args} -p 12345 ++ check_err $? + wait_local_port_listen "${PEER_NS}" 8000 udp + ./udpgso_bench_tx ${tx_args} +- ret=$? +- wait $(jobs -p) ++ check_err $? ++ wait ${PID1} ++ check_err $? ++ wait ${PID2} ++ check_err $? ++ [ "$ret" -eq 0 ] && echo "ok" || echo "failed" + return $ret + } + +@@ -196,11 +204,6 @@ run_all() { + return $ret + } + +-if [ ! -f ${BPF_FILE} ]; then +- echo "Missing ${BPF_FILE}. Run 'make' first" +- exit -1 +-fi +- + if [[ $# -eq 0 ]]; then + run_all + elif [[ $1 == "__subprocess" ]]; then +diff --git a/tools/testing/selftests/tc-testing/tdc.py b/tools/testing/selftests/tc-testing/tdc.py +index ee349187636fc..4f255cec0c22e 100755 +--- a/tools/testing/selftests/tc-testing/tdc.py ++++ b/tools/testing/selftests/tc-testing/tdc.py +@@ -143,7 +143,6 @@ class PluginMgr: + except Exception as ee: + print('exception {} in call to pre_case for {} plugin'. + format(ee, pgn_inst.__class__)) +- print('test_ordinal is {}'.format(test_ordinal)) + print('testid is {}'.format(caseinfo['id'])) + raise + +diff --git a/tools/tracing/rtla/src/osnoise_top.c b/tools/tracing/rtla/src/osnoise_top.c +index 07ba55d4ec06f..de33ea5005b6b 100644 +--- a/tools/tracing/rtla/src/osnoise_top.c ++++ b/tools/tracing/rtla/src/osnoise_top.c +@@ -640,8 +640,10 @@ struct osnoise_tool *osnoise_init_top(struct osnoise_top_params *params) + return NULL; + + tool->data = osnoise_alloc_top(nr_cpus); +- if (!tool->data) +- goto out_err; ++ if (!tool->data) { ++ osnoise_destroy_tool(tool); ++ return NULL; ++ } + + tool->params = params; + +@@ -649,11 +651,6 @@ struct osnoise_tool *osnoise_init_top(struct osnoise_top_params *params) + osnoise_top_handler, NULL); + + return tool; +- +-out_err: +- osnoise_free_top(tool->data); +- osnoise_destroy_tool(tool); +- return NULL; + } + + static int stop_tracing;