diff options
author | Mike Pagano <mpagano@gentoo.org> | 2024-02-16 13:59:22 -0500 |
---|---|---|
committer | Mike Pagano <mpagano@gentoo.org> | 2024-02-16 13:59:22 -0500 |
commit | e3eb74c0fafa53cbd3180d3378d1be2f567098f8 (patch) | |
tree | 0a97ddac74828e9cae3a532f9fd0cc8370bbcaee | |
parent | Fix x86 compilation patch (diff) | |
download | linux-patches-e3eb74c0fafa53cbd3180d3378d1be2f567098f8.tar.gz linux-patches-e3eb74c0fafa53cbd3180d3378d1be2f567098f8.tar.bz2 linux-patches-e3eb74c0fafa53cbd3180d3378d1be2f567098f8.zip |
Linux patch 6.6.17
Signed-off-by: Mike Pagano <mpagano@gentoo.org>
-rw-r--r-- | 0000_README | 4 | ||||
-rw-r--r-- | 1016_linux-6.6.17.patch | 6328 |
2 files changed, 6332 insertions, 0 deletions
diff --git a/0000_README b/0000_README index 89d72103..07c4e5f7 100644 --- a/0000_README +++ b/0000_README @@ -107,6 +107,10 @@ Patch: 1015_linux-6.6.16.patch From: https://www.kernel.org Desc: Linux 6.6.16 +Patch: 1016_linux-6.6.17.patch +From: https://www.kernel.org +Desc: Linux 6.6.17 + 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/1016_linux-6.6.17.patch b/1016_linux-6.6.17.patch new file mode 100644 index 00000000..2cbb1724 --- /dev/null +++ b/1016_linux-6.6.17.patch @@ -0,0 +1,6328 @@ +diff --git a/Documentation/process/changes.rst b/Documentation/process/changes.rst +index b48da698d6f25..bb96ca0f774b9 100644 +--- a/Documentation/process/changes.rst ++++ b/Documentation/process/changes.rst +@@ -31,7 +31,7 @@ you probably needn't concern yourself with pcmciautils. + ====================== =============== ======================================== + GNU C 5.1 gcc --version + Clang/LLVM (optional) 11.0.0 clang --version +-Rust (optional) 1.71.1 rustc --version ++Rust (optional) 1.73.0 rustc --version + bindgen (optional) 0.65.1 bindgen --version + GNU make 3.82 make --version + bash 4.2 bash --version +diff --git a/MAINTAINERS b/MAINTAINERS +index dd5de540ec0b5..40312bb550f06 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -23630,6 +23630,7 @@ F: include/xen/arm/swiotlb-xen.h + F: include/xen/swiotlb-xen.h + + XFS FILESYSTEM ++M: Catherine Hoang <catherine.hoang@oracle.com> + M: Chandan Babu R <chandan.babu@oracle.com> + R: Darrick J. Wong <djwong@kernel.org> + L: linux-xfs@vger.kernel.org +diff --git a/Makefile b/Makefile +index ef1c4163c43e2..3330c00c0a471 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 6 + PATCHLEVEL = 6 +-SUBLEVEL = 16 ++SUBLEVEL = 17 + EXTRAVERSION = + NAME = Hurr durr I'ma ninja sloth + +diff --git a/arch/arc/include/asm/cacheflush.h b/arch/arc/include/asm/cacheflush.h +index bd5b1a9a05440..6fc74500a9f52 100644 +--- a/arch/arc/include/asm/cacheflush.h ++++ b/arch/arc/include/asm/cacheflush.h +@@ -40,6 +40,7 @@ void dma_cache_wback(phys_addr_t start, unsigned long sz); + + /* TBD: optimize this */ + #define flush_cache_vmap(start, end) flush_cache_all() ++#define flush_cache_vmap_early(start, end) do { } while (0) + #define flush_cache_vunmap(start, end) flush_cache_all() + + #define flush_cache_dup_mm(mm) /* called on fork (VIVT only) */ +diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h +index f6181f69577fe..1075534b0a2ee 100644 +--- a/arch/arm/include/asm/cacheflush.h ++++ b/arch/arm/include/asm/cacheflush.h +@@ -340,6 +340,8 @@ static inline void flush_cache_vmap(unsigned long start, unsigned long end) + dsb(ishst); + } + ++#define flush_cache_vmap_early(start, end) do { } while (0) ++ + static inline void flush_cache_vunmap(unsigned long start, unsigned long end) + { + if (!cache_is_vipt_nonaliasing()) +diff --git a/arch/csky/abiv1/inc/abi/cacheflush.h b/arch/csky/abiv1/inc/abi/cacheflush.h +index 908d8b0bc4fdc..d011a81575d21 100644 +--- a/arch/csky/abiv1/inc/abi/cacheflush.h ++++ b/arch/csky/abiv1/inc/abi/cacheflush.h +@@ -43,6 +43,7 @@ static inline void flush_anon_page(struct vm_area_struct *vma, + */ + extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end); + #define flush_cache_vmap(start, end) cache_wbinv_all() ++#define flush_cache_vmap_early(start, end) do { } while (0) + #define flush_cache_vunmap(start, end) cache_wbinv_all() + + #define flush_icache_range(start, end) cache_wbinv_range(start, end) +diff --git a/arch/csky/abiv2/inc/abi/cacheflush.h b/arch/csky/abiv2/inc/abi/cacheflush.h +index 40be16907267d..6513ac5d25788 100644 +--- a/arch/csky/abiv2/inc/abi/cacheflush.h ++++ b/arch/csky/abiv2/inc/abi/cacheflush.h +@@ -41,6 +41,7 @@ void flush_icache_mm_range(struct mm_struct *mm, + void flush_icache_deferred(struct mm_struct *mm); + + #define flush_cache_vmap(start, end) do { } while (0) ++#define flush_cache_vmap_early(start, end) do { } while (0) + #define flush_cache_vunmap(start, end) do { } while (0) + + #define copy_to_user_page(vma, page, vaddr, dst, src, len) \ +diff --git a/arch/m68k/include/asm/cacheflush_mm.h b/arch/m68k/include/asm/cacheflush_mm.h +index ed12358c4783b..9a71b0148461a 100644 +--- a/arch/m68k/include/asm/cacheflush_mm.h ++++ b/arch/m68k/include/asm/cacheflush_mm.h +@@ -191,6 +191,7 @@ extern void cache_push_v(unsigned long vaddr, int len); + #define flush_cache_all() __flush_cache_all() + + #define flush_cache_vmap(start, end) flush_cache_all() ++#define flush_cache_vmap_early(start, end) do { } while (0) + #define flush_cache_vunmap(start, end) flush_cache_all() + + static inline void flush_cache_mm(struct mm_struct *mm) +diff --git a/arch/mips/include/asm/cacheflush.h b/arch/mips/include/asm/cacheflush.h +index f36c2519ed976..1f14132b3fc98 100644 +--- a/arch/mips/include/asm/cacheflush.h ++++ b/arch/mips/include/asm/cacheflush.h +@@ -97,6 +97,8 @@ static inline void flush_cache_vmap(unsigned long start, unsigned long end) + __flush_cache_vmap(); + } + ++#define flush_cache_vmap_early(start, end) do { } while (0) ++ + extern void (*__flush_cache_vunmap)(void); + + static inline void flush_cache_vunmap(unsigned long start, unsigned long end) +diff --git a/arch/nios2/include/asm/cacheflush.h b/arch/nios2/include/asm/cacheflush.h +index 348cea0977927..81484a776b333 100644 +--- a/arch/nios2/include/asm/cacheflush.h ++++ b/arch/nios2/include/asm/cacheflush.h +@@ -38,6 +38,7 @@ void flush_icache_pages(struct vm_area_struct *vma, struct page *page, + #define flush_icache_pages flush_icache_pages + + #define flush_cache_vmap(start, end) flush_dcache_range(start, end) ++#define flush_cache_vmap_early(start, end) do { } while (0) + #define flush_cache_vunmap(start, end) flush_dcache_range(start, end) + + extern void copy_to_user_page(struct vm_area_struct *vma, struct page *page, +diff --git a/arch/parisc/include/asm/cacheflush.h b/arch/parisc/include/asm/cacheflush.h +index b4006f2a97052..ba4c05bc24d69 100644 +--- a/arch/parisc/include/asm/cacheflush.h ++++ b/arch/parisc/include/asm/cacheflush.h +@@ -41,6 +41,7 @@ void flush_kernel_vmap_range(void *vaddr, int size); + void invalidate_kernel_vmap_range(void *vaddr, int size); + + #define flush_cache_vmap(start, end) flush_cache_all() ++#define flush_cache_vmap_early(start, end) do { } while (0) + #define flush_cache_vunmap(start, end) flush_cache_all() + + void flush_dcache_folio(struct folio *folio); +diff --git a/arch/riscv/include/asm/cacheflush.h b/arch/riscv/include/asm/cacheflush.h +index 3cb53c4df27cf..a129dac4521d3 100644 +--- a/arch/riscv/include/asm/cacheflush.h ++++ b/arch/riscv/include/asm/cacheflush.h +@@ -37,7 +37,8 @@ static inline void flush_dcache_page(struct page *page) + flush_icache_mm(vma->vm_mm, 0) + + #ifdef CONFIG_64BIT +-#define flush_cache_vmap(start, end) flush_tlb_kernel_range(start, end) ++#define flush_cache_vmap(start, end) flush_tlb_kernel_range(start, end) ++#define flush_cache_vmap_early(start, end) local_flush_tlb_kernel_range(start, end) + #endif + + #ifndef CONFIG_SMP +diff --git a/arch/riscv/include/asm/hugetlb.h b/arch/riscv/include/asm/hugetlb.h +index 4c5b0e929890f..20f9c3ba23414 100644 +--- a/arch/riscv/include/asm/hugetlb.h ++++ b/arch/riscv/include/asm/hugetlb.h +@@ -11,6 +11,9 @@ static inline void arch_clear_hugepage_flags(struct page *page) + } + #define arch_clear_hugepage_flags arch_clear_hugepage_flags + ++bool arch_hugetlb_migration_supported(struct hstate *h); ++#define arch_hugetlb_migration_supported arch_hugetlb_migration_supported ++ + #ifdef CONFIG_RISCV_ISA_SVNAPOT + #define __HAVE_ARCH_HUGE_PTE_CLEAR + void huge_pte_clear(struct mm_struct *mm, unsigned long addr, +diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h +index 5b4a1bf5f4395..b79d0228144f4 100644 +--- a/arch/riscv/include/asm/sbi.h ++++ b/arch/riscv/include/asm/sbi.h +@@ -273,9 +273,6 @@ void sbi_set_timer(uint64_t stime_value); + void sbi_shutdown(void); + void sbi_send_ipi(unsigned int cpu); + int sbi_remote_fence_i(const struct cpumask *cpu_mask); +-int sbi_remote_sfence_vma(const struct cpumask *cpu_mask, +- unsigned long start, +- unsigned long size); + + int sbi_remote_sfence_vma_asid(const struct cpumask *cpu_mask, + unsigned long start, +diff --git a/arch/riscv/include/asm/stacktrace.h b/arch/riscv/include/asm/stacktrace.h +index f7e8ef2418b99..b1495a7e06ce6 100644 +--- a/arch/riscv/include/asm/stacktrace.h ++++ b/arch/riscv/include/asm/stacktrace.h +@@ -21,4 +21,9 @@ static inline bool on_thread_stack(void) + return !(((unsigned long)(current->stack) ^ current_stack_pointer) & ~(THREAD_SIZE - 1)); + } + ++ ++#ifdef CONFIG_VMAP_STACK ++DECLARE_PER_CPU(unsigned long [OVERFLOW_STACK_SIZE/sizeof(long)], overflow_stack); ++#endif /* CONFIG_VMAP_STACK */ ++ + #endif /* _ASM_RISCV_STACKTRACE_H */ +diff --git a/arch/riscv/include/asm/tlb.h b/arch/riscv/include/asm/tlb.h +index 120bcf2ed8a87..50b63b5c15bd8 100644 +--- a/arch/riscv/include/asm/tlb.h ++++ b/arch/riscv/include/asm/tlb.h +@@ -15,7 +15,13 @@ static void tlb_flush(struct mmu_gather *tlb); + + static inline void tlb_flush(struct mmu_gather *tlb) + { +- flush_tlb_mm(tlb->mm); ++#ifdef CONFIG_MMU ++ if (tlb->fullmm || tlb->need_flush_all || tlb->freed_tables) ++ flush_tlb_mm(tlb->mm); ++ else ++ flush_tlb_mm_range(tlb->mm, tlb->start, tlb->end, ++ tlb_get_unmap_size(tlb)); ++#endif + } + + #endif /* _ASM_RISCV_TLB_H */ +diff --git a/arch/riscv/include/asm/tlbflush.h b/arch/riscv/include/asm/tlbflush.h +index a09196f8de688..51664ae4852e7 100644 +--- a/arch/riscv/include/asm/tlbflush.h ++++ b/arch/riscv/include/asm/tlbflush.h +@@ -11,6 +11,9 @@ + #include <asm/smp.h> + #include <asm/errata_list.h> + ++#define FLUSH_TLB_MAX_SIZE ((unsigned long)-1) ++#define FLUSH_TLB_NO_ASID ((unsigned long)-1) ++ + #ifdef CONFIG_MMU + extern unsigned long asid_mask; + +@@ -32,9 +35,13 @@ static inline void local_flush_tlb_page(unsigned long addr) + #if defined(CONFIG_SMP) && defined(CONFIG_MMU) + void flush_tlb_all(void); + void flush_tlb_mm(struct mm_struct *mm); ++void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start, ++ unsigned long end, unsigned int page_size); + void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr); + void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, + unsigned long end); ++void flush_tlb_kernel_range(unsigned long start, unsigned long end); ++void local_flush_tlb_kernel_range(unsigned long start, unsigned long end); + #ifdef CONFIG_TRANSPARENT_HUGEPAGE + #define __HAVE_ARCH_FLUSH_PMD_TLB_RANGE + void flush_pmd_tlb_range(struct vm_area_struct *vma, unsigned long start, +@@ -51,14 +58,16 @@ static inline void flush_tlb_range(struct vm_area_struct *vma, + local_flush_tlb_all(); + } + +-#define flush_tlb_mm(mm) flush_tlb_all() +-#endif /* !CONFIG_SMP || !CONFIG_MMU */ +- + /* Flush a range of kernel pages */ + static inline void flush_tlb_kernel_range(unsigned long start, + unsigned long end) + { +- flush_tlb_all(); ++ local_flush_tlb_all(); + } + ++#define flush_tlb_mm(mm) flush_tlb_all() ++#define flush_tlb_mm_range(mm, start, end, page_size) flush_tlb_all() ++#define local_flush_tlb_kernel_range(start, end) flush_tlb_all() ++#endif /* !CONFIG_SMP || !CONFIG_MMU */ ++ + #endif /* _ASM_RISCV_TLBFLUSH_H */ +diff --git a/arch/riscv/kernel/sbi.c b/arch/riscv/kernel/sbi.c +index c672c8ba9a2a6..5a62ed1da4533 100644 +--- a/arch/riscv/kernel/sbi.c ++++ b/arch/riscv/kernel/sbi.c +@@ -11,6 +11,7 @@ + #include <linux/reboot.h> + #include <asm/sbi.h> + #include <asm/smp.h> ++#include <asm/tlbflush.h> + + /* default SBI version is 0.1 */ + unsigned long sbi_spec_version __ro_after_init = SBI_SPEC_VERSION_DEFAULT; +@@ -376,32 +377,15 @@ int sbi_remote_fence_i(const struct cpumask *cpu_mask) + } + EXPORT_SYMBOL(sbi_remote_fence_i); + +-/** +- * sbi_remote_sfence_vma() - Execute SFENCE.VMA instructions on given remote +- * harts for the specified virtual address range. +- * @cpu_mask: A cpu mask containing all the target harts. +- * @start: Start of the virtual address +- * @size: Total size of the virtual address range. +- * +- * Return: 0 on success, appropriate linux error code otherwise. +- */ +-int sbi_remote_sfence_vma(const struct cpumask *cpu_mask, +- unsigned long start, +- unsigned long size) +-{ +- return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_SFENCE_VMA, +- cpu_mask, start, size, 0, 0); +-} +-EXPORT_SYMBOL(sbi_remote_sfence_vma); +- + /** + * sbi_remote_sfence_vma_asid() - Execute SFENCE.VMA instructions on given +- * remote harts for a virtual address range belonging to a specific ASID. ++ * remote harts for a virtual address range belonging to a specific ASID or not. + * + * @cpu_mask: A cpu mask containing all the target harts. + * @start: Start of the virtual address + * @size: Total size of the virtual address range. +- * @asid: The value of address space identifier (ASID). ++ * @asid: The value of address space identifier (ASID), or FLUSH_TLB_NO_ASID ++ * for flushing all address spaces. + * + * Return: 0 on success, appropriate linux error code otherwise. + */ +@@ -410,8 +394,12 @@ int sbi_remote_sfence_vma_asid(const struct cpumask *cpu_mask, + unsigned long size, + unsigned long asid) + { +- return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID, +- cpu_mask, start, size, asid, 0); ++ if (asid == FLUSH_TLB_NO_ASID) ++ return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_SFENCE_VMA, ++ cpu_mask, start, size, 0, 0); ++ else ++ return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID, ++ cpu_mask, start, size, asid, 0); + } + EXPORT_SYMBOL(sbi_remote_sfence_vma_asid); + +diff --git a/arch/riscv/mm/hugetlbpage.c b/arch/riscv/mm/hugetlbpage.c +index b52f0210481fa..e7b69281875b2 100644 +--- a/arch/riscv/mm/hugetlbpage.c ++++ b/arch/riscv/mm/hugetlbpage.c +@@ -125,6 +125,26 @@ pte_t *huge_pte_offset(struct mm_struct *mm, + return pte; + } + ++unsigned long hugetlb_mask_last_page(struct hstate *h) ++{ ++ unsigned long hp_size = huge_page_size(h); ++ ++ switch (hp_size) { ++#ifndef __PAGETABLE_PMD_FOLDED ++ case PUD_SIZE: ++ return P4D_SIZE - PUD_SIZE; ++#endif ++ case PMD_SIZE: ++ return PUD_SIZE - PMD_SIZE; ++ case napot_cont_size(NAPOT_CONT64KB_ORDER): ++ return PMD_SIZE - napot_cont_size(NAPOT_CONT64KB_ORDER); ++ default: ++ break; ++ } ++ ++ return 0UL; ++} ++ + static pte_t get_clear_contig(struct mm_struct *mm, + unsigned long addr, + pte_t *ptep, +@@ -177,13 +197,36 @@ pte_t arch_make_huge_pte(pte_t entry, unsigned int shift, vm_flags_t flags) + return entry; + } + ++static void clear_flush(struct mm_struct *mm, ++ unsigned long addr, ++ pte_t *ptep, ++ unsigned long pgsize, ++ unsigned long ncontig) ++{ ++ struct vm_area_struct vma = TLB_FLUSH_VMA(mm, 0); ++ unsigned long i, saddr = addr; ++ ++ for (i = 0; i < ncontig; i++, addr += pgsize, ptep++) ++ ptep_get_and_clear(mm, addr, ptep); ++ ++ flush_tlb_range(&vma, saddr, addr); ++} ++ ++/* ++ * When dealing with NAPOT mappings, the privileged specification indicates that ++ * "if an update needs to be made, the OS generally should first mark all of the ++ * PTEs invalid, then issue SFENCE.VMA instruction(s) covering all 4 KiB regions ++ * within the range, [...] then update the PTE(s), as described in Section ++ * 4.2.1.". That's the equivalent of the Break-Before-Make approach used by ++ * arm64. ++ */ + void set_huge_pte_at(struct mm_struct *mm, + unsigned long addr, + pte_t *ptep, + pte_t pte, + unsigned long sz) + { +- unsigned long hugepage_shift; ++ unsigned long hugepage_shift, pgsize; + int i, pte_num; + + if (sz >= PGDIR_SIZE) +@@ -198,7 +241,22 @@ void set_huge_pte_at(struct mm_struct *mm, + hugepage_shift = PAGE_SHIFT; + + pte_num = sz >> hugepage_shift; +- for (i = 0; i < pte_num; i++, ptep++, addr += (1 << hugepage_shift)) ++ pgsize = 1 << hugepage_shift; ++ ++ if (!pte_present(pte)) { ++ for (i = 0; i < pte_num; i++, ptep++, addr += pgsize) ++ set_ptes(mm, addr, ptep, pte, 1); ++ return; ++ } ++ ++ if (!pte_napot(pte)) { ++ set_ptes(mm, addr, ptep, pte, 1); ++ return; ++ } ++ ++ clear_flush(mm, addr, ptep, pgsize, pte_num); ++ ++ for (i = 0; i < pte_num; i++, ptep++, addr += pgsize) + set_pte_at(mm, addr, ptep, pte); + } + +@@ -306,7 +364,7 @@ void huge_pte_clear(struct mm_struct *mm, + pte_clear(mm, addr, ptep); + } + +-static __init bool is_napot_size(unsigned long size) ++static bool is_napot_size(unsigned long size) + { + unsigned long order; + +@@ -334,7 +392,7 @@ arch_initcall(napot_hugetlbpages_init); + + #else + +-static __init bool is_napot_size(unsigned long size) ++static bool is_napot_size(unsigned long size) + { + return false; + } +@@ -351,7 +409,7 @@ int pmd_huge(pmd_t pmd) + return pmd_leaf(pmd); + } + +-bool __init arch_hugetlb_valid_size(unsigned long size) ++static bool __hugetlb_valid_size(unsigned long size) + { + if (size == HPAGE_SIZE) + return true; +@@ -363,6 +421,16 @@ bool __init arch_hugetlb_valid_size(unsigned long size) + return false; + } + ++bool __init arch_hugetlb_valid_size(unsigned long size) ++{ ++ return __hugetlb_valid_size(size); ++} ++ ++bool arch_hugetlb_migration_supported(struct hstate *h) ++{ ++ return __hugetlb_valid_size(huge_page_size(h)); ++} ++ + #ifdef CONFIG_CONTIG_ALLOC + static __init int gigantic_pages_init(void) + { +diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c +index e71dd19ac8018..b50faa232b5e9 100644 +--- a/arch/riscv/mm/init.c ++++ b/arch/riscv/mm/init.c +@@ -1502,6 +1502,10 @@ void __init misc_mem_init(void) + early_memtest(min_low_pfn << PAGE_SHIFT, max_low_pfn << PAGE_SHIFT); + arch_numa_init(); + sparse_init(); ++#ifdef CONFIG_SPARSEMEM_VMEMMAP ++ /* The entire VMEMMAP region has been populated. Flush TLB for this region */ ++ local_flush_tlb_kernel_range(VMEMMAP_START, VMEMMAP_END); ++#endif + zone_sizes_init(); + reserve_crashkernel(); + memblock_dump_all(); +diff --git a/arch/riscv/mm/tlbflush.c b/arch/riscv/mm/tlbflush.c +index 77be59aadc735..bdee5de918e06 100644 +--- a/arch/riscv/mm/tlbflush.c ++++ b/arch/riscv/mm/tlbflush.c +@@ -8,28 +8,50 @@ + + static inline void local_flush_tlb_all_asid(unsigned long asid) + { +- __asm__ __volatile__ ("sfence.vma x0, %0" +- : +- : "r" (asid) +- : "memory"); ++ if (asid != FLUSH_TLB_NO_ASID) ++ __asm__ __volatile__ ("sfence.vma x0, %0" ++ : ++ : "r" (asid) ++ : "memory"); ++ else ++ local_flush_tlb_all(); + } + + static inline void local_flush_tlb_page_asid(unsigned long addr, + unsigned long asid) + { +- __asm__ __volatile__ ("sfence.vma %0, %1" +- : +- : "r" (addr), "r" (asid) +- : "memory"); ++ if (asid != FLUSH_TLB_NO_ASID) ++ __asm__ __volatile__ ("sfence.vma %0, %1" ++ : ++ : "r" (addr), "r" (asid) ++ : "memory"); ++ else ++ local_flush_tlb_page(addr); + } + +-static inline void local_flush_tlb_range(unsigned long start, +- unsigned long size, unsigned long stride) ++/* ++ * Flush entire TLB if number of entries to be flushed is greater ++ * than the threshold below. ++ */ ++static unsigned long tlb_flush_all_threshold __read_mostly = 64; ++ ++static void local_flush_tlb_range_threshold_asid(unsigned long start, ++ unsigned long size, ++ unsigned long stride, ++ unsigned long asid) + { +- if (size <= stride) +- local_flush_tlb_page(start); +- else +- local_flush_tlb_all(); ++ unsigned long nr_ptes_in_range = DIV_ROUND_UP(size, stride); ++ int i; ++ ++ if (nr_ptes_in_range > tlb_flush_all_threshold) { ++ local_flush_tlb_all_asid(asid); ++ return; ++ } ++ ++ for (i = 0; i < nr_ptes_in_range; ++i) { ++ local_flush_tlb_page_asid(start, asid); ++ start += stride; ++ } + } + + static inline void local_flush_tlb_range_asid(unsigned long start, +@@ -37,8 +59,16 @@ static inline void local_flush_tlb_range_asid(unsigned long start, + { + if (size <= stride) + local_flush_tlb_page_asid(start, asid); +- else ++ else if (size == FLUSH_TLB_MAX_SIZE) + local_flush_tlb_all_asid(asid); ++ else ++ local_flush_tlb_range_threshold_asid(start, size, stride, asid); ++} ++ ++/* Flush a range of kernel pages without broadcasting */ ++void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) ++{ ++ local_flush_tlb_range_asid(start, end - start, PAGE_SIZE, FLUSH_TLB_NO_ASID); + } + + static void __ipi_flush_tlb_all(void *info) +@@ -51,7 +81,7 @@ void flush_tlb_all(void) + if (riscv_use_ipi_for_rfence()) + on_each_cpu(__ipi_flush_tlb_all, NULL, 1); + else +- sbi_remote_sfence_vma(NULL, 0, -1); ++ sbi_remote_sfence_vma_asid(NULL, 0, FLUSH_TLB_MAX_SIZE, FLUSH_TLB_NO_ASID); + } + + struct flush_tlb_range_data { +@@ -68,68 +98,62 @@ static void __ipi_flush_tlb_range_asid(void *info) + local_flush_tlb_range_asid(d->start, d->size, d->stride, d->asid); + } + +-static void __ipi_flush_tlb_range(void *info) +-{ +- struct flush_tlb_range_data *d = info; +- +- local_flush_tlb_range(d->start, d->size, d->stride); +-} +- + static void __flush_tlb_range(struct mm_struct *mm, unsigned long start, + unsigned long size, unsigned long stride) + { + struct flush_tlb_range_data ftd; +- struct cpumask *cmask = mm_cpumask(mm); +- unsigned int cpuid; ++ const struct cpumask *cmask; ++ unsigned long asid = FLUSH_TLB_NO_ASID; + bool broadcast; + +- if (cpumask_empty(cmask)) +- return; ++ if (mm) { ++ unsigned int cpuid; ++ ++ cmask = mm_cpumask(mm); ++ if (cpumask_empty(cmask)) ++ return; ++ ++ cpuid = get_cpu(); ++ /* check if the tlbflush needs to be sent to other CPUs */ ++ broadcast = cpumask_any_but(cmask, cpuid) < nr_cpu_ids; ++ ++ if (static_branch_unlikely(&use_asid_allocator)) ++ asid = atomic_long_read(&mm->context.id) & asid_mask; ++ } else { ++ cmask = cpu_online_mask; ++ broadcast = true; ++ } + +- cpuid = get_cpu(); +- /* check if the tlbflush needs to be sent to other CPUs */ +- broadcast = cpumask_any_but(cmask, cpuid) < nr_cpu_ids; +- if (static_branch_unlikely(&use_asid_allocator)) { +- unsigned long asid = atomic_long_read(&mm->context.id) & asid_mask; +- +- if (broadcast) { +- if (riscv_use_ipi_for_rfence()) { +- ftd.asid = asid; +- ftd.start = start; +- ftd.size = size; +- ftd.stride = stride; +- on_each_cpu_mask(cmask, +- __ipi_flush_tlb_range_asid, +- &ftd, 1); +- } else +- sbi_remote_sfence_vma_asid(cmask, +- start, size, asid); +- } else { +- local_flush_tlb_range_asid(start, size, stride, asid); +- } ++ if (broadcast) { ++ if (riscv_use_ipi_for_rfence()) { ++ ftd.asid = asid; ++ ftd.start = start; ++ ftd.size = size; ++ ftd.stride = stride; ++ on_each_cpu_mask(cmask, ++ __ipi_flush_tlb_range_asid, ++ &ftd, 1); ++ } else ++ sbi_remote_sfence_vma_asid(cmask, ++ start, size, asid); + } else { +- if (broadcast) { +- if (riscv_use_ipi_for_rfence()) { +- ftd.asid = 0; +- ftd.start = start; +- ftd.size = size; +- ftd.stride = stride; +- on_each_cpu_mask(cmask, +- __ipi_flush_tlb_range, +- &ftd, 1); +- } else +- sbi_remote_sfence_vma(cmask, start, size); +- } else { +- local_flush_tlb_range(start, size, stride); +- } ++ local_flush_tlb_range_asid(start, size, stride, asid); + } + +- put_cpu(); ++ if (mm) ++ put_cpu(); + } + + void flush_tlb_mm(struct mm_struct *mm) + { +- __flush_tlb_range(mm, 0, -1, PAGE_SIZE); ++ __flush_tlb_range(mm, 0, FLUSH_TLB_MAX_SIZE, PAGE_SIZE); ++} ++ ++void flush_tlb_mm_range(struct mm_struct *mm, ++ unsigned long start, unsigned long end, ++ unsigned int page_size) ++{ ++ __flush_tlb_range(mm, start, end - start, page_size); + } + + void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr) +@@ -142,6 +166,12 @@ void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, + { + __flush_tlb_range(vma->vm_mm, start, end - start, PAGE_SIZE); + } ++ ++void flush_tlb_kernel_range(unsigned long start, unsigned long end) ++{ ++ __flush_tlb_range(NULL, start, end - start, PAGE_SIZE); ++} ++ + #ifdef CONFIG_TRANSPARENT_HUGEPAGE + void flush_pmd_tlb_range(struct vm_area_struct *vma, unsigned long start, + unsigned long end) +diff --git a/arch/sh/include/asm/cacheflush.h b/arch/sh/include/asm/cacheflush.h +index 878b6b551bd2d..51112f54552b3 100644 +--- a/arch/sh/include/asm/cacheflush.h ++++ b/arch/sh/include/asm/cacheflush.h +@@ -90,6 +90,7 @@ extern void copy_from_user_page(struct vm_area_struct *vma, + unsigned long len); + + #define flush_cache_vmap(start, end) local_flush_cache_all(NULL) ++#define flush_cache_vmap_early(start, end) do { } while (0) + #define flush_cache_vunmap(start, end) local_flush_cache_all(NULL) + + #define flush_dcache_mmap_lock(mapping) do { } while (0) +diff --git a/arch/sparc/include/asm/cacheflush_32.h b/arch/sparc/include/asm/cacheflush_32.h +index f3b7270bf71b2..9fee0ccfccb8e 100644 +--- a/arch/sparc/include/asm/cacheflush_32.h ++++ b/arch/sparc/include/asm/cacheflush_32.h +@@ -48,6 +48,7 @@ static inline void flush_dcache_page(struct page *page) + #define flush_dcache_mmap_unlock(mapping) do { } while (0) + + #define flush_cache_vmap(start, end) flush_cache_all() ++#define flush_cache_vmap_early(start, end) do { } while (0) + #define flush_cache_vunmap(start, end) flush_cache_all() + + /* When a context switch happens we must flush all user windows so that +diff --git a/arch/sparc/include/asm/cacheflush_64.h b/arch/sparc/include/asm/cacheflush_64.h +index 0e879004efff1..2b1261b77ecd1 100644 +--- a/arch/sparc/include/asm/cacheflush_64.h ++++ b/arch/sparc/include/asm/cacheflush_64.h +@@ -75,6 +75,7 @@ void flush_ptrace_access(struct vm_area_struct *, struct page *, + #define flush_dcache_mmap_unlock(mapping) do { } while (0) + + #define flush_cache_vmap(start, end) do { } while (0) ++#define flush_cache_vmap_early(start, end) do { } while (0) + #define flush_cache_vunmap(start, end) do { } while (0) + + #endif /* !__ASSEMBLY__ */ +diff --git a/arch/x86/lib/getuser.S b/arch/x86/lib/getuser.S +index 9c63713477bbb..f6aad480febd3 100644 +--- a/arch/x86/lib/getuser.S ++++ b/arch/x86/lib/getuser.S +@@ -163,23 +163,23 @@ SYM_CODE_END(__get_user_8_handle_exception) + #endif + + /* get_user */ +- _ASM_EXTABLE(1b, __get_user_handle_exception) +- _ASM_EXTABLE(2b, __get_user_handle_exception) +- _ASM_EXTABLE(3b, __get_user_handle_exception) ++ _ASM_EXTABLE_UA(1b, __get_user_handle_exception) ++ _ASM_EXTABLE_UA(2b, __get_user_handle_exception) ++ _ASM_EXTABLE_UA(3b, __get_user_handle_exception) + #ifdef CONFIG_X86_64 +- _ASM_EXTABLE(4b, __get_user_handle_exception) ++ _ASM_EXTABLE_UA(4b, __get_user_handle_exception) + #else +- _ASM_EXTABLE(4b, __get_user_8_handle_exception) +- _ASM_EXTABLE(5b, __get_user_8_handle_exception) ++ _ASM_EXTABLE_UA(4b, __get_user_8_handle_exception) ++ _ASM_EXTABLE_UA(5b, __get_user_8_handle_exception) + #endif + + /* __get_user */ +- _ASM_EXTABLE(6b, __get_user_handle_exception) +- _ASM_EXTABLE(7b, __get_user_handle_exception) +- _ASM_EXTABLE(8b, __get_user_handle_exception) ++ _ASM_EXTABLE_UA(6b, __get_user_handle_exception) ++ _ASM_EXTABLE_UA(7b, __get_user_handle_exception) ++ _ASM_EXTABLE_UA(8b, __get_user_handle_exception) + #ifdef CONFIG_X86_64 +- _ASM_EXTABLE(9b, __get_user_handle_exception) ++ _ASM_EXTABLE_UA(9b, __get_user_handle_exception) + #else +- _ASM_EXTABLE(9b, __get_user_8_handle_exception) +- _ASM_EXTABLE(10b, __get_user_8_handle_exception) ++ _ASM_EXTABLE_UA(9b, __get_user_8_handle_exception) ++ _ASM_EXTABLE_UA(10b, __get_user_8_handle_exception) + #endif +diff --git a/arch/x86/lib/putuser.S b/arch/x86/lib/putuser.S +index 235bbda6fc823..512dc58c938b8 100644 +--- a/arch/x86/lib/putuser.S ++++ b/arch/x86/lib/putuser.S +@@ -134,15 +134,15 @@ SYM_CODE_START_LOCAL(__put_user_handle_exception) + RET + SYM_CODE_END(__put_user_handle_exception) + +- _ASM_EXTABLE(1b, __put_user_handle_exception) +- _ASM_EXTABLE(2b, __put_user_handle_exception) +- _ASM_EXTABLE(3b, __put_user_handle_exception) +- _ASM_EXTABLE(4b, __put_user_handle_exception) +- _ASM_EXTABLE(5b, __put_user_handle_exception) +- _ASM_EXTABLE(6b, __put_user_handle_exception) +- _ASM_EXTABLE(7b, __put_user_handle_exception) +- _ASM_EXTABLE(9b, __put_user_handle_exception) ++ _ASM_EXTABLE_UA(1b, __put_user_handle_exception) ++ _ASM_EXTABLE_UA(2b, __put_user_handle_exception) ++ _ASM_EXTABLE_UA(3b, __put_user_handle_exception) ++ _ASM_EXTABLE_UA(4b, __put_user_handle_exception) ++ _ASM_EXTABLE_UA(5b, __put_user_handle_exception) ++ _ASM_EXTABLE_UA(6b, __put_user_handle_exception) ++ _ASM_EXTABLE_UA(7b, __put_user_handle_exception) ++ _ASM_EXTABLE_UA(9b, __put_user_handle_exception) + #ifdef CONFIG_X86_32 +- _ASM_EXTABLE(8b, __put_user_handle_exception) +- _ASM_EXTABLE(10b, __put_user_handle_exception) ++ _ASM_EXTABLE_UA(8b, __put_user_handle_exception) ++ _ASM_EXTABLE_UA(10b, __put_user_handle_exception) + #endif +diff --git a/arch/xtensa/include/asm/cacheflush.h b/arch/xtensa/include/asm/cacheflush.h +index 785a00ce83c11..38bcecb0e457d 100644 +--- a/arch/xtensa/include/asm/cacheflush.h ++++ b/arch/xtensa/include/asm/cacheflush.h +@@ -116,8 +116,9 @@ void flush_cache_page(struct vm_area_struct*, + #define flush_cache_mm(mm) flush_cache_all() + #define flush_cache_dup_mm(mm) flush_cache_mm(mm) + +-#define flush_cache_vmap(start,end) flush_cache_all() +-#define flush_cache_vunmap(start,end) flush_cache_all() ++#define flush_cache_vmap(start,end) flush_cache_all() ++#define flush_cache_vmap_early(start,end) do { } while (0) ++#define flush_cache_vunmap(start,end) flush_cache_all() + + void flush_dcache_folio(struct folio *folio); + #define flush_dcache_folio flush_dcache_folio +@@ -140,6 +141,7 @@ void local_flush_cache_page(struct vm_area_struct *vma, + #define flush_cache_dup_mm(mm) do { } while (0) + + #define flush_cache_vmap(start,end) do { } while (0) ++#define flush_cache_vmap_early(start,end) do { } while (0) + #define flush_cache_vunmap(start,end) do { } while (0) + + #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0 +diff --git a/block/blk-iocost.c b/block/blk-iocost.c +index 089fcb9cfce37..7ee8d85c2c68d 100644 +--- a/block/blk-iocost.c ++++ b/block/blk-iocost.c +@@ -1353,6 +1353,13 @@ static bool iocg_kick_delay(struct ioc_gq *iocg, struct ioc_now *now) + + lockdep_assert_held(&iocg->waitq.lock); + ++ /* ++ * If the delay is set by another CPU, we may be in the past. No need to ++ * change anything if so. This avoids decay calculation underflow. ++ */ ++ if (time_before64(now->now, iocg->delay_at)) ++ return false; ++ + /* calculate the current delay in effect - 1/2 every second */ + tdelta = now->now - iocg->delay_at; + if (iocg->delay) +diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c +index e327a0229dc17..e7f713cd70d3f 100644 +--- a/drivers/atm/idt77252.c ++++ b/drivers/atm/idt77252.c +@@ -2930,6 +2930,8 @@ open_card_ubr0(struct idt77252_dev *card) + vc->scq = alloc_scq(card, vc->class); + if (!vc->scq) { + printk("%s: can't get SCQ.\n", card->name); ++ kfree(card->vcs[0]); ++ card->vcs[0] = NULL; + return -ENOMEM; + } + +diff --git a/drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c b/drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c +index a42a37634881b..da91bc9a8e6f0 100644 +--- a/drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c ++++ b/drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c +@@ -38,15 +38,17 @@ static int dpaa2_qdma_alloc_chan_resources(struct dma_chan *chan) + if (!dpaa2_chan->fd_pool) + goto err; + +- dpaa2_chan->fl_pool = dma_pool_create("fl_pool", dev, +- sizeof(struct dpaa2_fl_entry), +- sizeof(struct dpaa2_fl_entry), 0); ++ dpaa2_chan->fl_pool = ++ dma_pool_create("fl_pool", dev, ++ sizeof(struct dpaa2_fl_entry) * 3, ++ sizeof(struct dpaa2_fl_entry), 0); ++ + if (!dpaa2_chan->fl_pool) + goto err_fd; + + dpaa2_chan->sdd_pool = + dma_pool_create("sdd_pool", dev, +- sizeof(struct dpaa2_qdma_sd_d), ++ sizeof(struct dpaa2_qdma_sd_d) * 2, + sizeof(struct dpaa2_qdma_sd_d), 0); + if (!dpaa2_chan->sdd_pool) + goto err_fl; +diff --git a/drivers/dma/fsl-qdma.c b/drivers/dma/fsl-qdma.c +index a8cc8a4bc6102..e4c293b76e050 100644 +--- a/drivers/dma/fsl-qdma.c ++++ b/drivers/dma/fsl-qdma.c +@@ -514,11 +514,11 @@ static struct fsl_qdma_queue + queue_temp = queue_head + i + (j * queue_num); + + queue_temp->cq = +- dma_alloc_coherent(&pdev->dev, +- sizeof(struct fsl_qdma_format) * +- queue_size[i], +- &queue_temp->bus_addr, +- GFP_KERNEL); ++ dmam_alloc_coherent(&pdev->dev, ++ sizeof(struct fsl_qdma_format) * ++ queue_size[i], ++ &queue_temp->bus_addr, ++ GFP_KERNEL); + if (!queue_temp->cq) + return NULL; + queue_temp->block_base = fsl_qdma->block_base + +@@ -563,11 +563,11 @@ static struct fsl_qdma_queue + /* + * Buffer for queue command + */ +- status_head->cq = dma_alloc_coherent(&pdev->dev, +- sizeof(struct fsl_qdma_format) * +- status_size, +- &status_head->bus_addr, +- GFP_KERNEL); ++ status_head->cq = dmam_alloc_coherent(&pdev->dev, ++ sizeof(struct fsl_qdma_format) * ++ status_size, ++ &status_head->bus_addr, ++ GFP_KERNEL); + if (!status_head->cq) { + devm_kfree(&pdev->dev, status_head); + return NULL; +@@ -1268,8 +1268,6 @@ static void fsl_qdma_cleanup_vchan(struct dma_device *dmadev) + + static int fsl_qdma_remove(struct platform_device *pdev) + { +- int i; +- struct fsl_qdma_queue *status; + struct device_node *np = pdev->dev.of_node; + struct fsl_qdma_engine *fsl_qdma = platform_get_drvdata(pdev); + +@@ -1278,11 +1276,6 @@ static int fsl_qdma_remove(struct platform_device *pdev) + of_dma_controller_free(np); + dma_async_device_unregister(&fsl_qdma->dma_dev); + +- for (i = 0; i < fsl_qdma->block_number; i++) { +- status = fsl_qdma->status[i]; +- dma_free_coherent(&pdev->dev, sizeof(struct fsl_qdma_format) * +- status->n_cq, status->cq, status->bus_addr); +- } + return 0; + } + +diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c +index 30fd2f386f36a..037f1408e7983 100644 +--- a/drivers/dma/ti/k3-udma.c ++++ b/drivers/dma/ti/k3-udma.c +@@ -3968,6 +3968,7 @@ static void udma_desc_pre_callback(struct virt_dma_chan *vc, + { + struct udma_chan *uc = to_udma_chan(&vc->chan); + struct udma_desc *d; ++ u8 status; + + if (!vd) + return; +@@ -3977,12 +3978,12 @@ static void udma_desc_pre_callback(struct virt_dma_chan *vc, + if (d->metadata_size) + udma_fetch_epib(uc, d); + +- /* Provide residue information for the client */ + if (result) { + void *desc_vaddr = udma_curr_cppi5_desc_vaddr(d, d->desc_idx); + + if (cppi5_desc_get_type(desc_vaddr) == + CPPI5_INFO0_DESC_TYPE_VAL_HOST) { ++ /* Provide residue information for the client */ + result->residue = d->residue - + cppi5_hdesc_get_pktlen(desc_vaddr); + if (result->residue) +@@ -3991,7 +3992,12 @@ static void udma_desc_pre_callback(struct virt_dma_chan *vc, + result->result = DMA_TRANS_NOERROR; + } else { + result->residue = 0; +- result->result = DMA_TRANS_NOERROR; ++ /* Propagate TR Response errors to the client */ ++ status = d->hwdesc[0].tr_resp_base->status; ++ if (status) ++ result->result = DMA_TRANS_ABORTED; ++ else ++ result->result = DMA_TRANS_NOERROR; + } + } + } +diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h +index 212687c30d79c..c04b82ea40f21 100644 +--- a/drivers/firmware/efi/libstub/efistub.h ++++ b/drivers/firmware/efi/libstub/efistub.h +@@ -956,7 +956,8 @@ efi_status_t efi_get_random_bytes(unsigned long size, u8 *out); + + efi_status_t efi_random_alloc(unsigned long size, unsigned long align, + unsigned long *addr, unsigned long random_seed, +- int memory_type, unsigned long alloc_limit); ++ int memory_type, unsigned long alloc_min, ++ unsigned long alloc_max); + + efi_status_t efi_random_get_seed(void); + +diff --git a/drivers/firmware/efi/libstub/kaslr.c b/drivers/firmware/efi/libstub/kaslr.c +index 62d63f7a2645b..1a9808012abd3 100644 +--- a/drivers/firmware/efi/libstub/kaslr.c ++++ b/drivers/firmware/efi/libstub/kaslr.c +@@ -119,7 +119,7 @@ efi_status_t efi_kaslr_relocate_kernel(unsigned long *image_addr, + */ + status = efi_random_alloc(*reserve_size, min_kimg_align, + reserve_addr, phys_seed, +- EFI_LOADER_CODE, EFI_ALLOC_LIMIT); ++ EFI_LOADER_CODE, 0, EFI_ALLOC_LIMIT); + if (status != EFI_SUCCESS) + efi_warn("efi_random_alloc() failed: 0x%lx\n", status); + } else { +diff --git a/drivers/firmware/efi/libstub/randomalloc.c b/drivers/firmware/efi/libstub/randomalloc.c +index 674a064b8f7ad..4e96a855fdf47 100644 +--- a/drivers/firmware/efi/libstub/randomalloc.c ++++ b/drivers/firmware/efi/libstub/randomalloc.c +@@ -17,7 +17,7 @@ + static unsigned long get_entry_num_slots(efi_memory_desc_t *md, + unsigned long size, + unsigned long align_shift, +- u64 alloc_limit) ++ u64 alloc_min, u64 alloc_max) + { + unsigned long align = 1UL << align_shift; + u64 first_slot, last_slot, region_end; +@@ -30,11 +30,11 @@ static unsigned long get_entry_num_slots(efi_memory_desc_t *md, + return 0; + + region_end = min(md->phys_addr + md->num_pages * EFI_PAGE_SIZE - 1, +- alloc_limit); ++ alloc_max); + if (region_end < size) + return 0; + +- first_slot = round_up(md->phys_addr, align); ++ first_slot = round_up(max(md->phys_addr, alloc_min), align); + last_slot = round_down(region_end - size + 1, align); + + if (first_slot > last_slot) +@@ -56,7 +56,8 @@ efi_status_t efi_random_alloc(unsigned long size, + unsigned long *addr, + unsigned long random_seed, + int memory_type, +- unsigned long alloc_limit) ++ unsigned long alloc_min, ++ unsigned long alloc_max) + { + unsigned long total_slots = 0, target_slot; + unsigned long total_mirrored_slots = 0; +@@ -78,7 +79,8 @@ efi_status_t efi_random_alloc(unsigned long size, + efi_memory_desc_t *md = (void *)map->map + map_offset; + unsigned long slots; + +- slots = get_entry_num_slots(md, size, ilog2(align), alloc_limit); ++ slots = get_entry_num_slots(md, size, ilog2(align), alloc_min, ++ alloc_max); + MD_NUM_SLOTS(md) = slots; + total_slots += slots; + if (md->attribute & EFI_MEMORY_MORE_RELIABLE) +diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c +index 70b325a2f1f31..4a11470bed5ea 100644 +--- a/drivers/firmware/efi/libstub/x86-stub.c ++++ b/drivers/firmware/efi/libstub/x86-stub.c +@@ -223,8 +223,8 @@ static void retrieve_apple_device_properties(struct boot_params *boot_params) + } + } + +-void efi_adjust_memory_range_protection(unsigned long start, +- unsigned long size) ++efi_status_t efi_adjust_memory_range_protection(unsigned long start, ++ unsigned long size) + { + efi_status_t status; + efi_gcd_memory_space_desc_t desc; +@@ -236,13 +236,17 @@ void efi_adjust_memory_range_protection(unsigned long start, + rounded_end = roundup(start + size, EFI_PAGE_SIZE); + + if (memattr != NULL) { +- efi_call_proto(memattr, clear_memory_attributes, rounded_start, +- rounded_end - rounded_start, EFI_MEMORY_XP); +- return; ++ status = efi_call_proto(memattr, clear_memory_attributes, ++ rounded_start, ++ rounded_end - rounded_start, ++ EFI_MEMORY_XP); ++ if (status != EFI_SUCCESS) ++ efi_warn("Failed to clear EFI_MEMORY_XP attribute\n"); ++ return status; + } + + if (efi_dxe_table == NULL) +- return; ++ return EFI_SUCCESS; + + /* + * Don't modify memory region attributes, they are +@@ -255,7 +259,7 @@ void efi_adjust_memory_range_protection(unsigned long start, + status = efi_dxe_call(get_memory_space_descriptor, start, &desc); + + if (status != EFI_SUCCESS) +- return; ++ break; + + next = desc.base_address + desc.length; + +@@ -280,8 +284,10 @@ void efi_adjust_memory_range_protection(unsigned long start, + unprotect_start, + unprotect_start + unprotect_size, + status); ++ break; + } + } ++ return EFI_SUCCESS; + } + + static void setup_unaccepted_memory(void) +@@ -825,6 +831,7 @@ static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry) + + status = efi_random_alloc(alloc_size, CONFIG_PHYSICAL_ALIGN, &addr, + seed[0], EFI_LOADER_CODE, ++ LOAD_PHYSICAL_ADDR, + EFI_X86_KERNEL_ALLOC_LIMIT); + if (status != EFI_SUCCESS) + return status; +@@ -837,9 +844,7 @@ static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry) + + *kernel_entry = addr + entry; + +- efi_adjust_memory_range_protection(addr, kernel_total_size); +- +- return EFI_SUCCESS; ++ return efi_adjust_memory_range_protection(addr, kernel_total_size); + } + + static void __noreturn enter_kernel(unsigned long kernel_addr, +diff --git a/drivers/firmware/efi/libstub/x86-stub.h b/drivers/firmware/efi/libstub/x86-stub.h +index 2748bca192dfb..4433d0f97441c 100644 +--- a/drivers/firmware/efi/libstub/x86-stub.h ++++ b/drivers/firmware/efi/libstub/x86-stub.h +@@ -7,8 +7,8 @@ extern struct boot_params *boot_params_pointer asm("boot_params"); + extern void trampoline_32bit_src(void *, bool); + extern const u16 trampoline_ljmp_imm_offset; + +-void efi_adjust_memory_range_protection(unsigned long start, +- unsigned long size); ++efi_status_t efi_adjust_memory_range_protection(unsigned long start, ++ unsigned long size); + + #ifdef CONFIG_X86_64 + efi_status_t efi_setup_5level_paging(void); +diff --git a/drivers/firmware/efi/libstub/zboot.c b/drivers/firmware/efi/libstub/zboot.c +index bdb17eac0cb40..1ceace9567586 100644 +--- a/drivers/firmware/efi/libstub/zboot.c ++++ b/drivers/firmware/efi/libstub/zboot.c +@@ -119,7 +119,7 @@ efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab) + } + + status = efi_random_alloc(alloc_size, min_kimg_align, &image_base, +- seed, EFI_LOADER_CODE, EFI_ALLOC_LIMIT); ++ seed, EFI_LOADER_CODE, 0, EFI_ALLOC_LIMIT); + if (status != EFI_SUCCESS) { + efi_err("Failed to allocate memory\n"); + goto free_cmdline; +diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hwseq.c +index f99b1bc49694f..1b08749b084b1 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hwseq.c +@@ -206,28 +206,32 @@ void dcn21_set_abm_immediate_disable(struct pipe_ctx *pipe_ctx) + void dcn21_set_pipe(struct pipe_ctx *pipe_ctx) + { + struct abm *abm = pipe_ctx->stream_res.abm; +- uint32_t otg_inst = pipe_ctx->stream_res.tg->inst; ++ struct timing_generator *tg = pipe_ctx->stream_res.tg; + struct panel_cntl *panel_cntl = pipe_ctx->stream->link->panel_cntl; + struct dmcu *dmcu = pipe_ctx->stream->ctx->dc->res_pool->dmcu; ++ uint32_t otg_inst; ++ ++ if (!abm && !tg && !panel_cntl) ++ return; ++ ++ otg_inst = tg->inst; + + if (dmcu) { + dce110_set_pipe(pipe_ctx); + return; + } + +- if (abm && panel_cntl) { +- if (abm->funcs && abm->funcs->set_pipe_ex) { +- abm->funcs->set_pipe_ex(abm, ++ if (abm->funcs && abm->funcs->set_pipe_ex) { ++ abm->funcs->set_pipe_ex(abm, + otg_inst, + SET_ABM_PIPE_NORMAL, + panel_cntl->inst, + panel_cntl->pwrseq_inst); +- } else { +- dmub_abm_set_pipe(abm, otg_inst, +- SET_ABM_PIPE_NORMAL, +- panel_cntl->inst, +- panel_cntl->pwrseq_inst); +- } ++ } else { ++ dmub_abm_set_pipe(abm, otg_inst, ++ SET_ABM_PIPE_NORMAL, ++ panel_cntl->inst, ++ panel_cntl->pwrseq_inst); + } + } + +@@ -237,34 +241,35 @@ bool dcn21_set_backlight_level(struct pipe_ctx *pipe_ctx, + { + struct dc_context *dc = pipe_ctx->stream->ctx; + struct abm *abm = pipe_ctx->stream_res.abm; ++ struct timing_generator *tg = pipe_ctx->stream_res.tg; + struct panel_cntl *panel_cntl = pipe_ctx->stream->link->panel_cntl; ++ uint32_t otg_inst; ++ ++ if (!abm && !tg && !panel_cntl) ++ return false; ++ ++ otg_inst = tg->inst; + + if (dc->dc->res_pool->dmcu) { + dce110_set_backlight_level(pipe_ctx, backlight_pwm_u16_16, frame_ramp); + return true; + } + +- if (abm != NULL) { +- uint32_t otg_inst = pipe_ctx->stream_res.tg->inst; +- +- if (abm && panel_cntl) { +- if (abm->funcs && abm->funcs->set_pipe_ex) { +- abm->funcs->set_pipe_ex(abm, +- otg_inst, +- SET_ABM_PIPE_NORMAL, +- panel_cntl->inst, +- panel_cntl->pwrseq_inst); +- } else { +- dmub_abm_set_pipe(abm, +- otg_inst, +- SET_ABM_PIPE_NORMAL, +- panel_cntl->inst, +- panel_cntl->pwrseq_inst); +- } +- } ++ if (abm->funcs && abm->funcs->set_pipe_ex) { ++ abm->funcs->set_pipe_ex(abm, ++ otg_inst, ++ SET_ABM_PIPE_NORMAL, ++ panel_cntl->inst, ++ panel_cntl->pwrseq_inst); ++ } else { ++ dmub_abm_set_pipe(abm, ++ otg_inst, ++ SET_ABM_PIPE_NORMAL, ++ panel_cntl->inst, ++ panel_cntl->pwrseq_inst); + } + +- if (abm && abm->funcs && abm->funcs->set_backlight_level_pwm) ++ if (abm->funcs && abm->funcs->set_backlight_level_pwm) + abm->funcs->set_backlight_level_pwm(abm, backlight_pwm_u16_16, + frame_ramp, 0, panel_cntl->inst); + else +diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c +index 79d6697d13b67..9485fda890cd7 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c +@@ -996,7 +996,7 @@ static struct stream_encoder *dcn301_stream_encoder_create(enum engine_id eng_id + vpg = dcn301_vpg_create(ctx, vpg_inst); + afmt = dcn301_afmt_create(ctx, afmt_inst); + +- if (!enc1 || !vpg || !afmt) { ++ if (!enc1 || !vpg || !afmt || eng_id >= ARRAY_SIZE(stream_enc_regs)) { + kfree(enc1); + kfree(vpg); + kfree(afmt); +diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c +index a9f7fa9b90bda..d30f8814d9b10 100644 +--- a/drivers/gpu/drm/i915/gvt/handlers.c ++++ b/drivers/gpu/drm/i915/gvt/handlers.c +@@ -2850,8 +2850,7 @@ static int handle_mmio(struct intel_gvt_mmio_table_iter *iter, u32 offset, + for (i = start; i < end; i += 4) { + p = intel_gvt_find_mmio_info(gvt, i); + if (p) { +- WARN(1, "dup mmio definition offset %x\n", +- info->offset); ++ WARN(1, "dup mmio definition offset %x\n", i); + + /* We return -EEXIST here to make GVT-g load fail. + * So duplicated MMIO can be found as soon as +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +index 7d4cf81fd31c9..ca4e5eae8e064 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +@@ -2063,7 +2063,7 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc) + } + + /* reset the merge 3D HW block */ +- if (phys_enc->hw_pp->merge_3d) { ++ if (phys_enc->hw_pp && phys_enc->hw_pp->merge_3d) { + phys_enc->hw_pp->merge_3d->ops.setup_3d_mode(phys_enc->hw_pp->merge_3d, + BLEND_3D_NONE); + if (phys_enc->hw_ctl->ops.update_pending_flush_merge_3d) +@@ -2085,7 +2085,7 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc) + if (phys_enc->hw_wb) + intf_cfg.wb = phys_enc->hw_wb->idx; + +- if (phys_enc->hw_pp->merge_3d) ++ if (phys_enc->hw_pp && phys_enc->hw_pp->merge_3d) + intf_cfg.merge_3d = phys_enc->hw_pp->merge_3d->idx; + + if (ctl->ops.reset_intf_cfg) +diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c +index 77a8d9366ed7b..fb588fde298a2 100644 +--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c ++++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c +@@ -135,11 +135,6 @@ static void dp_ctrl_config_ctrl(struct dp_ctrl_private *ctrl) + tbd = dp_link_get_test_bits_depth(ctrl->link, + ctrl->panel->dp_mode.bpp); + +- if (tbd == DP_TEST_BIT_DEPTH_UNKNOWN) { +- pr_debug("BIT_DEPTH not set. Configure default\n"); +- tbd = DP_TEST_BIT_DEPTH_8; +- } +- + config |= tbd << DP_CONFIGURATION_CTRL_BPC_SHIFT; + + /* Num of Lanes */ +diff --git a/drivers/gpu/drm/msm/dp/dp_link.c b/drivers/gpu/drm/msm/dp/dp_link.c +index 6375daaeb98e1..25950171caf3e 100644 +--- a/drivers/gpu/drm/msm/dp/dp_link.c ++++ b/drivers/gpu/drm/msm/dp/dp_link.c +@@ -7,6 +7,7 @@ + + #include <drm/drm_print.h> + ++#include "dp_reg.h" + #include "dp_link.h" + #include "dp_panel.h" + +@@ -1114,7 +1115,7 @@ int dp_link_process_request(struct dp_link *dp_link) + + int dp_link_get_colorimetry_config(struct dp_link *dp_link) + { +- u32 cc; ++ u32 cc = DP_MISC0_COLORIMERY_CFG_LEGACY_RGB; + struct dp_link_private *link; + + if (!dp_link) { +@@ -1128,10 +1129,11 @@ int dp_link_get_colorimetry_config(struct dp_link *dp_link) + * Unless a video pattern CTS test is ongoing, use RGB_VESA + * Only RGB_VESA and RGB_CEA supported for now + */ +- if (dp_link_is_video_pattern_requested(link)) +- cc = link->dp_link.test_video.test_dyn_range; +- else +- cc = DP_TEST_DYNAMIC_RANGE_VESA; ++ if (dp_link_is_video_pattern_requested(link)) { ++ if (link->dp_link.test_video.test_dyn_range & ++ DP_TEST_DYNAMIC_RANGE_CEA) ++ cc = DP_MISC0_COLORIMERY_CFG_CEA_RGB; ++ } + + return cc; + } +@@ -1211,6 +1213,9 @@ void dp_link_reset_phy_params_vx_px(struct dp_link *dp_link) + u32 dp_link_get_test_bits_depth(struct dp_link *dp_link, u32 bpp) + { + u32 tbd; ++ struct dp_link_private *link; ++ ++ link = container_of(dp_link, struct dp_link_private, dp_link); + + /* + * Few simplistic rules and assumptions made here: +@@ -1228,12 +1233,13 @@ u32 dp_link_get_test_bits_depth(struct dp_link *dp_link, u32 bpp) + tbd = DP_TEST_BIT_DEPTH_10; + break; + default: +- tbd = DP_TEST_BIT_DEPTH_UNKNOWN; ++ drm_dbg_dp(link->drm_dev, "bpp=%d not supported, use bpc=8\n", ++ bpp); ++ tbd = DP_TEST_BIT_DEPTH_8; + break; + } + +- if (tbd != DP_TEST_BIT_DEPTH_UNKNOWN) +- tbd = (tbd >> DP_TEST_BIT_DEPTH_SHIFT); ++ tbd = (tbd >> DP_TEST_BIT_DEPTH_SHIFT); + + return tbd; + } +diff --git a/drivers/gpu/drm/msm/dp/dp_reg.h b/drivers/gpu/drm/msm/dp/dp_reg.h +index ea85a691e72b5..78785ed4b40c4 100644 +--- a/drivers/gpu/drm/msm/dp/dp_reg.h ++++ b/drivers/gpu/drm/msm/dp/dp_reg.h +@@ -143,6 +143,9 @@ + #define DP_MISC0_COLORIMETRY_CFG_SHIFT (0x00000001) + #define DP_MISC0_TEST_BITS_DEPTH_SHIFT (0x00000005) + ++#define DP_MISC0_COLORIMERY_CFG_LEGACY_RGB (0) ++#define DP_MISC0_COLORIMERY_CFG_CEA_RGB (0x04) ++ + #define REG_DP_VALID_BOUNDARY (0x00000030) + #define REG_DP_VALID_BOUNDARY_2 (0x00000034) + +diff --git a/drivers/hwmon/aspeed-pwm-tacho.c b/drivers/hwmon/aspeed-pwm-tacho.c +index 997df4b405098..b2ae2176f11fe 100644 +--- a/drivers/hwmon/aspeed-pwm-tacho.c ++++ b/drivers/hwmon/aspeed-pwm-tacho.c +@@ -193,6 +193,8 @@ struct aspeed_pwm_tacho_data { + u8 fan_tach_ch_source[16]; + struct aspeed_cooling_device *cdev[8]; + const struct attribute_group *groups[3]; ++ /* protects access to shared ASPEED_PTCR_RESULT */ ++ struct mutex tach_lock; + }; + + enum type { TYPEM, TYPEN, TYPEO }; +@@ -527,6 +529,8 @@ static int aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tacho_data *priv, + u8 fan_tach_ch_source, type, mode, both; + int ret; + ++ mutex_lock(&priv->tach_lock); ++ + regmap_write(priv->regmap, ASPEED_PTCR_TRIGGER, 0); + regmap_write(priv->regmap, ASPEED_PTCR_TRIGGER, 0x1 << fan_tach_ch); + +@@ -544,6 +548,8 @@ static int aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tacho_data *priv, + ASPEED_RPM_STATUS_SLEEP_USEC, + usec); + ++ mutex_unlock(&priv->tach_lock); ++ + /* return -ETIMEDOUT if we didn't get an answer. */ + if (ret) + return ret; +@@ -903,6 +909,7 @@ static int aspeed_pwm_tacho_probe(struct platform_device *pdev) + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; ++ mutex_init(&priv->tach_lock); + priv->regmap = devm_regmap_init(dev, NULL, (__force void *)regs, + &aspeed_pwm_tacho_regmap_config); + if (IS_ERR(priv->regmap)) +diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c +index ba82d1e79c131..95f4c0b00b2d8 100644 +--- a/drivers/hwmon/coretemp.c ++++ b/drivers/hwmon/coretemp.c +@@ -419,7 +419,7 @@ static ssize_t show_temp(struct device *dev, + } + + static int create_core_attrs(struct temp_data *tdata, struct device *dev, +- int attr_no) ++ int index) + { + int i; + static ssize_t (*const rd_ptr[TOTAL_ATTRS]) (struct device *dev, +@@ -431,13 +431,20 @@ static int create_core_attrs(struct temp_data *tdata, struct device *dev, + }; + + for (i = 0; i < tdata->attr_size; i++) { ++ /* ++ * We map the attr number to core id of the CPU ++ * The attr number is always core id + 2 ++ * The Pkgtemp will always show up as temp1_*, if available ++ */ ++ int attr_no = tdata->is_pkg_data ? 1 : tdata->cpu_core_id + 2; ++ + snprintf(tdata->attr_name[i], CORETEMP_NAME_LENGTH, + "temp%d_%s", attr_no, suffixes[i]); + sysfs_attr_init(&tdata->sd_attrs[i].dev_attr.attr); + tdata->sd_attrs[i].dev_attr.attr.name = tdata->attr_name[i]; + tdata->sd_attrs[i].dev_attr.attr.mode = 0444; + tdata->sd_attrs[i].dev_attr.show = rd_ptr[i]; +- tdata->sd_attrs[i].index = attr_no; ++ tdata->sd_attrs[i].index = index; + tdata->attrs[i] = &tdata->sd_attrs[i].dev_attr.attr; + } + tdata->attr_group.attrs = tdata->attrs; +@@ -495,30 +502,25 @@ static int create_core_data(struct platform_device *pdev, unsigned int cpu, + struct platform_data *pdata = platform_get_drvdata(pdev); + struct cpuinfo_x86 *c = &cpu_data(cpu); + u32 eax, edx; +- int err, index, attr_no; ++ int err, index; + + if (!housekeeping_cpu(cpu, HK_TYPE_MISC)) + return 0; + + /* +- * Find attr number for sysfs: +- * We map the attr number to core id of the CPU +- * The attr number is always core id + 2 +- * The Pkgtemp will always show up as temp1_*, if available ++ * Get the index of tdata in pdata->core_data[] ++ * tdata for package: pdata->core_data[1] ++ * tdata for core: pdata->core_data[2] .. pdata->core_data[NUM_REAL_CORES + 1] + */ + if (pkg_flag) { +- attr_no = PKG_SYSFS_ATTR_NO; ++ index = PKG_SYSFS_ATTR_NO; + } else { +- index = ida_alloc(&pdata->ida, GFP_KERNEL); ++ index = ida_alloc_max(&pdata->ida, NUM_REAL_CORES - 1, GFP_KERNEL); + if (index < 0) + return index; +- pdata->cpu_map[index] = topology_core_id(cpu); +- attr_no = index + BASE_SYSFS_ATTR_NO; +- } + +- if (attr_no > MAX_CORE_DATA - 1) { +- err = -ERANGE; +- goto ida_free; ++ pdata->cpu_map[index] = topology_core_id(cpu); ++ index += BASE_SYSFS_ATTR_NO; + } + + tdata = init_temp_data(cpu, pkg_flag); +@@ -544,20 +546,20 @@ static int create_core_data(struct platform_device *pdev, unsigned int cpu, + if (get_ttarget(tdata, &pdev->dev) >= 0) + tdata->attr_size++; + +- pdata->core_data[attr_no] = tdata; ++ pdata->core_data[index] = tdata; + + /* Create sysfs interfaces */ +- err = create_core_attrs(tdata, pdata->hwmon_dev, attr_no); ++ err = create_core_attrs(tdata, pdata->hwmon_dev, index); + if (err) + goto exit_free; + + return 0; + exit_free: +- pdata->core_data[attr_no] = NULL; ++ pdata->core_data[index] = NULL; + kfree(tdata); + ida_free: + if (!pkg_flag) +- ida_free(&pdata->ida, index); ++ ida_free(&pdata->ida, index - BASE_SYSFS_ATTR_NO); + return err; + } + +diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c +index 13ef6284223da..c229bd6b3f7f2 100644 +--- a/drivers/input/keyboard/atkbd.c ++++ b/drivers/input/keyboard/atkbd.c +@@ -811,7 +811,6 @@ static int atkbd_probe(struct atkbd *atkbd) + { + struct ps2dev *ps2dev = &atkbd->ps2dev; + unsigned char param[2]; +- bool skip_getid; + + /* + * Some systems, where the bit-twiddling when testing the io-lines of the +@@ -825,6 +824,11 @@ static int atkbd_probe(struct atkbd *atkbd) + "keyboard reset failed on %s\n", + ps2dev->serio->phys); + ++ if (atkbd_skip_getid(atkbd)) { ++ atkbd->id = 0xab83; ++ return 0; ++ } ++ + /* + * Then we check the keyboard ID. We should get 0xab83 under normal conditions. + * Some keyboards report different values, but the first byte is always 0xab or +@@ -833,18 +837,17 @@ static int atkbd_probe(struct atkbd *atkbd) + */ + + param[0] = param[1] = 0xa5; /* initialize with invalid values */ +- skip_getid = atkbd_skip_getid(atkbd); +- if (skip_getid || ps2_command(ps2dev, param, ATKBD_CMD_GETID)) { ++ if (ps2_command(ps2dev, param, ATKBD_CMD_GETID)) { + + /* +- * If the get ID command was skipped or failed, we check if we can at least set ++ * If the get ID command failed, we check if we can at least set + * the LEDs on the keyboard. This should work on every keyboard out there. + * It also turns the LEDs off, which we want anyway. + */ + param[0] = 0; + if (ps2_command(ps2dev, param, ATKBD_CMD_SETLEDS)) + return -1; +- atkbd->id = skip_getid ? 0xab83 : 0xabba; ++ atkbd->id = 0xabba; + return 0; + } + +diff --git a/drivers/input/serio/i8042-acpipnpio.h b/drivers/input/serio/i8042-acpipnpio.h +index b585b1dab870e..cd45a65e17f2c 100644 +--- a/drivers/input/serio/i8042-acpipnpio.h ++++ b/drivers/input/serio/i8042-acpipnpio.h +@@ -1208,6 +1208,12 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { + SERIO_QUIRK_RESET_ALWAYS | SERIO_QUIRK_NOLOOP | + SERIO_QUIRK_NOPNP) + }, ++ { ++ .matches = { ++ DMI_MATCH(DMI_BOARD_NAME, "NS5x_7xPU"), ++ }, ++ .driver_data = (void *)(SERIO_QUIRK_NOAUX) ++ }, + { + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "NJ50_70CU"), +diff --git a/drivers/media/pci/solo6x10/solo6x10-offsets.h b/drivers/media/pci/solo6x10/solo6x10-offsets.h +index f414ee1316f29..fdbb817e63601 100644 +--- a/drivers/media/pci/solo6x10/solo6x10-offsets.h ++++ b/drivers/media/pci/solo6x10/solo6x10-offsets.h +@@ -57,16 +57,16 @@ + #define SOLO_MP4E_EXT_ADDR(__solo) \ + (SOLO_EREF_EXT_ADDR(__solo) + SOLO_EREF_EXT_AREA(__solo)) + #define SOLO_MP4E_EXT_SIZE(__solo) \ +- max((__solo->nr_chans * 0x00080000), \ +- min(((__solo->sdram_size - SOLO_MP4E_EXT_ADDR(__solo)) - \ +- __SOLO_JPEG_MIN_SIZE(__solo)), 0x00ff0000)) ++ clamp(__solo->sdram_size - SOLO_MP4E_EXT_ADDR(__solo) - \ ++ __SOLO_JPEG_MIN_SIZE(__solo), \ ++ __solo->nr_chans * 0x00080000, 0x00ff0000) + + #define __SOLO_JPEG_MIN_SIZE(__solo) (__solo->nr_chans * 0x00080000) + #define SOLO_JPEG_EXT_ADDR(__solo) \ + (SOLO_MP4E_EXT_ADDR(__solo) + SOLO_MP4E_EXT_SIZE(__solo)) + #define SOLO_JPEG_EXT_SIZE(__solo) \ +- max(__SOLO_JPEG_MIN_SIZE(__solo), \ +- min((__solo->sdram_size - SOLO_JPEG_EXT_ADDR(__solo)), 0x00ff0000)) ++ clamp(__solo->sdram_size - SOLO_JPEG_EXT_ADDR(__solo), \ ++ __SOLO_JPEG_MIN_SIZE(__solo), 0x00ff0000) + + #define SOLO_SDRAM_END(__solo) \ + (SOLO_JPEG_EXT_ADDR(__solo) + SOLO_JPEG_EXT_SIZE(__solo)) +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +index abd4832e4ed21..5acb3e16b5677 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c +@@ -993,7 +993,7 @@ int aq_ptp_ring_alloc(struct aq_nic_s *aq_nic) + return 0; + + err_exit_hwts_rx: +- aq_ring_free(&aq_ptp->hwts_rx); ++ aq_ring_hwts_rx_free(&aq_ptp->hwts_rx); + err_exit_ptp_rx: + aq_ring_free(&aq_ptp->ptp_rx); + err_exit_ptp_tx: +@@ -1011,7 +1011,7 @@ void aq_ptp_ring_free(struct aq_nic_s *aq_nic) + + aq_ring_free(&aq_ptp->ptp_tx); + aq_ring_free(&aq_ptp->ptp_rx); +- aq_ring_free(&aq_ptp->hwts_rx); ++ aq_ring_hwts_rx_free(&aq_ptp->hwts_rx); + + aq_ptp_skb_ring_release(&aq_ptp->skb_ring); + } +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +index cda8597b4e146..f7433abd65915 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +@@ -919,6 +919,19 @@ void aq_ring_free(struct aq_ring_s *self) + } + } + ++void aq_ring_hwts_rx_free(struct aq_ring_s *self) ++{ ++ if (!self) ++ return; ++ ++ if (self->dx_ring) { ++ dma_free_coherent(aq_nic_get_dev(self->aq_nic), ++ self->size * self->dx_size + AQ_CFG_RXDS_DEF, ++ self->dx_ring, self->dx_ring_pa); ++ self->dx_ring = NULL; ++ } ++} ++ + unsigned int aq_ring_fill_stats_data(struct aq_ring_s *self, u64 *data) + { + unsigned int count; +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.h b/drivers/net/ethernet/aquantia/atlantic/aq_ring.h +index 52847310740a2..d627ace850ff5 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.h +@@ -210,6 +210,7 @@ int aq_ring_rx_fill(struct aq_ring_s *self); + int aq_ring_hwts_rx_alloc(struct aq_ring_s *self, + struct aq_nic_s *aq_nic, unsigned int idx, + unsigned int size, unsigned int dx_size); ++void aq_ring_hwts_rx_free(struct aq_ring_s *self); + void aq_ring_hwts_rx_clean(struct aq_ring_s *self, struct aq_nic_s *aq_nic); + + unsigned int aq_ring_fill_stats_data(struct aq_ring_s *self, u64 *data); +diff --git a/drivers/net/ethernet/engleder/tsnep_main.c b/drivers/net/ethernet/engleder/tsnep_main.c +index 08e113e785a76..4f36b29d66c86 100644 +--- a/drivers/net/ethernet/engleder/tsnep_main.c ++++ b/drivers/net/ethernet/engleder/tsnep_main.c +@@ -668,17 +668,25 @@ static void tsnep_xdp_xmit_flush(struct tsnep_tx *tx) + + static bool tsnep_xdp_xmit_back(struct tsnep_adapter *adapter, + struct xdp_buff *xdp, +- struct netdev_queue *tx_nq, struct tsnep_tx *tx) ++ struct netdev_queue *tx_nq, struct tsnep_tx *tx, ++ bool zc) + { + struct xdp_frame *xdpf = xdp_convert_buff_to_frame(xdp); + bool xmit; ++ u32 type; + + if (unlikely(!xdpf)) + return false; + ++ /* no page pool for zero copy */ ++ if (zc) ++ type = TSNEP_TX_TYPE_XDP_NDO; ++ else ++ type = TSNEP_TX_TYPE_XDP_TX; ++ + __netif_tx_lock(tx_nq, smp_processor_id()); + +- xmit = tsnep_xdp_xmit_frame_ring(xdpf, tx, TSNEP_TX_TYPE_XDP_TX); ++ xmit = tsnep_xdp_xmit_frame_ring(xdpf, tx, type); + + /* Avoid transmit queue timeout since we share it with the slow path */ + if (xmit) +@@ -1222,7 +1230,7 @@ static bool tsnep_xdp_run_prog(struct tsnep_rx *rx, struct bpf_prog *prog, + case XDP_PASS: + return false; + case XDP_TX: +- if (!tsnep_xdp_xmit_back(rx->adapter, xdp, tx_nq, tx)) ++ if (!tsnep_xdp_xmit_back(rx->adapter, xdp, tx_nq, tx, false)) + goto out_failure; + *status |= TSNEP_XDP_TX; + return true; +@@ -1272,7 +1280,7 @@ static bool tsnep_xdp_run_prog_zc(struct tsnep_rx *rx, struct bpf_prog *prog, + case XDP_PASS: + return false; + case XDP_TX: +- if (!tsnep_xdp_xmit_back(rx->adapter, xdp, tx_nq, tx)) ++ if (!tsnep_xdp_xmit_back(rx->adapter, xdp, tx_nq, tx, true)) + goto out_failure; + *status |= TSNEP_XDP_TX; + return true; +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c +index 629cf1659e5f9..e6df4e6a78ab7 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c +@@ -951,8 +951,11 @@ int otx2_sq_init(struct otx2_nic *pfvf, u16 qidx, u16 sqb_aura) + if (pfvf->ptp && qidx < pfvf->hw.tx_queues) { + err = qmem_alloc(pfvf->dev, &sq->timestamps, qset->sqe_cnt, + sizeof(*sq->timestamps)); +- if (err) ++ if (err) { ++ kfree(sq->sg); ++ sq->sg = NULL; + return err; ++ } + } + + sq->head = 0; +@@ -968,7 +971,14 @@ int otx2_sq_init(struct otx2_nic *pfvf, u16 qidx, u16 sqb_aura) + sq->stats.bytes = 0; + sq->stats.pkts = 0; + +- return pfvf->hw_ops->sq_aq_init(pfvf, qidx, sqb_aura); ++ err = pfvf->hw_ops->sq_aq_init(pfvf, qidx, sqb_aura); ++ if (err) { ++ kfree(sq->sg); ++ sq->sg = NULL; ++ return err; ++ } ++ ++ return 0; + + } + +diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h +index 1e996c29043dc..3d4f34e178a88 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/common.h ++++ b/drivers/net/ethernet/stmicro/stmmac/common.h +@@ -216,6 +216,7 @@ struct stmmac_safety_stats { + unsigned long mac_errors[32]; + unsigned long mtl_errors[32]; + unsigned long dma_errors[32]; ++ unsigned long dma_dpp_errors[32]; + }; + + /* Number of fields in Safety Stats */ +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h +index a4e8b498dea96..17394847476f3 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h ++++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h +@@ -319,6 +319,8 @@ + #define XGMAC_RXCEIE BIT(4) + #define XGMAC_TXCEIE BIT(0) + #define XGMAC_MTL_ECC_INT_STATUS 0x000010cc ++#define XGMAC_MTL_DPP_CONTROL 0x000010e0 ++#define XGMAC_DPP_DISABLE BIT(0) + #define XGMAC_MTL_TXQ_OPMODE(x) (0x00001100 + (0x80 * (x))) + #define XGMAC_TQS GENMASK(25, 16) + #define XGMAC_TQS_SHIFT 16 +@@ -401,6 +403,7 @@ + #define XGMAC_DCEIE BIT(1) + #define XGMAC_TCEIE BIT(0) + #define XGMAC_DMA_ECC_INT_STATUS 0x0000306c ++#define XGMAC_DMA_DPP_INT_STATUS 0x00003074 + #define XGMAC_DMA_CH_CONTROL(x) (0x00003100 + (0x80 * (x))) + #define XGMAC_SPH BIT(24) + #define XGMAC_PBLx8 BIT(16) +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +index a74e71db79f94..b5509f244ecd1 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +@@ -830,6 +830,44 @@ static const struct dwxgmac3_error_desc dwxgmac3_dma_errors[32]= { + { false, "UNKNOWN", "Unknown Error" }, /* 31 */ + }; + ++#define DPP_RX_ERR "Read Rx Descriptor Parity checker Error" ++#define DPP_TX_ERR "Read Tx Descriptor Parity checker Error" ++ ++static const struct dwxgmac3_error_desc dwxgmac3_dma_dpp_errors[32] = { ++ { true, "TDPES0", DPP_TX_ERR }, ++ { true, "TDPES1", DPP_TX_ERR }, ++ { true, "TDPES2", DPP_TX_ERR }, ++ { true, "TDPES3", DPP_TX_ERR }, ++ { true, "TDPES4", DPP_TX_ERR }, ++ { true, "TDPES5", DPP_TX_ERR }, ++ { true, "TDPES6", DPP_TX_ERR }, ++ { true, "TDPES7", DPP_TX_ERR }, ++ { true, "TDPES8", DPP_TX_ERR }, ++ { true, "TDPES9", DPP_TX_ERR }, ++ { true, "TDPES10", DPP_TX_ERR }, ++ { true, "TDPES11", DPP_TX_ERR }, ++ { true, "TDPES12", DPP_TX_ERR }, ++ { true, "TDPES13", DPP_TX_ERR }, ++ { true, "TDPES14", DPP_TX_ERR }, ++ { true, "TDPES15", DPP_TX_ERR }, ++ { true, "RDPES0", DPP_RX_ERR }, ++ { true, "RDPES1", DPP_RX_ERR }, ++ { true, "RDPES2", DPP_RX_ERR }, ++ { true, "RDPES3", DPP_RX_ERR }, ++ { true, "RDPES4", DPP_RX_ERR }, ++ { true, "RDPES5", DPP_RX_ERR }, ++ { true, "RDPES6", DPP_RX_ERR }, ++ { true, "RDPES7", DPP_RX_ERR }, ++ { true, "RDPES8", DPP_RX_ERR }, ++ { true, "RDPES9", DPP_RX_ERR }, ++ { true, "RDPES10", DPP_RX_ERR }, ++ { true, "RDPES11", DPP_RX_ERR }, ++ { true, "RDPES12", DPP_RX_ERR }, ++ { true, "RDPES13", DPP_RX_ERR }, ++ { true, "RDPES14", DPP_RX_ERR }, ++ { true, "RDPES15", DPP_RX_ERR }, ++}; ++ + static void dwxgmac3_handle_dma_err(struct net_device *ndev, + void __iomem *ioaddr, bool correctable, + struct stmmac_safety_stats *stats) +@@ -841,6 +879,13 @@ static void dwxgmac3_handle_dma_err(struct net_device *ndev, + + dwxgmac3_log_error(ndev, value, correctable, "DMA", + dwxgmac3_dma_errors, STAT_OFF(dma_errors), stats); ++ ++ value = readl(ioaddr + XGMAC_DMA_DPP_INT_STATUS); ++ writel(value, ioaddr + XGMAC_DMA_DPP_INT_STATUS); ++ ++ dwxgmac3_log_error(ndev, value, false, "DMA_DPP", ++ dwxgmac3_dma_dpp_errors, ++ STAT_OFF(dma_dpp_errors), stats); + } + + static int +@@ -881,6 +926,12 @@ dwxgmac3_safety_feat_config(void __iomem *ioaddr, unsigned int asp, + value |= XGMAC_TMOUTEN; /* FSM Timeout Feature */ + writel(value, ioaddr + XGMAC_MAC_FSM_CONTROL); + ++ /* 5. Enable Data Path Parity Protection */ ++ value = readl(ioaddr + XGMAC_MTL_DPP_CONTROL); ++ /* already enabled by default, explicit enable it again */ ++ value &= ~XGMAC_DPP_DISABLE; ++ writel(value, ioaddr + XGMAC_MTL_DPP_CONTROL); ++ + return 0; + } + +@@ -914,7 +965,11 @@ static int dwxgmac3_safety_feat_irq_status(struct net_device *ndev, + ret |= !corr; + } + +- err = dma & (XGMAC_DEUIS | XGMAC_DECIS); ++ /* DMA_DPP_Interrupt_Status is indicated by MCSIS bit in ++ * DMA_Safety_Interrupt_Status, so we handle DMA Data Path ++ * Parity Errors here ++ */ ++ err = dma & (XGMAC_DEUIS | XGMAC_DECIS | XGMAC_MCSIS); + corr = dma & XGMAC_DECIS; + if (err) { + dwxgmac3_handle_dma_err(ndev, ioaddr, corr, stats); +@@ -930,6 +985,7 @@ static const struct dwxgmac3_error { + { dwxgmac3_mac_errors }, + { dwxgmac3_mtl_errors }, + { dwxgmac3_dma_errors }, ++ { dwxgmac3_dma_dpp_errors }, + }; + + static int dwxgmac3_safety_feat_dump(struct stmmac_safety_stats *stats, +diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c +index b4d3b9cde8bd6..92a7a36b93ac0 100644 +--- a/drivers/net/netdevsim/dev.c ++++ b/drivers/net/netdevsim/dev.c +@@ -835,14 +835,14 @@ static void nsim_dev_trap_report_work(struct work_struct *work) + trap_report_dw.work); + nsim_dev = nsim_trap_data->nsim_dev; + +- /* For each running port and enabled packet trap, generate a UDP +- * packet with a random 5-tuple and report it. +- */ + if (!devl_trylock(priv_to_devlink(nsim_dev))) { +- schedule_delayed_work(&nsim_dev->trap_data->trap_report_dw, 0); ++ schedule_delayed_work(&nsim_dev->trap_data->trap_report_dw, 1); + return; + } + ++ /* For each running port and enabled packet trap, generate a UDP ++ * packet with a random 5-tuple and report it. ++ */ + list_for_each_entry(nsim_dev_port, &nsim_dev->port_list, list) { + if (!netif_running(nsim_dev_port->ns->netdev)) + continue; +diff --git a/drivers/net/ppp/ppp_async.c b/drivers/net/ppp/ppp_async.c +index fbaaa8c102a1b..e94a4b08fd63b 100644 +--- a/drivers/net/ppp/ppp_async.c ++++ b/drivers/net/ppp/ppp_async.c +@@ -460,6 +460,10 @@ ppp_async_ioctl(struct ppp_channel *chan, unsigned int cmd, unsigned long arg) + case PPPIOCSMRU: + if (get_user(val, p)) + break; ++ if (val > U16_MAX) { ++ err = -EINVAL; ++ break; ++ } + if (val < PPP_MRU) + val = PPP_MRU; + ap->mru = val; +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +index 2a90bb24ba77f..6049f9a761d9d 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -3780,8 +3780,10 @@ static int brcmf_internal_escan_add_info(struct cfg80211_scan_request *req, + if (req->channels[i] == chan) + break; + } +- if (i == req->n_channels) +- req->channels[req->n_channels++] = chan; ++ if (i == req->n_channels) { ++ req->n_channels++; ++ req->channels[i] = chan; ++ } + + for (i = 0; i < req->n_ssids; i++) { + if (req->ssids[i].ssid_len == ssid_len && +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c +index 1e58f02342934..2d1fd7ac8577f 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c +@@ -435,6 +435,9 @@ __iwl_mvm_mld_unassign_vif_chanctx(struct iwl_mvm *mvm, + mvmvif->ap_ibss_active = false; + } + ++ iwl_mvm_link_changed(mvm, vif, link_conf, ++ LINK_CONTEXT_MODIFY_ACTIVE, false); ++ + if (iwl_mvm_is_esr_supported(mvm->fwrt.trans) && n_active > 1) { + int ret = iwl_mvm_esr_mode_inactive(mvm, vif); + +@@ -446,9 +449,6 @@ __iwl_mvm_mld_unassign_vif_chanctx(struct iwl_mvm *mvm, + if (vif->type == NL80211_IFTYPE_MONITOR) + iwl_mvm_mld_rm_snif_sta(mvm, vif); + +- iwl_mvm_link_changed(mvm, vif, link_conf, +- LINK_CONTEXT_MODIFY_ACTIVE, false); +- + if (switching_chanctx) + return; + mvmvif->link[link_id]->phy_ctxt = NULL; +diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c +index e53eace7c91e3..6387c0d34c551 100644 +--- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c ++++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c +@@ -673,8 +673,6 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) + channel->irq = platform_get_irq_optional(pdev, 0); + channel->dr_mode = rcar_gen3_get_dr_mode(dev->of_node); + if (channel->dr_mode != USB_DR_MODE_UNKNOWN) { +- int ret; +- + channel->is_otg_channel = true; + channel->uses_otg_pins = !of_property_read_bool(dev->of_node, + "renesas,no-otg-pins"); +@@ -738,8 +736,6 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) + ret = PTR_ERR(provider); + goto error; + } else if (channel->is_otg_channel) { +- int ret; +- + ret = device_create_file(dev, &dev_attr_role); + if (ret < 0) + goto error; +diff --git a/drivers/phy/ti/phy-omap-usb2.c b/drivers/phy/ti/phy-omap-usb2.c +index 762d3de8b3c53..6bd3c74923306 100644 +--- a/drivers/phy/ti/phy-omap-usb2.c ++++ b/drivers/phy/ti/phy-omap-usb2.c +@@ -116,7 +116,7 @@ static int omap_usb_set_vbus(struct usb_otg *otg, bool enabled) + { + struct omap_usb *phy = phy_to_omapusb(otg->usb_phy); + +- if (!phy->comparator) ++ if (!phy->comparator || !phy->comparator->set_vbus) + return -ENODEV; + + return phy->comparator->set_vbus(phy->comparator, enabled); +@@ -126,7 +126,7 @@ static int omap_usb_start_srp(struct usb_otg *otg) + { + struct omap_usb *phy = phy_to_omapusb(otg->usb_phy); + +- if (!phy->comparator) ++ if (!phy->comparator || !phy->comparator->start_srp) + return -ENODEV; + + return phy->comparator->start_srp(phy->comparator); +diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c +index 3328b175a8326..43eff1107038a 100644 +--- a/drivers/scsi/scsi_error.c ++++ b/drivers/scsi/scsi_error.c +@@ -282,11 +282,12 @@ static void scsi_eh_inc_host_failed(struct rcu_head *head) + { + struct scsi_cmnd *scmd = container_of(head, typeof(*scmd), rcu); + struct Scsi_Host *shost = scmd->device->host; ++ unsigned int busy = scsi_host_busy(shost); + unsigned long flags; + + spin_lock_irqsave(shost->host_lock, flags); + shost->host_failed++; +- scsi_eh_wakeup(shost, scsi_host_busy(shost)); ++ scsi_eh_wakeup(shost, busy); + spin_unlock_irqrestore(shost->host_lock, flags); + } + +diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c +index dfdffe55c5a6a..552809bca3507 100644 +--- a/drivers/scsi/scsi_lib.c ++++ b/drivers/scsi/scsi_lib.c +@@ -278,9 +278,11 @@ static void scsi_dec_host_busy(struct Scsi_Host *shost, struct scsi_cmnd *cmd) + rcu_read_lock(); + __clear_bit(SCMD_STATE_INFLIGHT, &cmd->state); + if (unlikely(scsi_host_in_recovery(shost))) { ++ unsigned int busy = scsi_host_busy(shost); ++ + spin_lock_irqsave(shost->host_lock, flags); + if (shost->host_failed || shost->host_eh_scheduled) +- scsi_eh_wakeup(shost, scsi_host_busy(shost)); ++ scsi_eh_wakeup(shost, busy); + spin_unlock_irqrestore(shost->host_lock, flags); + } + rcu_read_unlock(); +diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c +index 6604845c397cd..39564e17f3b07 100644 +--- a/drivers/usb/dwc3/dwc3-pci.c ++++ b/drivers/usb/dwc3/dwc3-pci.c +@@ -51,6 +51,8 @@ + #define PCI_DEVICE_ID_INTEL_MTLP 0x7ec1 + #define PCI_DEVICE_ID_INTEL_MTLS 0x7f6f + #define PCI_DEVICE_ID_INTEL_MTL 0x7e7e ++#define PCI_DEVICE_ID_INTEL_ARLH 0x7ec1 ++#define PCI_DEVICE_ID_INTEL_ARLH_PCH 0x777e + #define PCI_DEVICE_ID_INTEL_TGL 0x9a15 + #define PCI_DEVICE_ID_AMD_MR 0x163a + +@@ -421,6 +423,8 @@ static const struct pci_device_id dwc3_pci_id_table[] = { + { PCI_DEVICE_DATA(INTEL, MTLP, &dwc3_pci_intel_swnode) }, + { PCI_DEVICE_DATA(INTEL, MTL, &dwc3_pci_intel_swnode) }, + { PCI_DEVICE_DATA(INTEL, MTLS, &dwc3_pci_intel_swnode) }, ++ { PCI_DEVICE_DATA(INTEL, ARLH, &dwc3_pci_intel_swnode) }, ++ { PCI_DEVICE_DATA(INTEL, ARLH_PCH, &dwc3_pci_intel_swnode) }, + { PCI_DEVICE_DATA(INTEL, TGL, &dwc3_pci_intel_swnode) }, + + { PCI_DEVICE_DATA(AMD, NL_USB, &dwc3_pci_amd_swnode) }, +diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c +index 61f57fe5bb783..43230915323c7 100644 +--- a/drivers/usb/dwc3/host.c ++++ b/drivers/usb/dwc3/host.c +@@ -61,7 +61,7 @@ out: + + int dwc3_host_init(struct dwc3 *dwc) + { +- struct property_entry props[4]; ++ struct property_entry props[5]; + struct platform_device *xhci; + int ret, irq; + int prop_idx = 0; +@@ -89,6 +89,8 @@ int dwc3_host_init(struct dwc3 *dwc) + + memset(props, 0, sizeof(struct property_entry) * ARRAY_SIZE(props)); + ++ props[prop_idx++] = PROPERTY_ENTRY_BOOL("xhci-sg-trb-cache-size-quirk"); ++ + if (dwc->usb3_lpm_capable) + props[prop_idx++] = PROPERTY_ENTRY_BOOL("usb3-lpm-capable"); + +diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c +index f0853c4478f57..d68e9abcdc69a 100644 +--- a/drivers/usb/host/xhci-plat.c ++++ b/drivers/usb/host/xhci-plat.c +@@ -250,6 +250,9 @@ int xhci_plat_probe(struct platform_device *pdev, struct device *sysdev, const s + if (device_property_read_bool(tmpdev, "quirk-broken-port-ped")) + xhci->quirks |= XHCI_BROKEN_PORT_PED; + ++ if (device_property_read_bool(tmpdev, "xhci-sg-trb-cache-size-quirk")) ++ xhci->quirks |= XHCI_SG_TRB_CACHE_SIZE_QUIRK; ++ + device_property_read_u32(tmpdev, "imod-interval-ns", + &xhci->imod_interval); + } +diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c +index 3e5dc0723a8fc..c410a98ed63cf 100644 +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -2377,6 +2377,9 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep, + /* handle completion code */ + switch (trb_comp_code) { + case COMP_SUCCESS: ++ /* Don't overwrite status if TD had an error, see xHCI 4.9.1 */ ++ if (td->error_mid_td) ++ break; + if (remaining) { + frame->status = short_framestatus; + if (xhci->quirks & XHCI_TRUST_TX_LENGTH) +@@ -2392,9 +2395,13 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep, + case COMP_BANDWIDTH_OVERRUN_ERROR: + frame->status = -ECOMM; + break; +- case COMP_ISOCH_BUFFER_OVERRUN: + case COMP_BABBLE_DETECTED_ERROR: ++ sum_trbs_for_length = true; ++ fallthrough; ++ case COMP_ISOCH_BUFFER_OVERRUN: + frame->status = -EOVERFLOW; ++ if (ep_trb != td->last_trb) ++ td->error_mid_td = true; + break; + case COMP_INCOMPATIBLE_DEVICE_ERROR: + case COMP_STALL_ERROR: +@@ -2402,8 +2409,9 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep, + break; + case COMP_USB_TRANSACTION_ERROR: + frame->status = -EPROTO; ++ sum_trbs_for_length = true; + if (ep_trb != td->last_trb) +- return 0; ++ td->error_mid_td = true; + break; + case COMP_STOPPED: + sum_trbs_for_length = true; +@@ -2423,6 +2431,9 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep, + break; + } + ++ if (td->urb_length_set) ++ goto finish_td; ++ + if (sum_trbs_for_length) + frame->actual_length = sum_trb_lengths(xhci, ep->ring, ep_trb) + + ep_trb_len - remaining; +@@ -2431,6 +2442,14 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep, + + td->urb->actual_length += frame->actual_length; + ++finish_td: ++ /* Don't give back TD yet if we encountered an error mid TD */ ++ if (td->error_mid_td && ep_trb != td->last_trb) { ++ xhci_dbg(xhci, "Error mid isoc TD, wait for final completion event\n"); ++ td->urb_length_set = true; ++ return 0; ++ } ++ + return finish_td(xhci, ep, ep_ring, td, trb_comp_code); + } + +@@ -2809,17 +2828,51 @@ static int handle_tx_event(struct xhci_hcd *xhci, + } + + if (!ep_seg) { +- if (!ep->skip || +- !usb_endpoint_xfer_isoc(&td->urb->ep->desc)) { +- /* Some host controllers give a spurious +- * successful event after a short transfer. +- * Ignore it. +- */ +- if ((xhci->quirks & XHCI_SPURIOUS_SUCCESS) && +- ep_ring->last_td_was_short) { +- ep_ring->last_td_was_short = false; +- goto cleanup; ++ ++ if (ep->skip && usb_endpoint_xfer_isoc(&td->urb->ep->desc)) { ++ skip_isoc_td(xhci, td, ep, status); ++ goto cleanup; ++ } ++ ++ /* ++ * Some hosts give a spurious success event after a short ++ * transfer. Ignore it. ++ */ ++ if ((xhci->quirks & XHCI_SPURIOUS_SUCCESS) && ++ ep_ring->last_td_was_short) { ++ ep_ring->last_td_was_short = false; ++ goto cleanup; ++ } ++ ++ /* ++ * xhci 4.10.2 states isoc endpoints should continue ++ * processing the next TD if there was an error mid TD. ++ * So host like NEC don't generate an event for the last ++ * isoc TRB even if the IOC flag is set. ++ * xhci 4.9.1 states that if there are errors in mult-TRB ++ * TDs xHC should generate an error for that TRB, and if xHC ++ * proceeds to the next TD it should genete an event for ++ * any TRB with IOC flag on the way. Other host follow this. ++ * So this event might be for the next TD. ++ */ ++ if (td->error_mid_td && ++ !list_is_last(&td->td_list, &ep_ring->td_list)) { ++ struct xhci_td *td_next = list_next_entry(td, td_list); ++ ++ ep_seg = trb_in_td(xhci, td_next->start_seg, td_next->first_trb, ++ td_next->last_trb, ep_trb_dma, false); ++ if (ep_seg) { ++ /* give back previous TD, start handling new */ ++ xhci_dbg(xhci, "Missing TD completion event after mid TD error\n"); ++ ep_ring->dequeue = td->last_trb; ++ ep_ring->deq_seg = td->last_trb_seg; ++ inc_deq(xhci, ep_ring); ++ xhci_td_cleanup(xhci, td, ep_ring, td->status); ++ td = td_next; + } ++ } ++ ++ if (!ep_seg) { + /* HC is busted, give up! */ + xhci_err(xhci, + "ERROR Transfer event TRB DMA ptr not " +@@ -2831,9 +2884,6 @@ static int handle_tx_event(struct xhci_hcd *xhci, + ep_trb_dma, true); + return -ESHUTDOWN; + } +- +- skip_isoc_td(xhci, td, ep, status); +- goto cleanup; + } + if (trb_comp_code == COMP_SHORT_PACKET) + ep_ring->last_td_was_short = true; +diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h +index 5df370482521f..31088602c0708 100644 +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -1573,6 +1573,7 @@ struct xhci_td { + struct xhci_segment *bounce_seg; + /* actual_length of the URB has already been set */ + bool urb_length_set; ++ bool error_mid_td; + unsigned int num_trbs; + }; + +diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c +index 1e61fe0431715..923e0ed85444b 100644 +--- a/drivers/usb/serial/cp210x.c ++++ b/drivers/usb/serial/cp210x.c +@@ -146,6 +146,7 @@ static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x10C4, 0x85F8) }, /* Virtenio Preon32 */ + { USB_DEVICE(0x10C4, 0x8664) }, /* AC-Services CAN-IF */ + { USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */ ++ { USB_DEVICE(0x10C4, 0x87ED) }, /* IMST USB-Stick for Smart Meter */ + { USB_DEVICE(0x10C4, 0x8856) }, /* CEL EM357 ZigBee USB Stick - LR */ + { USB_DEVICE(0x10C4, 0x8857) }, /* CEL EM357 ZigBee USB Stick */ + { USB_DEVICE(0x10C4, 0x88A4) }, /* MMB Networks ZigBee USB Device */ +diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c +index 72390dbf07692..2ae124c49d448 100644 +--- a/drivers/usb/serial/option.c ++++ b/drivers/usb/serial/option.c +@@ -2269,6 +2269,7 @@ static const struct usb_device_id option_ids[] = { + { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0111, 0xff) }, /* Fibocom FM160 (MBIM mode) */ + { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a0, 0xff) }, /* Fibocom NL668-AM/NL652-EU (laptop MBIM) */ + { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a2, 0xff) }, /* Fibocom FM101-GL (laptop MBIM) */ ++ { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a3, 0xff) }, /* Fibocom FM101-GL (laptop MBIM) */ + { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a4, 0xff), /* Fibocom FM101-GL (laptop MBIM) */ + .driver_info = RSVD(4) }, + { USB_DEVICE_INTERFACE_CLASS(0x2df3, 0x9d03, 0xff) }, /* LongSung M5710 */ +diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c +index b1e844bf31f81..703a9c5635573 100644 +--- a/drivers/usb/serial/qcserial.c ++++ b/drivers/usb/serial/qcserial.c +@@ -184,6 +184,8 @@ static const struct usb_device_id id_table[] = { + {DEVICE_SWI(0x413c, 0x81d0)}, /* Dell Wireless 5819 */ + {DEVICE_SWI(0x413c, 0x81d1)}, /* Dell Wireless 5818 */ + {DEVICE_SWI(0x413c, 0x81d2)}, /* Dell Wireless 5818 */ ++ {DEVICE_SWI(0x413c, 0x8217)}, /* Dell Wireless DW5826e */ ++ {DEVICE_SWI(0x413c, 0x8218)}, /* Dell Wireless DW5826e QDL */ + + /* Huawei devices */ + {DEVICE_HWI(0x03f0, 0x581d)}, /* HP lt4112 LTE/HSPA+ Gobi 4G Modem (Huawei me906e) */ +diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c +index 6d455ca76125e..47ae2d520fda5 100644 +--- a/drivers/usb/typec/tcpm/tcpm.c ++++ b/drivers/usb/typec/tcpm/tcpm.c +@@ -4862,8 +4862,7 @@ static void run_state_machine(struct tcpm_port *port) + break; + case PORT_RESET: + tcpm_reset_port(port); +- tcpm_set_cc(port, tcpm_default_state(port) == SNK_UNATTACHED ? +- TYPEC_CC_RD : tcpm_rp_cc(port)); ++ tcpm_set_cc(port, TYPEC_CC_OPEN); + tcpm_set_state(port, PORT_RESET_WAIT_OFF, + PD_T_ERROR_RECOVERY); + break; +diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c +index 1fd4ed19060db..529ca47da0353 100644 +--- a/fs/ext4/mballoc.c ++++ b/fs/ext4/mballoc.c +@@ -1232,6 +1232,24 @@ void ext4_mb_generate_buddy(struct super_block *sb, + atomic64_add(period, &sbi->s_mb_generation_time); + } + ++static void mb_regenerate_buddy(struct ext4_buddy *e4b) ++{ ++ int count; ++ int order = 1; ++ void *buddy; ++ ++ while ((buddy = mb_find_buddy(e4b, order++, &count))) ++ mb_set_bits(buddy, 0, count); ++ ++ e4b->bd_info->bb_fragments = 0; ++ memset(e4b->bd_info->bb_counters, 0, ++ sizeof(*e4b->bd_info->bb_counters) * ++ (e4b->bd_sb->s_blocksize_bits + 2)); ++ ++ ext4_mb_generate_buddy(e4b->bd_sb, e4b->bd_buddy, ++ e4b->bd_bitmap, e4b->bd_group, e4b->bd_info); ++} ++ + /* The buddy information is attached the buddy cache inode + * for convenience. The information regarding each group + * is loaded via ext4_mb_load_buddy. The information involve +@@ -1920,6 +1938,8 @@ static void mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b, + ext4_mark_group_bitmap_corrupted( + sb, e4b->bd_group, + EXT4_GROUP_INFO_BBITMAP_CORRUPT); ++ } else { ++ mb_regenerate_buddy(e4b); + } + goto done; + } +diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h +index 0e6a2777870c3..29a9b0b29e4f8 100644 +--- a/fs/ntfs3/ntfs_fs.h ++++ b/fs/ntfs3/ntfs_fs.h +@@ -473,7 +473,7 @@ bool al_delete_le(struct ntfs_inode *ni, enum ATTR_TYPE type, CLST vcn, + int al_update(struct ntfs_inode *ni, int sync); + static inline size_t al_aligned(size_t size) + { +- return (size + 1023) & ~(size_t)1023; ++ return size_add(size, 1023) & ~(size_t)1023; + } + + /* Globals from bitfunc.c */ +diff --git a/fs/smb/client/sess.c b/fs/smb/client/sess.c +index 62596299a3964..a20a5d0836dc9 100644 +--- a/fs/smb/client/sess.c ++++ b/fs/smb/client/sess.c +@@ -263,6 +263,8 @@ int cifs_try_adding_channels(struct cifs_ses *ses) + &iface->sockaddr, + rc); + kref_put(&iface->refcount, release_iface); ++ /* failure to add chan should increase weight */ ++ iface->weight_fulfilled++; + continue; + } + +diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c +index f5006aa97f5b3..5d9c87d2e1e01 100644 +--- a/fs/smb/client/smb2pdu.c ++++ b/fs/smb/client/smb2pdu.c +@@ -410,7 +410,7 @@ skip_sess_setup: + rc = SMB3_request_interfaces(xid, tcon, false); + free_xid(xid); + +- if (rc == -EOPNOTSUPP) { ++ if (rc == -EOPNOTSUPP && ses->chan_count > 1) { + /* + * some servers like Azure SMB server do not advertise + * that multichannel has been disabled with server +diff --git a/fs/xfs/Kconfig b/fs/xfs/Kconfig +index ed0bc8cbc703d..567fb37274d35 100644 +--- a/fs/xfs/Kconfig ++++ b/fs/xfs/Kconfig +@@ -147,7 +147,7 @@ config XFS_ONLINE_SCRUB_STATS + bool "XFS online metadata check usage data collection" + default y + depends on XFS_ONLINE_SCRUB +- select XFS_DEBUG ++ select DEBUG_FS + help + If you say Y here, the kernel will gather usage data about + the online metadata check subsystem. This includes the number +diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c +index 3069194527dd0..100ab5931b313 100644 +--- a/fs/xfs/libxfs/xfs_alloc.c ++++ b/fs/xfs/libxfs/xfs_alloc.c +@@ -2275,16 +2275,37 @@ xfs_alloc_min_freelist( + + ASSERT(mp->m_alloc_maxlevels > 0); + ++ /* ++ * For a btree shorter than the maximum height, the worst case is that ++ * every level gets split and a new level is added, then while inserting ++ * another entry to refill the AGFL, every level under the old root gets ++ * split again. This is: ++ * ++ * (full height split reservation) + (AGFL refill split height) ++ * = (current height + 1) + (current height - 1) ++ * = (new height) + (new height - 2) ++ * = 2 * new height - 2 ++ * ++ * For a btree of maximum height, the worst case is that every level ++ * under the root gets split, then while inserting another entry to ++ * refill the AGFL, every level under the root gets split again. This is ++ * also: ++ * ++ * 2 * (current height - 1) ++ * = 2 * (new height - 1) ++ * = 2 * new height - 2 ++ */ ++ + /* space needed by-bno freespace btree */ + min_free = min_t(unsigned int, levels[XFS_BTNUM_BNOi] + 1, +- mp->m_alloc_maxlevels); ++ mp->m_alloc_maxlevels) * 2 - 2; + /* space needed by-size freespace btree */ + min_free += min_t(unsigned int, levels[XFS_BTNUM_CNTi] + 1, +- mp->m_alloc_maxlevels); ++ mp->m_alloc_maxlevels) * 2 - 2; + /* space needed reverse mapping used space btree */ + if (xfs_has_rmapbt(mp)) + min_free += min_t(unsigned int, levels[XFS_BTNUM_RMAPi] + 1, +- mp->m_rmap_maxlevels); ++ mp->m_rmap_maxlevels) * 2 - 2; + + return min_free; + } +diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c +index 30c931b38853c..617cc7e78e384 100644 +--- a/fs/xfs/libxfs/xfs_bmap.c ++++ b/fs/xfs/libxfs/xfs_bmap.c +@@ -4827,7 +4827,7 @@ xfs_bmap_del_extent_delay( + ASSERT(got_endoff >= del_endoff); + + if (isrt) { +- uint64_t rtexts = XFS_FSB_TO_B(mp, del->br_blockcount); ++ uint64_t rtexts = del->br_blockcount; + + do_div(rtexts, mp->m_sb.sb_rextsize); + xfs_mod_frextents(mp, rtexts); +@@ -5057,33 +5057,20 @@ xfs_bmap_del_extent_real( + + flags = XFS_ILOG_CORE; + if (whichfork == XFS_DATA_FORK && XFS_IS_REALTIME_INODE(ip)) { +- xfs_filblks_t len; +- xfs_extlen_t mod; +- +- len = div_u64_rem(del->br_blockcount, mp->m_sb.sb_rextsize, +- &mod); +- ASSERT(mod == 0); +- + if (!(bflags & XFS_BMAPI_REMAP)) { +- xfs_fsblock_t bno; +- +- bno = div_u64_rem(del->br_startblock, +- mp->m_sb.sb_rextsize, &mod); +- ASSERT(mod == 0); +- +- error = xfs_rtfree_extent(tp, bno, (xfs_extlen_t)len); ++ error = xfs_rtfree_blocks(tp, del->br_startblock, ++ del->br_blockcount); + if (error) + goto done; + } + + do_fx = 0; +- nblks = len * mp->m_sb.sb_rextsize; + qfield = XFS_TRANS_DQ_RTBCOUNT; + } else { + do_fx = 1; +- nblks = del->br_blockcount; + qfield = XFS_TRANS_DQ_BCOUNT; + } ++ nblks = del->br_blockcount; + + del_endblock = del->br_startblock + del->br_blockcount; + if (cur) { +diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c +index bcfb6a4203cdd..f71679ce23b95 100644 +--- a/fs/xfs/libxfs/xfs_defer.c ++++ b/fs/xfs/libxfs/xfs_defer.c +@@ -245,21 +245,18 @@ xfs_defer_create_intents( + return ret; + } + +-/* Abort all the intents that were committed. */ + STATIC void +-xfs_defer_trans_abort( +- struct xfs_trans *tp, +- struct list_head *dop_pending) ++xfs_defer_pending_abort( ++ struct xfs_mount *mp, ++ struct list_head *dop_list) + { + struct xfs_defer_pending *dfp; + const struct xfs_defer_op_type *ops; + +- trace_xfs_defer_trans_abort(tp, _RET_IP_); +- + /* Abort intent items that don't have a done item. */ +- list_for_each_entry(dfp, dop_pending, dfp_list) { ++ list_for_each_entry(dfp, dop_list, dfp_list) { + ops = defer_op_types[dfp->dfp_type]; +- trace_xfs_defer_pending_abort(tp->t_mountp, dfp); ++ trace_xfs_defer_pending_abort(mp, dfp); + if (dfp->dfp_intent && !dfp->dfp_done) { + ops->abort_intent(dfp->dfp_intent); + dfp->dfp_intent = NULL; +@@ -267,6 +264,16 @@ xfs_defer_trans_abort( + } + } + ++/* Abort all the intents that were committed. */ ++STATIC void ++xfs_defer_trans_abort( ++ struct xfs_trans *tp, ++ struct list_head *dop_pending) ++{ ++ trace_xfs_defer_trans_abort(tp, _RET_IP_); ++ xfs_defer_pending_abort(tp->t_mountp, dop_pending); ++} ++ + /* + * Capture resources that the caller said not to release ("held") when the + * transaction commits. Caller is responsible for zero-initializing @dres. +@@ -756,12 +763,13 @@ xfs_defer_ops_capture( + + /* Release all resources that we used to capture deferred ops. */ + void +-xfs_defer_ops_capture_free( ++xfs_defer_ops_capture_abort( + struct xfs_mount *mp, + struct xfs_defer_capture *dfc) + { + unsigned short i; + ++ xfs_defer_pending_abort(mp, &dfc->dfc_dfops); + xfs_defer_cancel_list(mp, &dfc->dfc_dfops); + + for (i = 0; i < dfc->dfc_held.dr_bufs; i++) +@@ -802,7 +810,7 @@ xfs_defer_ops_capture_and_commit( + /* Commit the transaction and add the capture structure to the list. */ + error = xfs_trans_commit(tp); + if (error) { +- xfs_defer_ops_capture_free(mp, dfc); ++ xfs_defer_ops_capture_abort(mp, dfc); + return error; + } + +diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h +index 114a3a4930a3c..8788ad5f6a731 100644 +--- a/fs/xfs/libxfs/xfs_defer.h ++++ b/fs/xfs/libxfs/xfs_defer.h +@@ -121,7 +121,7 @@ int xfs_defer_ops_capture_and_commit(struct xfs_trans *tp, + struct list_head *capture_list); + void xfs_defer_ops_continue(struct xfs_defer_capture *d, struct xfs_trans *tp, + struct xfs_defer_resources *dres); +-void xfs_defer_ops_capture_free(struct xfs_mount *mp, ++void xfs_defer_ops_capture_abort(struct xfs_mount *mp, + struct xfs_defer_capture *d); + void xfs_defer_resources_rele(struct xfs_defer_resources *dres); + +diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c +index a35781577cad9..0f970a0b33824 100644 +--- a/fs/xfs/libxfs/xfs_inode_buf.c ++++ b/fs/xfs/libxfs/xfs_inode_buf.c +@@ -508,6 +508,9 @@ xfs_dinode_verify( + if (mode && nextents + naextents > nblocks) + return __this_address; + ++ if (nextents + naextents == 0 && nblocks != 0) ++ return __this_address; ++ + if (S_ISDIR(mode) && nextents > mp->m_dir_geo->max_extents) + return __this_address; + +diff --git a/fs/xfs/libxfs/xfs_rtbitmap.c b/fs/xfs/libxfs/xfs_rtbitmap.c +index fa180ab66b73a..655108a4cd05d 100644 +--- a/fs/xfs/libxfs/xfs_rtbitmap.c ++++ b/fs/xfs/libxfs/xfs_rtbitmap.c +@@ -1005,6 +1005,39 @@ xfs_rtfree_extent( + return 0; + } + ++/* ++ * Free some blocks in the realtime subvolume. rtbno and rtlen are in units of ++ * rt blocks, not rt extents; must be aligned to the rt extent size; and rtlen ++ * cannot exceed XFS_MAX_BMBT_EXTLEN. ++ */ ++int ++xfs_rtfree_blocks( ++ struct xfs_trans *tp, ++ xfs_fsblock_t rtbno, ++ xfs_filblks_t rtlen) ++{ ++ struct xfs_mount *mp = tp->t_mountp; ++ xfs_rtblock_t bno; ++ xfs_filblks_t len; ++ xfs_extlen_t mod; ++ ++ ASSERT(rtlen <= XFS_MAX_BMBT_EXTLEN); ++ ++ len = div_u64_rem(rtlen, mp->m_sb.sb_rextsize, &mod); ++ if (mod) { ++ ASSERT(mod == 0); ++ return -EIO; ++ } ++ ++ bno = div_u64_rem(rtbno, mp->m_sb.sb_rextsize, &mod); ++ if (mod) { ++ ASSERT(mod == 0); ++ return -EIO; ++ } ++ ++ return xfs_rtfree_extent(tp, bno, len); ++} ++ + /* Find all the free records within a given range. */ + int + xfs_rtalloc_query_range( +diff --git a/fs/xfs/libxfs/xfs_sb.h b/fs/xfs/libxfs/xfs_sb.h +index a5e14740ec9ac..19134b23c10be 100644 +--- a/fs/xfs/libxfs/xfs_sb.h ++++ b/fs/xfs/libxfs/xfs_sb.h +@@ -25,7 +25,7 @@ extern uint64_t xfs_sb_version_to_features(struct xfs_sb *sbp); + + extern int xfs_update_secondary_sbs(struct xfs_mount *mp); + +-#define XFS_FS_GEOM_MAX_STRUCT_VER (4) ++#define XFS_FS_GEOM_MAX_STRUCT_VER (5) + extern void xfs_fs_geometry(struct xfs_mount *mp, struct xfs_fsop_geom *geo, + int struct_version); + extern int xfs_sb_read_secondary(struct xfs_mount *mp, +diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c +index fcefab6872859..ad4aba5002c12 100644 +--- a/fs/xfs/xfs_bmap_util.c ++++ b/fs/xfs/xfs_bmap_util.c +@@ -780,12 +780,10 @@ xfs_alloc_file_space( + { + xfs_mount_t *mp = ip->i_mount; + xfs_off_t count; +- xfs_filblks_t allocated_fsb; + xfs_filblks_t allocatesize_fsb; + xfs_extlen_t extsz, temp; + xfs_fileoff_t startoffset_fsb; + xfs_fileoff_t endoffset_fsb; +- int nimaps; + int rt; + xfs_trans_t *tp; + xfs_bmbt_irec_t imaps[1], *imapp; +@@ -808,7 +806,6 @@ xfs_alloc_file_space( + + count = len; + imapp = &imaps[0]; +- nimaps = 1; + startoffset_fsb = XFS_B_TO_FSBT(mp, offset); + endoffset_fsb = XFS_B_TO_FSB(mp, offset + count); + allocatesize_fsb = endoffset_fsb - startoffset_fsb; +@@ -819,6 +816,7 @@ xfs_alloc_file_space( + while (allocatesize_fsb && !error) { + xfs_fileoff_t s, e; + unsigned int dblocks, rblocks, resblks; ++ int nimaps = 1; + + /* + * Determine space reservations for data/realtime. +@@ -884,15 +882,19 @@ xfs_alloc_file_space( + if (error) + break; + +- allocated_fsb = imapp->br_blockcount; +- +- if (nimaps == 0) { +- error = -ENOSPC; +- break; ++ /* ++ * If the allocator cannot find a single free extent large ++ * enough to cover the start block of the requested range, ++ * xfs_bmapi_write will return 0 but leave *nimaps set to 0. ++ * ++ * In that case we simply need to keep looping with the same ++ * startoffset_fsb so that one of the following allocations ++ * will eventually reach the requested range. ++ */ ++ if (nimaps) { ++ startoffset_fsb += imapp->br_blockcount; ++ allocatesize_fsb -= imapp->br_blockcount; + } +- +- startoffset_fsb += allocated_fsb; +- allocatesize_fsb -= allocated_fsb; + } + + return error; +diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c +index ac6ba646624df..a013b87ab8d5e 100644 +--- a/fs/xfs/xfs_dquot.c ++++ b/fs/xfs/xfs_dquot.c +@@ -562,7 +562,8 @@ xfs_dquot_from_disk( + struct xfs_dquot *dqp, + struct xfs_buf *bp) + { +- struct xfs_disk_dquot *ddqp = bp->b_addr + dqp->q_bufoffset; ++ struct xfs_dqblk *dqb = xfs_buf_offset(bp, dqp->q_bufoffset); ++ struct xfs_disk_dquot *ddqp = &dqb->dd_diskdq; + + /* + * Ensure that we got the type and ID we were looking for. +@@ -1250,7 +1251,7 @@ xfs_qm_dqflush( + } + + /* Flush the incore dquot to the ondisk buffer. */ +- dqblk = bp->b_addr + dqp->q_bufoffset; ++ dqblk = xfs_buf_offset(bp, dqp->q_bufoffset); + xfs_dquot_to_disk(&dqblk->dd_diskdq, dqp); + + /* +diff --git a/fs/xfs/xfs_dquot_item_recover.c b/fs/xfs/xfs_dquot_item_recover.c +index 8966ba842395b..2c2720ce69238 100644 +--- a/fs/xfs/xfs_dquot_item_recover.c ++++ b/fs/xfs/xfs_dquot_item_recover.c +@@ -19,6 +19,7 @@ + #include "xfs_log.h" + #include "xfs_log_priv.h" + #include "xfs_log_recover.h" ++#include "xfs_error.h" + + STATIC void + xlog_recover_dquot_ra_pass2( +@@ -65,6 +66,7 @@ xlog_recover_dquot_commit_pass2( + { + struct xfs_mount *mp = log->l_mp; + struct xfs_buf *bp; ++ struct xfs_dqblk *dqb; + struct xfs_disk_dquot *ddq, *recddq; + struct xfs_dq_logformat *dq_f; + xfs_failaddr_t fa; +@@ -130,14 +132,14 @@ xlog_recover_dquot_commit_pass2( + return error; + + ASSERT(bp); +- ddq = xfs_buf_offset(bp, dq_f->qlf_boffset); ++ dqb = xfs_buf_offset(bp, dq_f->qlf_boffset); ++ ddq = &dqb->dd_diskdq; + + /* + * If the dquot has an LSN in it, recover the dquot only if it's less + * than the lsn of the transaction we are replaying. + */ + if (xfs_has_crc(mp)) { +- struct xfs_dqblk *dqb = (struct xfs_dqblk *)ddq; + xfs_lsn_t lsn = be64_to_cpu(dqb->dd_lsn); + + if (lsn && lsn != -1 && XFS_LSN_CMP(lsn, current_lsn) >= 0) { +@@ -147,10 +149,23 @@ xlog_recover_dquot_commit_pass2( + + memcpy(ddq, recddq, item->ri_buf[1].i_len); + if (xfs_has_crc(mp)) { +- xfs_update_cksum((char *)ddq, sizeof(struct xfs_dqblk), ++ xfs_update_cksum((char *)dqb, sizeof(struct xfs_dqblk), + XFS_DQUOT_CRC_OFF); + } + ++ /* Validate the recovered dquot. */ ++ fa = xfs_dqblk_verify(log->l_mp, dqb, dq_f->qlf_id); ++ if (fa) { ++ XFS_CORRUPTION_ERROR("Bad dquot after recovery", ++ XFS_ERRLEVEL_LOW, mp, dqb, ++ sizeof(struct xfs_dqblk)); ++ xfs_alert(mp, ++ "Metadata corruption detected at %pS, dquot 0x%x", ++ fa, dq_f->qlf_id); ++ error = -EFSCORRUPTED; ++ goto out_release; ++ } ++ + ASSERT(dq_f->qlf_size == 2); + ASSERT(bp->b_mount == mp); + bp->b_flags |= _XBF_LOGRECOVERY; +diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c +index 203700278ddbb..e33e5e13b95f4 100644 +--- a/fs/xfs/xfs_file.c ++++ b/fs/xfs/xfs_file.c +@@ -214,6 +214,43 @@ xfs_ilock_iocb( + return 0; + } + ++static int ++xfs_ilock_iocb_for_write( ++ struct kiocb *iocb, ++ unsigned int *lock_mode) ++{ ++ ssize_t ret; ++ struct xfs_inode *ip = XFS_I(file_inode(iocb->ki_filp)); ++ ++ ret = xfs_ilock_iocb(iocb, *lock_mode); ++ if (ret) ++ return ret; ++ ++ if (*lock_mode == XFS_IOLOCK_EXCL) ++ return 0; ++ if (!xfs_iflags_test(ip, XFS_IREMAPPING)) ++ return 0; ++ ++ xfs_iunlock(ip, *lock_mode); ++ *lock_mode = XFS_IOLOCK_EXCL; ++ return xfs_ilock_iocb(iocb, *lock_mode); ++} ++ ++static unsigned int ++xfs_ilock_for_write_fault( ++ struct xfs_inode *ip) ++{ ++ /* get a shared lock if no remapping in progress */ ++ xfs_ilock(ip, XFS_MMAPLOCK_SHARED); ++ if (!xfs_iflags_test(ip, XFS_IREMAPPING)) ++ return XFS_MMAPLOCK_SHARED; ++ ++ /* wait for remapping to complete */ ++ xfs_iunlock(ip, XFS_MMAPLOCK_SHARED); ++ xfs_ilock(ip, XFS_MMAPLOCK_EXCL); ++ return XFS_MMAPLOCK_EXCL; ++} ++ + STATIC ssize_t + xfs_file_dio_read( + struct kiocb *iocb, +@@ -551,7 +588,7 @@ xfs_file_dio_write_aligned( + unsigned int iolock = XFS_IOLOCK_SHARED; + ssize_t ret; + +- ret = xfs_ilock_iocb(iocb, iolock); ++ ret = xfs_ilock_iocb_for_write(iocb, &iolock); + if (ret) + return ret; + ret = xfs_file_write_checks(iocb, from, &iolock); +@@ -618,7 +655,7 @@ retry_exclusive: + flags = IOMAP_DIO_FORCE_WAIT; + } + +- ret = xfs_ilock_iocb(iocb, iolock); ++ ret = xfs_ilock_iocb_for_write(iocb, &iolock); + if (ret) + return ret; + +@@ -1180,7 +1217,7 @@ xfs_file_remap_range( + if (xfs_file_sync_writes(file_in) || xfs_file_sync_writes(file_out)) + xfs_log_force_inode(dest); + out_unlock: +- xfs_iunlock2_io_mmap(src, dest); ++ xfs_iunlock2_remapping(src, dest); + if (ret) + trace_xfs_reflink_remap_range_error(dest, ret, _RET_IP_); + return remapped > 0 ? remapped : ret; +@@ -1328,6 +1365,7 @@ __xfs_filemap_fault( + struct inode *inode = file_inode(vmf->vma->vm_file); + struct xfs_inode *ip = XFS_I(inode); + vm_fault_t ret; ++ unsigned int lock_mode = 0; + + trace_xfs_filemap_fault(ip, order, write_fault); + +@@ -1336,25 +1374,24 @@ __xfs_filemap_fault( + file_update_time(vmf->vma->vm_file); + } + ++ if (IS_DAX(inode) || write_fault) ++ lock_mode = xfs_ilock_for_write_fault(XFS_I(inode)); ++ + if (IS_DAX(inode)) { + pfn_t pfn; + +- xfs_ilock(XFS_I(inode), XFS_MMAPLOCK_SHARED); + ret = xfs_dax_fault(vmf, order, write_fault, &pfn); + if (ret & VM_FAULT_NEEDDSYNC) + ret = dax_finish_sync_fault(vmf, order, pfn); +- xfs_iunlock(XFS_I(inode), XFS_MMAPLOCK_SHARED); ++ } else if (write_fault) { ++ ret = iomap_page_mkwrite(vmf, &xfs_page_mkwrite_iomap_ops); + } else { +- if (write_fault) { +- xfs_ilock(XFS_I(inode), XFS_MMAPLOCK_SHARED); +- ret = iomap_page_mkwrite(vmf, +- &xfs_page_mkwrite_iomap_ops); +- xfs_iunlock(XFS_I(inode), XFS_MMAPLOCK_SHARED); +- } else { +- ret = filemap_fault(vmf); +- } ++ ret = filemap_fault(vmf); + } + ++ if (lock_mode) ++ xfs_iunlock(XFS_I(inode), lock_mode); ++ + if (write_fault) + sb_end_pagefault(inode->i_sb); + return ret; +diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c +index 4d55f58d99b7a..f9d29acd72b9e 100644 +--- a/fs/xfs/xfs_inode.c ++++ b/fs/xfs/xfs_inode.c +@@ -918,6 +918,13 @@ xfs_droplink( + xfs_trans_t *tp, + xfs_inode_t *ip) + { ++ if (VFS_I(ip)->i_nlink == 0) { ++ xfs_alert(ip->i_mount, ++ "%s: Attempt to drop inode (%llu) with nlink zero.", ++ __func__, ip->i_ino); ++ return -EFSCORRUPTED; ++ } ++ + xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG); + + drop_nlink(VFS_I(ip)); +@@ -3621,6 +3628,23 @@ xfs_iunlock2_io_mmap( + inode_unlock(VFS_I(ip1)); + } + ++/* Drop the MMAPLOCK and the IOLOCK after a remap completes. */ ++void ++xfs_iunlock2_remapping( ++ struct xfs_inode *ip1, ++ struct xfs_inode *ip2) ++{ ++ xfs_iflags_clear(ip1, XFS_IREMAPPING); ++ ++ if (ip1 != ip2) ++ xfs_iunlock(ip1, XFS_MMAPLOCK_SHARED); ++ xfs_iunlock(ip2, XFS_MMAPLOCK_EXCL); ++ ++ if (ip1 != ip2) ++ inode_unlock_shared(VFS_I(ip1)); ++ inode_unlock(VFS_I(ip2)); ++} ++ + /* + * Reload the incore inode list for this inode. Caller should ensure that + * the link count cannot change, either by taking ILOCK_SHARED or otherwise +diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h +index 0c5bdb91152e1..3beb470f18920 100644 +--- a/fs/xfs/xfs_inode.h ++++ b/fs/xfs/xfs_inode.h +@@ -347,6 +347,14 @@ static inline bool xfs_inode_has_large_extent_counts(struct xfs_inode *ip) + /* Quotacheck is running but inode has not been added to quota counts. */ + #define XFS_IQUOTAUNCHECKED (1 << 14) + ++/* ++ * Remap in progress. Callers that wish to update file data while ++ * holding a shared IOLOCK or MMAPLOCK must drop the lock and retake ++ * the lock in exclusive mode. Relocking the file will block until ++ * IREMAPPING is cleared. ++ */ ++#define XFS_IREMAPPING (1U << 15) ++ + /* All inode state flags related to inode reclaim. */ + #define XFS_ALL_IRECLAIM_FLAGS (XFS_IRECLAIMABLE | \ + XFS_IRECLAIM | \ +@@ -561,6 +569,14 @@ extern void xfs_setup_inode(struct xfs_inode *ip); + extern void xfs_setup_iops(struct xfs_inode *ip); + extern void xfs_diflags_to_iflags(struct xfs_inode *ip, bool init); + ++static inline void xfs_update_stable_writes(struct xfs_inode *ip) ++{ ++ if (bdev_stable_writes(xfs_inode_buftarg(ip)->bt_bdev)) ++ mapping_set_stable_writes(VFS_I(ip)->i_mapping); ++ else ++ mapping_clear_stable_writes(VFS_I(ip)->i_mapping); ++} ++ + /* + * When setting up a newly allocated inode, we need to call + * xfs_finish_inode_setup() once the inode is fully instantiated at +@@ -595,6 +611,7 @@ void xfs_end_io(struct work_struct *work); + + int xfs_ilock2_io_mmap(struct xfs_inode *ip1, struct xfs_inode *ip2); + void xfs_iunlock2_io_mmap(struct xfs_inode *ip1, struct xfs_inode *ip2); ++void xfs_iunlock2_remapping(struct xfs_inode *ip1, struct xfs_inode *ip2); + + static inline bool + xfs_inode_unlinked_incomplete( +diff --git a/fs/xfs/xfs_inode_item_recover.c b/fs/xfs/xfs_inode_item_recover.c +index e6609067ef261..144198a6b2702 100644 +--- a/fs/xfs/xfs_inode_item_recover.c ++++ b/fs/xfs/xfs_inode_item_recover.c +@@ -286,6 +286,7 @@ xlog_recover_inode_commit_pass2( + struct xfs_log_dinode *ldip; + uint isize; + int need_free = 0; ++ xfs_failaddr_t fa; + + if (item->ri_buf[0].i_len == sizeof(struct xfs_inode_log_format)) { + in_f = item->ri_buf[0].i_addr; +@@ -530,8 +531,19 @@ out_owner_change: + (dip->di_mode != 0)) + error = xfs_recover_inode_owner_change(mp, dip, in_f, + buffer_list); +- /* re-generate the checksum. */ ++ /* re-generate the checksum and validate the recovered inode. */ + xfs_dinode_calc_crc(log->l_mp, dip); ++ fa = xfs_dinode_verify(log->l_mp, in_f->ilf_ino, dip); ++ if (fa) { ++ XFS_CORRUPTION_ERROR( ++ "Bad dinode after recovery", ++ XFS_ERRLEVEL_LOW, mp, dip, sizeof(*dip)); ++ xfs_alert(mp, ++ "Metadata corruption detected at %pS, inode 0x%llx", ++ fa, in_f->ilf_ino); ++ error = -EFSCORRUPTED; ++ goto out_release; ++ } + + ASSERT(bp->b_mount == mp); + bp->b_flags |= _XBF_LOGRECOVERY; +diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c +index 55bb01173cde8..535f6d38cdb54 100644 +--- a/fs/xfs/xfs_ioctl.c ++++ b/fs/xfs/xfs_ioctl.c +@@ -1120,23 +1120,25 @@ xfs_ioctl_setattr_xflags( + struct fileattr *fa) + { + struct xfs_mount *mp = ip->i_mount; ++ bool rtflag = (fa->fsx_xflags & FS_XFLAG_REALTIME); + uint64_t i_flags2; + +- /* Can't change realtime flag if any extents are allocated. */ +- if ((ip->i_df.if_nextents || ip->i_delayed_blks) && +- XFS_IS_REALTIME_INODE(ip) != (fa->fsx_xflags & FS_XFLAG_REALTIME)) +- return -EINVAL; ++ if (rtflag != XFS_IS_REALTIME_INODE(ip)) { ++ /* Can't change realtime flag if any extents are allocated. */ ++ if (ip->i_df.if_nextents || ip->i_delayed_blks) ++ return -EINVAL; ++ } + +- /* If realtime flag is set then must have realtime device */ +- if (fa->fsx_xflags & FS_XFLAG_REALTIME) { ++ if (rtflag) { ++ /* If realtime flag is set then must have realtime device */ + if (mp->m_sb.sb_rblocks == 0 || mp->m_sb.sb_rextsize == 0 || + (ip->i_extsize % mp->m_sb.sb_rextsize)) + return -EINVAL; +- } + +- /* Clear reflink if we are actually able to set the rt flag. */ +- if ((fa->fsx_xflags & FS_XFLAG_REALTIME) && xfs_is_reflink_inode(ip)) +- ip->i_diflags2 &= ~XFS_DIFLAG2_REFLINK; ++ /* Clear reflink if we are actually able to set the rt flag. */ ++ if (xfs_is_reflink_inode(ip)) ++ ip->i_diflags2 &= ~XFS_DIFLAG2_REFLINK; ++ } + + /* diflags2 only valid for v3 inodes. */ + i_flags2 = xfs_flags2diflags2(ip, fa->fsx_xflags); +@@ -1147,6 +1149,14 @@ xfs_ioctl_setattr_xflags( + ip->i_diflags2 = i_flags2; + + xfs_diflags_to_iflags(ip, false); ++ ++ /* ++ * Make the stable writes flag match that of the device the inode ++ * resides on when flipping the RT flag. ++ */ ++ if (rtflag != XFS_IS_REALTIME_INODE(ip) && S_ISREG(VFS_I(ip)->i_mode)) ++ xfs_update_stable_writes(ip); ++ + xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG); + xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); + XFS_STATS_INC(mp, xs_ig_attrchg); +diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c +index 2b3b05c28e9e4..b8ec045708c31 100644 +--- a/fs/xfs/xfs_iops.c ++++ b/fs/xfs/xfs_iops.c +@@ -1298,6 +1298,13 @@ xfs_setup_inode( + gfp_mask = mapping_gfp_mask(inode->i_mapping); + mapping_set_gfp_mask(inode->i_mapping, (gfp_mask & ~(__GFP_FS))); + ++ /* ++ * For real-time inodes update the stable write flags to that of the RT ++ * device instead of the data device. ++ */ ++ if (S_ISREG(inode->i_mode) && XFS_IS_REALTIME_INODE(ip)) ++ xfs_update_stable_writes(ip); ++ + /* + * If there is no attribute fork no ACL can exist on this inode, + * and it can't have any file capabilities attached to it either. +diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c +index 51c100c861770..ee206facf0dc0 100644 +--- a/fs/xfs/xfs_log.c ++++ b/fs/xfs/xfs_log.c +@@ -1893,9 +1893,7 @@ xlog_write_iclog( + * the buffer manually, the code needs to be kept in sync + * with the I/O completion path. + */ +- xlog_state_done_syncing(iclog); +- up(&iclog->ic_sema); +- return; ++ goto sync; + } + + /* +@@ -1925,20 +1923,17 @@ xlog_write_iclog( + * avoid shutdown re-entering this path and erroring out again. + */ + if (log->l_targ != log->l_mp->m_ddev_targp && +- blkdev_issue_flush(log->l_mp->m_ddev_targp->bt_bdev)) { +- xlog_force_shutdown(log, SHUTDOWN_LOG_IO_ERROR); +- return; +- } ++ blkdev_issue_flush(log->l_mp->m_ddev_targp->bt_bdev)) ++ goto shutdown; + } + if (iclog->ic_flags & XLOG_ICL_NEED_FUA) + iclog->ic_bio.bi_opf |= REQ_FUA; + + iclog->ic_flags &= ~(XLOG_ICL_NEED_FLUSH | XLOG_ICL_NEED_FUA); + +- if (xlog_map_iclog_data(&iclog->ic_bio, iclog->ic_data, count)) { +- xlog_force_shutdown(log, SHUTDOWN_LOG_IO_ERROR); +- return; +- } ++ if (xlog_map_iclog_data(&iclog->ic_bio, iclog->ic_data, count)) ++ goto shutdown; ++ + if (is_vmalloc_addr(iclog->ic_data)) + flush_kernel_vmap_range(iclog->ic_data, count); + +@@ -1959,6 +1954,12 @@ xlog_write_iclog( + } + + submit_bio(&iclog->ic_bio); ++ return; ++shutdown: ++ xlog_force_shutdown(log, SHUTDOWN_LOG_IO_ERROR); ++sync: ++ xlog_state_done_syncing(iclog); ++ up(&iclog->ic_sema); + } + + /* +diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c +index 13b94d2e605bd..a1e18b24971a2 100644 +--- a/fs/xfs/xfs_log_recover.c ++++ b/fs/xfs/xfs_log_recover.c +@@ -2511,7 +2511,7 @@ xlog_abort_defer_ops( + + list_for_each_entry_safe(dfc, next, capture_list, dfc_list) { + list_del_init(&dfc->dfc_list); +- xfs_defer_ops_capture_free(mp, dfc); ++ xfs_defer_ops_capture_abort(mp, dfc); + } + } + +diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c +index eb9102453affb..e5b62dc284664 100644 +--- a/fs/xfs/xfs_reflink.c ++++ b/fs/xfs/xfs_reflink.c +@@ -784,6 +784,7 @@ xfs_reflink_end_cow_extent( + } + } + del = got; ++ xfs_trim_extent(&del, *offset_fsb, end_fsb - *offset_fsb); + + /* Grab the corresponding mapping in the data fork. */ + nmaps = 1; +@@ -1540,6 +1541,10 @@ xfs_reflink_remap_prep( + if (ret) + goto out_unlock; + ++ xfs_iflags_set(src, XFS_IREMAPPING); ++ if (inode_in != inode_out) ++ xfs_ilock_demote(src, XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL); ++ + return 0; + out_unlock: + xfs_iunlock2_io_mmap(src, dest); +diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c +index 16534e9873f69..0e4e2df08aed0 100644 +--- a/fs/xfs/xfs_rtalloc.c ++++ b/fs/xfs/xfs_rtalloc.c +@@ -211,6 +211,23 @@ xfs_rtallocate_range( + return error; + } + ++/* ++ * Make sure we don't run off the end of the rt volume. Be careful that ++ * adjusting maxlen downwards doesn't cause us to fail the alignment checks. ++ */ ++static inline xfs_extlen_t ++xfs_rtallocate_clamp_len( ++ struct xfs_mount *mp, ++ xfs_rtblock_t startrtx, ++ xfs_extlen_t rtxlen, ++ xfs_extlen_t prod) ++{ ++ xfs_extlen_t ret; ++ ++ ret = min(mp->m_sb.sb_rextents, startrtx + rtxlen) - startrtx; ++ return rounddown(ret, prod); ++} ++ + /* + * Attempt to allocate an extent minlen<=len<=maxlen starting from + * bitmap block bbno. If we don't get maxlen then use prod to trim +@@ -248,7 +265,7 @@ xfs_rtallocate_extent_block( + i <= end; + i++) { + /* Make sure we don't scan off the end of the rt volume. */ +- maxlen = min(mp->m_sb.sb_rextents, i + maxlen) - i; ++ maxlen = xfs_rtallocate_clamp_len(mp, i, maxlen, prod); + + /* + * See if there's a free extent of maxlen starting at i. +@@ -355,7 +372,8 @@ xfs_rtallocate_extent_exact( + int isfree; /* extent is free */ + xfs_rtblock_t next; /* next block to try (dummy) */ + +- ASSERT(minlen % prod == 0 && maxlen % prod == 0); ++ ASSERT(minlen % prod == 0); ++ ASSERT(maxlen % prod == 0); + /* + * Check if the range in question (for maxlen) is free. + */ +@@ -438,7 +456,9 @@ xfs_rtallocate_extent_near( + xfs_rtblock_t n; /* next block to try */ + xfs_rtblock_t r; /* result block */ + +- ASSERT(minlen % prod == 0 && maxlen % prod == 0); ++ ASSERT(minlen % prod == 0); ++ ASSERT(maxlen % prod == 0); ++ + /* + * If the block number given is off the end, silently set it to + * the last block. +@@ -447,7 +467,7 @@ xfs_rtallocate_extent_near( + bno = mp->m_sb.sb_rextents - 1; + + /* Make sure we don't run off the end of the rt volume. */ +- maxlen = min(mp->m_sb.sb_rextents, bno + maxlen) - bno; ++ maxlen = xfs_rtallocate_clamp_len(mp, bno, maxlen, prod); + if (maxlen < minlen) { + *rtblock = NULLRTBLOCK; + return 0; +@@ -638,7 +658,8 @@ xfs_rtallocate_extent_size( + xfs_rtblock_t r; /* result block number */ + xfs_suminfo_t sum; /* summary information for extents */ + +- ASSERT(minlen % prod == 0 && maxlen % prod == 0); ++ ASSERT(minlen % prod == 0); ++ ASSERT(maxlen % prod == 0); + ASSERT(maxlen != 0); + + /* +@@ -954,7 +975,7 @@ xfs_growfs_rt( + return -EINVAL; + + /* Unsupported realtime features. */ +- if (xfs_has_rmapbt(mp) || xfs_has_reflink(mp)) ++ if (xfs_has_rmapbt(mp) || xfs_has_reflink(mp) || xfs_has_quota(mp)) + return -EOPNOTSUPP; + + nrblocks = in->newblocks; +diff --git a/fs/xfs/xfs_rtalloc.h b/fs/xfs/xfs_rtalloc.h +index 62c7ad79cbb61..65c284e9d33e9 100644 +--- a/fs/xfs/xfs_rtalloc.h ++++ b/fs/xfs/xfs_rtalloc.h +@@ -58,6 +58,10 @@ xfs_rtfree_extent( + xfs_rtblock_t bno, /* starting block number to free */ + xfs_extlen_t len); /* length of extent freed */ + ++/* Same as above, but in units of rt blocks. */ ++int xfs_rtfree_blocks(struct xfs_trans *tp, xfs_fsblock_t rtbno, ++ xfs_filblks_t rtlen); ++ + /* + * Initialize realtime fields in the mount structure. + */ +@@ -137,16 +141,17 @@ int xfs_rtalloc_extent_is_free(struct xfs_mount *mp, struct xfs_trans *tp, + bool *is_free); + int xfs_rtalloc_reinit_frextents(struct xfs_mount *mp); + #else +-# define xfs_rtallocate_extent(t,b,min,max,l,f,p,rb) (ENOSYS) +-# define xfs_rtfree_extent(t,b,l) (ENOSYS) +-# define xfs_rtpick_extent(m,t,l,rb) (ENOSYS) +-# define xfs_growfs_rt(mp,in) (ENOSYS) +-# define xfs_rtalloc_query_range(t,l,h,f,p) (ENOSYS) +-# define xfs_rtalloc_query_all(m,t,f,p) (ENOSYS) +-# define xfs_rtbuf_get(m,t,b,i,p) (ENOSYS) +-# define xfs_verify_rtbno(m, r) (false) +-# define xfs_rtalloc_extent_is_free(m,t,s,l,i) (ENOSYS) +-# define xfs_rtalloc_reinit_frextents(m) (0) ++# define xfs_rtallocate_extent(t,b,min,max,l,f,p,rb) (-ENOSYS) ++# define xfs_rtfree_extent(t,b,l) (-ENOSYS) ++# define xfs_rtfree_blocks(t,rb,rl) (-ENOSYS) ++# define xfs_rtpick_extent(m,t,l,rb) (-ENOSYS) ++# define xfs_growfs_rt(mp,in) (-ENOSYS) ++# define xfs_rtalloc_query_range(m,t,l,h,f,p) (-ENOSYS) ++# define xfs_rtalloc_query_all(m,t,f,p) (-ENOSYS) ++# define xfs_rtbuf_get(m,t,b,i,p) (-ENOSYS) ++# define xfs_verify_rtbno(m, r) (false) ++# define xfs_rtalloc_extent_is_free(m,t,s,l,i) (-ENOSYS) ++# define xfs_rtalloc_reinit_frextents(m) (0) + static inline int /* error */ + xfs_rtmount_init( + xfs_mount_t *mp) /* file system mount structure */ +@@ -157,7 +162,7 @@ xfs_rtmount_init( + xfs_warn(mp, "Not built with CONFIG_XFS_RT"); + return -ENOSYS; + } +-# define xfs_rtmount_inodes(m) (((mp)->m_sb.sb_rblocks == 0)? 0 : (ENOSYS)) ++# define xfs_rtmount_inodes(m) (((mp)->m_sb.sb_rblocks == 0)? 0 : (-ENOSYS)) + # define xfs_rtunmount_inodes(m) + #endif /* CONFIG_XFS_RT */ + +diff --git a/include/asm-generic/cacheflush.h b/include/asm-generic/cacheflush.h +index 84ec53ccc4502..7ee8a179d1036 100644 +--- a/include/asm-generic/cacheflush.h ++++ b/include/asm-generic/cacheflush.h +@@ -91,6 +91,12 @@ static inline void flush_cache_vmap(unsigned long start, unsigned long end) + } + #endif + ++#ifndef flush_cache_vmap_early ++static inline void flush_cache_vmap_early(unsigned long start, unsigned long end) ++{ ++} ++#endif ++ + #ifndef flush_cache_vunmap + static inline void flush_cache_vunmap(unsigned long start, unsigned long end) + { +diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h +index 2eaaabbe98cb6..1717cc57cdacd 100644 +--- a/include/linux/ceph/messenger.h ++++ b/include/linux/ceph/messenger.h +@@ -283,7 +283,7 @@ struct ceph_msg { + struct kref kref; + bool more_to_follow; + bool needs_out_seq; +- bool sparse_read; ++ u64 sparse_read_total; + int front_alloc_len; + + struct ceph_msgpool *pool; +diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h +index c3656e5902131..cff3dba658209 100644 +--- a/include/linux/dmaengine.h ++++ b/include/linux/dmaengine.h +@@ -955,7 +955,8 @@ static inline int dmaengine_slave_config(struct dma_chan *chan, + + static inline bool is_slave_direction(enum dma_transfer_direction direction) + { +- return (direction == DMA_MEM_TO_DEV) || (direction == DMA_DEV_TO_MEM); ++ return (direction == DMA_MEM_TO_DEV) || (direction == DMA_DEV_TO_MEM) || ++ (direction == DMA_DEV_TO_DEV); + } + + static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_single( +diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h +index f2044d5a652b5..254d4a898179c 100644 +--- a/include/linux/hrtimer.h ++++ b/include/linux/hrtimer.h +@@ -197,6 +197,7 @@ enum hrtimer_base_type { + * @max_hang_time: Maximum time spent in hrtimer_interrupt + * @softirq_expiry_lock: Lock which is taken while softirq based hrtimer are + * expired ++ * @online: CPU is online from an hrtimers point of view + * @timer_waiters: A hrtimer_cancel() invocation waits for the timer + * callback to finish. + * @expires_next: absolute time of the next event, is required for remote +@@ -219,7 +220,8 @@ struct hrtimer_cpu_base { + unsigned int hres_active : 1, + in_hrtirq : 1, + hang_detected : 1, +- softirq_activated : 1; ++ softirq_activated : 1, ++ online : 1; + #ifdef CONFIG_HIGH_RES_TIMERS + unsigned int nr_events; + unsigned short nr_retries; +diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h +index f7e537f64db45..0dd4a21d172da 100644 +--- a/include/trace/events/rxrpc.h ++++ b/include/trace/events/rxrpc.h +@@ -128,6 +128,7 @@ + EM(rxrpc_skb_eaten_by_unshare_nomem, "ETN unshar-nm") \ + EM(rxrpc_skb_get_conn_secured, "GET conn-secd") \ + EM(rxrpc_skb_get_conn_work, "GET conn-work") \ ++ EM(rxrpc_skb_get_last_nack, "GET last-nack") \ + EM(rxrpc_skb_get_local_work, "GET locl-work") \ + EM(rxrpc_skb_get_reject_work, "GET rej-work ") \ + EM(rxrpc_skb_get_to_recvmsg, "GET to-recv ") \ +@@ -141,6 +142,7 @@ + EM(rxrpc_skb_put_error_report, "PUT error-rep") \ + EM(rxrpc_skb_put_input, "PUT input ") \ + EM(rxrpc_skb_put_jumbo_subpacket, "PUT jumbo-sub") \ ++ EM(rxrpc_skb_put_last_nack, "PUT last-nack") \ + EM(rxrpc_skb_put_purge, "PUT purge ") \ + EM(rxrpc_skb_put_rotate, "PUT rotate ") \ + EM(rxrpc_skb_put_unknown, "PUT unknown ") \ +@@ -1549,7 +1551,7 @@ TRACE_EVENT(rxrpc_congest, + memcpy(&__entry->sum, summary, sizeof(__entry->sum)); + ), + +- TP_printk("c=%08x r=%08x %s q=%08x %s cw=%u ss=%u nA=%u,%u+%u r=%u b=%u u=%u d=%u l=%x%s%s%s", ++ TP_printk("c=%08x r=%08x %s q=%08x %s cw=%u ss=%u nA=%u,%u+%u,%u b=%u u=%u d=%u l=%x%s%s%s", + __entry->call, + __entry->ack_serial, + __print_symbolic(__entry->sum.ack_reason, rxrpc_ack_names), +@@ -1557,9 +1559,9 @@ TRACE_EVENT(rxrpc_congest, + __print_symbolic(__entry->sum.mode, rxrpc_congest_modes), + __entry->sum.cwnd, + __entry->sum.ssthresh, +- __entry->sum.nr_acks, __entry->sum.saw_nacks, ++ __entry->sum.nr_acks, __entry->sum.nr_retained_nacks, + __entry->sum.nr_new_acks, +- __entry->sum.nr_rot_new_acks, ++ __entry->sum.nr_new_nacks, + __entry->top - __entry->hard_ack, + __entry->sum.cumulative_acks, + __entry->sum.dup_acks, +diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h +index ca30232b7bc8a..117c6a9b845b1 100644 +--- a/include/uapi/linux/netfilter/nf_tables.h ++++ b/include/uapi/linux/netfilter/nf_tables.h +@@ -285,9 +285,11 @@ enum nft_rule_attributes { + /** + * enum nft_rule_compat_flags - nf_tables rule compat flags + * ++ * @NFT_RULE_COMPAT_F_UNUSED: unused + * @NFT_RULE_COMPAT_F_INV: invert the check result + */ + enum nft_rule_compat_flags { ++ NFT_RULE_COMPAT_F_UNUSED = (1 << 0), + NFT_RULE_COMPAT_F_INV = (1 << 1), + NFT_RULE_COMPAT_F_MASK = NFT_RULE_COMPAT_F_INV, + }; +diff --git a/io_uring/io_uring.h b/io_uring/io_uring.h +index d2bad1df347da..c8cba78310831 100644 +--- a/io_uring/io_uring.h ++++ b/io_uring/io_uring.h +@@ -30,6 +30,13 @@ enum { + IOU_OK = 0, + IOU_ISSUE_SKIP_COMPLETE = -EIOCBQUEUED, + ++ /* ++ * Requeue the task_work to restart operations on this request. The ++ * actual value isn't important, should just be not an otherwise ++ * valid error code, yet less than -MAX_ERRNO and valid internally. ++ */ ++ IOU_REQUEUE = -3072, ++ + /* + * Intended only when both IO_URING_F_MULTISHOT is passed + * to indicate to the poll runner that multishot should be +diff --git a/io_uring/net.c b/io_uring/net.c +index 75d494dad7e2c..43bc9a5f96f9d 100644 +--- a/io_uring/net.c ++++ b/io_uring/net.c +@@ -60,6 +60,7 @@ struct io_sr_msg { + unsigned len; + unsigned done_io; + unsigned msg_flags; ++ unsigned nr_multishot_loops; + u16 flags; + /* initialised and used only by !msg send variants */ + u16 addr_len; +@@ -70,6 +71,13 @@ struct io_sr_msg { + struct io_kiocb *notif; + }; + ++/* ++ * Number of times we'll try and do receives if there's more data. If we ++ * exceed this limit, then add us to the back of the queue and retry from ++ * there. This helps fairness between flooding clients. ++ */ ++#define MULTISHOT_MAX_RETRY 32 ++ + static inline bool io_check_multishot(struct io_kiocb *req, + unsigned int issue_flags) + { +@@ -611,6 +619,7 @@ int io_recvmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) + sr->msg_flags |= MSG_CMSG_COMPAT; + #endif + sr->done_io = 0; ++ sr->nr_multishot_loops = 0; + return 0; + } + +@@ -645,23 +654,35 @@ static inline bool io_recv_finish(struct io_kiocb *req, int *ret, + return true; + } + +- if (!mshot_finished) { +- if (io_fill_cqe_req_aux(req, issue_flags & IO_URING_F_COMPLETE_DEFER, +- *ret, cflags | IORING_CQE_F_MORE)) { +- io_recv_prep_retry(req); +- /* Known not-empty or unknown state, retry */ +- if (cflags & IORING_CQE_F_SOCK_NONEMPTY || +- msg->msg_inq == -1) ++ if (mshot_finished) ++ goto finish; ++ ++ /* ++ * Fill CQE for this receive and see if we should keep trying to ++ * receive from this socket. ++ */ ++ if (io_fill_cqe_req_aux(req, issue_flags & IO_URING_F_COMPLETE_DEFER, ++ *ret, cflags | IORING_CQE_F_MORE)) { ++ struct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg); ++ int mshot_retry_ret = IOU_ISSUE_SKIP_COMPLETE; ++ ++ io_recv_prep_retry(req); ++ /* Known not-empty or unknown state, retry */ ++ if (cflags & IORING_CQE_F_SOCK_NONEMPTY || msg->msg_inq == -1) { ++ if (sr->nr_multishot_loops++ < MULTISHOT_MAX_RETRY) + return false; +- if (issue_flags & IO_URING_F_MULTISHOT) +- *ret = IOU_ISSUE_SKIP_COMPLETE; +- else +- *ret = -EAGAIN; +- return true; ++ /* mshot retries exceeded, force a requeue */ ++ sr->nr_multishot_loops = 0; ++ mshot_retry_ret = IOU_REQUEUE; + } +- /* Otherwise stop multishot but use the current result. */ ++ if (issue_flags & IO_URING_F_MULTISHOT) ++ *ret = mshot_retry_ret; ++ else ++ *ret = -EAGAIN; ++ return true; + } +- ++ /* Otherwise stop multishot but use the current result. */ ++finish: + io_req_set_res(req, *ret, cflags); + + if (issue_flags & IO_URING_F_MULTISHOT) +@@ -902,6 +923,7 @@ retry_multishot: + if (!buf) + return -ENOBUFS; + sr->buf = buf; ++ sr->len = len; + } + + ret = import_ubuf(ITER_DEST, sr->buf, len, &msg.msg_iter); +diff --git a/io_uring/poll.c b/io_uring/poll.c +index 4c360ba8793a5..48ca0810a54af 100644 +--- a/io_uring/poll.c ++++ b/io_uring/poll.c +@@ -226,8 +226,24 @@ enum { + IOU_POLL_NO_ACTION = 1, + IOU_POLL_REMOVE_POLL_USE_RES = 2, + IOU_POLL_REISSUE = 3, ++ IOU_POLL_REQUEUE = 4, + }; + ++static void __io_poll_execute(struct io_kiocb *req, int mask) ++{ ++ io_req_set_res(req, mask, 0); ++ req->io_task_work.func = io_poll_task_func; ++ ++ trace_io_uring_task_add(req, mask); ++ io_req_task_work_add(req); ++} ++ ++static inline void io_poll_execute(struct io_kiocb *req, int res) ++{ ++ if (io_poll_get_ownership(req)) ++ __io_poll_execute(req, res); ++} ++ + /* + * All poll tw should go through this. Checks for poll events, manages + * references, does rewait, etc. +@@ -309,6 +325,8 @@ static int io_poll_check_events(struct io_kiocb *req, struct io_tw_state *ts) + int ret = io_poll_issue(req, ts); + if (ret == IOU_STOP_MULTISHOT) + return IOU_POLL_REMOVE_POLL_USE_RES; ++ else if (ret == IOU_REQUEUE) ++ return IOU_POLL_REQUEUE; + if (ret < 0) + return ret; + } +@@ -331,8 +349,12 @@ void io_poll_task_func(struct io_kiocb *req, struct io_tw_state *ts) + int ret; + + ret = io_poll_check_events(req, ts); +- if (ret == IOU_POLL_NO_ACTION) ++ if (ret == IOU_POLL_NO_ACTION) { ++ return; ++ } else if (ret == IOU_POLL_REQUEUE) { ++ __io_poll_execute(req, 0); + return; ++ } + io_poll_remove_entries(req); + io_poll_tw_hash_eject(req, ts); + +@@ -364,21 +386,6 @@ void io_poll_task_func(struct io_kiocb *req, struct io_tw_state *ts) + } + } + +-static void __io_poll_execute(struct io_kiocb *req, int mask) +-{ +- io_req_set_res(req, mask, 0); +- req->io_task_work.func = io_poll_task_func; +- +- trace_io_uring_task_add(req, mask); +- io_req_task_work_add(req); +-} +- +-static inline void io_poll_execute(struct io_kiocb *req, int res) +-{ +- if (io_poll_get_ownership(req)) +- __io_poll_execute(req, res); +-} +- + static void io_poll_cancel_req(struct io_kiocb *req) + { + io_poll_mark_cancelled(req); +diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c +index 760793998cdd7..edb0f821dceaa 100644 +--- a/kernel/time/hrtimer.c ++++ b/kernel/time/hrtimer.c +@@ -1085,6 +1085,7 @@ static int enqueue_hrtimer(struct hrtimer *timer, + enum hrtimer_mode mode) + { + debug_activate(timer, mode); ++ WARN_ON_ONCE(!base->cpu_base->online); + + base->cpu_base->active_bases |= 1 << base->index; + +@@ -2183,6 +2184,7 @@ int hrtimers_prepare_cpu(unsigned int cpu) + cpu_base->softirq_next_timer = NULL; + cpu_base->expires_next = KTIME_MAX; + cpu_base->softirq_expires_next = KTIME_MAX; ++ cpu_base->online = 1; + hrtimer_cpu_base_init_expiry_lock(cpu_base); + return 0; + } +@@ -2250,6 +2252,7 @@ int hrtimers_cpu_dying(unsigned int dying_cpu) + smp_call_function_single(ncpu, retrigger_next_event, NULL, 0); + + raw_spin_unlock(&new_base->lock); ++ old_base->online = 0; + raw_spin_unlock(&old_base->lock); + + return 0; +diff --git a/mm/percpu.c b/mm/percpu.c +index a7665de8485fd..d287cebd58caa 100644 +--- a/mm/percpu.c ++++ b/mm/percpu.c +@@ -3306,13 +3306,7 @@ int __init pcpu_page_first_chunk(size_t reserved_size, pcpu_fc_cpu_to_node_fn_t + if (rc < 0) + panic("failed to map percpu area, err=%d\n", rc); + +- /* +- * FIXME: Archs with virtual cache should flush local +- * cache for the linear mapping here - something +- * equivalent to flush_cache_vmap() on the local cpu. +- * flush_cache_vmap() can't be used as most supporting +- * data structures are not set up yet. +- */ ++ flush_cache_vmap_early(unit_addr, unit_addr + ai->unit_size); + + /* copy static data */ + memcpy((void *)unit_addr, __per_cpu_load, ai->static_size); +diff --git a/net/ceph/messenger_v1.c b/net/ceph/messenger_v1.c +index f9a50d7f0d204..0cb61c76b9b87 100644 +--- a/net/ceph/messenger_v1.c ++++ b/net/ceph/messenger_v1.c +@@ -160,8 +160,9 @@ static size_t sizeof_footer(struct ceph_connection *con) + static void prepare_message_data(struct ceph_msg *msg, u32 data_len) + { + /* Initialize data cursor if it's not a sparse read */ +- if (!msg->sparse_read) +- ceph_msg_data_cursor_init(&msg->cursor, msg, data_len); ++ u64 len = msg->sparse_read_total ? : data_len; ++ ++ ceph_msg_data_cursor_init(&msg->cursor, msg, len); + } + + /* +@@ -991,7 +992,7 @@ static inline int read_partial_message_section(struct ceph_connection *con, + return read_partial_message_chunk(con, section, sec_len, crc); + } + +-static int read_sparse_msg_extent(struct ceph_connection *con, u32 *crc) ++static int read_partial_sparse_msg_extent(struct ceph_connection *con, u32 *crc) + { + struct ceph_msg_data_cursor *cursor = &con->in_msg->cursor; + bool do_bounce = ceph_test_opt(from_msgr(con->msgr), RXBOUNCE); +@@ -1026,7 +1027,7 @@ static int read_sparse_msg_extent(struct ceph_connection *con, u32 *crc) + return 1; + } + +-static int read_sparse_msg_data(struct ceph_connection *con) ++static int read_partial_sparse_msg_data(struct ceph_connection *con) + { + struct ceph_msg_data_cursor *cursor = &con->in_msg->cursor; + bool do_datacrc = !ceph_test_opt(from_msgr(con->msgr), NOCRC); +@@ -1036,31 +1037,31 @@ static int read_sparse_msg_data(struct ceph_connection *con) + if (do_datacrc) + crc = con->in_data_crc; + +- do { ++ while (cursor->total_resid) { + if (con->v1.in_sr_kvec.iov_base) + ret = read_partial_message_chunk(con, + &con->v1.in_sr_kvec, + con->v1.in_sr_len, + &crc); + else if (cursor->sr_resid > 0) +- ret = read_sparse_msg_extent(con, &crc); +- +- if (ret <= 0) { +- if (do_datacrc) +- con->in_data_crc = crc; +- return ret; +- } ++ ret = read_partial_sparse_msg_extent(con, &crc); ++ if (ret <= 0) ++ break; + + memset(&con->v1.in_sr_kvec, 0, sizeof(con->v1.in_sr_kvec)); + ret = con->ops->sparse_read(con, cursor, + (char **)&con->v1.in_sr_kvec.iov_base); ++ if (ret <= 0) { ++ ret = ret ? ret : 1; /* must return > 0 to indicate success */ ++ break; ++ } + con->v1.in_sr_len = ret; +- } while (ret > 0); ++ } + + if (do_datacrc) + con->in_data_crc = crc; + +- return ret < 0 ? ret : 1; /* must return > 0 to indicate success */ ++ return ret; + } + + static int read_partial_msg_data(struct ceph_connection *con) +@@ -1253,8 +1254,8 @@ static int read_partial_message(struct ceph_connection *con) + if (!m->num_data_items) + return -EIO; + +- if (m->sparse_read) +- ret = read_sparse_msg_data(con); ++ if (m->sparse_read_total) ++ ret = read_partial_sparse_msg_data(con); + else if (ceph_test_opt(from_msgr(con->msgr), RXBOUNCE)) + ret = read_partial_msg_data_bounce(con); + else +diff --git a/net/ceph/messenger_v2.c b/net/ceph/messenger_v2.c +index d09a39ff2cf04..a901cae2f1060 100644 +--- a/net/ceph/messenger_v2.c ++++ b/net/ceph/messenger_v2.c +@@ -1132,7 +1132,7 @@ static int decrypt_tail(struct ceph_connection *con) + struct sg_table enc_sgt = {}; + struct sg_table sgt = {}; + struct page **pages = NULL; +- bool sparse = con->in_msg->sparse_read; ++ bool sparse = !!con->in_msg->sparse_read_total; + int dpos = 0; + int tail_len; + int ret; +@@ -2064,7 +2064,7 @@ static int prepare_read_tail_plain(struct ceph_connection *con) + } + + if (data_len(msg)) { +- if (msg->sparse_read) ++ if (msg->sparse_read_total) + con->v2.in_state = IN_S_PREPARE_SPARSE_DATA; + else + con->v2.in_state = IN_S_PREPARE_READ_DATA; +diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c +index d3a759e052c81..8d9760397b887 100644 +--- a/net/ceph/osd_client.c ++++ b/net/ceph/osd_client.c +@@ -5510,7 +5510,7 @@ static struct ceph_msg *get_reply(struct ceph_connection *con, + } + + m = ceph_msg_get(req->r_reply); +- m->sparse_read = (bool)srlen; ++ m->sparse_read_total = srlen; + + dout("get_reply tid %lld %p\n", tid, m); + +@@ -5777,11 +5777,8 @@ static int prep_next_sparse_read(struct ceph_connection *con, + } + + if (o->o_sparse_op_idx < 0) { +- u64 srlen = sparse_data_requested(req); +- +- dout("%s: [%d] starting new sparse read req. srlen=0x%llx\n", +- __func__, o->o_osd, srlen); +- ceph_msg_data_cursor_init(cursor, con->in_msg, srlen); ++ dout("%s: [%d] starting new sparse read req\n", ++ __func__, o->o_osd); + } else { + u64 end; + +diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c +index 1c58bd72e1245..e59962f34caa6 100644 +--- a/net/ipv4/af_inet.c ++++ b/net/ipv4/af_inet.c +@@ -1628,10 +1628,12 @@ EXPORT_SYMBOL(inet_current_timestamp); + + int inet_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) + { +- if (sk->sk_family == AF_INET) ++ unsigned int family = READ_ONCE(sk->sk_family); ++ ++ if (family == AF_INET) + return ip_recv_error(sk, msg, len, addr_len); + #if IS_ENABLED(CONFIG_IPV6) +- if (sk->sk_family == AF_INET6) ++ if (family == AF_INET6) + return pingv6_ops.ipv6_recv_error(sk, msg, len, addr_len); + #endif + return -EINVAL; +diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c +index 586b1b3e35b80..80ccd6661aa32 100644 +--- a/net/ipv4/ip_tunnel_core.c ++++ b/net/ipv4/ip_tunnel_core.c +@@ -332,7 +332,7 @@ static int iptunnel_pmtud_build_icmpv6(struct sk_buff *skb, int mtu) + }; + skb_reset_network_header(skb); + +- csum = csum_partial(icmp6h, len, 0); ++ csum = skb_checksum(skb, skb_transport_offset(skb), len, 0); + icmp6h->icmp6_cksum = csum_ipv6_magic(&nip6h->saddr, &nip6h->daddr, len, + IPPROTO_ICMPV6, csum); + +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index 73f8df03d159c..d9e716f38b0e9 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -7727,8 +7727,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, + + rcu_read_lock(); + beacon_ies = rcu_dereference(req->bss->beacon_ies); +- +- if (beacon_ies) { ++ if (!beacon_ies) { + /* + * Wait up to one beacon interval ... + * should this be more if we miss one? +diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c +index d45d4be63dd87..5481acbfc1d43 100644 +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -3086,10 +3086,11 @@ void ieee80211_check_fast_xmit(struct sta_info *sta) + /* DA SA BSSID */ + build.da_offs = offsetof(struct ieee80211_hdr, addr1); + build.sa_offs = offsetof(struct ieee80211_hdr, addr2); ++ rcu_read_lock(); + link = rcu_dereference(sdata->link[tdls_link_id]); +- if (WARN_ON_ONCE(!link)) +- break; +- memcpy(hdr->addr3, link->u.mgd.bssid, ETH_ALEN); ++ if (!WARN_ON_ONCE(!link)) ++ memcpy(hdr->addr3, link->u.mgd.bssid, ETH_ALEN); ++ rcu_read_unlock(); + build.hdr_len = 24; + break; + } +diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c +index f0eeda97bfcd9..1f9474fefe849 100644 +--- a/net/netfilter/nft_compat.c ++++ b/net/netfilter/nft_compat.c +@@ -135,7 +135,7 @@ static void nft_target_eval_bridge(const struct nft_expr *expr, + + static const struct nla_policy nft_target_policy[NFTA_TARGET_MAX + 1] = { + [NFTA_TARGET_NAME] = { .type = NLA_NUL_STRING }, +- [NFTA_TARGET_REV] = { .type = NLA_U32 }, ++ [NFTA_TARGET_REV] = NLA_POLICY_MAX(NLA_BE32, 255), + [NFTA_TARGET_INFO] = { .type = NLA_BINARY }, + }; + +@@ -200,6 +200,7 @@ static const struct nla_policy nft_rule_compat_policy[NFTA_RULE_COMPAT_MAX + 1] + static int nft_parse_compat(const struct nlattr *attr, u16 *proto, bool *inv) + { + struct nlattr *tb[NFTA_RULE_COMPAT_MAX+1]; ++ u32 l4proto; + u32 flags; + int err; + +@@ -212,12 +213,18 @@ static int nft_parse_compat(const struct nlattr *attr, u16 *proto, bool *inv) + return -EINVAL; + + flags = ntohl(nla_get_be32(tb[NFTA_RULE_COMPAT_FLAGS])); +- if (flags & ~NFT_RULE_COMPAT_F_MASK) ++ if (flags & NFT_RULE_COMPAT_F_UNUSED || ++ flags & ~NFT_RULE_COMPAT_F_MASK) + return -EINVAL; + if (flags & NFT_RULE_COMPAT_F_INV) + *inv = true; + +- *proto = ntohl(nla_get_be32(tb[NFTA_RULE_COMPAT_PROTO])); ++ l4proto = ntohl(nla_get_be32(tb[NFTA_RULE_COMPAT_PROTO])); ++ if (l4proto > U16_MAX) ++ return -EINVAL; ++ ++ *proto = l4proto; ++ + return 0; + } + +@@ -419,7 +426,7 @@ static void nft_match_eval(const struct nft_expr *expr, + + static const struct nla_policy nft_match_policy[NFTA_MATCH_MAX + 1] = { + [NFTA_MATCH_NAME] = { .type = NLA_NUL_STRING }, +- [NFTA_MATCH_REV] = { .type = NLA_U32 }, ++ [NFTA_MATCH_REV] = NLA_POLICY_MAX(NLA_BE32, 255), + [NFTA_MATCH_INFO] = { .type = NLA_BINARY }, + }; + +@@ -724,7 +731,7 @@ out_put: + static const struct nla_policy nfnl_compat_policy_get[NFTA_COMPAT_MAX+1] = { + [NFTA_COMPAT_NAME] = { .type = NLA_NUL_STRING, + .len = NFT_COMPAT_NAME_MAX-1 }, +- [NFTA_COMPAT_REV] = { .type = NLA_U32 }, ++ [NFTA_COMPAT_REV] = NLA_POLICY_MAX(NLA_BE32, 255), + [NFTA_COMPAT_TYPE] = { .type = NLA_U32 }, + }; + +diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c +index aac98a3c966e9..bfd3e5a14dab6 100644 +--- a/net/netfilter/nft_ct.c ++++ b/net/netfilter/nft_ct.c +@@ -476,6 +476,9 @@ static int nft_ct_get_init(const struct nft_ctx *ctx, + break; + #endif + case NFT_CT_ID: ++ if (tb[NFTA_CT_DIRECTION]) ++ return -EINVAL; ++ + len = sizeof(u32); + break; + default: +diff --git a/net/netfilter/nft_set_pipapo.c b/net/netfilter/nft_set_pipapo.c +index 3ff31043f7148..8e9b200779666 100644 +--- a/net/netfilter/nft_set_pipapo.c ++++ b/net/netfilter/nft_set_pipapo.c +@@ -342,9 +342,6 @@ + #include "nft_set_pipapo_avx2.h" + #include "nft_set_pipapo.h" + +-/* Current working bitmap index, toggled between field matches */ +-static DEFINE_PER_CPU(bool, nft_pipapo_scratch_index); +- + /** + * pipapo_refill() - For each set bit, set bits from selected mapping table item + * @map: Bitmap to be scanned for set bits +@@ -412,6 +409,7 @@ bool nft_pipapo_lookup(const struct net *net, const struct nft_set *set, + const u32 *key, const struct nft_set_ext **ext) + { + struct nft_pipapo *priv = nft_set_priv(set); ++ struct nft_pipapo_scratch *scratch; + unsigned long *res_map, *fill_map; + u8 genmask = nft_genmask_cur(net); + const u8 *rp = (const u8 *)key; +@@ -422,15 +420,17 @@ bool nft_pipapo_lookup(const struct net *net, const struct nft_set *set, + + local_bh_disable(); + +- map_index = raw_cpu_read(nft_pipapo_scratch_index); +- + m = rcu_dereference(priv->match); + + if (unlikely(!m || !*raw_cpu_ptr(m->scratch))) + goto out; + +- res_map = *raw_cpu_ptr(m->scratch) + (map_index ? m->bsize_max : 0); +- fill_map = *raw_cpu_ptr(m->scratch) + (map_index ? 0 : m->bsize_max); ++ scratch = *raw_cpu_ptr(m->scratch); ++ ++ map_index = scratch->map_index; ++ ++ res_map = scratch->map + (map_index ? m->bsize_max : 0); ++ fill_map = scratch->map + (map_index ? 0 : m->bsize_max); + + memset(res_map, 0xff, m->bsize_max * sizeof(*res_map)); + +@@ -460,7 +460,7 @@ next_match: + b = pipapo_refill(res_map, f->bsize, f->rules, fill_map, f->mt, + last); + if (b < 0) { +- raw_cpu_write(nft_pipapo_scratch_index, map_index); ++ scratch->map_index = map_index; + local_bh_enable(); + + return false; +@@ -477,7 +477,7 @@ next_match: + * current inactive bitmap is clean and can be reused as + * *next* bitmap (not initial) for the next packet. + */ +- raw_cpu_write(nft_pipapo_scratch_index, map_index); ++ scratch->map_index = map_index; + local_bh_enable(); + + return true; +@@ -1101,6 +1101,25 @@ static void pipapo_map(struct nft_pipapo_match *m, + f->mt[map[i].to + j].e = e; + } + ++/** ++ * pipapo_free_scratch() - Free per-CPU map at original (not aligned) address ++ * @m: Matching data ++ * @cpu: CPU number ++ */ ++static void pipapo_free_scratch(const struct nft_pipapo_match *m, unsigned int cpu) ++{ ++ struct nft_pipapo_scratch *s; ++ void *mem; ++ ++ s = *per_cpu_ptr(m->scratch, cpu); ++ if (!s) ++ return; ++ ++ mem = s; ++ mem -= s->align_off; ++ kfree(mem); ++} ++ + /** + * pipapo_realloc_scratch() - Reallocate scratch maps for partial match results + * @clone: Copy of matching data with pending insertions and deletions +@@ -1114,12 +1133,13 @@ static int pipapo_realloc_scratch(struct nft_pipapo_match *clone, + int i; + + for_each_possible_cpu(i) { +- unsigned long *scratch; ++ struct nft_pipapo_scratch *scratch; + #ifdef NFT_PIPAPO_ALIGN +- unsigned long *scratch_aligned; ++ void *scratch_aligned; ++ u32 align_off; + #endif +- +- scratch = kzalloc_node(bsize_max * sizeof(*scratch) * 2 + ++ scratch = kzalloc_node(struct_size(scratch, map, ++ bsize_max * 2) + + NFT_PIPAPO_ALIGN_HEADROOM, + GFP_KERNEL, cpu_to_node(i)); + if (!scratch) { +@@ -1133,14 +1153,25 @@ static int pipapo_realloc_scratch(struct nft_pipapo_match *clone, + return -ENOMEM; + } + +- kfree(*per_cpu_ptr(clone->scratch, i)); +- +- *per_cpu_ptr(clone->scratch, i) = scratch; ++ pipapo_free_scratch(clone, i); + + #ifdef NFT_PIPAPO_ALIGN +- scratch_aligned = NFT_PIPAPO_LT_ALIGN(scratch); +- *per_cpu_ptr(clone->scratch_aligned, i) = scratch_aligned; ++ /* Align &scratch->map (not the struct itself): the extra ++ * %NFT_PIPAPO_ALIGN_HEADROOM bytes passed to kzalloc_node() ++ * above guarantee we can waste up to those bytes in order ++ * to align the map field regardless of its offset within ++ * the struct. ++ */ ++ BUILD_BUG_ON(offsetof(struct nft_pipapo_scratch, map) > NFT_PIPAPO_ALIGN_HEADROOM); ++ ++ scratch_aligned = NFT_PIPAPO_LT_ALIGN(&scratch->map); ++ scratch_aligned -= offsetof(struct nft_pipapo_scratch, map); ++ align_off = scratch_aligned - (void *)scratch; ++ ++ scratch = scratch_aligned; ++ scratch->align_off = align_off; + #endif ++ *per_cpu_ptr(clone->scratch, i) = scratch; + } + + return 0; +@@ -1293,11 +1324,6 @@ static struct nft_pipapo_match *pipapo_clone(struct nft_pipapo_match *old) + if (!new->scratch) + goto out_scratch; + +-#ifdef NFT_PIPAPO_ALIGN +- new->scratch_aligned = alloc_percpu(*new->scratch_aligned); +- if (!new->scratch_aligned) +- goto out_scratch; +-#endif + for_each_possible_cpu(i) + *per_cpu_ptr(new->scratch, i) = NULL; + +@@ -1349,10 +1375,7 @@ out_lt: + } + out_scratch_realloc: + for_each_possible_cpu(i) +- kfree(*per_cpu_ptr(new->scratch, i)); +-#ifdef NFT_PIPAPO_ALIGN +- free_percpu(new->scratch_aligned); +-#endif ++ pipapo_free_scratch(new, i); + out_scratch: + free_percpu(new->scratch); + kfree(new); +@@ -1637,13 +1660,9 @@ static void pipapo_free_match(struct nft_pipapo_match *m) + int i; + + for_each_possible_cpu(i) +- kfree(*per_cpu_ptr(m->scratch, i)); ++ pipapo_free_scratch(m, i); + +-#ifdef NFT_PIPAPO_ALIGN +- free_percpu(m->scratch_aligned); +-#endif + free_percpu(m->scratch); +- + pipapo_free_fields(m); + + kfree(m); +@@ -2130,7 +2149,7 @@ static int nft_pipapo_init(const struct nft_set *set, + m->field_count = field_count; + m->bsize_max = 0; + +- m->scratch = alloc_percpu(unsigned long *); ++ m->scratch = alloc_percpu(struct nft_pipapo_scratch *); + if (!m->scratch) { + err = -ENOMEM; + goto out_scratch; +@@ -2138,16 +2157,6 @@ static int nft_pipapo_init(const struct nft_set *set, + for_each_possible_cpu(i) + *per_cpu_ptr(m->scratch, i) = NULL; + +-#ifdef NFT_PIPAPO_ALIGN +- m->scratch_aligned = alloc_percpu(unsigned long *); +- if (!m->scratch_aligned) { +- err = -ENOMEM; +- goto out_free; +- } +- for_each_possible_cpu(i) +- *per_cpu_ptr(m->scratch_aligned, i) = NULL; +-#endif +- + rcu_head_init(&m->rcu); + + nft_pipapo_for_each_field(f, i, m) { +@@ -2178,9 +2187,6 @@ static int nft_pipapo_init(const struct nft_set *set, + return 0; + + out_free: +-#ifdef NFT_PIPAPO_ALIGN +- free_percpu(m->scratch_aligned); +-#endif + free_percpu(m->scratch); + out_scratch: + kfree(m); +@@ -2234,11 +2240,8 @@ static void nft_pipapo_destroy(const struct nft_ctx *ctx, + + nft_set_pipapo_match_destroy(ctx, set, m); + +-#ifdef NFT_PIPAPO_ALIGN +- free_percpu(m->scratch_aligned); +-#endif + for_each_possible_cpu(cpu) +- kfree(*per_cpu_ptr(m->scratch, cpu)); ++ pipapo_free_scratch(m, cpu); + free_percpu(m->scratch); + pipapo_free_fields(m); + kfree(m); +@@ -2251,11 +2254,8 @@ static void nft_pipapo_destroy(const struct nft_ctx *ctx, + if (priv->dirty) + nft_set_pipapo_match_destroy(ctx, set, m); + +-#ifdef NFT_PIPAPO_ALIGN +- free_percpu(priv->clone->scratch_aligned); +-#endif + for_each_possible_cpu(cpu) +- kfree(*per_cpu_ptr(priv->clone->scratch, cpu)); ++ pipapo_free_scratch(priv->clone, cpu); + free_percpu(priv->clone->scratch); + + pipapo_free_fields(priv->clone); +diff --git a/net/netfilter/nft_set_pipapo.h b/net/netfilter/nft_set_pipapo.h +index 2e164a319945f..a4a58812c1088 100644 +--- a/net/netfilter/nft_set_pipapo.h ++++ b/net/netfilter/nft_set_pipapo.h +@@ -130,21 +130,29 @@ struct nft_pipapo_field { + union nft_pipapo_map_bucket *mt; + }; + ++/** ++ * struct nft_pipapo_scratch - percpu data used for lookup and matching ++ * @map_index: Current working bitmap index, toggled between field matches ++ * @align_off: Offset to get the originally allocated address ++ * @map: store partial matching results during lookup ++ */ ++struct nft_pipapo_scratch { ++ u8 map_index; ++ u32 align_off; ++ unsigned long map[]; ++}; ++ + /** + * struct nft_pipapo_match - Data used for lookup and matching + * @field_count Amount of fields in set + * @scratch: Preallocated per-CPU maps for partial matching results +- * @scratch_aligned: Version of @scratch aligned to NFT_PIPAPO_ALIGN bytes + * @bsize_max: Maximum lookup table bucket size of all fields, in longs + * @rcu Matching data is swapped on commits + * @f: Fields, with lookup and mapping tables + */ + struct nft_pipapo_match { + int field_count; +-#ifdef NFT_PIPAPO_ALIGN +- unsigned long * __percpu *scratch_aligned; +-#endif +- unsigned long * __percpu *scratch; ++ struct nft_pipapo_scratch * __percpu *scratch; + size_t bsize_max; + struct rcu_head rcu; + struct nft_pipapo_field f[] __counted_by(field_count); +diff --git a/net/netfilter/nft_set_pipapo_avx2.c b/net/netfilter/nft_set_pipapo_avx2.c +index 52e0d026d30ad..90e275bb3e5d7 100644 +--- a/net/netfilter/nft_set_pipapo_avx2.c ++++ b/net/netfilter/nft_set_pipapo_avx2.c +@@ -71,9 +71,6 @@ + #define NFT_PIPAPO_AVX2_ZERO(reg) \ + asm volatile("vpxor %ymm" #reg ", %ymm" #reg ", %ymm" #reg) + +-/* Current working bitmap index, toggled between field matches */ +-static DEFINE_PER_CPU(bool, nft_pipapo_avx2_scratch_index); +- + /** + * nft_pipapo_avx2_prepare() - Prepare before main algorithm body + * +@@ -1120,11 +1117,12 @@ bool nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set, + const u32 *key, const struct nft_set_ext **ext) + { + struct nft_pipapo *priv = nft_set_priv(set); +- unsigned long *res, *fill, *scratch; ++ struct nft_pipapo_scratch *scratch; + u8 genmask = nft_genmask_cur(net); + const u8 *rp = (const u8 *)key; + struct nft_pipapo_match *m; + struct nft_pipapo_field *f; ++ unsigned long *res, *fill; + bool map_index; + int i, ret = 0; + +@@ -1141,15 +1139,16 @@ bool nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set, + */ + kernel_fpu_begin_mask(0); + +- scratch = *raw_cpu_ptr(m->scratch_aligned); ++ scratch = *raw_cpu_ptr(m->scratch); + if (unlikely(!scratch)) { + kernel_fpu_end(); + return false; + } +- map_index = raw_cpu_read(nft_pipapo_avx2_scratch_index); + +- res = scratch + (map_index ? m->bsize_max : 0); +- fill = scratch + (map_index ? 0 : m->bsize_max); ++ map_index = scratch->map_index; ++ ++ res = scratch->map + (map_index ? m->bsize_max : 0); ++ fill = scratch->map + (map_index ? 0 : m->bsize_max); + + /* Starting map doesn't need to be set for this implementation */ + +@@ -1221,7 +1220,7 @@ next_match: + + out: + if (i % 2) +- raw_cpu_write(nft_pipapo_avx2_scratch_index, !map_index); ++ scratch->map_index = !map_index; + kernel_fpu_end(); + + return ret >= 0; +diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c +index e34662f4a71e0..5bf5572e945cc 100644 +--- a/net/netfilter/nft_set_rbtree.c ++++ b/net/netfilter/nft_set_rbtree.c +@@ -235,7 +235,7 @@ static void nft_rbtree_gc_remove(struct net *net, struct nft_set *set, + + static const struct nft_rbtree_elem * + nft_rbtree_gc_elem(const struct nft_set *__set, struct nft_rbtree *priv, +- struct nft_rbtree_elem *rbe, u8 genmask) ++ struct nft_rbtree_elem *rbe) + { + struct nft_set *set = (struct nft_set *)__set; + struct rb_node *prev = rb_prev(&rbe->node); +@@ -254,7 +254,7 @@ nft_rbtree_gc_elem(const struct nft_set *__set, struct nft_rbtree *priv, + while (prev) { + rbe_prev = rb_entry(prev, struct nft_rbtree_elem, node); + if (nft_rbtree_interval_end(rbe_prev) && +- nft_set_elem_active(&rbe_prev->ext, genmask)) ++ nft_set_elem_active(&rbe_prev->ext, NFT_GENMASK_ANY)) + break; + + prev = rb_prev(prev); +@@ -365,7 +365,7 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set, + nft_set_elem_active(&rbe->ext, cur_genmask)) { + const struct nft_rbtree_elem *removed_end; + +- removed_end = nft_rbtree_gc_elem(set, priv, rbe, genmask); ++ removed_end = nft_rbtree_gc_elem(set, priv, rbe); + if (IS_ERR(removed_end)) + return PTR_ERR(removed_end); + +diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h +index e8b43408136ab..bda3f6690b321 100644 +--- a/net/rxrpc/ar-internal.h ++++ b/net/rxrpc/ar-internal.h +@@ -198,11 +198,19 @@ struct rxrpc_host_header { + */ + struct rxrpc_skb_priv { + struct rxrpc_connection *conn; /* Connection referred to (poke packet) */ +- u16 offset; /* Offset of data */ +- u16 len; /* Length of data */ +- u8 flags; ++ union { ++ struct { ++ u16 offset; /* Offset of data */ ++ u16 len; /* Length of data */ ++ u8 flags; + #define RXRPC_RX_VERIFIED 0x01 +- ++ }; ++ struct { ++ rxrpc_seq_t first_ack; /* First packet in acks table */ ++ u8 nr_acks; /* Number of acks+nacks */ ++ u8 nr_nacks; /* Number of nacks */ ++ }; ++ }; + struct rxrpc_host_header hdr; /* RxRPC packet header from this packet */ + }; + +@@ -506,7 +514,7 @@ struct rxrpc_connection { + enum rxrpc_call_completion completion; /* Completion condition */ + s32 abort_code; /* Abort code of connection abort */ + int debug_id; /* debug ID for printks */ +- atomic_t serial; /* packet serial number counter */ ++ rxrpc_serial_t tx_serial; /* Outgoing packet serial number counter */ + unsigned int hi_serial; /* highest serial number received */ + u32 service_id; /* Service ID, possibly upgraded */ + u32 security_level; /* Security level selected */ +@@ -688,11 +696,11 @@ struct rxrpc_call { + u8 cong_dup_acks; /* Count of ACKs showing missing packets */ + u8 cong_cumul_acks; /* Cumulative ACK count */ + ktime_t cong_tstamp; /* Last time cwnd was changed */ ++ struct sk_buff *cong_last_nack; /* Last ACK with nacks received */ + + /* Receive-phase ACK management (ACKs we send). */ + u8 ackr_reason; /* reason to ACK */ + u16 ackr_sack_base; /* Starting slot in SACK table ring */ +- rxrpc_serial_t ackr_serial; /* serial of packet being ACK'd */ + rxrpc_seq_t ackr_window; /* Base of SACK window */ + rxrpc_seq_t ackr_wtop; /* Base of SACK window */ + unsigned int ackr_nr_unacked; /* Number of unacked packets */ +@@ -726,7 +734,8 @@ struct rxrpc_call { + struct rxrpc_ack_summary { + u16 nr_acks; /* Number of ACKs in packet */ + u16 nr_new_acks; /* Number of new ACKs in packet */ +- u16 nr_rot_new_acks; /* Number of rotated new ACKs */ ++ u16 nr_new_nacks; /* Number of new nacks in packet */ ++ u16 nr_retained_nacks; /* Number of nacks retained between ACKs */ + u8 ack_reason; + bool saw_nacks; /* Saw NACKs in packet */ + bool new_low_nack; /* T if new low NACK found */ +@@ -818,6 +827,20 @@ static inline bool rxrpc_sending_to_client(const struct rxrpc_txbuf *txb) + + #include <trace/events/rxrpc.h> + ++/* ++ * Allocate the next serial number on a connection. 0 must be skipped. ++ */ ++static inline rxrpc_serial_t rxrpc_get_next_serial(struct rxrpc_connection *conn) ++{ ++ rxrpc_serial_t serial; ++ ++ serial = conn->tx_serial; ++ if (serial == 0) ++ serial = 1; ++ conn->tx_serial = serial + 1; ++ return serial; ++} ++ + /* + * af_rxrpc.c + */ +diff --git a/net/rxrpc/call_event.c b/net/rxrpc/call_event.c +index e363f21a20141..0f78544d043be 100644 +--- a/net/rxrpc/call_event.c ++++ b/net/rxrpc/call_event.c +@@ -43,8 +43,6 @@ void rxrpc_propose_delay_ACK(struct rxrpc_call *call, rxrpc_serial_t serial, + unsigned long expiry = rxrpc_soft_ack_delay; + unsigned long now = jiffies, ack_at; + +- call->ackr_serial = serial; +- + if (rxrpc_soft_ack_delay < expiry) + expiry = rxrpc_soft_ack_delay; + if (call->peer->srtt_us != 0) +@@ -114,6 +112,7 @@ static void rxrpc_congestion_timeout(struct rxrpc_call *call) + void rxrpc_resend(struct rxrpc_call *call, struct sk_buff *ack_skb) + { + struct rxrpc_ackpacket *ack = NULL; ++ struct rxrpc_skb_priv *sp; + struct rxrpc_txbuf *txb; + unsigned long resend_at; + rxrpc_seq_t transmitted = READ_ONCE(call->tx_transmitted); +@@ -141,14 +140,15 @@ void rxrpc_resend(struct rxrpc_call *call, struct sk_buff *ack_skb) + * explicitly NAK'd packets. + */ + if (ack_skb) { ++ sp = rxrpc_skb(ack_skb); + ack = (void *)ack_skb->data + sizeof(struct rxrpc_wire_header); + +- for (i = 0; i < ack->nAcks; i++) { ++ for (i = 0; i < sp->nr_acks; i++) { + rxrpc_seq_t seq; + + if (ack->acks[i] & 1) + continue; +- seq = ntohl(ack->firstPacket) + i; ++ seq = sp->first_ack + i; + if (after(txb->seq, transmitted)) + break; + if (after(txb->seq, seq)) +@@ -373,7 +373,6 @@ static void rxrpc_send_initial_ping(struct rxrpc_call *call) + bool rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb) + { + unsigned long now, next, t; +- rxrpc_serial_t ackr_serial; + bool resend = false, expired = false; + s32 abort_code; + +@@ -423,8 +422,7 @@ bool rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb) + if (time_after_eq(now, t)) { + trace_rxrpc_timer(call, rxrpc_timer_exp_ack, now); + cmpxchg(&call->delay_ack_at, t, now + MAX_JIFFY_OFFSET); +- ackr_serial = xchg(&call->ackr_serial, 0); +- rxrpc_send_ACK(call, RXRPC_ACK_DELAY, ackr_serial, ++ rxrpc_send_ACK(call, RXRPC_ACK_DELAY, 0, + rxrpc_propose_ack_ping_for_lost_ack); + } + +diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c +index f10b37c147721..0a50341d920af 100644 +--- a/net/rxrpc/call_object.c ++++ b/net/rxrpc/call_object.c +@@ -685,6 +685,7 @@ static void rxrpc_destroy_call(struct work_struct *work) + + del_timer_sync(&call->timer); + ++ rxrpc_free_skb(call->cong_last_nack, rxrpc_skb_put_last_nack); + rxrpc_cleanup_ring(call); + while ((txb = list_first_entry_or_null(&call->tx_sendmsg, + struct rxrpc_txbuf, call_link))) { +diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c +index 95f4bc206b3dc..1f251d758cb9d 100644 +--- a/net/rxrpc/conn_event.c ++++ b/net/rxrpc/conn_event.c +@@ -95,6 +95,14 @@ void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn, + + _enter("%d", conn->debug_id); + ++ if (sp && sp->hdr.type == RXRPC_PACKET_TYPE_ACK) { ++ if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header), ++ &pkt.ack, sizeof(pkt.ack)) < 0) ++ return; ++ if (pkt.ack.reason == RXRPC_ACK_PING_RESPONSE) ++ return; ++ } ++ + chan = &conn->channels[channel]; + + /* If the last call got moved on whilst we were waiting to run, just +@@ -117,7 +125,7 @@ void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn, + iov[2].iov_base = &ack_info; + iov[2].iov_len = sizeof(ack_info); + +- serial = atomic_inc_return(&conn->serial); ++ serial = rxrpc_get_next_serial(conn); + + pkt.whdr.epoch = htonl(conn->proto.epoch); + pkt.whdr.cid = htonl(conn->proto.cid | channel); +diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c +index 92495e73b8699..9691de00ade75 100644 +--- a/net/rxrpc/input.c ++++ b/net/rxrpc/input.c +@@ -45,11 +45,9 @@ static void rxrpc_congestion_management(struct rxrpc_call *call, + } + + cumulative_acks += summary->nr_new_acks; +- cumulative_acks += summary->nr_rot_new_acks; + if (cumulative_acks > 255) + cumulative_acks = 255; + +- summary->mode = call->cong_mode; + summary->cwnd = call->cong_cwnd; + summary->ssthresh = call->cong_ssthresh; + summary->cumulative_acks = cumulative_acks; +@@ -151,6 +149,7 @@ out_no_clear_ca: + cwnd = RXRPC_TX_MAX_WINDOW; + call->cong_cwnd = cwnd; + call->cong_cumul_acks = cumulative_acks; ++ summary->mode = call->cong_mode; + trace_rxrpc_congest(call, summary, acked_serial, change); + if (resend) + rxrpc_resend(call, skb); +@@ -213,7 +212,6 @@ static bool rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to, + list_for_each_entry_rcu(txb, &call->tx_buffer, call_link, false) { + if (before_eq(txb->seq, call->acks_hard_ack)) + continue; +- summary->nr_rot_new_acks++; + if (test_bit(RXRPC_TXBUF_LAST, &txb->flags)) { + set_bit(RXRPC_CALL_TX_LAST, &call->flags); + rot_last = true; +@@ -254,6 +252,11 @@ static void rxrpc_end_tx_phase(struct rxrpc_call *call, bool reply_begun, + { + ASSERT(test_bit(RXRPC_CALL_TX_LAST, &call->flags)); + ++ if (unlikely(call->cong_last_nack)) { ++ rxrpc_free_skb(call->cong_last_nack, rxrpc_skb_put_last_nack); ++ call->cong_last_nack = NULL; ++ } ++ + switch (__rxrpc_call_state(call)) { + case RXRPC_CALL_CLIENT_SEND_REQUEST: + case RXRPC_CALL_CLIENT_AWAIT_REPLY: +@@ -702,6 +705,43 @@ static void rxrpc_input_ackinfo(struct rxrpc_call *call, struct sk_buff *skb, + wake_up(&call->waitq); + } + ++/* ++ * Determine how many nacks from the previous ACK have now been satisfied. ++ */ ++static rxrpc_seq_t rxrpc_input_check_prev_ack(struct rxrpc_call *call, ++ struct rxrpc_ack_summary *summary, ++ rxrpc_seq_t seq) ++{ ++ struct sk_buff *skb = call->cong_last_nack; ++ struct rxrpc_ackpacket ack; ++ struct rxrpc_skb_priv *sp = rxrpc_skb(skb); ++ unsigned int i, new_acks = 0, retained_nacks = 0; ++ rxrpc_seq_t old_seq = sp->first_ack; ++ u8 *acks = skb->data + sizeof(struct rxrpc_wire_header) + sizeof(ack); ++ ++ if (after_eq(seq, old_seq + sp->nr_acks)) { ++ summary->nr_new_acks += sp->nr_nacks; ++ summary->nr_new_acks += seq - (old_seq + sp->nr_acks); ++ summary->nr_retained_nacks = 0; ++ } else if (seq == old_seq) { ++ summary->nr_retained_nacks = sp->nr_nacks; ++ } else { ++ for (i = 0; i < sp->nr_acks; i++) { ++ if (acks[i] == RXRPC_ACK_TYPE_NACK) { ++ if (before(old_seq + i, seq)) ++ new_acks++; ++ else ++ retained_nacks++; ++ } ++ } ++ ++ summary->nr_new_acks += new_acks; ++ summary->nr_retained_nacks = retained_nacks; ++ } ++ ++ return old_seq + sp->nr_acks; ++} ++ + /* + * Process individual soft ACKs. + * +@@ -711,25 +751,51 @@ static void rxrpc_input_ackinfo(struct rxrpc_call *call, struct sk_buff *skb, + * the timer on the basis that the peer might just not have processed them at + * the time the ACK was sent. + */ +-static void rxrpc_input_soft_acks(struct rxrpc_call *call, u8 *acks, +- rxrpc_seq_t seq, int nr_acks, +- struct rxrpc_ack_summary *summary) ++static void rxrpc_input_soft_acks(struct rxrpc_call *call, ++ struct rxrpc_ack_summary *summary, ++ struct sk_buff *skb, ++ rxrpc_seq_t seq, ++ rxrpc_seq_t since) + { +- unsigned int i; ++ struct rxrpc_skb_priv *sp = rxrpc_skb(skb); ++ unsigned int i, old_nacks = 0; ++ rxrpc_seq_t lowest_nak = seq + sp->nr_acks; ++ u8 *acks = skb->data + sizeof(struct rxrpc_wire_header) + sizeof(struct rxrpc_ackpacket); + +- for (i = 0; i < nr_acks; i++) { ++ for (i = 0; i < sp->nr_acks; i++) { + if (acks[i] == RXRPC_ACK_TYPE_ACK) { + summary->nr_acks++; +- summary->nr_new_acks++; ++ if (after_eq(seq, since)) ++ summary->nr_new_acks++; + } else { +- if (!summary->saw_nacks && +- call->acks_lowest_nak != seq + i) { +- call->acks_lowest_nak = seq + i; +- summary->new_low_nack = true; +- } + summary->saw_nacks = true; ++ if (before(seq, since)) { ++ /* Overlap with previous ACK */ ++ old_nacks++; ++ } else { ++ summary->nr_new_nacks++; ++ sp->nr_nacks++; ++ } ++ ++ if (before(seq, lowest_nak)) ++ lowest_nak = seq; + } ++ seq++; ++ } ++ ++ if (lowest_nak != call->acks_lowest_nak) { ++ call->acks_lowest_nak = lowest_nak; ++ summary->new_low_nack = true; + } ++ ++ /* We *can* have more nacks than we did - the peer is permitted to drop ++ * packets it has soft-acked and re-request them. Further, it is ++ * possible for the nack distribution to change whilst the number of ++ * nacks stays the same or goes down. ++ */ ++ if (old_nacks < summary->nr_retained_nacks) ++ summary->nr_new_acks += summary->nr_retained_nacks - old_nacks; ++ summary->nr_retained_nacks = old_nacks; + } + + /* +@@ -773,7 +839,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb) + struct rxrpc_skb_priv *sp = rxrpc_skb(skb); + struct rxrpc_ackinfo info; + rxrpc_serial_t ack_serial, acked_serial; +- rxrpc_seq_t first_soft_ack, hard_ack, prev_pkt; ++ rxrpc_seq_t first_soft_ack, hard_ack, prev_pkt, since; + int nr_acks, offset, ioffset; + + _enter(""); +@@ -789,6 +855,8 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb) + prev_pkt = ntohl(ack.previousPacket); + hard_ack = first_soft_ack - 1; + nr_acks = ack.nAcks; ++ sp->first_ack = first_soft_ack; ++ sp->nr_acks = nr_acks; + summary.ack_reason = (ack.reason < RXRPC_ACK__INVALID ? + ack.reason : RXRPC_ACK__INVALID); + +@@ -858,6 +926,16 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb) + if (nr_acks > 0) + skb_condense(skb); + ++ if (call->cong_last_nack) { ++ since = rxrpc_input_check_prev_ack(call, &summary, first_soft_ack); ++ rxrpc_free_skb(call->cong_last_nack, rxrpc_skb_put_last_nack); ++ call->cong_last_nack = NULL; ++ } else { ++ summary.nr_new_acks = first_soft_ack - call->acks_first_seq; ++ call->acks_lowest_nak = first_soft_ack + nr_acks; ++ since = first_soft_ack; ++ } ++ + call->acks_latest_ts = skb->tstamp; + call->acks_first_seq = first_soft_ack; + call->acks_prev_seq = prev_pkt; +@@ -866,7 +944,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb) + case RXRPC_ACK_PING: + break; + default: +- if (after(acked_serial, call->acks_highest_serial)) ++ if (acked_serial && after(acked_serial, call->acks_highest_serial)) + call->acks_highest_serial = acked_serial; + break; + } +@@ -905,8 +983,9 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb) + if (nr_acks > 0) { + if (offset > (int)skb->len - nr_acks) + return rxrpc_proto_abort(call, 0, rxrpc_eproto_ackr_short_sack); +- rxrpc_input_soft_acks(call, skb->data + offset, first_soft_ack, +- nr_acks, &summary); ++ rxrpc_input_soft_acks(call, &summary, skb, first_soft_ack, since); ++ rxrpc_get_skb(skb, rxrpc_skb_get_last_nack); ++ call->cong_last_nack = skb; + } + + if (test_bit(RXRPC_CALL_TX_LAST, &call->flags) && +diff --git a/net/rxrpc/output.c b/net/rxrpc/output.c +index a0906145e8293..4a292f860ae37 100644 +--- a/net/rxrpc/output.c ++++ b/net/rxrpc/output.c +@@ -216,7 +216,7 @@ int rxrpc_send_ack_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb) + iov[0].iov_len = sizeof(txb->wire) + sizeof(txb->ack) + n; + len = iov[0].iov_len; + +- serial = atomic_inc_return(&conn->serial); ++ serial = rxrpc_get_next_serial(conn); + txb->wire.serial = htonl(serial); + trace_rxrpc_tx_ack(call->debug_id, serial, + ntohl(txb->ack.firstPacket), +@@ -302,7 +302,7 @@ int rxrpc_send_abort_packet(struct rxrpc_call *call) + iov[0].iov_base = &pkt; + iov[0].iov_len = sizeof(pkt); + +- serial = atomic_inc_return(&conn->serial); ++ serial = rxrpc_get_next_serial(conn); + pkt.whdr.serial = htonl(serial); + + iov_iter_kvec(&msg.msg_iter, WRITE, iov, 1, sizeof(pkt)); +@@ -334,7 +334,7 @@ int rxrpc_send_data_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb) + _enter("%x,{%d}", txb->seq, txb->len); + + /* Each transmission of a Tx packet needs a new serial number */ +- serial = atomic_inc_return(&conn->serial); ++ serial = rxrpc_get_next_serial(conn); + txb->wire.serial = htonl(serial); + + if (test_bit(RXRPC_CONN_PROBING_FOR_UPGRADE, &conn->flags) && +@@ -558,7 +558,7 @@ void rxrpc_send_conn_abort(struct rxrpc_connection *conn) + + len = iov[0].iov_len + iov[1].iov_len; + +- serial = atomic_inc_return(&conn->serial); ++ serial = rxrpc_get_next_serial(conn); + whdr.serial = htonl(serial); + + iov_iter_kvec(&msg.msg_iter, WRITE, iov, 2, len); +diff --git a/net/rxrpc/proc.c b/net/rxrpc/proc.c +index 682636d3b060b..208312c244f6b 100644 +--- a/net/rxrpc/proc.c ++++ b/net/rxrpc/proc.c +@@ -181,7 +181,7 @@ print: + atomic_read(&conn->active), + state, + key_serial(conn->key), +- atomic_read(&conn->serial), ++ conn->tx_serial, + conn->hi_serial, + conn->channels[0].call_id, + conn->channels[1].call_id, +diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c +index b52dedcebce0a..6b32d61d4cdc4 100644 +--- a/net/rxrpc/rxkad.c ++++ b/net/rxrpc/rxkad.c +@@ -664,7 +664,7 @@ static int rxkad_issue_challenge(struct rxrpc_connection *conn) + + len = iov[0].iov_len + iov[1].iov_len; + +- serial = atomic_inc_return(&conn->serial); ++ serial = rxrpc_get_next_serial(conn); + whdr.serial = htonl(serial); + + ret = kernel_sendmsg(conn->local->socket, &msg, iov, 2, len); +@@ -721,7 +721,7 @@ static int rxkad_send_response(struct rxrpc_connection *conn, + + len = iov[0].iov_len + iov[1].iov_len + iov[2].iov_len; + +- serial = atomic_inc_return(&conn->serial); ++ serial = rxrpc_get_next_serial(conn); + whdr.serial = htonl(serial); + + rxrpc_local_dont_fragment(conn->local, false); +diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c +index 2cde375477e38..878415c435276 100644 +--- a/net/tipc/bearer.c ++++ b/net/tipc/bearer.c +@@ -1086,6 +1086,12 @@ int tipc_nl_bearer_add(struct sk_buff *skb, struct genl_info *info) + + #ifdef CONFIG_TIPC_MEDIA_UDP + if (attrs[TIPC_NLA_BEARER_UDP_OPTS]) { ++ if (b->media->type_id != TIPC_MEDIA_TYPE_UDP) { ++ rtnl_unlock(); ++ NL_SET_ERR_MSG(info->extack, "UDP option is unsupported"); ++ return -EINVAL; ++ } ++ + err = tipc_udp_nl_bearer_add(b, + attrs[TIPC_NLA_BEARER_UDP_OPTS]); + if (err) { +diff --git a/net/unix/garbage.c b/net/unix/garbage.c +index 2405f0f9af31c..8f63f0b4bf012 100644 +--- a/net/unix/garbage.c ++++ b/net/unix/garbage.c +@@ -314,6 +314,17 @@ void unix_gc(void) + /* Here we are. Hitlist is filled. Die. */ + __skb_queue_purge(&hitlist); + ++#if IS_ENABLED(CONFIG_AF_UNIX_OOB) ++ list_for_each_entry_safe(u, next, &gc_candidates, link) { ++ struct sk_buff *skb = u->oob_skb; ++ ++ if (skb) { ++ u->oob_skb = NULL; ++ kfree_skb(skb); ++ } ++ } ++#endif ++ + spin_lock(&unix_gc_lock); + + /* There could be io_uring registered files, just push them back to +diff --git a/rust/alloc/alloc.rs b/rust/alloc/alloc.rs +index 0b6bf5b6da434..8cb4a31cf6e54 100644 +--- a/rust/alloc/alloc.rs ++++ b/rust/alloc/alloc.rs +@@ -6,9 +6,7 @@ + + #[cfg(not(test))] + use core::intrinsics; +-use core::intrinsics::{min_align_of_val, size_of_val}; + +-use core::ptr::Unique; + #[cfg(not(test))] + use core::ptr::{self, NonNull}; + +@@ -40,7 +38,6 @@ extern "Rust" { + #[rustc_nounwind] + fn __rust_alloc_zeroed(size: usize, align: usize) -> *mut u8; + +- #[cfg(not(bootstrap))] + static __rust_no_alloc_shim_is_unstable: u8; + } + +@@ -98,7 +95,6 @@ pub unsafe fn alloc(layout: Layout) -> *mut u8 { + unsafe { + // Make sure we don't accidentally allow omitting the allocator shim in + // stable code until it is actually stabilized. +- #[cfg(not(bootstrap))] + core::ptr::read_volatile(&__rust_no_alloc_shim_is_unstable); + + __rust_alloc(layout.size(), layout.align()) +@@ -339,22 +335,6 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { + } + } + +-#[cfg_attr(not(test), lang = "box_free")] +-#[inline] +-// This signature has to be the same as `Box`, otherwise an ICE will happen. +-// When an additional parameter to `Box` is added (like `A: Allocator`), this has to be added here as +-// well. +-// For example if `Box` is changed to `struct Box<T: ?Sized, A: Allocator>(Unique<T>, A)`, +-// this function has to be changed to `fn box_free<T: ?Sized, A: Allocator>(Unique<T>, A)` as well. +-pub(crate) unsafe fn box_free<T: ?Sized, A: Allocator>(ptr: Unique<T>, alloc: A) { +- unsafe { +- let size = size_of_val(ptr.as_ref()); +- let align = min_align_of_val(ptr.as_ref()); +- let layout = Layout::from_size_align_unchecked(size, align); +- alloc.deallocate(From::from(ptr.cast()), layout) +- } +-} +- + // # Allocation error handler + + #[cfg(not(no_global_oom_handling))] +@@ -414,7 +394,6 @@ pub mod __alloc_error_handler { + static __rust_alloc_error_handler_should_panic: u8; + } + +- #[allow(unused_unsafe)] + if unsafe { __rust_alloc_error_handler_should_panic != 0 } { + panic!("memory allocation of {size} bytes failed") + } else { +diff --git a/rust/alloc/boxed.rs b/rust/alloc/boxed.rs +index c8173cea83177..9620eba172687 100644 +--- a/rust/alloc/boxed.rs ++++ b/rust/alloc/boxed.rs +@@ -159,12 +159,12 @@ use core::hash::{Hash, Hasher}; + use core::iter::FusedIterator; + use core::marker::Tuple; + use core::marker::Unsize; +-use core::mem; ++use core::mem::{self, SizedTypeProperties}; + use core::ops::{ + CoerceUnsized, Deref, DerefMut, DispatchFromDyn, Generator, GeneratorState, Receiver, + }; + use core::pin::Pin; +-use core::ptr::{self, Unique}; ++use core::ptr::{self, NonNull, Unique}; + use core::task::{Context, Poll}; + + #[cfg(not(no_global_oom_handling))] +@@ -483,8 +483,12 @@ impl<T, A: Allocator> Box<T, A> { + where + A: Allocator, + { +- let layout = Layout::new::<mem::MaybeUninit<T>>(); +- let ptr = alloc.allocate(layout)?.cast(); ++ let ptr = if T::IS_ZST { ++ NonNull::dangling() ++ } else { ++ let layout = Layout::new::<mem::MaybeUninit<T>>(); ++ alloc.allocate(layout)?.cast() ++ }; + unsafe { Ok(Box::from_raw_in(ptr.as_ptr(), alloc)) } + } + +@@ -553,8 +557,12 @@ impl<T, A: Allocator> Box<T, A> { + where + A: Allocator, + { +- let layout = Layout::new::<mem::MaybeUninit<T>>(); +- let ptr = alloc.allocate_zeroed(layout)?.cast(); ++ let ptr = if T::IS_ZST { ++ NonNull::dangling() ++ } else { ++ let layout = Layout::new::<mem::MaybeUninit<T>>(); ++ alloc.allocate_zeroed(layout)?.cast() ++ }; + unsafe { Ok(Box::from_raw_in(ptr.as_ptr(), alloc)) } + } + +@@ -679,14 +687,16 @@ impl<T> Box<[T]> { + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn try_new_uninit_slice(len: usize) -> Result<Box<[mem::MaybeUninit<T>]>, AllocError> { +- unsafe { ++ let ptr = if T::IS_ZST || len == 0 { ++ NonNull::dangling() ++ } else { + let layout = match Layout::array::<mem::MaybeUninit<T>>(len) { + Ok(l) => l, + Err(_) => return Err(AllocError), + }; +- let ptr = Global.allocate(layout)?; +- Ok(RawVec::from_raw_parts_in(ptr.as_mut_ptr() as *mut _, len, Global).into_box(len)) +- } ++ Global.allocate(layout)?.cast() ++ }; ++ unsafe { Ok(RawVec::from_raw_parts_in(ptr.as_ptr(), len, Global).into_box(len)) } + } + + /// Constructs a new boxed slice with uninitialized contents, with the memory +@@ -711,14 +721,16 @@ impl<T> Box<[T]> { + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn try_new_zeroed_slice(len: usize) -> Result<Box<[mem::MaybeUninit<T>]>, AllocError> { +- unsafe { ++ let ptr = if T::IS_ZST || len == 0 { ++ NonNull::dangling() ++ } else { + let layout = match Layout::array::<mem::MaybeUninit<T>>(len) { + Ok(l) => l, + Err(_) => return Err(AllocError), + }; +- let ptr = Global.allocate_zeroed(layout)?; +- Ok(RawVec::from_raw_parts_in(ptr.as_mut_ptr() as *mut _, len, Global).into_box(len)) +- } ++ Global.allocate_zeroed(layout)?.cast() ++ }; ++ unsafe { Ok(RawVec::from_raw_parts_in(ptr.as_ptr(), len, Global).into_box(len)) } + } + } + +@@ -1215,8 +1227,18 @@ impl<T: ?Sized, A: Allocator> Box<T, A> { + + #[stable(feature = "rust1", since = "1.0.0")] + unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Box<T, A> { ++ #[inline] + fn drop(&mut self) { +- // FIXME: Do nothing, drop is currently performed by compiler. ++ // the T in the Box is dropped by the compiler before the destructor is run ++ ++ let ptr = self.0; ++ ++ unsafe { ++ let layout = Layout::for_value_raw(ptr.as_ptr()); ++ if layout.size() != 0 { ++ self.1.deallocate(From::from(ptr.cast()), layout); ++ } ++ } + } + } + +@@ -2165,7 +2187,7 @@ impl dyn Error + Send { + let err: Box<dyn Error> = self; + <dyn Error>::downcast(err).map_err(|s| unsafe { + // Reapply the `Send` marker. +- mem::transmute::<Box<dyn Error>, Box<dyn Error + Send>>(s) ++ Box::from_raw(Box::into_raw(s) as *mut (dyn Error + Send)) + }) + } + } +@@ -2179,7 +2201,7 @@ impl dyn Error + Send + Sync { + let err: Box<dyn Error> = self; + <dyn Error>::downcast(err).map_err(|s| unsafe { + // Reapply the `Send + Sync` marker. +- mem::transmute::<Box<dyn Error>, Box<dyn Error + Send + Sync>>(s) ++ Box::from_raw(Box::into_raw(s) as *mut (dyn Error + Send + Sync)) + }) + } + } +diff --git a/rust/alloc/lib.rs b/rust/alloc/lib.rs +index 85e91356ecb30..73b9ffd845d95 100644 +--- a/rust/alloc/lib.rs ++++ b/rust/alloc/lib.rs +@@ -58,6 +58,11 @@ + //! [`Rc`]: rc + //! [`RefCell`]: core::cell + ++// To run alloc tests without x.py without ending up with two copies of alloc, Miri needs to be ++// able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>. ++// rustc itself never sets the feature, so this line has no effect there. ++#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))] ++// + #![allow(unused_attributes)] + #![stable(feature = "alloc", since = "1.36.0")] + #![doc( +@@ -77,11 +82,6 @@ + ))] + #![no_std] + #![needs_allocator] +-// To run alloc tests without x.py without ending up with two copies of alloc, Miri needs to be +-// able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>. +-// rustc itself never sets the feature, so this line has no affect there. +-#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))] +-// + // Lints: + #![deny(unsafe_op_in_unsafe_fn)] + #![deny(fuzzy_provenance_casts)] +@@ -90,6 +90,8 @@ + #![warn(missing_docs)] + #![allow(explicit_outlives_requirements)] + #![warn(multiple_supertrait_upcastable)] ++#![cfg_attr(not(bootstrap), allow(internal_features))] ++#![cfg_attr(not(bootstrap), allow(rustdoc::redundant_explicit_links))] + // + // Library features: + // tidy-alphabetical-start +@@ -139,7 +141,6 @@ + #![feature(maybe_uninit_uninit_array_transpose)] + #![feature(pattern)] + #![feature(pointer_byte_offsets)] +-#![feature(provide_any)] + #![feature(ptr_internals)] + #![feature(ptr_metadata)] + #![feature(ptr_sub_ptr)] +diff --git a/rust/alloc/raw_vec.rs b/rust/alloc/raw_vec.rs +index 65d5ce15828e4..a7425582a323f 100644 +--- a/rust/alloc/raw_vec.rs ++++ b/rust/alloc/raw_vec.rs +@@ -471,16 +471,26 @@ impl<T, A: Allocator> RawVec<T, A> { + let (ptr, layout) = if let Some(mem) = self.current_memory() { mem } else { return Ok(()) }; + // See current_memory() why this assert is here + let _: () = const { assert!(mem::size_of::<T>() % mem::align_of::<T>() == 0) }; +- let ptr = unsafe { +- // `Layout::array` cannot overflow here because it would have +- // overflowed earlier when capacity was larger. +- let new_size = mem::size_of::<T>().unchecked_mul(cap); +- let new_layout = Layout::from_size_align_unchecked(new_size, layout.align()); +- self.alloc +- .shrink(ptr, layout, new_layout) +- .map_err(|_| AllocError { layout: new_layout, non_exhaustive: () })? +- }; +- self.set_ptr_and_cap(ptr, cap); ++ ++ // If shrinking to 0, deallocate the buffer. We don't reach this point ++ // for the T::IS_ZST case since current_memory() will have returned ++ // None. ++ if cap == 0 { ++ unsafe { self.alloc.deallocate(ptr, layout) }; ++ self.ptr = Unique::dangling(); ++ self.cap = 0; ++ } else { ++ let ptr = unsafe { ++ // `Layout::array` cannot overflow here because it would have ++ // overflowed earlier when capacity was larger. ++ let new_size = mem::size_of::<T>().unchecked_mul(cap); ++ let new_layout = Layout::from_size_align_unchecked(new_size, layout.align()); ++ self.alloc ++ .shrink(ptr, layout, new_layout) ++ .map_err(|_| AllocError { layout: new_layout, non_exhaustive: () })? ++ }; ++ self.set_ptr_and_cap(ptr, cap); ++ } + Ok(()) + } + } +diff --git a/rust/alloc/vec/drain_filter.rs b/rust/alloc/vec/drain_filter.rs +deleted file mode 100644 +index 09efff090e428..0000000000000 +--- a/rust/alloc/vec/drain_filter.rs ++++ /dev/null +@@ -1,199 +0,0 @@ +-// SPDX-License-Identifier: Apache-2.0 OR MIT +- +-use crate::alloc::{Allocator, Global}; +-use core::mem::{ManuallyDrop, SizedTypeProperties}; +-use core::ptr; +-use core::slice; +- +-use super::Vec; +- +-/// An iterator which uses a closure to determine if an element should be removed. +-/// +-/// This struct is created by [`Vec::drain_filter`]. +-/// See its documentation for more. +-/// +-/// # Example +-/// +-/// ``` +-/// #![feature(drain_filter)] +-/// +-/// let mut v = vec![0, 1, 2]; +-/// let iter: std::vec::DrainFilter<'_, _, _> = v.drain_filter(|x| *x % 2 == 0); +-/// ``` +-#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] +-#[derive(Debug)] +-pub struct DrainFilter< +- 'a, +- T, +- F, +- #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +-> where +- F: FnMut(&mut T) -> bool, +-{ +- pub(super) vec: &'a mut Vec<T, A>, +- /// The index of the item that will be inspected by the next call to `next`. +- pub(super) idx: usize, +- /// The number of items that have been drained (removed) thus far. +- pub(super) del: usize, +- /// The original length of `vec` prior to draining. +- pub(super) old_len: usize, +- /// The filter test predicate. +- pub(super) pred: F, +- /// A flag that indicates a panic has occurred in the filter test predicate. +- /// This is used as a hint in the drop implementation to prevent consumption +- /// of the remainder of the `DrainFilter`. Any unprocessed items will be +- /// backshifted in the `vec`, but no further items will be dropped or +- /// tested by the filter predicate. +- pub(super) panic_flag: bool, +-} +- +-impl<T, F, A: Allocator> DrainFilter<'_, T, F, A> +-where +- F: FnMut(&mut T) -> bool, +-{ +- /// Returns a reference to the underlying allocator. +- #[unstable(feature = "allocator_api", issue = "32838")] +- #[inline] +- pub fn allocator(&self) -> &A { +- self.vec.allocator() +- } +- +- /// Keep unyielded elements in the source `Vec`. +- /// +- /// # Examples +- /// +- /// ``` +- /// #![feature(drain_filter)] +- /// #![feature(drain_keep_rest)] +- /// +- /// let mut vec = vec!['a', 'b', 'c']; +- /// let mut drain = vec.drain_filter(|_| true); +- /// +- /// assert_eq!(drain.next().unwrap(), 'a'); +- /// +- /// // This call keeps 'b' and 'c' in the vec. +- /// drain.keep_rest(); +- /// +- /// // If we wouldn't call `keep_rest()`, +- /// // `vec` would be empty. +- /// assert_eq!(vec, ['b', 'c']); +- /// ``` +- #[unstable(feature = "drain_keep_rest", issue = "101122")] +- pub fn keep_rest(self) { +- // At this moment layout looks like this: +- // +- // _____________________/-- old_len +- // / \ +- // [kept] [yielded] [tail] +- // \_______/ ^-- idx +- // \-- del +- // +- // Normally `Drop` impl would drop [tail] (via .for_each(drop), ie still calling `pred`) +- // +- // 1. Move [tail] after [kept] +- // 2. Update length of the original vec to `old_len - del` +- // a. In case of ZST, this is the only thing we want to do +- // 3. Do *not* drop self, as everything is put in a consistent state already, there is nothing to do +- let mut this = ManuallyDrop::new(self); +- +- unsafe { +- // ZSTs have no identity, so we don't need to move them around. +- if !T::IS_ZST && this.idx < this.old_len && this.del > 0 { +- let ptr = this.vec.as_mut_ptr(); +- let src = ptr.add(this.idx); +- let dst = src.sub(this.del); +- let tail_len = this.old_len - this.idx; +- src.copy_to(dst, tail_len); +- } +- +- let new_len = this.old_len - this.del; +- this.vec.set_len(new_len); +- } +- } +-} +- +-#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] +-impl<T, F, A: Allocator> Iterator for DrainFilter<'_, T, F, A> +-where +- F: FnMut(&mut T) -> bool, +-{ +- type Item = T; +- +- fn next(&mut self) -> Option<T> { +- unsafe { +- while self.idx < self.old_len { +- let i = self.idx; +- let v = slice::from_raw_parts_mut(self.vec.as_mut_ptr(), self.old_len); +- self.panic_flag = true; +- let drained = (self.pred)(&mut v[i]); +- self.panic_flag = false; +- // Update the index *after* the predicate is called. If the index +- // is updated prior and the predicate panics, the element at this +- // index would be leaked. +- self.idx += 1; +- if drained { +- self.del += 1; +- return Some(ptr::read(&v[i])); +- } else if self.del > 0 { +- let del = self.del; +- let src: *const T = &v[i]; +- let dst: *mut T = &mut v[i - del]; +- ptr::copy_nonoverlapping(src, dst, 1); +- } +- } +- None +- } +- } +- +- fn size_hint(&self) -> (usize, Option<usize>) { +- (0, Some(self.old_len - self.idx)) +- } +-} +- +-#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] +-impl<T, F, A: Allocator> Drop for DrainFilter<'_, T, F, A> +-where +- F: FnMut(&mut T) -> bool, +-{ +- fn drop(&mut self) { +- struct BackshiftOnDrop<'a, 'b, T, F, A: Allocator> +- where +- F: FnMut(&mut T) -> bool, +- { +- drain: &'b mut DrainFilter<'a, T, F, A>, +- } +- +- impl<'a, 'b, T, F, A: Allocator> Drop for BackshiftOnDrop<'a, 'b, T, F, A> +- where +- F: FnMut(&mut T) -> bool, +- { +- fn drop(&mut self) { +- unsafe { +- if self.drain.idx < self.drain.old_len && self.drain.del > 0 { +- // This is a pretty messed up state, and there isn't really an +- // obviously right thing to do. We don't want to keep trying +- // to execute `pred`, so we just backshift all the unprocessed +- // elements and tell the vec that they still exist. The backshift +- // is required to prevent a double-drop of the last successfully +- // drained item prior to a panic in the predicate. +- let ptr = self.drain.vec.as_mut_ptr(); +- let src = ptr.add(self.drain.idx); +- let dst = src.sub(self.drain.del); +- let tail_len = self.drain.old_len - self.drain.idx; +- src.copy_to(dst, tail_len); +- } +- self.drain.vec.set_len(self.drain.old_len - self.drain.del); +- } +- } +- } +- +- let backshift = BackshiftOnDrop { drain: self }; +- +- // Attempt to consume any remaining elements if the filter predicate +- // has not yet panicked. We'll backshift any remaining elements +- // whether we've already panicked or if the consumption here panics. +- if !backshift.drain.panic_flag { +- backshift.drain.for_each(drop); +- } +- } +-} +diff --git a/rust/alloc/vec/extract_if.rs b/rust/alloc/vec/extract_if.rs +new file mode 100644 +index 0000000000000..f314a51d4d3db +--- /dev/null ++++ b/rust/alloc/vec/extract_if.rs +@@ -0,0 +1,115 @@ ++// SPDX-License-Identifier: Apache-2.0 OR MIT ++ ++use crate::alloc::{Allocator, Global}; ++use core::ptr; ++use core::slice; ++ ++use super::Vec; ++ ++/// An iterator which uses a closure to determine if an element should be removed. ++/// ++/// This struct is created by [`Vec::extract_if`]. ++/// See its documentation for more. ++/// ++/// # Example ++/// ++/// ``` ++/// #![feature(extract_if)] ++/// ++/// let mut v = vec![0, 1, 2]; ++/// let iter: std::vec::ExtractIf<'_, _, _> = v.extract_if(|x| *x % 2 == 0); ++/// ``` ++#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")] ++#[derive(Debug)] ++#[must_use = "iterators are lazy and do nothing unless consumed"] ++pub struct ExtractIf< ++ 'a, ++ T, ++ F, ++ #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, ++> where ++ F: FnMut(&mut T) -> bool, ++{ ++ pub(super) vec: &'a mut Vec<T, A>, ++ /// The index of the item that will be inspected by the next call to `next`. ++ pub(super) idx: usize, ++ /// The number of items that have been drained (removed) thus far. ++ pub(super) del: usize, ++ /// The original length of `vec` prior to draining. ++ pub(super) old_len: usize, ++ /// The filter test predicate. ++ pub(super) pred: F, ++} ++ ++impl<T, F, A: Allocator> ExtractIf<'_, T, F, A> ++where ++ F: FnMut(&mut T) -> bool, ++{ ++ /// Returns a reference to the underlying allocator. ++ #[unstable(feature = "allocator_api", issue = "32838")] ++ #[inline] ++ pub fn allocator(&self) -> &A { ++ self.vec.allocator() ++ } ++} ++ ++#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")] ++impl<T, F, A: Allocator> Iterator for ExtractIf<'_, T, F, A> ++where ++ F: FnMut(&mut T) -> bool, ++{ ++ type Item = T; ++ ++ fn next(&mut self) -> Option<T> { ++ unsafe { ++ while self.idx < self.old_len { ++ let i = self.idx; ++ let v = slice::from_raw_parts_mut(self.vec.as_mut_ptr(), self.old_len); ++ let drained = (self.pred)(&mut v[i]); ++ // Update the index *after* the predicate is called. If the index ++ // is updated prior and the predicate panics, the element at this ++ // index would be leaked. ++ self.idx += 1; ++ if drained { ++ self.del += 1; ++ return Some(ptr::read(&v[i])); ++ } else if self.del > 0 { ++ let del = self.del; ++ let src: *const T = &v[i]; ++ let dst: *mut T = &mut v[i - del]; ++ ptr::copy_nonoverlapping(src, dst, 1); ++ } ++ } ++ None ++ } ++ } ++ ++ fn size_hint(&self) -> (usize, Option<usize>) { ++ (0, Some(self.old_len - self.idx)) ++ } ++} ++ ++#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")] ++impl<T, F, A: Allocator> Drop for ExtractIf<'_, T, F, A> ++where ++ F: FnMut(&mut T) -> bool, ++{ ++ fn drop(&mut self) { ++ unsafe { ++ if self.idx < self.old_len && self.del > 0 { ++ // This is a pretty messed up state, and there isn't really an ++ // obviously right thing to do. We don't want to keep trying ++ // to execute `pred`, so we just backshift all the unprocessed ++ // elements and tell the vec that they still exist. The backshift ++ // is required to prevent a double-drop of the last successfully ++ // drained item prior to a panic in the predicate. ++ let ptr = self.vec.as_mut_ptr(); ++ let src = ptr.add(self.idx); ++ let dst = src.sub(self.del); ++ let tail_len = self.old_len - self.idx; ++ src.copy_to(dst, tail_len); ++ } ++ self.vec.set_len(self.old_len - self.del); ++ } ++ } ++} +diff --git a/rust/alloc/vec/mod.rs b/rust/alloc/vec/mod.rs +index 05c70de0227ed..209a88cfe598f 100644 +--- a/rust/alloc/vec/mod.rs ++++ b/rust/alloc/vec/mod.rs +@@ -74,10 +74,10 @@ use crate::boxed::Box; + use crate::collections::{TryReserveError, TryReserveErrorKind}; + use crate::raw_vec::RawVec; + +-#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] +-pub use self::drain_filter::DrainFilter; ++#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")] ++pub use self::extract_if::ExtractIf; + +-mod drain_filter; ++mod extract_if; + + #[cfg(not(no_global_oom_handling))] + #[stable(feature = "vec_splice", since = "1.21.0")] +@@ -216,7 +216,7 @@ mod spec_extend; + /// + /// # Indexing + /// +-/// The `Vec` type allows to access values by index, because it implements the ++/// The `Vec` type allows access to values by index, because it implements the + /// [`Index`] trait. An example will be more explicit: + /// + /// ``` +@@ -618,22 +618,20 @@ impl<T> Vec<T> { + /// Using memory that was allocated elsewhere: + /// + /// ```rust +- /// #![feature(allocator_api)] +- /// +- /// use std::alloc::{AllocError, Allocator, Global, Layout}; ++ /// use std::alloc::{alloc, Layout}; + /// + /// fn main() { + /// let layout = Layout::array::<u32>(16).expect("overflow cannot happen"); + /// + /// let vec = unsafe { +- /// let mem = match Global.allocate(layout) { +- /// Ok(mem) => mem.cast::<u32>().as_ptr(), +- /// Err(AllocError) => return, +- /// }; ++ /// let mem = alloc(layout).cast::<u32>(); ++ /// if mem.is_null() { ++ /// return; ++ /// } + /// + /// mem.write(1_000_000); + /// +- /// Vec::from_raw_parts_in(mem, 1, 16, Global) ++ /// Vec::from_raw_parts(mem, 1, 16) + /// }; + /// + /// assert_eq!(vec, &[1_000_000]); +@@ -876,19 +874,22 @@ impl<T, A: Allocator> Vec<T, A> { + /// Using memory that was allocated elsewhere: + /// + /// ```rust +- /// use std::alloc::{alloc, Layout}; ++ /// #![feature(allocator_api)] ++ /// ++ /// use std::alloc::{AllocError, Allocator, Global, Layout}; + /// + /// fn main() { + /// let layout = Layout::array::<u32>(16).expect("overflow cannot happen"); ++ /// + /// let vec = unsafe { +- /// let mem = alloc(layout).cast::<u32>(); +- /// if mem.is_null() { +- /// return; +- /// } ++ /// let mem = match Global.allocate(layout) { ++ /// Ok(mem) => mem.cast::<u32>().as_ptr(), ++ /// Err(AllocError) => return, ++ /// }; + /// + /// mem.write(1_000_000); + /// +- /// Vec::from_raw_parts(mem, 1, 16) ++ /// Vec::from_raw_parts_in(mem, 1, 16, Global) + /// }; + /// + /// assert_eq!(vec, &[1_000_000]); +@@ -2507,7 +2508,7 @@ impl<T: Clone, A: Allocator> Vec<T, A> { + let len = self.len(); + + if new_len > len { +- self.extend_with(new_len - len, ExtendElement(value)) ++ self.extend_with(new_len - len, value) + } else { + self.truncate(new_len); + } +@@ -2545,7 +2546,7 @@ impl<T: Clone, A: Allocator> Vec<T, A> { + let len = self.len(); + + if new_len > len { +- self.try_extend_with(new_len - len, ExtendElement(value)) ++ self.try_extend_with(new_len - len, value) + } else { + self.truncate(new_len); + Ok(()) +@@ -2684,26 +2685,10 @@ impl<T, A: Allocator, const N: usize> Vec<[T; N], A> { + } + } + +-// This code generalizes `extend_with_{element,default}`. +-trait ExtendWith<T> { +- fn next(&mut self) -> T; +- fn last(self) -> T; +-} +- +-struct ExtendElement<T>(T); +-impl<T: Clone> ExtendWith<T> for ExtendElement<T> { +- fn next(&mut self) -> T { +- self.0.clone() +- } +- fn last(self) -> T { +- self.0 +- } +-} +- +-impl<T, A: Allocator> Vec<T, A> { ++impl<T: Clone, A: Allocator> Vec<T, A> { + #[cfg(not(no_global_oom_handling))] +- /// Extend the vector by `n` values, using the given generator. +- fn extend_with<E: ExtendWith<T>>(&mut self, n: usize, mut value: E) { ++ /// Extend the vector by `n` clones of value. ++ fn extend_with(&mut self, n: usize, value: T) { + self.reserve(n); + + unsafe { +@@ -2715,15 +2700,15 @@ impl<T, A: Allocator> Vec<T, A> { + + // Write all elements except the last one + for _ in 1..n { +- ptr::write(ptr, value.next()); ++ ptr::write(ptr, value.clone()); + ptr = ptr.add(1); +- // Increment the length in every step in case next() panics ++ // Increment the length in every step in case clone() panics + local_len.increment_len(1); + } + + if n > 0 { + // We can write the last element directly without cloning needlessly +- ptr::write(ptr, value.last()); ++ ptr::write(ptr, value); + local_len.increment_len(1); + } + +@@ -2731,8 +2716,8 @@ impl<T, A: Allocator> Vec<T, A> { + } + } + +- /// Try to extend the vector by `n` values, using the given generator. +- fn try_extend_with<E: ExtendWith<T>>(&mut self, n: usize, mut value: E) -> Result<(), TryReserveError> { ++ /// Try to extend the vector by `n` clones of value. ++ fn try_extend_with(&mut self, n: usize, value: T) -> Result<(), TryReserveError> { + self.try_reserve(n)?; + + unsafe { +@@ -2744,15 +2729,15 @@ impl<T, A: Allocator> Vec<T, A> { + + // Write all elements except the last one + for _ in 1..n { +- ptr::write(ptr, value.next()); ++ ptr::write(ptr, value.clone()); + ptr = ptr.add(1); +- // Increment the length in every step in case next() panics ++ // Increment the length in every step in case clone() panics + local_len.increment_len(1); + } + + if n > 0 { + // We can write the last element directly without cloning needlessly +- ptr::write(ptr, value.last()); ++ ptr::write(ptr, value); + local_len.increment_len(1); + } + +@@ -3210,6 +3195,12 @@ impl<T, A: Allocator> Vec<T, A> { + /// If the closure returns false, the element will remain in the vector and will not be yielded + /// by the iterator. + /// ++ /// If the returned `ExtractIf` is not exhausted, e.g. because it is dropped without iterating ++ /// or the iteration short-circuits, then the remaining elements will be retained. ++ /// Use [`retain`] with a negated predicate if you do not need the returned iterator. ++ /// ++ /// [`retain`]: Vec::retain ++ /// + /// Using this method is equivalent to the following code: + /// + /// ``` +@@ -3228,10 +3219,10 @@ impl<T, A: Allocator> Vec<T, A> { + /// # assert_eq!(vec, vec![1, 4, 5]); + /// ``` + /// +- /// But `drain_filter` is easier to use. `drain_filter` is also more efficient, ++ /// But `extract_if` is easier to use. `extract_if` is also more efficient, + /// because it can backshift the elements of the array in bulk. + /// +- /// Note that `drain_filter` also lets you mutate every element in the filter closure, ++ /// Note that `extract_if` also lets you mutate every element in the filter closure, + /// regardless of whether you choose to keep or remove it. + /// + /// # Examples +@@ -3239,17 +3230,17 @@ impl<T, A: Allocator> Vec<T, A> { + /// Splitting an array into evens and odds, reusing the original allocation: + /// + /// ``` +- /// #![feature(drain_filter)] ++ /// #![feature(extract_if)] + /// let mut numbers = vec![1, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15]; + /// +- /// let evens = numbers.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>(); ++ /// let evens = numbers.extract_if(|x| *x % 2 == 0).collect::<Vec<_>>(); + /// let odds = numbers; + /// + /// assert_eq!(evens, vec![2, 4, 6, 8, 14]); + /// assert_eq!(odds, vec![1, 3, 5, 9, 11, 13, 15]); + /// ``` +- #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] +- pub fn drain_filter<F>(&mut self, filter: F) -> DrainFilter<'_, T, F, A> ++ #[unstable(feature = "extract_if", reason = "recently added", issue = "43244")] ++ pub fn extract_if<F>(&mut self, filter: F) -> ExtractIf<'_, T, F, A> + where + F: FnMut(&mut T) -> bool, + { +@@ -3260,7 +3251,7 @@ impl<T, A: Allocator> Vec<T, A> { + self.set_len(0); + } + +- DrainFilter { vec: self, idx: 0, del: 0, old_len, pred: filter, panic_flag: false } ++ ExtractIf { vec: self, idx: 0, del: 0, old_len, pred: filter } + } + } + +@@ -3272,7 +3263,7 @@ impl<T, A: Allocator> Vec<T, A> { + /// [`copy_from_slice`]: slice::copy_from_slice + #[cfg(not(no_global_oom_handling))] + #[stable(feature = "extend_ref", since = "1.2.0")] +-impl<'a, T: Copy + 'a, A: Allocator + 'a> Extend<&'a T> for Vec<T, A> { ++impl<'a, T: Copy + 'a, A: Allocator> Extend<&'a T> for Vec<T, A> { + fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) { + self.spec_extend(iter.into_iter()) + } +@@ -3290,9 +3281,14 @@ impl<'a, T: Copy + 'a, A: Allocator + 'a> Extend<&'a T> for Vec<T, A> { + + /// Implements comparison of vectors, [lexicographically](Ord#lexicographical-comparison). + #[stable(feature = "rust1", since = "1.0.0")] +-impl<T: PartialOrd, A: Allocator> PartialOrd for Vec<T, A> { ++impl<T, A1, A2> PartialOrd<Vec<T, A2>> for Vec<T, A1> ++where ++ T: PartialOrd, ++ A1: Allocator, ++ A2: Allocator, ++{ + #[inline] +- fn partial_cmp(&self, other: &Self) -> Option<Ordering> { ++ fn partial_cmp(&self, other: &Vec<T, A2>) -> Option<Ordering> { + PartialOrd::partial_cmp(&**self, &**other) + } + } +diff --git a/rust/alloc/vec/spec_extend.rs b/rust/alloc/vec/spec_extend.rs +index a6a735201e59b..ada9195374460 100644 +--- a/rust/alloc/vec/spec_extend.rs ++++ b/rust/alloc/vec/spec_extend.rs +@@ -77,7 +77,7 @@ impl<T, A: Allocator> TrySpecExtend<T, IntoIter<T>> for Vec<T, A> { + } + + #[cfg(not(no_global_oom_handling))] +-impl<'a, T: 'a, I, A: Allocator + 'a> SpecExtend<&'a T, I> for Vec<T, A> ++impl<'a, T: 'a, I, A: Allocator> SpecExtend<&'a T, I> for Vec<T, A> + where + I: Iterator<Item = &'a T>, + T: Clone, +@@ -87,7 +87,7 @@ where + } + } + +-impl<'a, T: 'a, I, A: Allocator + 'a> TrySpecExtend<&'a T, I> for Vec<T, A> ++impl<'a, T: 'a, I, A: Allocator> TrySpecExtend<&'a T, I> for Vec<T, A> + where + I: Iterator<Item = &'a T>, + T: Clone, +@@ -98,7 +98,7 @@ where + } + + #[cfg(not(no_global_oom_handling))] +-impl<'a, T: 'a, A: Allocator + 'a> SpecExtend<&'a T, slice::Iter<'a, T>> for Vec<T, A> ++impl<'a, T: 'a, A: Allocator> SpecExtend<&'a T, slice::Iter<'a, T>> for Vec<T, A> + where + T: Copy, + { +@@ -108,7 +108,7 @@ where + } + } + +-impl<'a, T: 'a, A: Allocator + 'a> TrySpecExtend<&'a T, slice::Iter<'a, T>> for Vec<T, A> ++impl<'a, T: 'a, A: Allocator> TrySpecExtend<&'a T, slice::Iter<'a, T>> for Vec<T, A> + where + T: Copy, + { +diff --git a/rust/compiler_builtins.rs b/rust/compiler_builtins.rs +index fb8ac3f211de5..bba2922c6ef77 100644 +--- a/rust/compiler_builtins.rs ++++ b/rust/compiler_builtins.rs +@@ -19,6 +19,7 @@ + //! [`compiler_builtins`]: https://github.com/rust-lang/compiler-builtins + //! [`compiler-rt`]: https://compiler-rt.llvm.org/ + ++#![allow(internal_features)] + #![feature(compiler_builtins)] + #![compiler_builtins] + #![no_builtins] +diff --git a/rust/kernel/print.rs b/rust/kernel/print.rs +index 8009184bf6d76..f48926e3e9fe3 100644 +--- a/rust/kernel/print.rs ++++ b/rust/kernel/print.rs +@@ -399,6 +399,7 @@ macro_rules! pr_debug ( + /// Mimics the interface of [`std::print!`]. See [`core::fmt`] and + /// `alloc::format!` for information about the formatting syntax. + /// ++/// [`pr_info!`]: crate::pr_info! + /// [`pr_cont`]: https://www.kernel.org/doc/html/latest/core-api/printk-basics.html#c.pr_cont + /// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html + /// +diff --git a/rust/kernel/sync/arc.rs b/rust/kernel/sync/arc.rs +index 3d496391a9bd8..7f04e4f00a2c7 100644 +--- a/rust/kernel/sync/arc.rs ++++ b/rust/kernel/sync/arc.rs +@@ -302,7 +302,7 @@ impl<T: ?Sized> Drop for Arc<T> { + // The count reached zero, we must free the memory. + // + // SAFETY: The pointer was initialised from the result of `Box::leak`. +- unsafe { Box::from_raw(self.ptr.as_ptr()) }; ++ unsafe { drop(Box::from_raw(self.ptr.as_ptr())) }; + } + } + } +diff --git a/rust/kernel/task.rs b/rust/kernel/task.rs +index 7eda15e5f1b37..b2299bc7ac1ff 100644 +--- a/rust/kernel/task.rs ++++ b/rust/kernel/task.rs +@@ -82,7 +82,7 @@ impl Task { + /// Returns a task reference for the currently executing task/thread. + /// + /// The recommended way to get the current task/thread is to use the +- /// [`current`](crate::current) macro because it is safe. ++ /// [`current`] macro because it is safe. + /// + /// # Safety + /// +diff --git a/scripts/min-tool-version.sh b/scripts/min-tool-version.sh +index d65ab8bfeaf4b..fd5ffdb81bab7 100755 +--- a/scripts/min-tool-version.sh ++++ b/scripts/min-tool-version.sh +@@ -31,7 +31,7 @@ llvm) + fi + ;; + rustc) +- echo 1.71.1 ++ echo 1.73.0 + ;; + bindgen) + echo 0.65.1 +diff --git a/sound/soc/amd/acp-config.c b/sound/soc/amd/acp-config.c +index 955145448c23b..f27c275800091 100644 +--- a/sound/soc/amd/acp-config.c ++++ b/sound/soc/amd/acp-config.c +@@ -3,7 +3,7 @@ + // This file is provided under a dual BSD/GPLv2 license. When using or + // redistributing this file, you may do so under either license. + // +-// Copyright(c) 2021, 2023 Advanced Micro Devices, Inc. ++// Copyright(c) 2021 Advanced Micro Devices, Inc. + // + // Authors: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com> + // +@@ -47,19 +47,6 @@ static const struct config_entry config_table[] = { + {} + }, + }, +- { +- .flags = FLAG_AMD_LEGACY, +- .device = ACP_PCI_DEV_ID, +- .dmi_table = (const struct dmi_system_id []) { +- { +- .matches = { +- DMI_MATCH(DMI_SYS_VENDOR, "Valve"), +- DMI_MATCH(DMI_PRODUCT_NAME, "Jupiter"), +- }, +- }, +- {} +- }, +- }, + { + .flags = FLAG_AMD_SOF, + .device = ACP_PCI_DEV_ID, +diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c +index 07cc6a201579a..09712e61c606e 100644 +--- a/sound/usb/quirks.c ++++ b/sound/usb/quirks.c +@@ -2031,10 +2031,14 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { + QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_IGNORE_CTL_ERROR), + DEVICE_FLG(0x0499, 0x1509, /* Steinberg UR22 */ + QUIRK_FLAG_GENERIC_IMPLICIT_FB), ++ DEVICE_FLG(0x0499, 0x3108, /* Yamaha YIT-W12TX */ ++ QUIRK_FLAG_GET_SAMPLE_RATE), + DEVICE_FLG(0x04d8, 0xfeea, /* Benchmark DAC1 Pre */ + QUIRK_FLAG_GET_SAMPLE_RATE), + DEVICE_FLG(0x04e8, 0xa051, /* Samsung USBC Headset (AKG) */ + QUIRK_FLAG_SKIP_CLOCK_SELECTOR | QUIRK_FLAG_CTL_MSG_DELAY_5M), ++ DEVICE_FLG(0x0525, 0xa4ad, /* Hamedal C20 usb camero */ ++ QUIRK_FLAG_IFACE_SKIP_CLOSE), + DEVICE_FLG(0x054c, 0x0b8c, /* Sony WALKMAN NW-A45 DAC */ + QUIRK_FLAG_SET_IFACE_FIRST), + DEVICE_FLG(0x0556, 0x0014, /* Phoenix Audio TMX320VC */ +@@ -2073,14 +2077,22 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { + QUIRK_FLAG_GENERIC_IMPLICIT_FB), + DEVICE_FLG(0x0763, 0x2031, /* M-Audio Fast Track C600 */ + QUIRK_FLAG_GENERIC_IMPLICIT_FB), ++ DEVICE_FLG(0x07fd, 0x000b, /* MOTU M Series 2nd hardware revision */ ++ QUIRK_FLAG_CTL_MSG_DELAY_1M), + DEVICE_FLG(0x08bb, 0x2702, /* LineX FM Transmitter */ + QUIRK_FLAG_IGNORE_CTL_ERROR), + DEVICE_FLG(0x0951, 0x16ad, /* Kingston HyperX */ + QUIRK_FLAG_CTL_MSG_DELAY_1M), + DEVICE_FLG(0x0b0e, 0x0349, /* Jabra 550a */ + QUIRK_FLAG_CTL_MSG_DELAY_1M), ++ DEVICE_FLG(0x0ecb, 0x205c, /* JBL Quantum610 Wireless */ ++ QUIRK_FLAG_FIXED_RATE), ++ DEVICE_FLG(0x0ecb, 0x2069, /* JBL Quantum810 Wireless */ ++ QUIRK_FLAG_FIXED_RATE), + DEVICE_FLG(0x0fd9, 0x0008, /* Hauppauge HVR-950Q */ + QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), ++ DEVICE_FLG(0x1224, 0x2a25, /* Jieli Technology USB PHY 2.0 */ ++ QUIRK_FLAG_GET_SAMPLE_RATE), + DEVICE_FLG(0x1395, 0x740a, /* Sennheiser DECT */ + QUIRK_FLAG_GET_SAMPLE_RATE), + DEVICE_FLG(0x1397, 0x0507, /* Behringer UMC202HD */ +@@ -2113,6 +2125,10 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { + QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY), + DEVICE_FLG(0x1901, 0x0191, /* GE B850V3 CP2114 audio interface */ + QUIRK_FLAG_GET_SAMPLE_RATE), ++ DEVICE_FLG(0x19f7, 0x0035, /* RODE NT-USB+ */ ++ QUIRK_FLAG_GET_SAMPLE_RATE), ++ DEVICE_FLG(0x1bcf, 0x2283, /* NexiGo N930AF FHD Webcam */ ++ QUIRK_FLAG_GET_SAMPLE_RATE), + DEVICE_FLG(0x2040, 0x7200, /* Hauppauge HVR-950Q */ + QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), + DEVICE_FLG(0x2040, 0x7201, /* Hauppauge HVR-950Q-MXL */ +@@ -2155,6 +2171,12 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { + QUIRK_FLAG_IGNORE_CTL_ERROR), + DEVICE_FLG(0x2912, 0x30c8, /* Audioengine D1 */ + QUIRK_FLAG_GET_SAMPLE_RATE), ++ DEVICE_FLG(0x2b53, 0x0023, /* Fiero SC-01 (firmware v1.0.0 @ 48 kHz) */ ++ QUIRK_FLAG_GENERIC_IMPLICIT_FB), ++ DEVICE_FLG(0x2b53, 0x0024, /* Fiero SC-01 (firmware v1.0.0 @ 96 kHz) */ ++ QUIRK_FLAG_GENERIC_IMPLICIT_FB), ++ DEVICE_FLG(0x2b53, 0x0031, /* Fiero SC-01 (firmware v1.1.0) */ ++ QUIRK_FLAG_GENERIC_IMPLICIT_FB), + DEVICE_FLG(0x30be, 0x0101, /* Schiit Hel */ + QUIRK_FLAG_IGNORE_CTL_ERROR), + DEVICE_FLG(0x413c, 0xa506, /* Dell AE515 sound bar */ +@@ -2163,22 +2185,6 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { + QUIRK_FLAG_ALIGN_TRANSFER), + DEVICE_FLG(0x534d, 0x2109, /* MacroSilicon MS2109 */ + QUIRK_FLAG_ALIGN_TRANSFER), +- DEVICE_FLG(0x1224, 0x2a25, /* Jieli Technology USB PHY 2.0 */ +- QUIRK_FLAG_GET_SAMPLE_RATE), +- DEVICE_FLG(0x2b53, 0x0023, /* Fiero SC-01 (firmware v1.0.0 @ 48 kHz) */ +- QUIRK_FLAG_GENERIC_IMPLICIT_FB), +- DEVICE_FLG(0x2b53, 0x0024, /* Fiero SC-01 (firmware v1.0.0 @ 96 kHz) */ +- QUIRK_FLAG_GENERIC_IMPLICIT_FB), +- DEVICE_FLG(0x2b53, 0x0031, /* Fiero SC-01 (firmware v1.1.0) */ +- QUIRK_FLAG_GENERIC_IMPLICIT_FB), +- DEVICE_FLG(0x0525, 0xa4ad, /* Hamedal C20 usb camero */ +- QUIRK_FLAG_IFACE_SKIP_CLOSE), +- DEVICE_FLG(0x0ecb, 0x205c, /* JBL Quantum610 Wireless */ +- QUIRK_FLAG_FIXED_RATE), +- DEVICE_FLG(0x0ecb, 0x2069, /* JBL Quantum810 Wireless */ +- QUIRK_FLAG_FIXED_RATE), +- DEVICE_FLG(0x1bcf, 0x2283, /* NexiGo N930AF FHD Webcam */ +- QUIRK_FLAG_GET_SAMPLE_RATE), + + /* Vendor matches */ + VENDOR_FLG(0x045e, /* MS Lifecam */ +diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c +index c779b9f2e6220..8a8fe1fa0d386 100644 +--- a/tools/perf/util/evlist.c ++++ b/tools/perf/util/evlist.c +@@ -103,7 +103,14 @@ struct evlist *evlist__new_default(void) + err = parse_event(evlist, can_profile_kernel ? "cycles:P" : "cycles:Pu"); + if (err) { + evlist__delete(evlist); +- evlist = NULL; ++ return NULL; ++ } ++ ++ if (evlist->core.nr_entries > 1) { ++ struct evsel *evsel; ++ ++ evlist__for_each_entry(evlist, evsel) ++ evsel__set_sample_id(evsel, /*can_sample_identifier=*/false); + } + + return evlist; +diff --git a/tools/testing/selftests/net/big_tcp.sh b/tools/testing/selftests/net/big_tcp.sh +index cde9a91c47971..2db9d15cd45fe 100755 +--- a/tools/testing/selftests/net/big_tcp.sh ++++ b/tools/testing/selftests/net/big_tcp.sh +@@ -122,7 +122,9 @@ do_netperf() { + local netns=$1 + + [ "$NF" = "6" ] && serip=$SERVER_IP6 +- ip net exec $netns netperf -$NF -t TCP_STREAM -H $serip 2>&1 >/dev/null ++ ++ # use large write to be sure to generate big tcp packets ++ ip net exec $netns netperf -$NF -t TCP_STREAM -l 1 -H $serip -- -m 262144 2>&1 >/dev/null + } + + do_test() { +diff --git a/tools/testing/selftests/net/cmsg_ipv6.sh b/tools/testing/selftests/net/cmsg_ipv6.sh +index 330d0b1ceced3..c921750ca118d 100755 +--- a/tools/testing/selftests/net/cmsg_ipv6.sh ++++ b/tools/testing/selftests/net/cmsg_ipv6.sh +@@ -91,7 +91,7 @@ for ovr in setsock cmsg both diff; do + check_result $? 0 "TCLASS $prot $ovr - pass" + + while [ -d /proc/$BG ]; do +- $NSEXE ./cmsg_sender -6 -p u $TGT6 1234 ++ $NSEXE ./cmsg_sender -6 -p $p $m $((TOS2)) $TGT6 1234 + done + + tcpdump -r $TMPF -v 2>&1 | grep "class $TOS2" >> /dev/null +@@ -128,7 +128,7 @@ for ovr in setsock cmsg both diff; do + check_result $? 0 "HOPLIMIT $prot $ovr - pass" + + while [ -d /proc/$BG ]; do +- $NSEXE ./cmsg_sender -6 -p u $TGT6 1234 ++ $NSEXE ./cmsg_sender -6 -p $p $m $LIM $TGT6 1234 + done + + tcpdump -r $TMPF -v 2>&1 | grep "hlim $LIM[^0-9]" >> /dev/null +diff --git a/tools/testing/selftests/net/pmtu.sh b/tools/testing/selftests/net/pmtu.sh +index 4a5f031be2324..d65fdd407d73f 100755 +--- a/tools/testing/selftests/net/pmtu.sh ++++ b/tools/testing/selftests/net/pmtu.sh +@@ -1,4 +1,4 @@ +-#!/bin/sh ++#!/bin/bash + # SPDX-License-Identifier: GPL-2.0 + # + # Check that route PMTU values match expectations, and that initial device MTU +@@ -198,8 +198,8 @@ + # - pmtu_ipv6_route_change + # Same as above but with IPv6 + +-# Kselftest framework requirement - SKIP code is 4. +-ksft_skip=4 ++source lib.sh ++source net_helper.sh + + PAUSE_ON_FAIL=no + VERBOSE=0 +@@ -268,16 +268,6 @@ tests=" + pmtu_ipv4_route_change ipv4: PMTU exception w/route replace 1 + pmtu_ipv6_route_change ipv6: PMTU exception w/route replace 1" + +-NS_A="ns-A" +-NS_B="ns-B" +-NS_C="ns-C" +-NS_R1="ns-R1" +-NS_R2="ns-R2" +-ns_a="ip netns exec ${NS_A}" +-ns_b="ip netns exec ${NS_B}" +-ns_c="ip netns exec ${NS_C}" +-ns_r1="ip netns exec ${NS_R1}" +-ns_r2="ip netns exec ${NS_R2}" + # Addressing and routing for tests with routers: four network segments, with + # index SEGMENT between 1 and 4, a common prefix (PREFIX4 or PREFIX6) and an + # identifier ID, which is 1 for hosts (A and B), 2 for routers (R1 and R2). +@@ -543,13 +533,17 @@ setup_ip6ip6() { + } + + setup_namespaces() { ++ setup_ns NS_A NS_B NS_C NS_R1 NS_R2 + for n in ${NS_A} ${NS_B} ${NS_C} ${NS_R1} ${NS_R2}; do +- ip netns add ${n} || return 1 +- + # Disable DAD, so that we don't have to wait to use the + # configured IPv6 addresses + ip netns exec ${n} sysctl -q net/ipv6/conf/default/accept_dad=0 + done ++ ns_a="ip netns exec ${NS_A}" ++ ns_b="ip netns exec ${NS_B}" ++ ns_c="ip netns exec ${NS_C}" ++ ns_r1="ip netns exec ${NS_R1}" ++ ns_r2="ip netns exec ${NS_R2}" + } + + setup_veth() { +@@ -839,7 +833,7 @@ setup_bridge() { + run_cmd ${ns_a} ip link set br0 up + + run_cmd ${ns_c} ip link add veth_C-A type veth peer name veth_A-C +- run_cmd ${ns_c} ip link set veth_A-C netns ns-A ++ run_cmd ${ns_c} ip link set veth_A-C netns ${NS_A} + + run_cmd ${ns_a} ip link set veth_A-C up + run_cmd ${ns_c} ip link set veth_C-A up +@@ -944,9 +938,7 @@ cleanup() { + done + socat_pids= + +- for n in ${NS_A} ${NS_B} ${NS_C} ${NS_R1} ${NS_R2}; do +- ip netns del ${n} 2> /dev/null +- done ++ cleanup_all_ns + + ip link del veth_A-C 2>/dev/null + ip link del veth_A-R1 2>/dev/null +@@ -1345,13 +1337,15 @@ test_pmtu_ipvX_over_bridged_vxlanY_or_geneveY_exception() { + TCPDST="TCP:[${dst}]:50000" + fi + ${ns_b} socat -T 3 -u -6 TCP-LISTEN:50000 STDOUT > $tmpoutfile & ++ local socat_pid=$! + +- sleep 1 ++ wait_local_port_listen ${NS_B} 50000 tcp + + dd if=/dev/zero status=none bs=1M count=1 | ${target} socat -T 3 -u STDIN $TCPDST,connect-timeout=3 + + size=$(du -sb $tmpoutfile) + size=${size%%/tmp/*} ++ wait ${socat_pid} + + [ $size -ne 1048576 ] && err "File size $size mismatches exepcted value in locally bridged vxlan test" && return 1 + done +@@ -1963,6 +1957,13 @@ check_command() { + return 0 + } + ++check_running() { ++ pid=${1} ++ cmd=${2} ++ ++ [ "$(cat /proc/${pid}/cmdline 2>/dev/null | tr -d '\0')" = "{cmd}" ] ++} ++ + test_cleanup_vxlanX_exception() { + outer="${1}" + encap="vxlan" +@@ -1993,11 +1994,12 @@ test_cleanup_vxlanX_exception() { + + ${ns_a} ip link del dev veth_A-R1 & + iplink_pid=$! +- sleep 1 +- if [ "$(cat /proc/${iplink_pid}/cmdline 2>/dev/null | tr -d '\0')" = "iplinkdeldevveth_A-R1" ]; then +- err " can't delete veth device in a timely manner, PMTU dst likely leaked" +- return 1 +- fi ++ for i in $(seq 1 20); do ++ check_running ${iplink_pid} "iplinkdeldevveth_A-R1" || return 0 ++ sleep 0.1 ++ done ++ err " can't delete veth device in a timely manner, PMTU dst likely leaked" ++ return 1 + } + + test_cleanup_ipv6_exception() { +diff --git a/tools/testing/selftests/net/udpgro_fwd.sh b/tools/testing/selftests/net/udpgro_fwd.sh +index d6b9c759043ca..9cd5e885e91f7 100755 +--- a/tools/testing/selftests/net/udpgro_fwd.sh ++++ b/tools/testing/selftests/net/udpgro_fwd.sh +@@ -39,6 +39,10 @@ create_ns() { + for ns in $NS_SRC $NS_DST; do + ip netns add $ns + ip -n $ns link set dev lo up ++ ++ # disable route solicitations to decrease 'noise' traffic ++ ip netns exec $ns sysctl -qw net.ipv6.conf.default.router_solicitations=0 ++ ip netns exec $ns sysctl -qw net.ipv6.conf.all.router_solicitations=0 + done + + ip link add name veth$SRC type veth peer name veth$DST +@@ -80,6 +84,12 @@ create_vxlan_pair() { + create_vxlan_endpoint $BASE$ns veth$ns $BM_NET_V6$((3 - $ns)) vxlan6$ns 6 + ip -n $BASE$ns addr add dev vxlan6$ns $OL_NET_V6$ns/24 nodad + done ++ ++ # preload neighbur cache, do avoid some noisy traffic ++ local addr_dst=$(ip -j -n $BASE$DST link show dev vxlan6$DST |jq -r '.[]["address"]') ++ local addr_src=$(ip -j -n $BASE$SRC link show dev vxlan6$SRC |jq -r '.[]["address"]') ++ ip -n $BASE$DST neigh add dev vxlan6$DST lladdr $addr_src $OL_NET_V6$SRC ++ ip -n $BASE$SRC neigh add dev vxlan6$SRC lladdr $addr_dst $OL_NET_V6$DST + } + + is_ipv6() { +@@ -119,7 +129,7 @@ run_test() { + # not enable GRO + ip netns exec $NS_DST $ipt -A INPUT -p udp --dport 4789 + ip netns exec $NS_DST $ipt -A INPUT -p udp --dport 8000 +- ip netns exec $NS_DST ./udpgso_bench_rx -C 1000 -R 10 -n 10 -l 1300 $rx_args & ++ ip netns exec $NS_DST ./udpgso_bench_rx -C 2000 -R 100 -n 10 -l 1300 $rx_args & + local spid=$! + wait_local_port_listen "$NS_DST" 8000 udp + ip netns exec $NS_SRC ./udpgso_bench_tx $family -M 1 -s 13000 -S 1300 -D $dst +@@ -168,7 +178,7 @@ run_bench() { + # bind the sender and the receiver to different CPUs to try + # get reproducible results + ip netns exec $NS_DST bash -c "echo 2 > /sys/class/net/veth$DST/queues/rx-0/rps_cpus" +- ip netns exec $NS_DST taskset 0x2 ./udpgso_bench_rx -C 1000 -R 10 & ++ ip netns exec $NS_DST taskset 0x2 ./udpgso_bench_rx -C 2000 -R 100 & + local spid=$! + wait_local_port_listen "$NS_DST" 8000 udp + ip netns exec $NS_SRC taskset 0x1 ./udpgso_bench_tx $family -l 3 -S 1300 -D $dst +diff --git a/tools/testing/selftests/net/udpgso_bench_rx.c b/tools/testing/selftests/net/udpgso_bench_rx.c +index f35a924d4a303..1cbadd267c963 100644 +--- a/tools/testing/selftests/net/udpgso_bench_rx.c ++++ b/tools/testing/selftests/net/udpgso_bench_rx.c +@@ -375,7 +375,7 @@ static void do_recv(void) + do_flush_udp(fd); + + tnow = gettimeofday_ms(); +- if (tnow > treport) { ++ if (!cfg_expected_pkt_nr && tnow > treport) { + if (packets) + fprintf(stderr, + "%s rx: %6lu MB/s %8lu calls/s\n", +diff --git a/tools/testing/selftests/net/unicast_extensions.sh b/tools/testing/selftests/net/unicast_extensions.sh +index 2d10ccac898a7..f52aa5f7da524 100755 +--- a/tools/testing/selftests/net/unicast_extensions.sh ++++ b/tools/testing/selftests/net/unicast_extensions.sh +@@ -1,4 +1,4 @@ +-#!/bin/sh ++#!/bin/bash + # SPDX-License-Identifier: GPL-2.0 + # + # By Seth Schoen (c) 2021, for the IPv4 Unicast Extensions Project +@@ -28,8 +28,7 @@ + # These tests provide an easy way to flip the expected result of any + # of these behaviors for testing kernel patches that change them. + +-# Kselftest framework requirement - SKIP code is 4. +-ksft_skip=4 ++source lib.sh + + # nettest can be run from PATH or from same directory as this selftest + if ! which nettest >/dev/null; then +@@ -61,20 +60,20 @@ _do_segmenttest(){ + # foo --- bar + # Arguments: ip_a ip_b prefix_length test_description + # +- # Caller must set up foo-ns and bar-ns namespaces ++ # Caller must set up $foo_ns and $bar_ns namespaces + # containing linked veth devices foo and bar, + # respectively. + +- ip -n foo-ns address add $1/$3 dev foo || return 1 +- ip -n foo-ns link set foo up || return 1 +- ip -n bar-ns address add $2/$3 dev bar || return 1 +- ip -n bar-ns link set bar up || return 1 ++ ip -n $foo_ns address add $1/$3 dev foo || return 1 ++ ip -n $foo_ns link set foo up || return 1 ++ ip -n $bar_ns address add $2/$3 dev bar || return 1 ++ ip -n $bar_ns link set bar up || return 1 + +- ip netns exec foo-ns timeout 2 ping -c 1 $2 || return 1 +- ip netns exec bar-ns timeout 2 ping -c 1 $1 || return 1 ++ ip netns exec $foo_ns timeout 2 ping -c 1 $2 || return 1 ++ ip netns exec $bar_ns timeout 2 ping -c 1 $1 || return 1 + +- nettest -B -N bar-ns -O foo-ns -r $1 || return 1 +- nettest -B -N foo-ns -O bar-ns -r $2 || return 1 ++ nettest -B -N $bar_ns -O $foo_ns -r $1 || return 1 ++ nettest -B -N $foo_ns -O $bar_ns -r $2 || return 1 + + return 0 + } +@@ -88,31 +87,31 @@ _do_route_test(){ + # Arguments: foo_ip foo1_ip bar1_ip bar_ip prefix_len test_description + # Displays test result and returns success or failure. + +- # Caller must set up foo-ns, bar-ns, and router-ns ++ # Caller must set up $foo_ns, $bar_ns, and $router_ns + # containing linked veth devices foo-foo1, bar1-bar +- # (foo in foo-ns, foo1 and bar1 in router-ns, and +- # bar in bar-ns). +- +- ip -n foo-ns address add $1/$5 dev foo || return 1 +- ip -n foo-ns link set foo up || return 1 +- ip -n foo-ns route add default via $2 || return 1 +- ip -n bar-ns address add $4/$5 dev bar || return 1 +- ip -n bar-ns link set bar up || return 1 +- ip -n bar-ns route add default via $3 || return 1 +- ip -n router-ns address add $2/$5 dev foo1 || return 1 +- ip -n router-ns link set foo1 up || return 1 +- ip -n router-ns address add $3/$5 dev bar1 || return 1 +- ip -n router-ns link set bar1 up || return 1 +- +- echo 1 | ip netns exec router-ns tee /proc/sys/net/ipv4/ip_forward +- +- ip netns exec foo-ns timeout 2 ping -c 1 $2 || return 1 +- ip netns exec foo-ns timeout 2 ping -c 1 $4 || return 1 +- ip netns exec bar-ns timeout 2 ping -c 1 $3 || return 1 +- ip netns exec bar-ns timeout 2 ping -c 1 $1 || return 1 +- +- nettest -B -N bar-ns -O foo-ns -r $1 || return 1 +- nettest -B -N foo-ns -O bar-ns -r $4 || return 1 ++ # (foo in $foo_ns, foo1 and bar1 in $router_ns, and ++ # bar in $bar_ns). ++ ++ ip -n $foo_ns address add $1/$5 dev foo || return 1 ++ ip -n $foo_ns link set foo up || return 1 ++ ip -n $foo_ns route add default via $2 || return 1 ++ ip -n $bar_ns address add $4/$5 dev bar || return 1 ++ ip -n $bar_ns link set bar up || return 1 ++ ip -n $bar_ns route add default via $3 || return 1 ++ ip -n $router_ns address add $2/$5 dev foo1 || return 1 ++ ip -n $router_ns link set foo1 up || return 1 ++ ip -n $router_ns address add $3/$5 dev bar1 || return 1 ++ ip -n $router_ns link set bar1 up || return 1 ++ ++ echo 1 | ip netns exec $router_ns tee /proc/sys/net/ipv4/ip_forward ++ ++ ip netns exec $foo_ns timeout 2 ping -c 1 $2 || return 1 ++ ip netns exec $foo_ns timeout 2 ping -c 1 $4 || return 1 ++ ip netns exec $bar_ns timeout 2 ping -c 1 $3 || return 1 ++ ip netns exec $bar_ns timeout 2 ping -c 1 $1 || return 1 ++ ++ nettest -B -N $bar_ns -O $foo_ns -r $1 || return 1 ++ nettest -B -N $foo_ns -O $bar_ns -r $4 || return 1 + + return 0 + } +@@ -121,17 +120,15 @@ segmenttest(){ + # Sets up veth link and tries to connect over it. + # Arguments: ip_a ip_b prefix_len test_description + hide_output +- ip netns add foo-ns +- ip netns add bar-ns +- ip link add foo netns foo-ns type veth peer name bar netns bar-ns ++ setup_ns foo_ns bar_ns ++ ip link add foo netns $foo_ns type veth peer name bar netns $bar_ns + + test_result=0 + _do_segmenttest "$@" || test_result=1 + +- ip netns pids foo-ns | xargs -r kill -9 +- ip netns pids bar-ns | xargs -r kill -9 +- ip netns del foo-ns +- ip netns del bar-ns ++ ip netns pids $foo_ns | xargs -r kill -9 ++ ip netns pids $bar_ns | xargs -r kill -9 ++ cleanup_ns $foo_ns $bar_ns + show_output + + # inverted tests will expect failure instead of success +@@ -147,21 +144,17 @@ route_test(){ + # Returns success or failure. + + hide_output +- ip netns add foo-ns +- ip netns add bar-ns +- ip netns add router-ns +- ip link add foo netns foo-ns type veth peer name foo1 netns router-ns +- ip link add bar netns bar-ns type veth peer name bar1 netns router-ns ++ setup_ns foo_ns bar_ns router_ns ++ ip link add foo netns $foo_ns type veth peer name foo1 netns $router_ns ++ ip link add bar netns $bar_ns type veth peer name bar1 netns $router_ns + + test_result=0 + _do_route_test "$@" || test_result=1 + +- ip netns pids foo-ns | xargs -r kill -9 +- ip netns pids bar-ns | xargs -r kill -9 +- ip netns pids router-ns | xargs -r kill -9 +- ip netns del foo-ns +- ip netns del bar-ns +- ip netns del router-ns ++ ip netns pids $foo_ns | xargs -r kill -9 ++ ip netns pids $bar_ns | xargs -r kill -9 ++ ip netns pids $router_ns | xargs -r kill -9 ++ cleanup_ns $foo_ns $bar_ns $router_ns + + show_output + |