diff -u linux-5.15.0/Makefile linux-5.15.0/Makefile --- linux-5.15.0/Makefile +++ linux-5.15.0/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 VERSION = 5 PATCHLEVEL = 15 -SUBLEVEL = 35 +SUBLEVEL = 39 EXTRAVERSION = NAME = Trick or Treat diff -u linux-5.15.0/arch/arm/boot/dts/dra7-l4.dtsi linux-5.15.0/arch/arm/boot/dts/dra7-l4.dtsi --- linux-5.15.0/arch/arm/boot/dts/dra7-l4.dtsi +++ linux-5.15.0/arch/arm/boot/dts/dra7-l4.dtsi @@ -4188,11 +4188,11 @@ reg = <0x1d0010 0x4>; reg-names = "sysc"; ti,sysc-midle = , - , - ; + ; ti,sysc-sidle = , , ; + power-domains = <&prm_vpe>; clocks = <&vpe_clkctrl DRA7_VPE_VPE_CLKCTRL 0>; clock-names = "fck"; #address-cells = <1>; diff -u linux-5.15.0/arch/arm/boot/dts/omap3-gta04.dtsi linux-5.15.0/arch/arm/boot/dts/omap3-gta04.dtsi --- linux-5.15.0/arch/arm/boot/dts/omap3-gta04.dtsi +++ linux-5.15.0/arch/arm/boot/dts/omap3-gta04.dtsi @@ -31,6 +31,8 @@ aliases { display0 = &lcd; display1 = &tv0; + /delete-property/ mmc2; + /delete-property/ mmc3; }; ldo_3v3: fixedregulator { diff -u linux-5.15.0/arch/arm64/Kconfig linux-5.15.0/arch/arm64/Kconfig --- linux-5.15.0/arch/arm64/Kconfig +++ linux-5.15.0/arch/arm64/Kconfig @@ -154,7 +154,6 @@ select HAVE_ARCH_KGDB select HAVE_ARCH_MMAP_RND_BITS select HAVE_ARCH_MMAP_RND_COMPAT_BITS if COMPAT - select HAVE_ARCH_PFN_VALID select HAVE_ARCH_PREL32_RELOCATIONS select HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET select HAVE_ARCH_SECCOMP_FILTER diff -u linux-5.15.0/arch/arm64/boot/dts/amlogic/meson-sm1-bananapi-m5.dts linux-5.15.0/arch/arm64/boot/dts/amlogic/meson-sm1-bananapi-m5.dts --- linux-5.15.0/arch/arm64/boot/dts/amlogic/meson-sm1-bananapi-m5.dts +++ linux-5.15.0/arch/arm64/boot/dts/amlogic/meson-sm1-bananapi-m5.dts @@ -437,6 +437,7 @@ "", "eMMC_RST#", /* BOOT_12 */ "eMMC_DS", /* BOOT_13 */ + "", "", /* GPIOC */ "SD_D0_B", /* GPIOC_0 */ "SD_D1_B", /* GPIOC_1 */ diff -u linux-5.15.0/arch/arm64/boot/dts/intel/socfpga_agilex.dtsi linux-5.15.0/arch/arm64/boot/dts/intel/socfpga_agilex.dtsi --- linux-5.15.0/arch/arm64/boot/dts/intel/socfpga_agilex.dtsi +++ linux-5.15.0/arch/arm64/boot/dts/intel/socfpga_agilex.dtsi @@ -628,7 +628,7 @@ }; qspi: spi@ff8d2000 { - compatible = "cdns,qspi-nor"; + compatible = "intel,socfpga-qspi", "cdns,qspi-nor"; #address-cells = <1>; #size-cells = <0>; reg = <0xff8d2000 0x100>, diff -u linux-5.15.0/arch/arm64/boot/dts/qcom/sc7180.dtsi linux-5.15.0/arch/arm64/boot/dts/qcom/sc7180.dtsi --- linux-5.15.0/arch/arm64/boot/dts/qcom/sc7180.dtsi +++ linux-5.15.0/arch/arm64/boot/dts/qcom/sc7180.dtsi @@ -1460,6 +1460,8 @@ "imem", "config"; + qcom,qmp = <&aoss_qmp>; + qcom,smem-states = <&ipa_smp2p_out 0>, <&ipa_smp2p_out 1>; qcom,smem-state-names = "ipa-clock-enabled-valid", diff -u linux-5.15.0/arch/arm64/boot/dts/qcom/sc7280.dtsi linux-5.15.0/arch/arm64/boot/dts/qcom/sc7280.dtsi --- linux-5.15.0/arch/arm64/boot/dts/qcom/sc7280.dtsi +++ linux-5.15.0/arch/arm64/boot/dts/qcom/sc7280.dtsi @@ -615,6 +615,8 @@ interconnect-names = "memory", "config"; + qcom,qmp = <&aoss_qmp>; + qcom,smem-states = <&ipa_smp2p_out 0>, <&ipa_smp2p_out 1>; qcom,smem-state-names = "ipa-clock-enabled-valid", diff -u linux-5.15.0/arch/arm64/boot/dts/qcom/sm8350.dtsi linux-5.15.0/arch/arm64/boot/dts/qcom/sm8350.dtsi --- linux-5.15.0/arch/arm64/boot/dts/qcom/sm8350.dtsi +++ linux-5.15.0/arch/arm64/boot/dts/qcom/sm8350.dtsi @@ -736,6 +736,8 @@ interconnect-names = "memory", "config"; + qcom,qmp = <&aoss_qmp>; + qcom,smem-states = <&ipa_smp2p_out 0>, <&ipa_smp2p_out 1>; qcom,smem-state-names = "ipa-clock-enabled-valid", diff -u linux-5.15.0/arch/arm64/include/asm/pgtable.h linux-5.15.0/arch/arm64/include/asm/pgtable.h --- linux-5.15.0/arch/arm64/include/asm/pgtable.h +++ linux-5.15.0/arch/arm64/include/asm/pgtable.h @@ -535,7 +535,7 @@ PMD_TYPE_TABLE) #define pmd_sect(pmd) ((pmd_val(pmd) & PMD_TYPE_MASK) == \ PMD_TYPE_SECT) -#define pmd_leaf(pmd) pmd_sect(pmd) +#define pmd_leaf(pmd) (pmd_present(pmd) && !pmd_table(pmd)) #define pmd_bad(pmd) (!pmd_table(pmd)) #define pmd_leaf_size(pmd) (pmd_cont(pmd) ? CONT_PMD_SIZE : PMD_SIZE) @@ -625,7 +625,7 @@ #define pud_none(pud) (!pud_val(pud)) #define pud_bad(pud) (!pud_table(pud)) #define pud_present(pud) pte_present(pud_pte(pud)) -#define pud_leaf(pud) pud_sect(pud) +#define pud_leaf(pud) (pud_present(pud) && !pud_table(pud)) #define pud_valid(pud) pte_valid(pud_pte(pud)) static inline void set_pud(pud_t *pudp, pud_t pud) diff -u linux-5.15.0/arch/arm64/mm/init.c linux-5.15.0/arch/arm64/mm/init.c --- linux-5.15.0/arch/arm64/mm/init.c +++ linux-5.15.0/arch/arm64/mm/init.c @@ -184,43 +184,6 @@ free_area_init(max_zone_pfns); } -int pfn_valid(unsigned long pfn) -{ - phys_addr_t addr = PFN_PHYS(pfn); - struct mem_section *ms; - - /* - * Ensure the upper PAGE_SHIFT bits are clear in the - * pfn. Else it might lead to false positives when - * some of the upper bits are set, but the lower bits - * match a valid pfn. - */ - if (PHYS_PFN(addr) != pfn) - return 0; - - if (pfn_to_section_nr(pfn) >= NR_MEM_SECTIONS) - return 0; - - ms = __pfn_to_section(pfn); - if (!valid_section(ms)) - return 0; - - /* - * ZONE_DEVICE memory does not have the memblock entries. - * memblock_is_map_memory() check for ZONE_DEVICE based - * addresses will always fail. Even the normal hotplugged - * memory will never have MEMBLOCK_NOMAP flag set in their - * memblock entries. Skip memblock search for all non early - * memory sections covering all of hotplug memory including - * both normal and ZONE_DEVICE based. - */ - if (!early_section(ms)) - return pfn_section_valid(ms, pfn); - - return memblock_is_memory(addr); -} -EXPORT_SYMBOL(pfn_valid); - int pfn_is_map_memory(unsigned long pfn) { phys_addr_t addr = PFN_PHYS(pfn); diff -u linux-5.15.0/arch/parisc/kernel/time.c linux-5.15.0/arch/parisc/kernel/time.c --- linux-5.15.0/arch/parisc/kernel/time.c +++ linux-5.15.0/arch/parisc/kernel/time.c @@ -249,13 +249,9 @@ static int __init init_cr16_clocksource(void) { /* - * The cr16 interval timers are not syncronized across CPUs, even if - * they share the same socket. + * The cr16 interval timers are not synchronized across CPUs. */ if (num_online_cpus() > 1 && !running_on_qemu) { - /* mark sched_clock unstable */ - clear_sched_clock_stable(); - clocksource_cr16.name = "cr16_unstable"; clocksource_cr16.flags = CLOCK_SOURCE_UNSTABLE; clocksource_cr16.rating = 0; diff -u linux-5.15.0/arch/powerpc/kernel/kvm.c linux-5.15.0/arch/powerpc/kernel/kvm.c --- linux-5.15.0/arch/powerpc/kernel/kvm.c +++ linux-5.15.0/arch/powerpc/kernel/kvm.c @@ -669,7 +669,8 @@ on_each_cpu(kvm_map_magic_page, &features, 1); /* Quick self-test to see if the mapping works */ - if (fault_in_pages_readable((const char *)KVM_MAGIC_PAGE, sizeof(u32))) { + if (fault_in_readable((const char __user *)KVM_MAGIC_PAGE, + sizeof(u32))) { kvm_patching_worked = false; return; } diff -u linux-5.15.0/arch/powerpc/kernel/signal_32.c linux-5.15.0/arch/powerpc/kernel/signal_32.c --- linux-5.15.0/arch/powerpc/kernel/signal_32.c +++ linux-5.15.0/arch/powerpc/kernel/signal_32.c @@ -1048,7 +1048,7 @@ if (new_ctx == NULL) return 0; if (!access_ok(new_ctx, ctx_size) || - fault_in_pages_readable((u8 __user *)new_ctx, ctx_size)) + fault_in_readable((char __user *)new_ctx, ctx_size)) return -EFAULT; /* @@ -1239,7 +1239,7 @@ #endif if (!access_ok(ctx, sizeof(*ctx)) || - fault_in_pages_readable((u8 __user *)ctx, sizeof(*ctx))) + fault_in_readable((char __user *)ctx, sizeof(*ctx))) return -EFAULT; /* diff -u linux-5.15.0/arch/powerpc/kernel/signal_64.c linux-5.15.0/arch/powerpc/kernel/signal_64.c --- linux-5.15.0/arch/powerpc/kernel/signal_64.c +++ linux-5.15.0/arch/powerpc/kernel/signal_64.c @@ -688,7 +688,7 @@ if (new_ctx == NULL) return 0; if (!access_ok(new_ctx, ctx_size) || - fault_in_pages_readable((u8 __user *)new_ctx, ctx_size)) + fault_in_readable((char __user *)new_ctx, ctx_size)) return -EFAULT; /* diff -u linux-5.15.0/arch/powerpc/perf/power10-pmu.c linux-5.15.0/arch/powerpc/perf/power10-pmu.c --- linux-5.15.0/arch/powerpc/perf/power10-pmu.c +++ linux-5.15.0/arch/powerpc/perf/power10-pmu.c @@ -91,8 +91,8 @@ /* Table of alternatives, sorted by column 0 */ static const unsigned int power10_event_alternatives[][MAX_ALT] = { - { PM_CYC_ALT, PM_CYC }, { PM_INST_CMPL_ALT, PM_INST_CMPL }, + { PM_CYC_ALT, PM_CYC }, }; static int power10_get_alternatives(u64 event, unsigned int flags, u64 alt[]) diff -u linux-5.15.0/arch/riscv/mm/init.c linux-5.15.0/arch/riscv/mm/init.c --- linux-5.15.0/arch/riscv/mm/init.c +++ linux-5.15.0/arch/riscv/mm/init.c @@ -218,8 +218,25 @@ * early_init_fdt_reserve_self() since __pa() does * not work for DTB pointers that are fixmap addresses */ - if (!IS_ENABLED(CONFIG_BUILTIN_DTB)) - memblock_reserve(dtb_early_pa, fdt_totalsize(dtb_early_va)); + if (!IS_ENABLED(CONFIG_BUILTIN_DTB)) { + /* + * In case the DTB is not located in a memory region we won't + * be able to locate it later on via the linear mapping and + * get a segfault when accessing it via __va(dtb_early_pa). + * To avoid this situation copy DTB to a memory region. + * Note that memblock_phys_alloc will also reserve DTB region. + */ + if (!memblock_is_memory(dtb_early_pa)) { + size_t fdt_size = fdt_totalsize(dtb_early_va); + phys_addr_t new_dtb_early_pa = memblock_phys_alloc(fdt_size, PAGE_SIZE); + void *new_dtb_early_va = early_memremap(new_dtb_early_pa, fdt_size); + + memcpy(new_dtb_early_va, dtb_early_va, fdt_size); + early_memunmap(new_dtb_early_va, fdt_size); + _dtb_early_pa = new_dtb_early_pa; + } else + memblock_reserve(dtb_early_pa, fdt_totalsize(dtb_early_va)); + } early_init_fdt_scan_reserved_mem(); dma_contiguous_reserve(dma32_phys_limit); diff -u linux-5.15.0/arch/s390/mm/gmap.c linux-5.15.0/arch/s390/mm/gmap.c --- linux-5.15.0/arch/s390/mm/gmap.c +++ linux-5.15.0/arch/s390/mm/gmap.c @@ -2608,6 +2608,18 @@ return 0; } +/* + * Give a chance to schedule after setting a key to 256 pages. + * We only hold the mm lock, which is a rwsem and the kvm srcu. + * Both can sleep. + */ +static int __s390_enable_skey_pmd(pmd_t *pmd, unsigned long addr, + unsigned long next, struct mm_walk *walk) +{ + cond_resched(); + return 0; +} + static int __s390_enable_skey_hugetlb(pte_t *pte, unsigned long addr, unsigned long hmask, unsigned long next, struct mm_walk *walk) @@ -2630,12 +2642,14 @@ end = start + HPAGE_SIZE - 1; __storage_key_init_range(start, end); set_bit(PG_arch_1, &page->flags); + cond_resched(); return 0; } static const struct mm_walk_ops enable_skey_walk_ops = { .hugetlb_entry = __s390_enable_skey_hugetlb, .pte_entry = __s390_enable_skey_pte, + .pmd_entry = __s390_enable_skey_pmd, }; int s390_enable_skey(void) diff -u linux-5.15.0/arch/s390/mm/pgtable.c linux-5.15.0/arch/s390/mm/pgtable.c --- linux-5.15.0/arch/s390/mm/pgtable.c +++ linux-5.15.0/arch/s390/mm/pgtable.c @@ -748,7 +748,7 @@ pgste_val(pgste) |= PGSTE_GR_BIT | PGSTE_GC_BIT; ptev = pte_val(*ptep); if (!(ptev & _PAGE_INVALID) && (ptev & _PAGE_WRITE)) - page_set_storage_key(ptev & PAGE_MASK, PAGE_DEFAULT_KEY, 1); + page_set_storage_key(ptev & PAGE_MASK, PAGE_DEFAULT_KEY, 0); pgste_set_unlock(ptep, pgste); preempt_enable(); } diff -u linux-5.15.0/arch/x86/kernel/fpu/core.c linux-5.15.0/arch/x86/kernel/fpu/core.c --- linux-5.15.0/arch/x86/kernel/fpu/core.c +++ linux-5.15.0/arch/x86/kernel/fpu/core.c @@ -40,17 +40,7 @@ */ struct fpstate init_fpstate __ro_after_init; -/* - * Track whether the kernel is using the FPU state - * currently. - * - * This flag is used: - * - * - by IRQ context code to potentially use the FPU - * if it's unused. - * - * - to debug kernel_fpu_begin()/end() correctness - */ +/* Track in-kernel FPU usage */ static DEFINE_PER_CPU(bool, in_kernel_fpu); /* @@ -58,42 +48,37 @@ */ DEFINE_PER_CPU(struct fpu *, fpu_fpregs_owner_ctx); -static bool kernel_fpu_disabled(void) -{ - return this_cpu_read(in_kernel_fpu); -} - -static bool interrupted_kernel_fpu_idle(void) -{ - return !kernel_fpu_disabled(); -} - -/* - * Were we in user mode (or vm86 mode) when we were - * interrupted? - * - * Doing kernel_fpu_begin/end() is ok if we are running - * in an interrupt context from user mode - we'll just - * save the FPU state as required. - */ -static bool interrupted_user_mode(void) -{ - struct pt_regs *regs = get_irq_regs(); - return regs && user_mode(regs); -} - /* * Can we use the FPU in kernel mode with the * whole "kernel_fpu_begin/end()" sequence? - * - * It's always ok in process context (ie "not interrupt") - * but it is sometimes ok even from an irq. */ bool irq_fpu_usable(void) { - return !in_interrupt() || - interrupted_user_mode() || - interrupted_kernel_fpu_idle(); + if (WARN_ON_ONCE(in_nmi())) + return false; + + /* In kernel FPU usage already active? */ + if (this_cpu_read(in_kernel_fpu)) + return false; + + /* + * When not in NMI or hard interrupt context, FPU can be used in: + * + * - Task context except from within fpregs_lock()'ed critical + * regions. + * + * - Soft interrupt processing context which cannot happen + * while in a fpregs_lock()'ed critical region. + */ + if (!in_hardirq()) + return true; + + /* + * In hard interrupt context it's safe when soft interrupts + * are enabled, which means the interrupt did not hit in + * a fpregs_lock()'ed critical region. + */ + return !softirq_count(); } EXPORT_SYMBOL(irq_fpu_usable); diff -u linux-5.15.0/arch/x86/kernel/fpu/signal.c linux-5.15.0/arch/x86/kernel/fpu/signal.c --- linux-5.15.0/arch/x86/kernel/fpu/signal.c +++ linux-5.15.0/arch/x86/kernel/fpu/signal.c @@ -309,7 +309,7 @@ if (ret != X86_TRAP_PF) return false; - if (!fault_in_pages_readable(buf, size)) + if (!fault_in_readable(buf, size)) goto retry; return false; } diff -u linux-5.15.0/arch/x86/kernel/kvm.c linux-5.15.0/arch/x86/kernel/kvm.c --- linux-5.15.0/arch/x86/kernel/kvm.c +++ linux-5.15.0/arch/x86/kernel/kvm.c @@ -66,6 +66,7 @@ DEFINE_PER_CPU_DECRYPTED(struct kvm_steal_time, steal_time) __aligned(64) __visible; static int has_steal_clock = 0; +static int has_guest_poll = 0; /* * No need for any "IO delay" on KVM */ @@ -650,14 +651,26 @@ static int kvm_suspend(void) { + u64 val = 0; + kvm_guest_cpu_offline(false); +#ifdef CONFIG_ARCH_CPUIDLE_HALTPOLL + if (kvm_para_has_feature(KVM_FEATURE_POLL_CONTROL)) + rdmsrl(MSR_KVM_POLL_CONTROL, val); + has_guest_poll = !(val & 1); +#endif return 0; } static void kvm_resume(void) { kvm_cpu_online(raw_smp_processor_id()); + +#ifdef CONFIG_ARCH_CPUIDLE_HALTPOLL + if (kvm_para_has_feature(KVM_FEATURE_POLL_CONTROL) && has_guest_poll) + wrmsrl(MSR_KVM_POLL_CONTROL, 0); +#endif } static struct syscore_ops kvm_syscore_ops = { diff -u linux-5.15.0/arch/x86/kvm/cpuid.c linux-5.15.0/arch/x86/kvm/cpuid.c --- linux-5.15.0/arch/x86/kvm/cpuid.c +++ linux-5.15.0/arch/x86/kvm/cpuid.c @@ -725,6 +725,11 @@ union cpuid10_eax eax; union cpuid10_edx edx; + if (!static_cpu_has(X86_FEATURE_ARCH_PERFMON)) { + entry->eax = entry->ebx = entry->ecx = entry->edx = 0; + break; + } + perf_get_x86_pmu_capability(&cap); /* diff -u linux-5.15.0/arch/x86/kvm/lapic.c linux-5.15.0/arch/x86/kvm/lapic.c --- linux-5.15.0/arch/x86/kvm/lapic.c +++ linux-5.15.0/arch/x86/kvm/lapic.c @@ -113,7 +113,8 @@ static bool kvm_can_post_timer_interrupt(struct kvm_vcpu *vcpu) { - return pi_inject_timer && kvm_vcpu_apicv_active(vcpu); + return pi_inject_timer && kvm_vcpu_apicv_active(vcpu) && + (kvm_mwait_in_guest(vcpu->kvm) || kvm_hlt_in_guest(vcpu->kvm)); } bool kvm_can_use_hv_timer(struct kvm_vcpu *vcpu) @@ -2125,10 +2126,9 @@ break; case APIC_SELF_IPI: - if (apic_x2apic_mode(apic)) { - kvm_lapic_reg_write(apic, APIC_ICR, - APIC_DEST_SELF | (val & APIC_VECTOR_MASK)); - } else + if (apic_x2apic_mode(apic)) + kvm_apic_send_ipi(apic, APIC_DEST_SELF | (val & APIC_VECTOR_MASK), 0); + else ret = 1; break; default: diff -u linux-5.15.0/arch/x86/kvm/mmu/mmu.c linux-5.15.0/arch/x86/kvm/mmu/mmu.c --- linux-5.15.0/arch/x86/kvm/mmu/mmu.c +++ linux-5.15.0/arch/x86/kvm/mmu/mmu.c @@ -3314,6 +3314,8 @@ return; sp = to_shadow_page(*root_hpa & PT64_BASE_ADDR_MASK); + if (WARN_ON(!sp)) + return; if (is_tdp_mmu_page(sp)) kvm_tdp_mmu_put_root(kvm, sp, false); @@ -5394,14 +5396,16 @@ uint i; if (pcid == kvm_get_active_pcid(vcpu)) { - mmu->invlpg(vcpu, gva, mmu->root_hpa); + if (mmu->invlpg) + mmu->invlpg(vcpu, gva, mmu->root_hpa); tlb_flush = true; } for (i = 0; i < KVM_MMU_NUM_PREV_ROOTS; i++) { if (VALID_PAGE(mmu->prev_roots[i].hpa) && pcid == kvm_get_pcid(vcpu, mmu->prev_roots[i].pgd)) { - mmu->invlpg(vcpu, gva, mmu->prev_roots[i].hpa); + if (mmu->invlpg) + mmu->invlpg(vcpu, gva, mmu->prev_roots[i].hpa); tlb_flush = true; } } diff -u linux-5.15.0/arch/x86/kvm/pmu.h linux-5.15.0/arch/x86/kvm/pmu.h --- linux-5.15.0/arch/x86/kvm/pmu.h +++ linux-5.15.0/arch/x86/kvm/pmu.h @@ -141,6 +141,15 @@ return sample_period; } +static inline void pmc_update_sample_period(struct kvm_pmc *pmc) +{ + if (!pmc->perf_event || pmc->is_paused) + return; + + perf_event_period(pmc->perf_event, + get_sample_period(pmc, pmc->counter)); +} + void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel); void reprogram_fixed_counter(struct kvm_pmc *pmc, u8 ctrl, int fixed_idx); void reprogram_counter(struct kvm_pmu *pmu, int pmc_idx); diff -u linux-5.15.0/arch/x86/kvm/svm/pmu.c linux-5.15.0/arch/x86/kvm/svm/pmu.c --- linux-5.15.0/arch/x86/kvm/svm/pmu.c +++ linux-5.15.0/arch/x86/kvm/svm/pmu.c @@ -44,6 +44,22 @@ [7] = { 0xd1, 0x00, PERF_COUNT_HW_STALLED_CYCLES_BACKEND }, }; +/* duplicated from amd_f17h_perfmon_event_map. */ +static struct kvm_event_hw_type_mapping amd_f17h_event_mapping[] = { + [0] = { 0x76, 0x00, PERF_COUNT_HW_CPU_CYCLES }, + [1] = { 0xc0, 0x00, PERF_COUNT_HW_INSTRUCTIONS }, + [2] = { 0x60, 0xff, PERF_COUNT_HW_CACHE_REFERENCES }, + [3] = { 0x64, 0x09, PERF_COUNT_HW_CACHE_MISSES }, + [4] = { 0xc2, 0x00, PERF_COUNT_HW_BRANCH_INSTRUCTIONS }, + [5] = { 0xc3, 0x00, PERF_COUNT_HW_BRANCH_MISSES }, + [6] = { 0x87, 0x02, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND }, + [7] = { 0x87, 0x01, PERF_COUNT_HW_STALLED_CYCLES_BACKEND }, +}; + +/* amd_pmc_perf_hw_id depends on these being the same size */ +static_assert(ARRAY_SIZE(amd_event_mapping) == + ARRAY_SIZE(amd_f17h_event_mapping)); + static unsigned int get_msr_base(struct kvm_pmu *pmu, enum pmu_type type) { struct kvm_vcpu *vcpu = pmu_to_vcpu(pmu); @@ -136,19 +152,25 @@ static unsigned int amd_pmc_perf_hw_id(struct kvm_pmc *pmc) { + struct kvm_event_hw_type_mapping *event_mapping; u8 event_select = pmc->eventsel & ARCH_PERFMON_EVENTSEL_EVENT; u8 unit_mask = (pmc->eventsel & ARCH_PERFMON_EVENTSEL_UMASK) >> 8; int i; + if (guest_cpuid_family(pmc->vcpu) >= 0x17) + event_mapping = amd_f17h_event_mapping; + else + event_mapping = amd_event_mapping; + for (i = 0; i < ARRAY_SIZE(amd_event_mapping); i++) - if (amd_event_mapping[i].eventsel == event_select - && amd_event_mapping[i].unit_mask == unit_mask) + if (event_mapping[i].eventsel == event_select + && event_mapping[i].unit_mask == unit_mask) break; if (i == ARRAY_SIZE(amd_event_mapping)) return PERF_COUNT_HW_MAX; - return amd_event_mapping[i].event_type; + return event_mapping[i].event_type; } /* return PERF_COUNT_HW_MAX as AMD doesn't have fixed events */ @@ -256,6 +278,7 @@ pmc = get_gp_pmc_amd(pmu, msr, PMU_TYPE_COUNTER); if (pmc) { pmc->counter += data - pmc_read_counter(pmc); + pmc_update_sample_period(pmc); return 0; } /* MSR_EVNTSELn */ diff -u linux-5.15.0/arch/x86/kvm/svm/sev.c linux-5.15.0/arch/x86/kvm/svm/sev.c --- linux-5.15.0/arch/x86/kvm/svm/sev.c +++ linux-5.15.0/arch/x86/kvm/svm/sev.c @@ -1990,11 +1990,14 @@ unsigned long len) { /* - * If hardware enforced cache coherency for encrypted mappings of the - * same physical page is supported, nothing to do. + * If CPU enforced cache coherency for encrypted mappings of the + * same physical page is supported, use CLFLUSHOPT instead. NOTE: cache + * flush is still needed in order to work properly with DMA devices. */ - if (boot_cpu_has(X86_FEATURE_SME_COHERENT)) + if (boot_cpu_has(X86_FEATURE_SME_COHERENT)) { + clflush_cache_range(va, PAGE_SIZE); return; + } /* * If the VM Page Flush MSR is supported, use it to flush the page diff -u linux-5.15.0/arch/x86/kvm/vmx/nested.c linux-5.15.0/arch/x86/kvm/vmx/nested.c --- linux-5.15.0/arch/x86/kvm/vmx/nested.c +++ linux-5.15.0/arch/x86/kvm/vmx/nested.c @@ -4601,6 +4601,11 @@ kvm_make_request(KVM_REQ_APIC_PAGE_RELOAD, vcpu); } + if (vmx->nested.update_vmcs01_apicv_status) { + vmx->nested.update_vmcs01_apicv_status = false; + kvm_make_request(KVM_REQ_APICV_UPDATE, vcpu); + } + if ((vm_exit_reason != -1) && (enable_shadow_vmcs || evmptr_is_valid(vmx->nested.hv_evmcs_vmptr))) vmx->nested.need_vmcs12_to_shadow_sync = true; diff -u linux-5.15.0/arch/x86/kvm/vmx/pmu_intel.c linux-5.15.0/arch/x86/kvm/vmx/pmu_intel.c --- linux-5.15.0/arch/x86/kvm/vmx/pmu_intel.c +++ linux-5.15.0/arch/x86/kvm/vmx/pmu_intel.c @@ -439,15 +439,11 @@ !(msr & MSR_PMC_FULL_WIDTH_BIT)) data = (s64)(s32)data; pmc->counter += data - pmc_read_counter(pmc); - if (pmc->perf_event && !pmc->is_paused) - perf_event_period(pmc->perf_event, - get_sample_period(pmc, data)); + pmc_update_sample_period(pmc); return 0; } else if ((pmc = get_fixed_pmc(pmu, msr))) { pmc->counter += data - pmc_read_counter(pmc); - if (pmc->perf_event && !pmc->is_paused) - perf_event_period(pmc->perf_event, - get_sample_period(pmc, data)); + pmc_update_sample_period(pmc); return 0; } else if ((pmc = get_gp_pmc(pmu, msr, MSR_P6_EVNTSEL0))) { if (data == pmc->eventsel) diff -u linux-5.15.0/arch/x86/kvm/vmx/vmx.c linux-5.15.0/arch/x86/kvm/vmx/vmx.c --- linux-5.15.0/arch/x86/kvm/vmx/vmx.c +++ linux-5.15.0/arch/x86/kvm/vmx/vmx.c @@ -4159,6 +4159,11 @@ { struct vcpu_vmx *vmx = to_vmx(vcpu); + if (is_guest_mode(vcpu)) { + vmx->nested.update_vmcs01_apicv_status = true; + return; + } + pin_controls_set(vmx, vmx_pin_based_exec_ctrl(vmx)); if (cpu_has_secondary_exec_ctrls()) { if (kvm_vcpu_apicv_active(vcpu)) diff -u linux-5.15.0/arch/x86/kvm/vmx/vmx.h linux-5.15.0/arch/x86/kvm/vmx/vmx.h --- linux-5.15.0/arch/x86/kvm/vmx/vmx.h +++ linux-5.15.0/arch/x86/kvm/vmx/vmx.h @@ -164,6 +164,7 @@ bool change_vmcs01_virtual_apic_mode; bool reload_vmcs01_apic_access_page; bool update_vmcs01_cpu_dirty_logging; + bool update_vmcs01_apicv_status; /* * Enlightened VMCS has been enabled. It does not mean that L1 has to diff -u linux-5.15.0/arch/x86/kvm/x86.c linux-5.15.0/arch/x86/kvm/x86.c --- linux-5.15.0/arch/x86/kvm/x86.c +++ linux-5.15.0/arch/x86/kvm/x86.c @@ -10635,8 +10635,21 @@ r = kvm_create_lapic(vcpu, lapic_timer_advance_ns); if (r < 0) goto fail_mmu_destroy; - if (kvm_apicv_activated(vcpu->kvm)) + + /* + * Defer evaluating inhibits until the vCPU is first run, as + * this vCPU will not get notified of any changes until this + * vCPU is visible to other vCPUs (marked online and added to + * the set of vCPUs). Opportunistically mark APICv active as + * VMX in particularly is highly unlikely to have inhibits. + * Ignore the current per-VM APICv state so that vCPU creation + * is guaranteed to run with a deterministic value, the request + * will ensure the vCPU gets the correct state before VM-Entry. + */ + if (enable_apicv) { vcpu->arch.apicv_active = true; + kvm_make_request(KVM_REQ_APICV_UPDATE, vcpu); + } } else static_branch_inc(&kvm_has_noapic_vcpu); diff -u linux-5.15.0/arch/x86/power/cpu.c linux-5.15.0/arch/x86/power/cpu.c --- linux-5.15.0/arch/x86/power/cpu.c +++ linux-5.15.0/arch/x86/power/cpu.c @@ -25,6 +25,7 @@ #include #include #include +#include #ifdef CONFIG_X86_32 __visible unsigned long saved_context_ebx; @@ -262,11 +263,18 @@ x86_platform.restore_sched_clock_state(); mtrr_bp_restore(); perf_restore_debug_store(); - msr_restore_context(ctxt); c = &cpu_data(smp_processor_id()); if (cpu_has(c, X86_FEATURE_MSR_IA32_FEAT_CTL)) init_ia32_feat_ctl(c); + + microcode_bsp_resume(); + + /* + * This needs to happen after the microcode has been updated upon resume + * because some of the MSRs are "emulated" in microcode. + */ + msr_restore_context(ctxt); } /* Needed by apm.c */ diff -u linux-5.15.0/arch/xtensa/kernel/jump_label.c linux-5.15.0/arch/xtensa/kernel/jump_label.c --- linux-5.15.0/arch/xtensa/kernel/jump_label.c +++ linux-5.15.0/arch/xtensa/kernel/jump_label.c @@ -40,7 +40,7 @@ { struct patch *patch = data; - if (atomic_inc_return(&patch->cpu_count) == 1) { + if (atomic_inc_return(&patch->cpu_count) == num_online_cpus()) { local_patch_text(patch->addr, patch->data, patch->sz); atomic_inc(&patch->cpu_count); } else { diff -u linux-5.15.0/block/blk-iocost.c linux-5.15.0/block/blk-iocost.c --- linux-5.15.0/block/blk-iocost.c +++ linux-5.15.0/block/blk-iocost.c @@ -2322,7 +2322,17 @@ iocg->hweight_donating = hwa; iocg->hweight_after_donation = new_hwi; list_add(&iocg->surplus_list, &surpluses); - } else { + } else if (!iocg->abs_vdebt) { + /* + * @iocg doesn't have enough to donate. Reset + * its inuse to active. + * + * Don't reset debtors as their inuse's are + * owned by debt handling. This shouldn't affect + * donation calculuation in any meaningful way + * as @iocg doesn't have a meaningful amount of + * share anyway. + */ TRACE_IOCG_PATH(inuse_shortage, iocg, &now, iocg->inuse, iocg->active, iocg->hweight_inuse, new_hwi); diff -u linux-5.15.0/block/ioctl.c linux-5.15.0/block/ioctl.c --- linux-5.15.0/block/ioctl.c +++ linux-5.15.0/block/ioctl.c @@ -645,7 +645,7 @@ (bdev->bd_disk->bdi->ra_pages * PAGE_SIZE) / 512); case BLKGETSIZE: size = i_size_read(bdev->bd_inode); - if ((size >> 9) > ~0UL) + if ((size >> 9) > ~(compat_ulong_t)0) return -EFBIG; return compat_put_ulong(argp, size >> 9); diff -u linux-5.15.0/debian.master/abi/abiname linux-5.15.0/debian.master/abi/abiname --- linux-5.15.0/debian.master/abi/abiname +++ linux-5.15.0/debian.master/abi/abiname @@ -1 +1 @@ -39 +40 diff -u linux-5.15.0/debian.master/abi/amd64/generic linux-5.15.0/debian.master/abi/amd64/generic --- linux-5.15.0/debian.master/abi/amd64/generic +++ linux-5.15.0/debian.master/abi/amd64/generic @@ -2113,6 +2113,16 @@ EXPORT_SYMBOL drivers/media/pci/cx88/cx88xx 0xf13797c2 cx88_reset EXPORT_SYMBOL drivers/media/pci/cx88/cx88xx 0xfa9a562f cx88_dsp_detect_stereo_sap EXPORT_SYMBOL drivers/media/pci/ddbridge/ddbridge-dummy-fe 0xc5f8b52d ddbridge_dummy_fe_qam_attach +EXPORT_SYMBOL drivers/media/pci/intel/ipu6/intel-ipu6 0x0fe08bb1 ipu_fw_authenticate +EXPORT_SYMBOL drivers/media/pci/intel/ipu6/intel-ipu6 0x10480628 ipu_mmu_hw_cleanup +EXPORT_SYMBOL drivers/media/pci/intel/ipu6/intel-ipu6 0x23bd380f ipu_bus_register_driver +EXPORT_SYMBOL drivers/media/pci/intel/ipu6/intel-ipu6 0x2bbebe45 ipu_buttress_auth_done +EXPORT_SYMBOL drivers/media/pci/intel/ipu6/intel-ipu6 0x4f874a56 ipu_mmu_hw_init +EXPORT_SYMBOL drivers/media/pci/intel/ipu6/intel-ipu6 0x6423266b ipu_configure_spc +EXPORT_SYMBOL drivers/media/pci/intel/ipu6/intel-ipu6 0x6bc9710a ipu_buttress_start_tsc_sync +EXPORT_SYMBOL drivers/media/pci/intel/ipu6/intel-ipu6 0xc1e956fe ipu_bus_unregister_driver +EXPORT_SYMBOL drivers/media/pci/intel/ipu6/intel-ipu6 0xc7231f03 ipu_ver +EXPORT_SYMBOL drivers/media/pci/intel/ipu6/intel-ipu6 0xdbfe8d3b request_cpd_fw EXPORT_SYMBOL drivers/media/pci/ivtv/ivtv 0x059b0b32 ivtv_release_stream EXPORT_SYMBOL drivers/media/pci/ivtv/ivtv 0x14f67530 ivtv_debug EXPORT_SYMBOL drivers/media/pci/ivtv/ivtv 0x382d7739 ivtv_udma_prepare @@ -3715,72 +3725,72 @@ EXPORT_SYMBOL drivers/net/wireless/realtek/rtlwifi/rtlwifi 0xecc32825 rtl_cam_mark_invalid EXPORT_SYMBOL drivers/net/wireless/realtek/rtlwifi/rtlwifi 0xed7c8cf2 rtl_evm_db_to_percentage EXPORT_SYMBOL drivers/net/wireless/realtek/rtlwifi/rtlwifi 0xed928d3e rtl_cam_get_free_entry -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8723d 0x45a3a802 rtw8723d_hw_spec -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8821c 0xd863df8f rtw8821c_hw_spec -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8822b 0xae43d2b0 rtw8822b_hw_spec -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8822c 0x4181b98e rtw8822c_hw_spec -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x0a131d70 rtw_phy_parsing_cfo -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x0de20b21 __rtw_dbg -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x0fcdf6fa rtw_phy_cfg_mac -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x12f46d98 rtw_set_channel_mac -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x1ceb6cf3 rtw_core_init -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x204c4f12 rtw_bf_cfg_csi_rate -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x29124cf9 rtw_phy_cfg_agc -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x293f0364 rtw_register_hw -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x2b7f4905 rtw_phy_set_tx_power_level -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x3303bdfd rtw_phy_pwrtrack_get_delta +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8723d 0x48a4f56d rtw8723d_hw_spec +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8821c 0xd56482e0 rtw8821c_hw_spec +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8822b 0xa3448fdf rtw8822b_hw_spec +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8822c 0x4c86e4e1 rtw8822c_hw_spec +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x03851566 rtw_bf_enable_bfee_su +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x072e0003 rtw_fw_do_iqk +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x0b0eb9ef rtw_read8_physical_efuse +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x0b711bb7 rtw_coex_read_indirect_reg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x0c5508b7 rtw_bf_remove_bfee_mu +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x0ef1a07e rtw_bf_remove_bfee_su +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x12924e31 rtw_bf_set_gid_table +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x157ce05c rtw_coex_write_scbd +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x1b4400c2 rtw_fw_inform_rfk_status +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x1bd151a9 rtw_core_deinit +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x205d2356 rtw_tx_write_data_rsvd_page_get +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x2df9b6cb rtw_phy_read_rf_sipi +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x2e46c0db rtw_phy_get_tx_power_index +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x338ebb88 rtw_bf_cfg_csi_rate EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x33b3f3c0 rtw_debug_mask -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x34d78ad1 rtw_tx_write_data_rsvd_page_get -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x36288262 rtw_fw_inform_rfk_status EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x36c5bfca rtw_disable_lps_deep_mode -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x3ab1f975 rtw_phy_pwrtrack_get_pwridx -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x3c98822c rtw_phy_pwrtrack_avg -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x3eba8e66 rtw_dump_reg -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x420e684a rtw_phy_cfg_bb +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x3a2be036 rtw_fw_c2h_cmd_rx_irqsafe +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x3d7d4d3e rtw_phy_cfg_agc +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x41c58df0 __rtw_dbg EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x440b7589 rtw_phy_rf_power_2_rssi -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x455d6d1f rtw_phy_load_tables +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x47bb68e1 rtw_rx_fill_rx_status +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x496a4b5d check_hw_ready EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x4c1802cb rtw_ops -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x505d828e rtw_bf_enable_bfee_su -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x51318eb9 rtw_restore_reg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x4e51a5aa rtw_coex_write_indirect_reg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x5164f04d rtw_parse_tbl_bb_pg EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x519c8ba9 rtw_rate_size +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x53dfb467 rtw_phy_read_rf EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x58210e60 rtw_rate_section -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x5fa106b8 rtw_unregister_hw -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x62954a37 rtw_rx_fill_rx_status -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x6c0a0bef rtw_rx_stats -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x6cdf8d66 rtw_phy_pwrtrack_thermal_changed -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x6ce72383 rtw_read8_physical_efuse -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x72cd0de3 rtw_bf_remove_bfee_mu -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x7708bdec rtw_fw_do_iqk -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x813b95ce rtw_bf_set_gid_table -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x817c86a5 rtw_phy_get_tx_power_index -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x86034277 rtw_tx_write_data_h2c_get -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x919f105a rtw_phy_cfg_rf -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x9548dfd6 rtw_bf_remove_bfee_su -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x988f2ba0 rtw_parse_tbl_phy_cond -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x989a99e3 rtw_chip_info_setup -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x9ca259f9 rtw_phy_read_rf_sipi -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x9dfe1060 rtw_core_deinit -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x9f502401 rtw_phy_write_rf_reg_mix -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xa5aaa7de rtw_phy_init -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xa7b189a8 rtw_coex_write_scbd -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xb2e75c32 rtw_bf_enable_bfee_mu -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xc2781548 rtw_bf_phy_init -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xc349c3b5 rtw_phy_write_rf_reg_sipi -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xc7512607 rtw_coex_write_indirect_reg -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xc83e2c16 rtw_fw_c2h_cmd_isr -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xcb1713a4 rtw_parse_tbl_bb_pg -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xd13da2f1 rtw_phy_read_rf -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xd3e348f3 rtw_coex_read_indirect_reg -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xd42c4a99 rtw_phy_pwrtrack_need_lck -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xd462b268 rtw_fw_c2h_cmd_rx_irqsafe -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xde87b2c8 rtw_tx_report_enqueue -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xe5b18fd6 rtw_phy_pwrtrack_need_iqk -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xe7dc9cf6 check_hw_ready -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xe956a957 rtw_parse_tbl_txpwr_lmt -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xef4bad0b rtw_dump_fw -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xf1b10d66 rtw_tx_fill_tx_desc -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xf2ad6115 rtw_power_mode_change -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xf60242a4 rtw_phy_config_swing_table +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x5918c855 rtw_set_channel_mac +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x5af15af4 rtw_chip_info_setup +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x643f7477 rtw_phy_config_swing_table +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x6659e49e rtw_phy_parsing_cfo +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x73d3a8ed rtw_phy_write_rf_reg_sipi +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x7b032200 rtw_phy_pwrtrack_need_iqk +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x815587cb rtw_power_mode_change +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x8a11898b rtw_phy_cfg_bb +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x8e24b7c0 rtw_bf_enable_bfee_mu +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x8e6fddb3 rtw_phy_load_tables +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x906dd07c rtw_phy_pwrtrack_get_delta +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x99af66b5 rtw_phy_pwrtrack_thermal_changed +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x9bff0c2b rtw_restore_reg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xaa3b0a32 rtw_phy_pwrtrack_avg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xae3cf09b rtw_phy_pwrtrack_get_pwridx +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xb6e5a90c rtw_tx_write_data_h2c_get +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xbb7d47b8 rtw_tx_fill_tx_desc +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xbc3463e4 rtw_unregister_hw +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xbc3ee079 rtw_phy_write_rf_reg_mix +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xbea01df4 rtw_phy_set_tx_power_level +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xbfb2fb05 rtw_fw_c2h_cmd_isr +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xc12b2388 rtw_bf_phy_init +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xcd4a8475 rtw_rx_stats +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xcde608b4 rtw_parse_tbl_txpwr_lmt +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xd0d81704 rtw_register_hw +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xd2e69f36 rtw_phy_init +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xd303013c rtw_parse_tbl_phy_cond +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xd6d887ac rtw_phy_cfg_mac +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xd8b564e7 rtw_tx_report_enqueue +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xd8f86364 rtw_dump_fw +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xe2595f92 rtw_phy_pwrtrack_need_lck +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xe3c76875 rtw_phy_cfg_rf +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xe3dd2dbe rtw_dump_reg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xeb3158ab rtw_core_init EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_pci 0x378381f5 rtw_pm_ops EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_pci 0x3983d376 rtw_pci_remove EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_pci 0x8625e296 rtw_pci_probe @@ -13840,6 +13850,7 @@ EXPORT_SYMBOL_GPL drivers/media/i2c/max9271 0xab6109ba max9271_set_address EXPORT_SYMBOL_GPL drivers/media/i2c/max9271 0xc2adc17e max9271_set_high_threshold EXPORT_SYMBOL_GPL drivers/media/i2c/max9271 0xcdb8f217 max9271_set_gpios +EXPORT_SYMBOL_GPL drivers/media/i2c/power_ctrl_logic 0x61e30e03 power_ctrl_logic_set_power EXPORT_SYMBOL_GPL drivers/media/mc/mc 0x00ed5c1e __media_device_register EXPORT_SYMBOL_GPL drivers/media/mc/mc 0x0b06dfb1 media_device_cleanup EXPORT_SYMBOL_GPL drivers/media/mc/mc 0x1075931e __media_pipeline_stop @@ -13889,6 +13900,32 @@ EXPORT_SYMBOL_GPL drivers/media/mc/mc 0xfc781c47 __media_entity_enum_init EXPORT_SYMBOL_GPL drivers/media/mc/mc 0xfc93b7a0 __media_remove_intf_links EXPORT_SYMBOL_GPL drivers/media/pci/cx88/cx88xx 0xba1f1f35 cx88_setup_xc3028 +EXPORT_SYMBOL_GPL drivers/media/pci/intel/ipu6/intel-ipu6 0x06c0374c ipu_buttress_tsc_read +EXPORT_SYMBOL_GPL drivers/media/pci/intel/ipu6/intel-ipu6 0x2b42c6f7 ipu_cpd_pkg_dir_get_num_entries +EXPORT_SYMBOL_GPL drivers/media/pci/intel/ipu6/intel-ipu6 0x4c7b984d ipu_cpd_validate_cpd_file +EXPORT_SYMBOL_GPL drivers/media/pci/intel/ipu6/intel-ipu6 0x560ca831 ipu_buttress_tsc_ticks_to_ns +EXPORT_SYMBOL_GPL drivers/media/pci/intel/ipu6/intel-ipu6 0x58745343 ipu_send_get_token +EXPORT_SYMBOL_GPL drivers/media/pci/intel/ipu6/intel-ipu6 0x5d5d2189 ipu_recv_put_token +EXPORT_SYMBOL_GPL drivers/media/pci/intel/ipu6/intel-ipu6 0x60d86d60 ipu_trace_init +EXPORT_SYMBOL_GPL drivers/media/pci/intel/ipu6/intel-ipu6 0x64aaeec2 ipu_cpd_pkg_dir_get_address +EXPORT_SYMBOL_GPL drivers/media/pci/intel/ipu6/intel-ipu6 0x6a444cf9 ipu_buttress_add_psys_constraint +EXPORT_SYMBOL_GPL drivers/media/pci/intel/ipu6/intel-ipu6 0x72ee0473 ipu_cpd_free_pkg_dir +EXPORT_SYMBOL_GPL drivers/media/pci/intel/ipu6/intel-ipu6 0x7842c730 ipu_cpd_pkg_dir_get_type +EXPORT_SYMBOL_GPL drivers/media/pci/intel/ipu6/intel-ipu6 0x797d49b5 ipu_buttress_unmap_fw_image +EXPORT_SYMBOL_GPL drivers/media/pci/intel/ipu6/intel-ipu6 0x7aa19e81 ipu_trace_restore +EXPORT_SYMBOL_GPL drivers/media/pci/intel/ipu6/intel-ipu6 0x9643335b ipu_fw_com_prepare +EXPORT_SYMBOL_GPL drivers/media/pci/intel/ipu6/intel-ipu6 0x99c64c01 ipu_buttress_remove_psys_constraint +EXPORT_SYMBOL_GPL drivers/media/pci/intel/ipu6/intel-ipu6 0xa996e10f ipu_fw_com_release +EXPORT_SYMBOL_GPL drivers/media/pci/intel/ipu6/intel-ipu6 0xace0ba97 ipu_cpd_create_pkg_dir +EXPORT_SYMBOL_GPL drivers/media/pci/intel/ipu6/intel-ipu6 0xc76903d5 ipu_fw_com_close +EXPORT_SYMBOL_GPL drivers/media/pci/intel/ipu6/intel-ipu6 0xc99af248 ipu_trace_stop +EXPORT_SYMBOL_GPL drivers/media/pci/intel/ipu6/intel-ipu6 0xcfff394e ipu_fw_com_open +EXPORT_SYMBOL_GPL drivers/media/pci/intel/ipu6/intel-ipu6 0xd82eb3df ipu_cpd_pkg_dir_get_size +EXPORT_SYMBOL_GPL drivers/media/pci/intel/ipu6/intel-ipu6 0xe0902b23 ipu_buttress_map_fw_image +EXPORT_SYMBOL_GPL drivers/media/pci/intel/ipu6/intel-ipu6 0xe10e6751 ipu_fw_com_ready +EXPORT_SYMBOL_GPL drivers/media/pci/intel/ipu6/intel-ipu6 0xe597cbe1 ipu_trace_uninit +EXPORT_SYMBOL_GPL drivers/media/pci/intel/ipu6/intel-ipu6 0xf19708cf ipu_send_put_token +EXPORT_SYMBOL_GPL drivers/media/pci/intel/ipu6/intel-ipu6 0xf4be7a05 ipu_recv_get_token EXPORT_SYMBOL_GPL drivers/media/pci/mantis/mantis_core 0x0998eb56 mantis_uart_init EXPORT_SYMBOL_GPL drivers/media/pci/mantis/mantis_core 0x117e5b82 mantis_get_mac EXPORT_SYMBOL_GPL drivers/media/pci/mantis/mantis_core 0x1c7604a4 mantis_input_exit @@ -14279,6 +14316,10 @@ EXPORT_SYMBOL_GPL drivers/mfd/kempld-core 0xaa146bcf kempld_get_mutex EXPORT_SYMBOL_GPL drivers/mfd/kempld-core 0xbafd3a6b kempld_write32 EXPORT_SYMBOL_GPL drivers/mfd/kempld-core 0xfb7ed973 kempld_release_mutex +EXPORT_SYMBOL_GPL drivers/mfd/ljca 0x364494aa ljca_unregister_event_cb +EXPORT_SYMBOL_GPL drivers/mfd/ljca 0x5f7b7144 ljca_register_event_cb +EXPORT_SYMBOL_GPL drivers/mfd/ljca 0x8ce4fc49 ljca_transfer +EXPORT_SYMBOL_GPL drivers/mfd/ljca 0xb43d2f48 ljca_transfer_noack EXPORT_SYMBOL_GPL drivers/mfd/lm3533-core 0xce6e6f98 lm3533_write EXPORT_SYMBOL_GPL drivers/mfd/lm3533-core 0xe075f07c lm3533_read EXPORT_SYMBOL_GPL drivers/mfd/lm3533-core 0xe1a5e359 lm3533_update @@ -14463,6 +14504,12 @@ EXPORT_SYMBOL_GPL drivers/misc/enclosure 0x709a449b enclosure_add_device EXPORT_SYMBOL_GPL drivers/misc/enclosure 0x81babe7f enclosure_component_register EXPORT_SYMBOL_GPL drivers/misc/enclosure 0xec82f5a5 enclosure_register +EXPORT_SYMBOL_GPL drivers/misc/ivsc/intel_vsc 0x11ec310c vsc_unregister_csi +EXPORT_SYMBOL_GPL drivers/misc/ivsc/intel_vsc 0x45138f90 vsc_register_csi +EXPORT_SYMBOL_GPL drivers/misc/ivsc/intel_vsc 0x5763033e vsc_acquire_camera_sensor +EXPORT_SYMBOL_GPL drivers/misc/ivsc/intel_vsc 0x6b97696c vsc_release_camera_sensor +EXPORT_SYMBOL_GPL drivers/misc/ivsc/intel_vsc 0x77b2fb7c vsc_unregister_ace +EXPORT_SYMBOL_GPL drivers/misc/ivsc/intel_vsc 0xfaaaa50d vsc_register_ace EXPORT_SYMBOL_GPL drivers/misc/lis3lv02d/lis3lv02d 0x01c3dfbd lis3lv02d_init_device EXPORT_SYMBOL_GPL drivers/misc/lis3lv02d/lis3lv02d 0x0507780f lis3lv02d_joystick_enable EXPORT_SYMBOL_GPL drivers/misc/lis3lv02d/lis3lv02d 0x46bcabbe lis3lv02d_poweron diff -u linux-5.15.0/debian.master/abi/amd64/generic.modules linux-5.15.0/debian.master/abi/amd64/generic.modules --- linux-5.15.0/debian.master/abi/amd64/generic.modules +++ linux-5.15.0/debian.master/abi/amd64/generic.modules @@ -1608,6 +1608,7 @@ gpio-it87 gpio-janz-ttl gpio-kempld +gpio-ljca gpio-lp3943 gpio-lp873x gpio-madera @@ -1895,6 +1896,7 @@ hih6130 hinic hisi-spmi-controller +hm11b1 hmc425a hmc5843_core hmc5843_i2c @@ -1969,6 +1971,7 @@ i2c-isch i2c-ismt i2c-kempld +i2c-ljca i2c-matroxfb i2c-mlxcpld i2c-mux @@ -2136,6 +2139,9 @@ int51x1 intel-cstate intel-hid +intel-ipu6 +intel-ipu6-isys +intel-ipu6-psys intel-ish-ipc intel-ishtp intel-ishtp-hid @@ -2198,6 +2204,7 @@ intel_th_pti intel_th_sth intel_vr_nor +intel_vsc intelfb interact interrupt-cnt @@ -2592,6 +2599,7 @@ liquidio_vf lis3lv02d lis3lv02d_i2c +ljca lkkbd ll_temac llc @@ -2897,8 +2905,13 @@ mei mei-me mei-txe +mei-vsc +mei_ace +mei_ace_debug +mei_csi mei_hdcp mei_phy +mei_pse mei_wdt melfas_mip4 memory-notifier-error-inject @@ -3449,7 +3462,10 @@ orinoco_usb oti6858 otm3225a +ov01a10 +ov01a1s ov02a10 +ov02c10 ov13858 ov2640 ov2659 @@ -3692,6 +3708,7 @@ poly1305-x86_64 poly1305_generic port100 +power_ctrl_logic powermate powr1220 ppa @@ -5030,6 +5047,7 @@ spi-dw-pci spi-gpio spi-lantiq-ssc +spi-ljca spi-lm70llp spi-loopback-test spi-mux diff -u linux-5.15.0/debian.master/abi/arm64/generic linux-5.15.0/debian.master/abi/arm64/generic --- linux-5.15.0/debian.master/abi/arm64/generic +++ linux-5.15.0/debian.master/abi/arm64/generic @@ -3788,71 +3788,71 @@ EXPORT_SYMBOL drivers/net/wireless/realtek/rtlwifi/rtlwifi 0xebedfe5f rtl_wowlan_fw_cb EXPORT_SYMBOL drivers/net/wireless/realtek/rtlwifi/rtlwifi 0xed7c8cf2 rtl_evm_db_to_percentage EXPORT_SYMBOL drivers/net/wireless/realtek/rtlwifi/rtlwifi 0xf21a259d rtl_bb_delay -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8723d 0xf329d93f rtw8723d_hw_spec -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8821c 0x6ee9aeb2 rtw8821c_hw_spec -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8822b 0x18c9a38d rtw8822b_hw_spec -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8822c 0xf70bc8b3 rtw8822c_hw_spec -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x02ca6381 rtw_phy_pwrtrack_get_delta -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x047a2f21 rtw_core_deinit -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x0784402a rtw_phy_read_rf -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x0fb517fa rtw_chip_info_setup -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x13acfb93 rtw_parse_tbl_bb_pg -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x1e224cb4 rtw_phy_get_tx_power_index -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x1f35a474 rtw_fw_inform_rfk_status -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x22c1e775 rtw_phy_write_rf_reg_mix -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x22f40f33 __rtw_dbg -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x2607e972 rtw_bf_set_gid_table +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8723d 0x236c09de rtw8723d_hw_spec +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8821c 0xbeac7e53 rtw8821c_hw_spec +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8822b 0xc88c736c rtw8822b_hw_spec +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8822c 0x274e1852 rtw8822c_hw_spec +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x04636e4d rtw_bf_enable_bfee_mu +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x06cc0878 rtw_rx_fill_rx_status +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x071a1b0a rtw_bf_enable_bfee_su +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x100bdd0c rtw_phy_load_tables +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x11e56f0f rtw_phy_pwrtrack_get_pwridx +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x147f96dd rtw_parse_tbl_bb_pg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x16a176bb rtw_phy_pwrtrack_need_iqk +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x18e03871 rtw_tx_write_data_rsvd_page_get +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x194039af rtw_parse_tbl_phy_cond +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x1b626763 rtw_phy_read_rf +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x2930c4a4 rtw_bf_set_gid_table +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x2dde7904 rtw_dump_reg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x2ee79d20 rtw_phy_pwrtrack_get_delta +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x2f259a9d rtw_phy_read_rf_sipi +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x31368913 rtw_fw_do_iqk EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x33b3f3c0 rtw_debug_mask +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x358a1ef4 rtw_unregister_hw EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x36c5bfca rtw_disable_lps_deep_mode -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x36e8f8a7 rtw_coex_read_indirect_reg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x385658d1 rtw_dump_fw +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x4102a19b rtw_phy_cfg_bb EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x440b7589 rtw_phy_rf_power_2_rssi -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x4718556b rtw_read8_physical_efuse -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x47edccaf rtw_tx_write_data_rsvd_page_get -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x4e275e15 rtw_phy_cfg_rf -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x4fc27ccc rtw_bf_enable_bfee_su -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x4fd7b48b rtw_phy_pwrtrack_avg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x4525d692 rtw_core_deinit +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x48cf8bab rtw_phy_parsing_cfo EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x519c8ba9 rtw_rate_size +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x5541e741 rtw_set_channel_mac EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x58210e60 rtw_rate_section -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x598ac379 rtw_restore_reg -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x5d90f907 rtw_rx_fill_rx_status -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x60c8567f rtw_bf_enable_bfee_mu -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x65d4e1b8 rtw_parse_tbl_phy_cond -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x6666f187 rtw_fw_do_iqk -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x667fcfc5 rtw_phy_init -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x67ba4727 rtw_set_channel_mac -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x6bc558db rtw_phy_set_tx_power_level -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x6deb908c rtw_bf_remove_bfee_su -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x76d500e3 rtw_rx_stats -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x77bcdbe4 rtw_tx_report_enqueue -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x790ad82d rtw_register_hw -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x79a87853 rtw_power_mode_change -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x7c6b4982 rtw_dump_fw -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x87942d73 rtw_dump_reg -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x8d8e27c7 rtw_phy_read_rf_sipi -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x8dfb4261 rtw_phy_pwrtrack_need_lck -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x909b202d rtw_parse_tbl_txpwr_lmt -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x951ea2e1 rtw_phy_pwrtrack_need_iqk -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x96c68f2d rtw_unregister_hw -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x973b026d rtw_tx_fill_tx_desc -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x9ca934b8 rtw_phy_cfg_agc -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xa70fb309 rtw_bf_remove_bfee_mu -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xab8f8d9b rtw_phy_load_tables -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xac8d3248 rtw_coex_write_indirect_reg -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xb61368c6 rtw_coex_write_scbd -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xbd05b824 rtw_fw_c2h_cmd_rx_irqsafe -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xc4c457ce rtw_bf_phy_init -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xc6be845d rtw_phy_pwrtrack_get_pwridx -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xc82ffc57 rtw_bf_cfg_csi_rate -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xcab67519 rtw_phy_config_swing_table -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xcc41c62b rtw_tx_write_data_h2c_get -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xd77f580a rtw_phy_cfg_bb -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xd9cd077a rtw_phy_cfg_mac -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xdce72938 rtw_core_init -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xde8f8c94 rtw_phy_write_rf_reg_sipi -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xe40f49fe rtw_phy_parsing_cfo -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xe701e970 rtw_phy_pwrtrack_thermal_changed -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xe7649e07 check_hw_ready -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xf4f158ee rtw_fw_c2h_cmd_isr +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x5d1a4996 rtw_rx_stats +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x5e87117b rtw_fw_c2h_cmd_rx_irqsafe +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x6ea4d14e rtw_bf_cfg_csi_rate +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x704137dd __rtw_dbg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x726ca0c8 rtw_coex_read_indirect_reg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x7fc851d6 rtw_chip_info_setup +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x88b66c52 rtw_core_init +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x8ce7c9c1 rtw_phy_get_tx_power_index +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x90aac11a rtw_tx_report_enqueue +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x914b637d rtw_phy_pwrtrack_avg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x9390ef7f rtw_bf_remove_bfee_mu +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x94ae9a6d rtw_coex_write_scbd +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x9dc87397 rtw_phy_pwrtrack_thermal_changed +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x9e92fefc rtw_phy_set_tx_power_level +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xa0323732 rtw_phy_write_rf_reg_mix +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xa3d6309b rtw_fw_inform_rfk_status +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xa3fc825c rtw_phy_config_swing_table +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xa969dddd rtw_power_mode_change +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xac9f6619 rtw_phy_cfg_agc +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xad67ba7d rtw_fw_c2h_cmd_isr +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xc07b2392 rtw_bf_phy_init +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xc37d6fb4 rtw_phy_write_rf_reg_sipi +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xc3c96f8e rtw_phy_cfg_mac +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xc6d682d2 rtw_parse_tbl_txpwr_lmt +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xc9b6da55 rtw_coex_write_indirect_reg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xcbf128ea check_hw_ready +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xcd3fe1fe rtw_read8_physical_efuse +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xd29f2035 rtw_register_hw +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xda40052d rtw_tx_fill_tx_desc +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xe5ade271 rtw_phy_pwrtrack_need_lck +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xef9bb1e9 rtw_phy_init +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xf39cc5ab rtw_tx_write_data_h2c_get +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xf6c6db43 rtw_bf_remove_bfee_su +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xf8561301 rtw_restore_reg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xf937c153 rtw_phy_cfg_rf EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xfa680f12 rtw_ops EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_pci 0x0706d875 rtw_pci_shutdown EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_pci 0x65f32e72 rtw_pci_probe diff -u linux-5.15.0/debian.master/abi/arm64/generic-64k linux-5.15.0/debian.master/abi/arm64/generic-64k --- linux-5.15.0/debian.master/abi/arm64/generic-64k +++ linux-5.15.0/debian.master/abi/arm64/generic-64k @@ -3788,72 +3788,72 @@ EXPORT_SYMBOL drivers/net/wireless/realtek/rtlwifi/rtlwifi 0xebedfe5f rtl_wowlan_fw_cb EXPORT_SYMBOL drivers/net/wireless/realtek/rtlwifi/rtlwifi 0xed7c8cf2 rtl_evm_db_to_percentage EXPORT_SYMBOL drivers/net/wireless/realtek/rtlwifi/rtlwifi 0xf514bee7 rtl_rx_ampdu_apply -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8723d 0x4a9c6faa rtw8723d_hw_spec -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8821c 0xd75c1827 rtw8821c_hw_spec -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8822b 0xa17c1518 rtw8822b_hw_spec -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8822c 0x4ebe7e26 rtw8822c_hw_spec -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x076a16c3 rtw_phy_set_tx_power_level -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x07a0b999 rtw_fw_c2h_cmd_isr -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x083f1beb rtw_core_init -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x0e87edba rtw_chip_info_setup +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8723d 0x40fa36c3 rtw8723d_hw_spec +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8821c 0xdd3a414e rtw8821c_hw_spec +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8822b 0xab1a4c71 rtw8822b_hw_spec +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8822c 0x44d8274f rtw8822c_hw_spec +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x05bd2087 rtw_bf_enable_bfee_su +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x096bfa71 rtw_parse_tbl_bb_pg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x0fafb18c rtw_bf_remove_bfee_mu +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x12f0e94c rtw_phy_cfg_agc EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x1478e233 rtw_ops -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x1997c4c6 rtw_rx_fill_rx_status -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x19ade57f rtw_tx_fill_tx_desc -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x1c56c53c __rtw_dbg -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x23985d8c rtw_bf_set_gid_table -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x2f313787 rtw_phy_get_tx_power_index -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x33019870 check_hw_ready +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x186e8bbc rtw_core_init +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x1a126ae4 rtw_bf_enable_bfee_mu EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x33b3f3c0 rtw_debug_mask EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x36c5bfca rtw_disable_lps_deep_mode -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x38f079d8 rtw_phy_read_rf -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x3cc90962 rtw_unregister_hw -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x4195fe20 rtw_tx_report_enqueue -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x4372b1b2 rtw_power_mode_change +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x42582c57 rtw_power_mode_change EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x440b7589 rtw_phy_rf_power_2_rssi -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x48874108 rtw_register_hw +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x46f1e674 rtw_phy_read_rf_sipi +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x4b676215 rtw_unregister_hw +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x4ca99e59 rtw_core_deinit +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x4df920b5 check_hw_ready EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x519c8ba9 rtw_rate_size -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x52c2563f rtw_bf_remove_bfee_su EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x58210e60 rtw_rate_section -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x5e374e98 rtw_dump_fw -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x62eb8310 rtw_phy_pwrtrack_avg -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x6338afec rtw_coex_read_indirect_reg -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x662ccf86 rtw_phy_init -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x665adaae rtw_phy_parsing_cfo -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x6df96392 rtw_rx_stats -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x704aa89a rtw_bf_cfg_csi_rate -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x7400b69b rtw_parse_tbl_phy_cond -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x77663446 rtw_phy_cfg_rf -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x7c7411fe rtw_restore_reg -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x8b430d26 rtw_dump_reg -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x8ca11263 rtw_phy_cfg_mac -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x918bc52c rtw_phy_cfg_agc -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x9190b1be rtw_tx_write_data_h2c_get -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x980dae40 rtw_coex_write_scbd -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x98d9b72c rtw_phy_pwrtrack_need_lck -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x9998414e rtw_parse_tbl_txpwr_lmt -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x999cfced rtw_bf_enable_bfee_su -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xa09f9b95 rtw_set_channel_mac -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xad949491 rtw_phy_pwrtrack_need_iqk -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xae37c48b rtw_phy_write_rf_reg_sipi -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xb0419d87 rtw_core_deinit -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xb442e7db rtw_bf_enable_bfee_mu -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xb9d9dc04 rtw_coex_write_indirect_reg -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xbafbe59e rtw_phy_cfg_bb -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xbb38149f rtw_tx_write_data_rsvd_page_get -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xc3c474a5 rtw_read8_physical_efuse -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xc53b88a1 rtw_phy_read_rf_sipi -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xccaafe4b rtw_phy_config_swing_table -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xd0722981 rtw_fw_inform_rfk_status -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xd9ae0a28 rtw_parse_tbl_bb_pg -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xdc640f70 rtw_bf_remove_bfee_mu -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xdc91b238 rtw_phy_pwrtrack_thermal_changed -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xdf5db3c0 rtw_phy_load_tables -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xed4e0c5a rtw_bf_phy_init -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xf32f946d rtw_phy_write_rf_reg_mix -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xf62107e4 rtw_phy_pwrtrack_get_delta -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xf88aa9b2 rtw_phy_pwrtrack_get_pwridx -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xf93dc83d rtw_fw_do_iqk -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xfa07510b rtw_fw_c2h_cmd_rx_irqsafe +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x5e01607d rtw_phy_init +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x5eff23f1 rtw_phy_config_swing_table +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x5f017260 rtw_dump_reg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x6062a830 rtw_parse_tbl_txpwr_lmt +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x6167cb37 rtw_phy_pwrtrack_need_lck +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x6700912d rtw_phy_pwrtrack_thermal_changed +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x6a962edf rtw_fw_do_iqk +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x6b4ac686 rtw_rx_fill_rx_status +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x6bda29ae rtw_dump_fw +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x6d5e99e5 rtw_phy_cfg_bb +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x71d4f6b1 rtw_rx_stats +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x71f05e0b rtw_tx_report_enqueue +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x76095c2d rtw_coex_read_indirect_reg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x76a7fa9a rtw_phy_parsing_cfo +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x785d505a rtw_phy_write_rf_reg_sipi +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x7909f18f rtw_parse_tbl_phy_cond +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x79e18c3e rtw_phy_set_tx_power_level +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x7e09dab7 rtw_phy_get_tx_power_index +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x87a3fa3e rtw_register_hw +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x8b3b441c rtw_fw_c2h_cmd_rx_irqsafe +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x8b6e0d9b rtw_fw_inform_rfk_status +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x8bef7011 rtw_restore_reg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x8c021268 rtw_coex_write_indirect_reg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x92350968 rtw_phy_write_rf_reg_mix +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x96dac49e rtw_phy_pwrtrack_get_pwridx +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x9a83f3ec rtw_set_channel_mac +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x9bd38ed2 rtw_tx_write_data_h2c_get +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x9e006e37 rtw_phy_load_tables +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x9e5ddfd3 rtw_tx_write_data_rsvd_page_get +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x9e8cffaf rtw_read8_physical_efuse +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xa0dfe99f rtw_bf_set_gid_table +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xb289cca1 rtw_phy_read_rf +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xbe479e7e rtw_bf_cfg_csi_rate +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xbe6ee8be __rtw_dbg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xd0fb40ec rtw_phy_pwrtrack_get_delta +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xd35b0a73 rtw_bf_remove_bfee_su +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xd5eb5a7c rtw_phy_cfg_mac +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xd75437a3 rtw_coex_write_scbd +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xd7c5a7ff rtw_phy_pwrtrack_avg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xe27fd8b7 rtw_bf_phy_init +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xe612401c rtw_chip_info_setup +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xea6fc4f2 rtw_phy_pwrtrack_need_iqk +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xf32465e2 rtw_tx_fill_tx_desc +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xf4796a6f rtw_fw_c2h_cmd_isr +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xfc9569cb rtw_phy_cfg_rf EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_pci 0x01b2ffa6 rtw_pci_shutdown EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_pci 0x8db88688 rtw_pci_probe EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_pci 0xa8fe3b11 rtw_pm_ops diff -u linux-5.15.0/debian.master/abi/armhf/generic linux-5.15.0/debian.master/abi/armhf/generic --- linux-5.15.0/debian.master/abi/armhf/generic +++ linux-5.15.0/debian.master/abi/armhf/generic @@ -3701,72 +3701,72 @@ EXPORT_SYMBOL drivers/net/wireless/realtek/rtlwifi/rtlwifi 0xed7c8cf2 rtl_evm_db_to_percentage EXPORT_SYMBOL drivers/net/wireless/realtek/rtlwifi/rtlwifi 0xf1fd3bf1 rtl_signal_scale_mapping EXPORT_SYMBOL drivers/net/wireless/realtek/rtlwifi/rtlwifi 0xf49702cc rtl_efuse_shadow_map_update -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8723d 0xbe20519d rtw8723d_hw_spec -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8821c 0x23e02610 rtw8821c_hw_spec -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8822b 0x55c02b2f rtw8822b_hw_spec -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8822c 0xba024011 rtw8822c_hw_spec -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x015ffd13 rtw_tx_write_data_rsvd_page_get -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x032ea7be __rtw_dbg -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x076da750 rtw_coex_read_indirect_reg -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x0c591b9b rtw_phy_pwrtrack_get_delta -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x0e0360e3 rtw_phy_cfg_bb -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x1538310d rtw_bf_enable_bfee_mu -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x18033ccf rtw_phy_write_rf_reg_sipi -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x1c4e0302 rtw_phy_read_rf_sipi -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x1df88adb check_hw_ready -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x21ef5f9b rtw_rx_fill_rx_status -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x2895b7cd rtw_phy_get_tx_power_index -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x2ad02eb7 rtw_parse_tbl_bb_pg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8723d 0x6287bf35 rtw8723d_hw_spec +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8821c 0xff47c8b8 rtw8821c_hw_spec +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8822b 0x8967c587 rtw8822b_hw_spec +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8822c 0x66a5aeb9 rtw8822c_hw_spec +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x0996f9ee rtw_core_deinit +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x0e97d2f1 __rtw_dbg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x10473c38 rtw_bf_set_gid_table +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x18af578e rtw_bf_cfg_csi_rate +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x2194fd23 rtw_read8_physical_efuse +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x24c98502 rtw_phy_cfg_rf +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x264b7b38 rtw_fw_inform_rfk_status +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x2b2c5de2 rtw_coex_read_indirect_reg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x2de88009 rtw_bf_enable_bfee_mu +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x2e57559e rtw_set_channel_mac +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x3101a050 rtw_phy_read_rf EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x33b3f3c0 rtw_debug_mask +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x35e8a7da rtw_phy_config_swing_table EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x36c5bfca rtw_disable_lps_deep_mode -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x39009278 rtw_phy_pwrtrack_thermal_changed -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x391ad762 rtw_bf_remove_bfee_mu -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x39bb364d rtw_bf_cfg_csi_rate -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x39f5ef67 rtw_phy_pwrtrack_need_iqk -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x3bda8f84 rtw_phy_parsing_cfo -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x3ffb486f rtw_bf_enable_bfee_su +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x37bdba8a rtw_core_init +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x430fd7bc rtw_phy_read_rf_sipi +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x4375a21c rtw_dump_fw EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x440b7589 rtw_phy_rf_power_2_rssi -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x4ddd0f89 rtw_unregister_hw +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x459ec656 rtw_phy_pwrtrack_need_iqk +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x48eafcdf rtw_phy_set_tx_power_level +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x4bfa3462 rtw_bf_phy_init +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x4c17649b rtw_tx_write_data_h2c_get +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x4db349e0 rtw_register_hw +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x4efe839a rtw_parse_tbl_txpwr_lmt +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x50596530 rtw_phy_pwrtrack_get_pwridx EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x519c8ba9 rtw_rate_size -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x538132de rtw_register_hw EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x58210e60 rtw_rate_section -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x59485f86 rtw_core_init -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x5be75669 rtw_set_channel_mac -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x62852203 rtw_rx_stats -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x6a03fa59 rtw_read8_physical_efuse -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x71f691bb rtw_fw_c2h_cmd_isr -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x73fb0cf8 rtw_phy_read_rf -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x772e07e9 rtw_fw_inform_rfk_status -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x79445502 rtw_phy_write_rf_reg_mix -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x87ce477a rtw_phy_cfg_agc -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x88f6251a rtw_core_deinit -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x8d189c9f rtw_parse_tbl_phy_cond -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x8da8ef34 rtw_fw_do_iqk -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x91e8422a rtw_phy_pwrtrack_avg -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x9215cf0b rtw_parse_tbl_txpwr_lmt +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x5878c10d rtw_fw_c2h_cmd_rx_irqsafe +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x5edb4672 rtw_bf_remove_bfee_su +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x5f941d7e rtw_coex_write_indirect_reg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x646af5ec rtw_chip_info_setup +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x687f71a4 rtw_phy_get_tx_power_index +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x6e922c93 rtw_phy_pwrtrack_need_lck +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x738f3c98 rtw_phy_load_tables +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x74a331c5 rtw_phy_write_rf_reg_sipi +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x78057f98 rtw_power_mode_change +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x7e748500 rtw_bf_enable_bfee_su +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x8435f469 rtw_parse_tbl_bb_pg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x993700cd rtw_phy_cfg_mac EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x9b51a433 rtw_ops -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x9d6d64a5 rtw_phy_cfg_rf -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x9e4f75ce rtw_chip_info_setup -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xaee5261f rtw_power_mode_change -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xb9c2e599 rtw_bf_phy_init -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xbedad631 rtw_phy_pwrtrack_get_pwridx -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xc0e17566 rtw_bf_remove_bfee_su -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xc2e6ff18 rtw_dump_reg -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xcd6aa960 rtw_tx_report_enqueue -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xcef87462 rtw_phy_cfg_mac -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xd5c4d531 rtw_phy_config_swing_table -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xd62da957 rtw_phy_load_tables -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xe1a5b101 rtw_tx_fill_tx_desc -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xe69635ad rtw_bf_set_gid_table -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xe8dbdc9f rtw_tx_write_data_h2c_get -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xeb0fb71c rtw_restore_reg -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xec7d3976 rtw_coex_write_indirect_reg -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xf1fe053e rtw_dump_fw -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xf2e81c20 rtw_phy_set_tx_power_level -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xf2ee8bca rtw_coex_write_scbd -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xf32922d9 rtw_phy_init -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xf808fb6e rtw_phy_pwrtrack_need_lck -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xf8e78df7 rtw_fw_c2h_cmd_rx_irqsafe +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xa373eb8b rtw_tx_fill_tx_desc +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xa4bcdbf0 rtw_phy_init +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xa58701ed rtw_tx_write_data_rsvd_page_get +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xa6a7179b rtw_phy_pwrtrack_avg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xa7fbce21 rtw_tx_report_enqueue +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xa9b7ecea rtw_phy_parsing_cfo +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xa9ff2b98 rtw_phy_write_rf_reg_mix +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xb2df3610 rtw_dump_reg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xbb387208 check_hw_ready +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xbbc3229a rtw_rx_fill_rx_status +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xc5b35783 rtw_parse_tbl_phy_cond +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xd007c930 rtw_fw_do_iqk +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xd4ad42cf rtw_phy_cfg_agc +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xd595fbff rtw_unregister_hw +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xd8a29a9f rtw_phy_pwrtrack_thermal_changed +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xd8f226af rtw_coex_write_scbd +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xdb366b66 rtw_fw_c2h_cmd_isr +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xe0d98313 rtw_restore_reg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xe16b1089 rtw_phy_cfg_bb +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xe862f732 rtw_rx_stats +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xee04fab7 rtw_phy_pwrtrack_get_delta +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xf289b089 rtw_bf_remove_bfee_mu EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_pci 0x1eaedc4d rtw_pci_probe EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_pci 0x40b9b5bd rtw_pm_ops EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_pci 0x4b5f72d5 rtw_pci_shutdown diff -u linux-5.15.0/debian.master/abi/armhf/generic-lpae linux-5.15.0/debian.master/abi/armhf/generic-lpae --- linux-5.15.0/debian.master/abi/armhf/generic-lpae +++ linux-5.15.0/debian.master/abi/armhf/generic-lpae @@ -3624,72 +3624,72 @@ EXPORT_SYMBOL drivers/net/wireless/realtek/rtlwifi/rtlwifi 0xe4f46a87 rtl_phy_scan_operation_backup EXPORT_SYMBOL drivers/net/wireless/realtek/rtlwifi/rtlwifi 0xed7c8cf2 rtl_evm_db_to_percentage EXPORT_SYMBOL drivers/net/wireless/realtek/rtlwifi/rtlwifi 0xee6af641 efuse_one_byte_read -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8723d 0x2ec71e1e rtw8723d_hw_spec -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8821c 0xb3076993 rtw8821c_hw_spec -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8822b 0xc52764ac rtw8822b_hw_spec -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8822c 0x2ae50f92 rtw8822c_hw_spec -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x004e7685 rtw_fw_do_iqk -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x03b30a67 rtw_phy_cfg_bb -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x03fc114b check_hw_ready -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x18ff8f5b rtw_read8_physical_efuse -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x1cc1c977 rtw_phy_pwrtrack_need_lck -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x1f92ebaf rtw_coex_read_indirect_reg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8723d 0x2f0e2505 rtw8723d_hw_spec +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8821c 0xb2ce5288 rtw8821c_hw_spec +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8822b 0xc4ee5fb7 rtw8822b_hw_spec +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8822c 0x2b2c3489 rtw8822c_hw_spec +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x008dfa08 rtw_bf_enable_bfee_mu +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x01545d84 rtw_core_deinit +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x018d3cd3 rtw_phy_load_tables +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x02069100 rtw_parse_tbl_txpwr_lmt +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x0310c458 rtw_phy_parsing_cfo +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x033262e4 rtw_tx_fill_tx_desc +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x03f94518 rtw_phy_cfg_rf +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x047dec2d rtw_phy_get_tx_power_index +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x05f78e24 rtw_register_hw +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x0a1f0fe5 rtw_tx_write_data_h2c_get +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x0af03211 rtw_bf_enable_bfee_su +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x108e8e20 rtw_bf_remove_bfee_su +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x11da19bd rtw_phy_write_rf_reg_sipi +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x13dbf189 rtw_phy_config_swing_table +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x1544a595 rtw_core_init +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x1adae673 rtw_fw_c2h_cmd_isr EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x2589111d rtw_ops -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x312fa705 rtw_phy_pwrtrack_avg -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x31d3b503 rtw_bf_remove_bfee_mu +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x292e10df rtw_fw_c2h_cmd_rx_irqsafe +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x2df279bd rtw_rx_fill_rx_status +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x32f2f792 rtw_phy_read_rf EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x33b3f3c0 rtw_debug_mask +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x34b7fa2d rtw_restore_reg EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x36c5bfca rtw_disable_lps_deep_mode -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x3bbc1c02 rtw_bf_enable_bfee_su -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x3e90e2f1 rtw_phy_load_tables -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x3f4a0c49 rtw_bf_enable_bfee_mu -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x41222965 rtw_phy_cfg_agc -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x41d7037e rtw_tx_write_data_rsvd_page_get -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x42d5ca5b rtw_phy_pwrtrack_thermal_changed +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x3db8d0a6 rtw_bf_remove_bfee_mu +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x3dbe27e5 __rtw_dbg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x3e395247 rtw_read8_physical_efuse +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x3f3c0cd5 rtw_bf_phy_init EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x440b7589 rtw_phy_rf_power_2_rssi -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x4c07c43c rtw_phy_write_rf_reg_sipi -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x4d37e99f rtw_dump_fw -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x4fc3dbb2 rtw_tx_write_data_h2c_get -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x515f5b0f rtw_chip_info_setup +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x44a09478 rtw_bf_cfg_csi_rate +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x475f5862 rtw_power_mode_change EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x519c8ba9 rtw_rate_size -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x55916a7e rtw_phy_pwrtrack_get_pwridx +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x548a7342 rtw_phy_cfg_bb EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x58210e60 rtw_rate_section -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x5854558e rtw_phy_init -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x5b10af31 rtw_bf_remove_bfee_su -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x5c181e23 rtw_core_deinit -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x5fbffaef rtw_phy_read_rf_sipi -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x6130ac86 rtw_core_init -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x654c48c3 rtw_rx_fill_rx_status -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x66eb964e rtw_phy_cfg_rf -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x72007fd2 rtw_phy_write_rf_reg_mix -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x76e86203 rtw_fw_inform_rfk_status -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x78e1a99f rtw_rx_stats -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x791cf8b6 rtw_parse_tbl_bb_pg -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x81cbd056 rtw_unregister_hw -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x86ac274c rtw_phy_read_rf -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x90443de3 rtw_bf_set_gid_table -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x905759d9 rtw_parse_tbl_phy_cond -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x9bd33f99 rtw_dump_reg -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x9c92421d rtw_phy_cfg_mac -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x9f8e9e50 rtw_power_mode_change -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xa1c4aa82 rtw_coex_write_indirect_reg -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xa5fa90be rtw_register_hw -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xa95a01a7 rtw_restore_reg -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xaaba7c61 rtw_phy_parsing_cfo -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xaf291625 rtw_phy_pwrtrack_need_iqk -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xb300da6f rtw_fw_c2h_cmd_rx_irqsafe -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xb455b72c rtw_tx_report_enqueue -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xb4dd7ec4 rtw_phy_get_tx_power_index -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xbd7ad5d6 __rtw_dbg -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xcb2de073 rtw_parse_tbl_txpwr_lmt -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xcc32857f rtw_bf_cfg_csi_rate -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xcea6e77b rtw_coex_write_scbd -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xcf8c065d rtw_phy_config_swing_table -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xd3989349 rtw_fw_c2h_cmd_isr -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xde6e197d rtw_set_channel_mac -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xde7870d1 rtw_bf_phy_init -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xf0c08743 rtw_tx_fill_tx_desc -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xf154c5a1 rtw_phy_pwrtrack_get_delta -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xfc9bfb3f rtw_phy_set_tx_power_level +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x582649ba rtw_tx_report_enqueue +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x5aa8f9a8 rtw_phy_cfg_agc +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x5b00d64f rtw_phy_init +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x5b89e482 rtw_unregister_hw +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x5e8745a3 check_hw_ready +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x5ed011ad rtw_phy_pwrtrack_need_iqk +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x6210fb9c rtw_phy_set_tx_power_level +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x62551fe2 rtw_bf_set_gid_table +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x62cc82e6 rtw_fw_inform_rfk_status +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x6786a3c4 rtw_dump_reg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x6b5653a5 rtw_dump_fw +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x6c1e25bb rtw_set_channel_mac +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x768d846c rtw_parse_tbl_bb_pg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x796156f7 rtw_phy_pwrtrack_avg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x7adea575 rtw_parse_tbl_phy_cond +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x7cc196cd rtw_phy_pwrtrack_need_lck +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x83440ea5 rtw_phy_pwrtrack_get_delta +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x8b131e18 rtw_coex_write_indirect_reg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xaa142010 rtw_fw_do_iqk +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xab8e1041 rtw_phy_write_rf_reg_mix +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xac2577e7 rtw_phy_pwrtrack_get_pwridx +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xb0ff69b8 rtw_phy_read_rf_sipi +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xb548c80a rtw_rx_stats +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xc68a6945 rtw_chip_info_setup +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xcbeef29d rtw_tx_write_data_rsvd_page_get +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xd30b4e6a rtw_phy_cfg_mac +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xd8eccc38 rtw_coex_write_scbd +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xf494ecf9 rtw_coex_read_indirect_reg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xf530c80e rtw_phy_pwrtrack_thermal_changed EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_pci 0x1bef3fff rtw_pci_shutdown EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_pci 0x47876bac rtw_pci_probe EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_pci 0x957990b8 rtw_pci_remove diff -u linux-5.15.0/debian.master/abi/ppc64el/generic linux-5.15.0/debian.master/abi/ppc64el/generic --- linux-5.15.0/debian.master/abi/ppc64el/generic +++ linux-5.15.0/debian.master/abi/ppc64el/generic @@ -3590,72 +3590,72 @@ EXPORT_SYMBOL drivers/net/wireless/realtek/rtlwifi/rtlwifi 0xed7c8cf2 rtl_evm_db_to_percentage EXPORT_SYMBOL drivers/net/wireless/realtek/rtlwifi/rtlwifi 0xf37c7513 rtl_cmd_send_packet EXPORT_SYMBOL drivers/net/wireless/realtek/rtlwifi/rtlwifi 0xfae9bbd4 rtl_get_tcb_desc -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8723d 0xd837df20 rtw8723d_hw_spec -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8821c 0x45f7a8ad rtw8821c_hw_spec -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8822b 0x33d7a592 rtw8822b_hw_spec -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8822c 0xdc15ceac rtw8822c_hw_spec -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x015f2644 rtw_phy_load_tables -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x045c7c57 rtw_set_channel_mac -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x07d059a8 rtw_phy_write_rf_reg_sipi -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x084d85e3 rtw_core_deinit -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x0ffa0b5a rtw_coex_write_indirect_reg -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x10ac24ec rtw_tx_write_data_h2c_get -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x16217dc0 rtw_phy_pwrtrack_need_lck -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x22dbf34a rtw_parse_tbl_bb_pg -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x2e27261c rtw_phy_init +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8723d 0xcc1016f3 rtw8723d_hw_spec +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8821c 0x51d0617e rtw8821c_hw_spec +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8822b 0x27f06c41 rtw8822b_hw_spec +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_8822c 0xc832077f rtw8822c_hw_spec +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x001f0fef rtw_phy_pwrtrack_get_pwridx +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x02df1f7b rtw_power_mode_change +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x063a51ac rtw_phy_config_swing_table +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x12b3e48d rtw_bf_enable_bfee_su +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x169835de rtw_coex_write_scbd +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x17e11448 rtw_fw_do_iqk +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x188b5d7a rtw_bf_set_gid_table +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x194de48b rtw_register_hw +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x24deddbd rtw_phy_pwrtrack_get_delta +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x27bfd5c2 rtw_parse_tbl_txpwr_lmt +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x30876db9 rtw_coex_read_indirect_reg EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x33b3f3c0 rtw_debug_mask -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x3577c21b rtw_bf_remove_bfee_mu EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x36c5bfca rtw_disable_lps_deep_mode -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x3b46a0f1 rtw_phy_read_rf_sipi -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x3fdc4550 rtw_parse_tbl_phy_cond +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x3a1361c4 rtw_parse_tbl_phy_cond +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x3b3a9b17 rtw_phy_init +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x3fcb5cf7 rtw_bf_phy_init EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x4336bc00 rtw_ops EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x440b7589 rtw_phy_rf_power_2_rssi -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x46e909ba rtw_phy_config_swing_table -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x4b55fced rtw_phy_cfg_bb -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x4d3130f9 rtw_phy_pwrtrack_need_iqk +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x4d1c29bb rtw_phy_write_rf_reg_mix +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x4f252da4 rtw_coex_write_indirect_reg EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x519c8ba9 rtw_rate_size -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x53e8ef9e rtw_power_mode_change -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x5607ebf5 rtw_phy_pwrtrack_avg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x53ed97f9 rtw_core_init +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x55e32fe7 rtw_bf_remove_bfee_mu EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x58210e60 rtw_rate_section -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x5db19ff5 rtw_phy_cfg_agc -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x5eeb7d2a rtw_tx_fill_tx_desc -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x60ef4fc3 rtw_bf_remove_bfee_su -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x6f31969d rtw_bf_phy_init -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x7813b365 rtw_phy_write_rf_reg_mix -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x7890caa5 rtw_phy_pwrtrack_thermal_changed -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x7e888415 rtw_restore_reg -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x80681e99 __rtw_dbg -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x81ecddee rtw_bf_enable_bfee_su -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x8b97873c rtw_phy_get_tx_power_index -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x8ffec2f4 rtw_rx_fill_rx_status -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x910b24f8 rtw_fw_c2h_cmd_isr -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x9580bb77 rtw_bf_cfg_csi_rate -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x969c51bc rtw_chip_info_setup -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x98706bd9 rtw_read8_physical_efuse -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x9a894cd1 rtw_dump_reg -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x9acfbca5 rtw_coex_read_indirect_reg -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x9bf234b7 rtw_phy_parsing_cfo -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xa341c46d rtw_phy_set_tx_power_level -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xa7eae8de rtw_phy_read_rf -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xb5034d8a rtw_phy_cfg_mac -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xb7fc81fd rtw_phy_pwrtrack_get_pwridx -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xb82dcf59 rtw_dump_fw -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xb852a8a7 rtw_coex_write_scbd -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xb99223ad rtw_tx_write_data_rsvd_page_get -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xc2944cf1 rtw_bf_set_gid_table -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xc7a4d93b rtw_tx_report_enqueue -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xcb7e41d0 rtw_phy_pwrtrack_get_delta -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xdfcbc313 rtw_rx_stats -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xe62108f7 rtw_register_hw -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xe6e9e1db rtw_fw_c2h_cmd_rx_irqsafe -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xe7a6bbb1 rtw_parse_tbl_txpwr_lmt -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xe81bee0a rtw_bf_enable_bfee_mu -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xe84c734b rtw_fw_do_iqk -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xe8f7b46d rtw_phy_cfg_rf -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xee815476 rtw_core_init -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xf7eb9e7c check_hw_ready -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xf973162d rtw_fw_inform_rfk_status -EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xfecf60af rtw_unregister_hw +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x588b85c3 rtw_phy_write_rf_reg_sipi +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x67ea3a02 rtw_parse_tbl_bb_pg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x693bda4d check_hw_ready +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x69e8744a rtw_phy_read_rf_sipi +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x6b2f8750 rtw_phy_pwrtrack_avg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x6cafc565 rtw_phy_cfg_agc +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x70fd194d rtw_bf_enable_bfee_mu +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x722281cb __rtw_dbg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x74915f65 rtw_phy_pwrtrack_thermal_changed +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x753fea99 rtw_set_channel_mac +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x766ac67a rtw_rx_fill_rx_status +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x76a94ef9 rtw_fw_c2h_cmd_rx_irqsafe +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x786541ff rtw_dump_reg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x7a85e36b rtw_fw_c2h_cmd_isr +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x879842f7 rtw_chip_info_setup +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x89439f34 rtw_phy_get_tx_power_index +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x9193ec1d rtw_dump_fw +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x9e6aa648 rtw_phy_cfg_mac +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0x9fb8cff7 rtw_tx_report_enqueue +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xa2375cb2 rtw_phy_cfg_bb +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xa4123574 rtw_bf_remove_bfee_su +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xa44e8bc2 rtw_phy_parsing_cfo +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xac5787ef rtw_phy_cfg_rf +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xb2a4c4c5 rtw_phy_pwrtrack_need_lck +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xb3771e19 rtw_read8_physical_efuse +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xb69c9c26 rtw_phy_set_tx_power_level +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xbb0019c9 rtw_core_deinit +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xc0f082b4 rtw_phy_pwrtrack_need_iqk +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xc112bb7f rtw_unregister_hw +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xc442177b rtw_tx_fill_tx_desc +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xc87dc836 rtw_phy_load_tables +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xcb150a12 rtw_fw_inform_rfk_status +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xda77c129 rtw_phy_read_rf +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xe6fb1a80 rtw_tx_write_data_rsvd_page_get +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xead4af03 rtw_restore_reg +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xf21cca48 rtw_tx_write_data_h2c_get +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xf8dcdfb8 rtw_rx_stats +EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_core 0xf989174c rtw_bf_cfg_csi_rate EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_pci 0x752641ff rtw_pm_ops EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_pci 0x870c1edd rtw_pci_shutdown EXPORT_SYMBOL drivers/net/wireless/realtek/rtw88/rtw88_pci 0xa7b69efd rtw_pci_remove diff -u linux-5.15.0/debian.master/abi/version linux-5.15.0/debian.master/abi/version --- linux-5.15.0/debian.master/abi/version +++ linux-5.15.0/debian.master/abi/version @@ -1 +1 @@ -5.15.0-39.42 +5.15.0-40.43 diff -u linux-5.15.0/debian.master/changelog linux-5.15.0/debian.master/changelog --- linux-5.15.0/debian.master/changelog +++ linux-5.15.0/debian.master/changelog @@ -1,3 +1,565 @@ +linux (5.15.0-41.44) jammy; urgency=medium + + * jammy/linux: 5.15.0-41.44 -proposed tracker (LP: #1979448) + + * Fix can't boot up after change to vmd (LP: #1976587) + - PCI: vmd: Assign VMD IRQ domain before enumeration + - PCI: vmd: Revert 2565e5b69c44 ("PCI: vmd: Do not disable MSI-X remapping if + interrupt remapping is enabled by IOMMU.") + + * [SRU][Jammy/OEM-5.17][PATCH 0/1] Fix calltrace in mac80211 (LP: #1978297) + - mac80211: fix struct ieee80211_tx_info size + + * [SRU][Jammy][PATCH 0/1] Fix amd display corruption on s2idle resume + (LP: #1978244) + - drm/amd/display: Don't reinitialize DMCUB on s0ix resume + + * pl2303 serial adapter not recognized (LP: #1967493) + - USB: serial: pl2303: fix type detection for odd device + + * Remove SAUCE patches from test_vxlan_under_vrf.sh in net of + ubuntu_kernel_selftests (LP: #1975691) + - Revert "UBUNTU: SAUCE: selftests: net: Don't fail test_vxlan_under_vrf on + xfail" + - Revert "UBUNTU: SAUCE: selftests: net: Make test for VXLAN underlay in non- + default VRF an expected failure" + + * Fix hp_wmi_read_int() reporting error (0x05) (LP: #1979051) + - platform/x86: hp-wmi: Fix hp_wmi_read_int() reporting error (0x05) + + * Request to back port vmci patches to Ubuntu kernel (LP: #1978145) + - VMCI: dma dg: whitespace formatting change for vmci register defines + - VMCI: dma dg: add MMIO access to registers + - VMCI: dma dg: detect DMA datagram capability + - VMCI: dma dg: set OS page size + - VMCI: dma dg: register dummy IRQ handlers for DMA datagrams + - VMCI: dma dg: allocate send and receive buffers for DMA datagrams + - VMCI: dma dg: add support for DMA datagrams sends + - VMCI: dma dg: add support for DMA datagrams receive + - VMCI: Fix some error handling paths in vmci_guest_probe_device() + - VMCI: Release notification_bitmap in error path + - VMCI: Check exclusive_vectors when freeing interrupt 1 + - VMCI: Add support for ARM64 + - [Config] Update policies for VMWARE_VMCI and VMWARE_VMCI_VSOCKETS + + * [UBUNTU 20.04] rcu stalls with many storage key guests (LP: #1975582) + - s390/gmap: voluntarily schedule during key setting + - s390/mm: use non-quiescing sske for KVM switch to keyed guest + + * [SRU][OEM-5.14/OEM-5.17/Jammy][PATCH 0/1] Fix i915 calltrace on new ADL BIOS + (LP: #1976214) + - drm/i915: update new TMDS clock setting defined by VBT + + * Revert PPC get_user workaround (LP: #1976248) + - powerpc: Export mmu_feature_keys[] as non-GPL + + * Jammy update: v5.15.39 upstream stable release (LP: #1978240) + - MIPS: Fix CP0 counter erratum detection for R4k CPUs + - parisc: Merge model and model name into one line in /proc/cpuinfo + - ALSA: hda/realtek: Add quirk for Yoga Duet 7 13ITL6 speakers + - ALSA: fireworks: fix wrong return count shorter than expected by 4 bytes + - mmc: sdhci-msm: Reset GCC_SDCC_BCR register for SDHC + - mmc: sunxi-mmc: Fix DMA descriptors allocated above 32 bits + - mmc: core: Set HS clock speed before sending HS CMD13 + - gpiolib: of: fix bounds check for 'gpio-reserved-ranges' + - x86/fpu: Prevent FPU state corruption + - KVM: x86/svm: Account for family 17h event renumberings in + amd_pmc_perf_hw_id + - iommu/vt-d: Calculate mask for non-aligned flushes + - iommu/arm-smmu-v3: Fix size calculation in arm_smmu_mm_invalidate_range() + - drm/amd/display: Avoid reading audio pattern past AUDIO_CHANNELS_COUNT + - drm/amdgpu: do not use passthrough mode in Xen dom0 + - RISC-V: relocate DTB if it's outside memory region + - Revert "SUNRPC: attempt AF_LOCAL connect on setup" + - timekeeping: Mark NMI safe time accessors as notrace + - firewire: fix potential uaf in outbound_phy_packet_callback() + - firewire: remove check of list iterator against head past the loop body + - firewire: core: extend card->lock in fw_core_handle_bus_reset + - net: stmmac: disable Split Header (SPH) for Intel platforms + - genirq: Synchronize interrupt thread startup + - ASoC: da7219: Fix change notifications for tone generator frequency + - ASoC: wm8958: Fix change notifications for DSP controls + - ASoC: meson: Fix event generation for AUI ACODEC mux + - ASoC: meson: Fix event generation for G12A tohdmi mux + - ASoC: meson: Fix event generation for AUI CODEC mux + - s390/dasd: fix data corruption for ESE devices + - s390/dasd: prevent double format of tracks for ESE devices + - s390/dasd: Fix read for ESE with blksize < 4k + - s390/dasd: Fix read inconsistency for ESE DASD devices + - can: grcan: grcan_close(): fix deadlock + - can: isotp: remove re-binding of bound socket + - can: grcan: use ofdev->dev when allocating DMA memory + - can: grcan: grcan_probe(): fix broken system id check for errata workaround + needs + - can: grcan: only use the NAPI poll budget for RX + - nfc: replace improper check device_is_registered() in netlink related + functions + - nfc: nfcmrvl: main: reorder destructive operations in + nfcmrvl_nci_unregister_dev to avoid bugs + - NFC: netlink: fix sleep in atomic bug when firmware download timeout + - gpio: visconti: Fix fwnode of GPIO IRQ + - gpio: pca953x: fix irq_stat not updated when irq is disabled (irq_mask not + set) + - hwmon: (adt7470) Fix warning on module removal + - hwmon: (pmbus) disable PEC if not enabled + - ASoC: dmaengine: Restore NULL prepare_slave_config() callback + - ASoC: soc-ops: fix error handling + - iommu/vt-d: Drop stop marker messages + - iommu/dart: check return value after calling platform_get_resource() + - net/mlx5e: Fix trust state reset in reload + - net/mlx5e: Don't match double-vlan packets if cvlan is not set + - net/mlx5e: CT: Fix queued up restore put() executing after relevant ft + release + - net/mlx5e: Fix the calling of update_buffer_lossy() API + - net/mlx5: Avoid double clear or set of sync reset requested + - net/mlx5: Fix deadlock in sync reset flow + - selftests/seccomp: Don't call read() on TTY from background pgrp + - SUNRPC release the transport of a relocated task with an assigned transport + - RDMA/siw: Fix a condition race issue in MPA request processing + - RDMA/irdma: Flush iWARP QP if modified to ERR from RTR state + - RDMA/irdma: Reduce iWARP QP destroy time + - RDMA/irdma: Fix possible crash due to NULL netdev in notifier + - NFSv4: Don't invalidate inode attributes on delegation return + - net: ethernet: mediatek: add missing of_node_put() in mtk_sgmii_init() + - net: dsa: mt7530: add missing of_node_put() in mt7530_setup() + - net: stmmac: dwmac-sun8i: add missing of_node_put() in + sun8i_dwmac_register_mdio_mux() + - net: mdio: Fix ENOMEM return value in BCM6368 mux bus controller + - net: cpsw: add missing of_node_put() in cpsw_probe_dt() + - net: igmp: respect RCU rules in ip_mc_source() and ip_mc_msfilter() + - net: emaclite: Add error handling for of_address_to_resource() + - selftests/net: so_txtime: fix parsing of start time stamp on 32 bit systems + - selftests/net: so_txtime: usage(): fix documentation of default clock + - drm/msm/dp: remove fail safe mode related code + - btrfs: do not BUG_ON() on failure to update inode when setting xattr + - hinic: fix bug of wq out of bound access + - mld: respect RCU rules in ip6_mc_source() and ip6_mc_msfilter() + - rxrpc: Enable IPv6 checksums on transport socket + - selftests: mirror_gre_bridge_1q: Avoid changing PVID while interface is + operational + - bnxt_en: Fix possible bnxt_open() failure caused by wrong RFS flag + - bnxt_en: Fix unnecessary dropping of RX packets + - selftests: ocelot: tc_flower_chains: specify conform-exceed action for + policer + - smsc911x: allow using IRQ0 + - btrfs: force v2 space cache usage for subpage mount + - btrfs: always log symlinks in full mode + - gpio: mvebu: drop pwm base assignment + - kvm: x86/cpuid: Only provide CPUID leaf 0xA if host has architectural PMU + - net/mlx5: Fix slab-out-of-bounds while reading resource dump menu + - net/mlx5e: Lag, Fix use-after-free in fib event handler + - net/mlx5e: Lag, Fix fib_info pointer assignment + - net/mlx5e: Lag, Don't skip fib events on current dst + - iommu/dart: Add missing module owner to ops structure + - kvm: selftests: do not use bitfields larger than 32-bits for PTEs + - KVM: selftests: Silence compiler warning in the kvm_page_table_test + - x86/kvm: Preserve BSP MSR_KVM_POLL_CONTROL across suspend/resume + - KVM: x86: Do not change ICR on write to APIC_SELF_IPI + - KVM: x86/mmu: avoid NULL-pointer dereference on page freeing bugs + - KVM: LAPIC: Enable timer posted-interrupt only when mwait/hlt is advertised + - selftest/vm: verify mmap addr in mremap_test + - selftest/vm: verify remap destination address in mremap_test + - Revert "parisc: Mark sched_clock unstable only if clocks are not + syncronized" + - rcu: Fix callbacks processing time limit retaining cond_resched() + - rcu: Apply callbacks processing time limit only on softirq + - PCI: pci-bridge-emul: Add description for class_revision field + - PCI: pci-bridge-emul: Add definitions for missing capabilities registers + - PCI: aardvark: Add support for DEVCAP2, DEVCTL2, LNKCAP2 and LNKCTL2 + registers on emulated bridge + - PCI: aardvark: Clear all MSIs at setup + - PCI: aardvark: Comment actions in driver remove method + - PCI: aardvark: Disable bus mastering when unbinding driver + - PCI: aardvark: Mask all interrupts when unbinding driver + - PCI: aardvark: Fix memory leak in driver unbind + - PCI: aardvark: Assert PERST# when unbinding driver + - PCI: aardvark: Disable link training when unbinding driver + - PCI: aardvark: Disable common PHY when unbinding driver + - PCI: aardvark: Replace custom PCIE_CORE_INT_* macros with PCI_INTERRUPT_* + - PCI: aardvark: Check return value of generic_handle_domain_irq() when + processing INTx IRQ + - PCI: aardvark: Make MSI irq_chip structures static driver structures + - PCI: aardvark: Make msi_domain_info structure a static driver structure + - PCI: aardvark: Use dev_fwnode() instead of of_node_to_fwnode(dev->of_node) + - PCI: aardvark: Refactor unmasking summary MSI interrupt + - PCI: aardvark: Add support for masking MSI interrupts + - PCI: aardvark: Fix setting MSI address + - PCI: aardvark: Enable MSI-X support + - PCI: aardvark: Add support for ERR interrupt on emulated bridge + - PCI: aardvark: Optimize writing PCI_EXP_RTCTL_PMEIE and PCI_EXP_RTSTA_PME on + emulated bridge + - PCI: aardvark: Add support for PME interrupts + - PCI: aardvark: Fix support for PME requester on emulated bridge + - PCI: aardvark: Use separate INTA interrupt for emulated root bridge + - PCI: aardvark: Remove irq_mask_ack() callback for INTx interrupts + - PCI: aardvark: Don't mask irq when mapping + - PCI: aardvark: Drop __maybe_unused from advk_pcie_disable_phy() + - PCI: aardvark: Update comment about link going down after link-up + - Linux 5.15.39 + + * Jammy update: v5.15.38 upstream stable release (LP: #1978234) + - usb: mtu3: fix USB 3.0 dual-role-switch from device to host + - USB: quirks: add a Realtek card reader + - USB: quirks: add STRING quirk for VCOM device + - USB: serial: whiteheat: fix heap overflow in WHITEHEAT_GET_DTR_RTS + - USB: serial: cp210x: add PIDs for Kamstrup USB Meter Reader + - USB: serial: option: add support for Cinterion MV32-WA/MV32-WB + - USB: serial: option: add Telit 0x1057, 0x1058, 0x1075 compositions + - usb: xhci: tegra:Fix PM usage reference leak of + tegra_xusb_unpowergate_partitions + - xhci: Enable runtime PM on second Alderlake controller + - xhci: stop polling roothubs after shutdown + - xhci: increase usb U3 -> U0 link resume timeout from 100ms to 500ms + - iio: dac: ad5592r: Fix the missing return value. + - iio: dac: ad5446: Fix read_raw not returning set value + - iio: magnetometer: ak8975: Fix the error handling in ak8975_power_on() + - iio: imu: inv_icm42600: Fix I2C init possible nack + - usb: misc: fix improper handling of refcount in uss720_probe() + - usb: core: Don't hold the device lock while sleeping in do_proc_control() + - usb: typec: ucsi: Fix reuse of completion structure + - usb: typec: ucsi: Fix role swapping + - usb: gadget: uvc: Fix crash when encoding data for usb request + - usb: gadget: configfs: clear deactivation flag in + configfs_composite_unbind() + - usb: dwc3: Try usb-role-switch first in dwc3_drd_init + - usb: dwc3: core: Fix tx/rx threshold settings + - usb: dwc3: core: Only handle soft-reset in DCTL + - usb: dwc3: gadget: Return proper request status + - usb: dwc3: pci: add support for the Intel Meteor Lake-P + - usb: cdns3: Fix issue for clear halt endpoint + - usb: phy: generic: Get the vbus supply + - serial: imx: fix overrun interrupts in DMA mode + - serial: amba-pl011: do not time out prematurely when draining tx fifo + - serial: 8250: Also set sticky MCR bits in console restoration + - serial: 8250: Correct the clock for EndRun PTP/1588 PCIe device + - arch_topology: Do not set llc_sibling if llc_id is invalid + - ceph: fix possible NULL pointer dereference for req->r_session + - bus: mhi: host: pci_generic: Add missing poweroff() PM callback + - bus: mhi: host: pci_generic: Flush recovery worker during freeze + - arm64: dts: imx8mm-venice: fix spi2 pin configuration + - pinctrl: samsung: fix missing GPIOLIB on ARM64 Exynos config + - hex2bin: make the function hex_to_bin constant-time + - hex2bin: fix access beyond string end + - riscv: patch_text: Fixup last cpu should be master + - x86/pci/xen: Disable PCI/MSI[-X] masking for XEN_HVM guests + - iocost: don't reset the inuse weight of under-weighted debtors + - virtio_net: fix wrong buf address calculation when using xdp + - cpufreq: qcom-hw: fix the race between LMH worker and cpuhp + - cpufreq: qcom-cpufreq-hw: Fix throttle frequency value on EPSS platforms + - video: fbdev: udlfb: properly check endpoint type + - arm64: dts: meson: remove CPU opps below 1GHz for G12B boards + - arm64: dts: meson: remove CPU opps below 1GHz for SM1 boards + - iio:imu:bmi160: disable regulator in error path + - mtd: rawnand: fix ecc parameters for mt7622 + - xsk: Fix l2fwd for copy mode + busy poll combo + - arm64: dts: imx8qm: Correct SCU clock controller's compatible property + - USB: Fix xhci event ring dequeue pointer ERDP update issue + - ARM: dts: imx6qdl-apalis: Fix sgtl5000 detection issue + - arm64: dts: imx8mn: Fix SAI nodes + - arm64: dts: meson-sm1-bananapi-m5: fix wrong GPIO pin labeling for CON1 + - phy: samsung: Fix missing of_node_put() in exynos_sata_phy_probe + - phy: samsung: exynos5250-sata: fix missing device put in probe error paths + - ARM: OMAP2+: Fix refcount leak in omap_gic_of_init + - bus: ti-sysc: Make omap3 gpt12 quirk handling SoC specific + - ARM: dts: dra7: Fix suspend warning for vpe powerdomain + - phy: ti: omap-usb2: Fix error handling in omap_usb2_enable_clocks + - ARM: dts: at91: Map MCLK for wm8731 on at91sam9g20ek + - ARM: dts: at91: sama5d4_xplained: fix pinctrl phandle name + - ARM: dts: at91: fix pinctrl phandles + - phy: mapphone-mdm6600: Fix PM error handling in phy_mdm6600_probe + - phy: ti: Add missing pm_runtime_disable() in serdes_am654_probe + - interconnect: qcom: sdx55: Drop IP0 interconnects + - ARM: dts: Fix mmc order for omap3-gta04 + - ARM: dts: am3517-evm: Fix misc pinmuxing + - ARM: dts: logicpd-som-lv: Fix wrong pinmuxing on OMAP35 + - ipvs: correctly print the memory size of ip_vs_conn_tab + - phy: amlogic: fix error path in phy_g12a_usb3_pcie_probe() + - pinctrl: mediatek: moore: Fix build error + - mtd: rawnand: Fix return value check of wait_for_completion_timeout + - mtd: fix 'part' field data corruption in mtd_info + - pinctrl: stm32: Do not call stm32_gpio_get() for edge triggered IRQs in EOI + - memory: renesas-rpc-if: Fix HF/OSPI data transfer in Manual Mode + - net: dsa: Add missing of_node_put() in dsa_port_link_register_of + - netfilter: nft_set_rbtree: overlap detection with element re-addition after + deletion + - bpf, lwt: Fix crash when using bpf_skb_set_tunnel_key() from bpf_xmit lwt + hook + - pinctrl: rockchip: fix RK3308 pinmux bits + - tcp: md5: incorrect tcp_header_len for incoming connections + - pinctrl: stm32: Keep pinctrl block clock enabled when LEVEL IRQ requested + - tcp: ensure to use the most recently sent skb when filling the rate sample + - wireguard: device: check for metadata_dst with skb_valid_dst() + - sctp: check asoc strreset_chunk in sctp_generate_reconf_event + - ARM: dts: imx6ull-colibri: fix vqmmc regulator + - arm64: dts: imx8mn-ddr4-evk: Describe the 32.768 kHz PMIC clock + - pinctrl: pistachio: fix use of irq_of_parse_and_map() + - cpufreq: fix memory leak in sun50i_cpufreq_nvmem_probe + - net: hns3: clear inited state and stop client after failed to register + netdev + - net: hns3: modify the return code of hclge_get_ring_chain_from_mbx + - net: hns3: add validity check for message data length + - net: hns3: add return value for mailbox handling in PF + - net/smc: sync err code when tcp connection was refused + - ip_gre: Make o_seqno start from 0 in native mode + - ip6_gre: Make o_seqno start from 0 in native mode + - ip_gre, ip6_gre: Fix race condition on o_seqno in collect_md mode + - tcp: fix potential xmit stalls caused by TCP_NOTSENT_LOWAT + - tcp: make sure treq->af_specific is initialized + - bus: sunxi-rsb: Fix the return value of sunxi_rsb_device_create() + - clk: sunxi: sun9i-mmc: check return value after calling + platform_get_resource() + - cpufreq: qcom-cpufreq-hw: Clear dcvs interrupts + - net: bcmgenet: hide status block before TX timestamping + - net: phy: marvell10g: fix return value on error + - net: dsa: mv88e6xxx: Fix port_hidden_wait to account for port_base_addr + - drm/sun4i: Remove obsolete references to PHYS_OFFSET + - net: dsa: lantiq_gswip: Don't set GSWIP_MII_CFG_RMII_CLK + - io_uring: check reserved fields for send/sendmsg + - io_uring: check reserved fields for recv/recvmsg + - netfilter: conntrack: fix udp offload timeout sysctl + - drm/amdkfd: Fix GWS queue count + - drm/amd/display: Fix memory leak in dcn21_clock_source_create + - tls: Skip tls_append_frag on zero copy size + - bnx2x: fix napi API usage sequence + - net: fec: add missing of_node_put() in fec_enet_init_stop_mode() + - gfs2: Prevent endless loops in gfs2_file_buffered_write + - gfs2: Minor retry logic cleanup + - gfs2: Make sure not to return short direct writes + - gfs2: No short reads or writes upon glock contention + - perf arm-spe: Fix addresses of synthesized SPE events + - ixgbe: ensure IPsec VF<->PF compatibility + - Revert "ibmvnic: Add ethtool private flag for driver-defined queue limits" + - tcp: fix F-RTO may not work correctly when receiving DSACK + - ASoC: Intel: soc-acpi: correct device endpoints for max98373 + - ASoC: wm8731: Disable the regulator when probing fails + - ext4: fix bug_on in start_this_handle during umount filesystem + - arch: xtensa: platforms: Fix deadlock in rs_close() + - ksmbd: increment reference count of parent fp + - ksmbd: set fixed sector size to FS_SECTOR_SIZE_INFORMATION + - bonding: do not discard lowest hash bit for non layer3+4 hashing + - x86: __memcpy_flushcache: fix wrong alignment if size > 2^32 + - cifs: destage any unwritten data to the server before calling + copychunk_write + - drivers: net: hippi: Fix deadlock in rr_close() + - powerpc/perf: Fix 32bit compile + - selftest/vm: verify mmap addr in mremap_test + - selftest/vm: verify remap destination address in mremap_test + - Revert "ACPI: processor: idle: fix lockup regression on 32-bit ThinkPad T40" + - zonefs: Fix management of open zones + - zonefs: Clear inode information flags on inode creation + - kasan: prevent cpu_quarantine corruption when CPU offline and cache shrink + occur at same time + - mtd: rawnand: qcom: fix memory corruption that causes panic + - netfilter: Update ip6_route_me_harder to consider L3 domain + - drm/i915: Check EDID for HDR static metadata when choosing blc + - drm/i915: Fix SEL_FETCH_PLANE_*(PIPE_B+) register addresses + - net: ethernet: stmmac: fix write to sgmii_adapter_base + - ACPI: processor: idle: Avoid falling back to C3 type C-states + - thermal: int340x: Fix attr.show callback prototype + - btrfs: fix leaked plug after failure syncing log on zoned filesystems + - ARM: dts: at91: sama7g5ek: enable pull-up on flexcom3 console lines + - ARM: dts: imx8mm-venice-gw{71xx,72xx,73xx}: fix OTG controller OC mode + - x86/cpu: Load microcode during restore_processor_state() + - perf symbol: Pass is_kallsyms to symbols__fixup_end() + - perf symbol: Update symbols__fixup_end() + - tty: n_gsm: fix restart handling via CLD command + - tty: n_gsm: fix decoupled mux resource + - tty: n_gsm: fix mux cleanup after unregister tty device + - tty: n_gsm: fix wrong signal octet encoding in convergence layer type 2 + - tty: n_gsm: fix malformed counter for out of frame data + - netfilter: nft_socket: only do sk lookups when indev is available + - tty: n_gsm: fix insufficient txframe size + - tty: n_gsm: fix wrong DLCI release order + - tty: n_gsm: fix missing explicit ldisc flush + - tty: n_gsm: fix wrong command retry handling + - tty: n_gsm: fix wrong command frame length field encoding + - tty: n_gsm: fix wrong signal octets encoding in MSC + - tty: n_gsm: fix missing tty wakeup in convergence layer type 2 + - tty: n_gsm: fix reset fifo race condition + - tty: n_gsm: fix incorrect UA handling + - tty: n_gsm: fix software flow control handling + - perf symbol: Remove arch__symbols__fixup_end() + - eeprom: at25: Use DMA safe buffers + - objtool: Fix code relocs vs weak symbols + - objtool: Fix type of reloc::addend + - powerpc/64: Add UADDR64 relocation support + - Linux 5.15.38 + + * Jammy update: v5.15.37 upstream stable release (LP: #1976135) + - floppy: disable FDRAWCMD by default + - [Config] updateconfigs for BLK_DEV_FD_RAWCMD + - bpf: Introduce composable reg, ret and arg types. + - bpf: Replace ARG_XXX_OR_NULL with ARG_XXX | PTR_MAYBE_NULL + - bpf: Replace RET_XXX_OR_NULL with RET_XXX | PTR_MAYBE_NULL + - bpf: Replace PTR_TO_XXX_OR_NULL with PTR_TO_XXX | PTR_MAYBE_NULL + - bpf: Introduce MEM_RDONLY flag + - bpf: Convert PTR_TO_MEM_OR_NULL to composable types. + - bpf: Make per_cpu_ptr return rdonly PTR_TO_MEM. + - bpf: Add MEM_RDONLY for helper args that are pointers to rdonly mem. + - bpf/selftests: Test PTR_TO_RDONLY_MEM + - bpf: Fix crash due to out of bounds access into reg2btf_ids. + - spi: cadence-quadspi: fix write completion support + - ARM: dts: socfpga: change qspi to "intel,socfpga-qspi" + - mm: kfence: fix objcgs vector allocation + - gup: Turn fault_in_pages_{readable,writeable} into + fault_in_{readable,writeable} + - iov_iter: Turn iov_iter_fault_in_readable into fault_in_iov_iter_readable + - iov_iter: Introduce fault_in_iov_iter_writeable + - gfs2: Add wrapper for iomap_file_buffered_write + - gfs2: Clean up function may_grant + - gfs2: Introduce flag for glock holder auto-demotion + - gfs2: Move the inode glock locking to gfs2_file_buffered_write + - gfs2: Eliminate ip->i_gh + - gfs2: Fix mmap + page fault deadlocks for buffered I/O + - iomap: Fix iomap_dio_rw return value for user copies + - iomap: Support partial direct I/O on user copy failures + - iomap: Add done_before argument to iomap_dio_rw + - gup: Introduce FOLL_NOFAULT flag to disable page faults + - iov_iter: Introduce nofault flag to disable page faults + - gfs2: Fix mmap + page fault deadlocks for direct I/O + - btrfs: fix deadlock due to page faults during direct IO reads and writes + - btrfs: fallback to blocking mode when doing async dio over multiple extents + - mm: gup: make fault_in_safe_writeable() use fixup_user_fault() + - selftests/bpf: Add test for reg2btf_ids out of bounds access + - Linux 5.15.37 + + * CVE-2022-1789 + - KVM: x86/mmu: fix NULL pointer dereference on guest INVPCID + + * Jammy update: v5.15.36 upstream stable release (LP: #1972905) + - block: simplify the block device syncing code + - xfs: return errors in xfs_fs_sync_fs + - dma-mapping: remove bogus test for pfn_valid from dma_map_resource + - arm64/mm: drop HAVE_ARCH_PFN_VALID + - etherdevice: Adjust ether_addr* prototypes to silence -Wstringop-overead + - mm: page_alloc: fix building error on -Werror=array-compare + - perf tools: Fix segfault accessing sample_id xyarray + - mm, kfence: support kmem_dump_obj() for KFENCE objects + - gfs2: assign rgrp glock before compute_bitstructs + - scsi: ufs: core: scsi_get_lba() error fix + - ALSA: usb-audio: Clear MIDI port active flag after draining + - ALSA: hda/realtek: Add quirk for Clevo NP70PNP + - ASoC: atmel: Remove system clock tree configuration for at91sam9g20ek + - ASoC: topology: Correct error handling in soc_tplg_dapm_widget_create() + - ASoC: rk817: Use devm_clk_get() in rk817_platform_probe + - ASoC: msm8916-wcd-digital: Check failure for devm_snd_soc_register_component + - ASoC: codecs: wcd934x: do not switch off SIDO Buck when codec is in use + - dmaengine: idxd: fix device cleanup on disable + - dmaengine: imx-sdma: Fix error checking in sdma_event_remap + - dmaengine: mediatek:Fix PM usage reference leak of + mtk_uart_apdma_alloc_chan_resources + - dmaengine: dw-edma: Fix unaligned 64bit access + - spi: spi-mtk-nor: initialize spi controller after resume + - esp: limit skb_page_frag_refill use to a single page + - spi: cadence-quadspi: fix incorrect supports_op() return value + - igc: Fix infinite loop in release_swfw_sync + - igc: Fix BUG: scheduling while atomic + - igc: Fix suspending when PTM is active + - ALSA: hda/hdmi: fix warning about PCM count when used with SOF + - rxrpc: Restore removed timer deletion + - net/smc: Fix sock leak when release after smc_shutdown() + - net/packet: fix packet_sock xmit return value checking + - ip6_gre: Avoid updating tunnel->tun_hlen in __gre6_xmit() + - ip6_gre: Fix skb_under_panic in __gre6_xmit() + - net: restore alpha order to Ethernet devices in config + - net/sched: cls_u32: fix possible leak in u32_init_knode() + - l3mdev: l3mdev_master_upper_ifindex_by_index_rcu should be using + netdev_master_upper_dev_get_rcu + - ipv6: make ip6_rt_gc_expire an atomic_t + - can: isotp: stop timeout monitoring when no first frame was sent + - net: dsa: hellcreek: Calculate checksums in tagger + - net: mscc: ocelot: fix broken IP multicast flooding + - netlink: reset network and mac headers in netlink_dump() + - drm/i915/display/psr: Unset enable_psr2_sel_fetch if other checks in + intel_psr2_config_valid() fails + - net: stmmac: Use readl_poll_timeout_atomic() in atomic state + - dmaengine: idxd: add RO check for wq max_batch_size write + - dmaengine: idxd: add RO check for wq max_transfer_size write + - dmaengine: idxd: skip clearing device context when device is read-only + - selftests: mlxsw: vxlan_flooding: Prevent flooding of unwanted packets + - arm64: mm: fix p?d_leaf() + - ARM: vexpress/spc: Avoid negative array index when !SMP + - reset: renesas: Check return value of reset_control_deassert() + - reset: tegra-bpmp: Restore Handle errors in BPMP response + - platform/x86: samsung-laptop: Fix an unsigned comparison which can never be + negative + - ALSA: usb-audio: Fix undefined behavior due to shift overflowing the + constant + - drm/msm/disp: check the return value of kzalloc() + - arm64: dts: imx: Fix imx8*-var-som touchscreen property sizes + - vxlan: fix error return code in vxlan_fdb_append + - cifs: Check the IOCB_DIRECT flag, not O_DIRECT + - mt76: Fix undefined behavior due to shift overflowing the constant + - brcmfmac: sdio: Fix undefined behavior due to shift overflowing the constant + - dpaa_eth: Fix missing of_node_put in dpaa_get_ts_info() + - drm/msm/mdp5: check the return of kzalloc() + - net: macb: Restart tx only if queue pointer is lagging + - scsi: iscsi: Release endpoint ID when its freed + - scsi: iscsi: Merge suspend fields + - scsi: iscsi: Fix NOP handling during conn recovery + - scsi: qedi: Fix failed disconnect handling + - stat: fix inconsistency between struct stat and struct compat_stat + - VFS: filename_create(): fix incorrect intent. + - nvme: add a quirk to disable namespace identifiers + - nvme-pci: disable namespace identifiers for the MAXIO MAP1002/1202 + - nvme-pci: disable namespace identifiers for Qemu controllers + - EDAC/synopsys: Read the error count from the correct register + - mm/memory-failure.c: skip huge_zero_page in memory_failure() + - memcg: sync flush only if periodic flush is delayed + - mm, hugetlb: allow for "high" userspace addresses + - oom_kill.c: futex: delay the OOM reaper to allow time for proper futex + cleanup + - mm/mmu_notifier.c: fix race in mmu_interval_notifier_remove() + - ata: pata_marvell: Check the 'bmdma_addr' beforing reading + - dma: at_xdmac: fix a missing check on list iterator + - dmaengine: imx-sdma: fix init of uart scripts + - net: atlantic: invert deep par in pm functions, preventing null derefs + - Input: omap4-keypad - fix pm_runtime_get_sync() error checking + - scsi: sr: Do not leak information in ioctl + - sched/pelt: Fix attach_entity_load_avg() corner case + - perf/core: Fix perf_mmap fail when CONFIG_PERF_USE_VMALLOC enabled + - drm/panel/raspberrypi-touchscreen: Avoid NULL deref if not initialised + - drm/panel/raspberrypi-touchscreen: Initialise the bridge in prepare + - KVM: PPC: Fix TCE handling for VFIO + - drm/vc4: Use pm_runtime_resume_and_get to fix pm_runtime_get_sync() usage + - powerpc/perf: Fix power9 event alternatives + - powerpc/perf: Fix power10 event alternatives + - perf script: Always allow field 'data_src' for auxtrace + - perf report: Set PERF_SAMPLE_DATA_SRC bit for Arm SPE event + - xtensa: patch_text: Fixup last cpu should be master + - xtensa: fix a7 clobbering in coprocessor context load/store + - openvswitch: fix OOB access in reserve_sfa_size() + - ASoC: soc-dapm: fix two incorrect uses of list iterator + - e1000e: Fix possible overflow in LTR decoding + - ARC: entry: fix syscall_trace_exit argument + - arm_pmu: Validate single/group leader events + - KVM: x86/pmu: Update AMD PMC sample period to fix guest NMI-watchdog + - KVM: x86: Pend KVM_REQ_APICV_UPDATE during vCPU creation to fix a race + - KVM: nVMX: Defer APICv updates while L2 is active until L1 is active + - KVM: SVM: Flush when freeing encrypted pages even on SME_COHERENT CPUs + - netfilter: conntrack: convert to refcount_t api + - netfilter: conntrack: avoid useless indirection during conntrack destruction + - ext4: fix fallocate to use file_modified to update permissions consistently + - ext4: fix symlink file size not match to file content + - ext4: fix use-after-free in ext4_search_dir + - ext4, doc: fix incorrect h_reserved size + - ext4: fix overhead calculation to account for the reserved gdt blocks + - ext4: force overhead calculation if the s_overhead_cluster makes no sense + - netfilter: nft_ct: fix use after free when attaching zone template + - jbd2: fix a potential race while discarding reserved buffers after an abort + - spi: atmel-quadspi: Fix the buswidth adjustment between spi-mem and + controller + - block/compat_ioctl: fix range check in BLKGETSIZE + - arm64: dts: qcom: add IPA qcom,qmp property + - Linux 5.15.36 + + * Aquantia GbE LAN driver causes UBSAN error during kernel boot + (LP: #1958770) // Jammy update: v5.15.36 upstream stable release + (LP: #1972905) + - net: atlantic: Avoid out-of-bounds indexing + + -- Stefan Bader Wed, 22 Jun 2022 14:42:28 +0200 + linux (5.15.0-40.43) jammy; urgency=medium * jammy/linux: 5.15.0-40.43 -proposed tracker (LP: #1978610) diff -u linux-5.15.0/debian.master/config/annotations linux-5.15.0/debian.master/config/annotations --- linux-5.15.0/debian.master/config/annotations +++ linux-5.15.0/debian.master/config/annotations @@ -4785,7 +4785,8 @@ CONFIG_INTEL_VSC_CSI policy<{'amd64': 'm'}> CONFIG_INTEL_VSC_PSE policy<{'amd64': 'm', 'arm64': 'n', 'armhf': 'n', 'ppc64el': 'n', 's390x': 'n'}> CONFIG_INTEL_MEI_VSC policy<{'amd64': 'm'}> -CONFIG_VMWARE_VMCI policy<{'amd64': 'm'}> +CONFIG_VMWARE_VMCI policy<{'amd64': 'm', 'arm64': 'm'}> +CONFIG_VMWARE_VMCI note CONFIG_ECHO policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm', 's390x': 'n'}> CONFIG_CXL policy<{'ppc64el': 'm'}> CONFIG_OCXL policy<{'ppc64el': 'm'}> @@ -13182,7 +13183,8 @@ CONFIG_VSOCKETS policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm', 's390x': 'm'}> CONFIG_VSOCKETS_DIAG policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm', 's390x': 'm'}> CONFIG_VSOCKETS_LOOPBACK policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm', 's390x': 'm'}> -CONFIG_VMWARE_VMCI_VSOCKETS policy<{'amd64': 'm'}> +CONFIG_VMWARE_VMCI_VSOCKETS policy<{'amd64': 'm', 'arm64': 'm'}> +CONFIG_VMWARE_VMCI_VSOCKETS note CONFIG_VIRTIO_VSOCKETS policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm', 's390x': 'm'}> CONFIG_HYPERV_VSOCKETS policy<{'amd64': 'm', 'arm64': 'm'}> diff -u linux-5.15.0/debian.master/config/config.common.ubuntu linux-5.15.0/debian.master/config/config.common.ubuntu --- linux-5.15.0/debian.master/config/config.common.ubuntu +++ linux-5.15.0/debian.master/config/config.common.ubuntu @@ -1187,6 +1187,7 @@ CONFIG_BLK_DEV_DM_BUILTIN=y CONFIG_BLK_DEV_DRBD=m CONFIG_BLK_DEV_FD=m +# CONFIG_BLK_DEV_FD_RAWCMD is not set CONFIG_BLK_DEV_INITRD=y CONFIG_BLK_DEV_INTEGRITY=y CONFIG_BLK_DEV_INTEGRITY_T10=y diff -u linux-5.15.0/debian.master/reconstruct linux-5.15.0/debian.master/reconstruct --- linux-5.15.0/debian.master/reconstruct +++ linux-5.15.0/debian.master/reconstruct @@ -7,6 +7,8 @@ rm -f 'drivers/platform/x86/i2c-multi-instantiate.c' rm -f 'drivers/staging/most/dim2/sysfs.c' rm -f 'tools/build/feature/test-libpython-version.c' +rm -f 'tools/perf/arch/arm64/util/machine.c' +rm -f 'tools/perf/arch/powerpc/util/machine.c' rm -f 'tools/perf/util/bpf_skel/bperf.h' chmod +x 'debian/cloud-tools/hv_get_dhcp_info' chmod +x 'debian/cloud-tools/hv_get_dns_info' diff -u linux-5.15.0/debian.master/tracking-bug linux-5.15.0/debian.master/tracking-bug --- linux-5.15.0/debian.master/tracking-bug +++ linux-5.15.0/debian.master/tracking-bug @@ -1 +1 @@ -1978610 2022.05.30-2 +1979448 2022.06.20-1 diff -u linux-5.15.0/debian.master/upstream-stable linux-5.15.0/debian.master/upstream-stable --- linux-5.15.0/debian.master/upstream-stable +++ linux-5.15.0/debian.master/upstream-stable @@ -3 +3 @@ - linux-5.15.y = v5.15.35 + linux-5.15.y = v5.15.39 diff -u linux-5.15.0/debian/changelog linux-5.15.0/debian/changelog --- linux-5.15.0/debian/changelog +++ linux-5.15.0/debian/changelog @@ -1,3 +1,565 @@ +linux (5.15.0-41.44) jammy; urgency=medium + + * jammy/linux: 5.15.0-41.44 -proposed tracker (LP: #1979448) + + * Fix can't boot up after change to vmd (LP: #1976587) + - PCI: vmd: Assign VMD IRQ domain before enumeration + - PCI: vmd: Revert 2565e5b69c44 ("PCI: vmd: Do not disable MSI-X remapping if + interrupt remapping is enabled by IOMMU.") + + * [SRU][Jammy/OEM-5.17][PATCH 0/1] Fix calltrace in mac80211 (LP: #1978297) + - mac80211: fix struct ieee80211_tx_info size + + * [SRU][Jammy][PATCH 0/1] Fix amd display corruption on s2idle resume + (LP: #1978244) + - drm/amd/display: Don't reinitialize DMCUB on s0ix resume + + * pl2303 serial adapter not recognized (LP: #1967493) + - USB: serial: pl2303: fix type detection for odd device + + * Remove SAUCE patches from test_vxlan_under_vrf.sh in net of + ubuntu_kernel_selftests (LP: #1975691) + - Revert "UBUNTU: SAUCE: selftests: net: Don't fail test_vxlan_under_vrf on + xfail" + - Revert "UBUNTU: SAUCE: selftests: net: Make test for VXLAN underlay in non- + default VRF an expected failure" + + * Fix hp_wmi_read_int() reporting error (0x05) (LP: #1979051) + - platform/x86: hp-wmi: Fix hp_wmi_read_int() reporting error (0x05) + + * Request to back port vmci patches to Ubuntu kernel (LP: #1978145) + - VMCI: dma dg: whitespace formatting change for vmci register defines + - VMCI: dma dg: add MMIO access to registers + - VMCI: dma dg: detect DMA datagram capability + - VMCI: dma dg: set OS page size + - VMCI: dma dg: register dummy IRQ handlers for DMA datagrams + - VMCI: dma dg: allocate send and receive buffers for DMA datagrams + - VMCI: dma dg: add support for DMA datagrams sends + - VMCI: dma dg: add support for DMA datagrams receive + - VMCI: Fix some error handling paths in vmci_guest_probe_device() + - VMCI: Release notification_bitmap in error path + - VMCI: Check exclusive_vectors when freeing interrupt 1 + - VMCI: Add support for ARM64 + - [Config] Update policies for VMWARE_VMCI and VMWARE_VMCI_VSOCKETS + + * [UBUNTU 20.04] rcu stalls with many storage key guests (LP: #1975582) + - s390/gmap: voluntarily schedule during key setting + - s390/mm: use non-quiescing sske for KVM switch to keyed guest + + * [SRU][OEM-5.14/OEM-5.17/Jammy][PATCH 0/1] Fix i915 calltrace on new ADL BIOS + (LP: #1976214) + - drm/i915: update new TMDS clock setting defined by VBT + + * Revert PPC get_user workaround (LP: #1976248) + - powerpc: Export mmu_feature_keys[] as non-GPL + + * Jammy update: v5.15.39 upstream stable release (LP: #1978240) + - MIPS: Fix CP0 counter erratum detection for R4k CPUs + - parisc: Merge model and model name into one line in /proc/cpuinfo + - ALSA: hda/realtek: Add quirk for Yoga Duet 7 13ITL6 speakers + - ALSA: fireworks: fix wrong return count shorter than expected by 4 bytes + - mmc: sdhci-msm: Reset GCC_SDCC_BCR register for SDHC + - mmc: sunxi-mmc: Fix DMA descriptors allocated above 32 bits + - mmc: core: Set HS clock speed before sending HS CMD13 + - gpiolib: of: fix bounds check for 'gpio-reserved-ranges' + - x86/fpu: Prevent FPU state corruption + - KVM: x86/svm: Account for family 17h event renumberings in + amd_pmc_perf_hw_id + - iommu/vt-d: Calculate mask for non-aligned flushes + - iommu/arm-smmu-v3: Fix size calculation in arm_smmu_mm_invalidate_range() + - drm/amd/display: Avoid reading audio pattern past AUDIO_CHANNELS_COUNT + - drm/amdgpu: do not use passthrough mode in Xen dom0 + - RISC-V: relocate DTB if it's outside memory region + - Revert "SUNRPC: attempt AF_LOCAL connect on setup" + - timekeeping: Mark NMI safe time accessors as notrace + - firewire: fix potential uaf in outbound_phy_packet_callback() + - firewire: remove check of list iterator against head past the loop body + - firewire: core: extend card->lock in fw_core_handle_bus_reset + - net: stmmac: disable Split Header (SPH) for Intel platforms + - genirq: Synchronize interrupt thread startup + - ASoC: da7219: Fix change notifications for tone generator frequency + - ASoC: wm8958: Fix change notifications for DSP controls + - ASoC: meson: Fix event generation for AUI ACODEC mux + - ASoC: meson: Fix event generation for G12A tohdmi mux + - ASoC: meson: Fix event generation for AUI CODEC mux + - s390/dasd: fix data corruption for ESE devices + - s390/dasd: prevent double format of tracks for ESE devices + - s390/dasd: Fix read for ESE with blksize < 4k + - s390/dasd: Fix read inconsistency for ESE DASD devices + - can: grcan: grcan_close(): fix deadlock + - can: isotp: remove re-binding of bound socket + - can: grcan: use ofdev->dev when allocating DMA memory + - can: grcan: grcan_probe(): fix broken system id check for errata workaround + needs + - can: grcan: only use the NAPI poll budget for RX + - nfc: replace improper check device_is_registered() in netlink related + functions + - nfc: nfcmrvl: main: reorder destructive operations in + nfcmrvl_nci_unregister_dev to avoid bugs + - NFC: netlink: fix sleep in atomic bug when firmware download timeout + - gpio: visconti: Fix fwnode of GPIO IRQ + - gpio: pca953x: fix irq_stat not updated when irq is disabled (irq_mask not + set) + - hwmon: (adt7470) Fix warning on module removal + - hwmon: (pmbus) disable PEC if not enabled + - ASoC: dmaengine: Restore NULL prepare_slave_config() callback + - ASoC: soc-ops: fix error handling + - iommu/vt-d: Drop stop marker messages + - iommu/dart: check return value after calling platform_get_resource() + - net/mlx5e: Fix trust state reset in reload + - net/mlx5e: Don't match double-vlan packets if cvlan is not set + - net/mlx5e: CT: Fix queued up restore put() executing after relevant ft + release + - net/mlx5e: Fix the calling of update_buffer_lossy() API + - net/mlx5: Avoid double clear or set of sync reset requested + - net/mlx5: Fix deadlock in sync reset flow + - selftests/seccomp: Don't call read() on TTY from background pgrp + - SUNRPC release the transport of a relocated task with an assigned transport + - RDMA/siw: Fix a condition race issue in MPA request processing + - RDMA/irdma: Flush iWARP QP if modified to ERR from RTR state + - RDMA/irdma: Reduce iWARP QP destroy time + - RDMA/irdma: Fix possible crash due to NULL netdev in notifier + - NFSv4: Don't invalidate inode attributes on delegation return + - net: ethernet: mediatek: add missing of_node_put() in mtk_sgmii_init() + - net: dsa: mt7530: add missing of_node_put() in mt7530_setup() + - net: stmmac: dwmac-sun8i: add missing of_node_put() in + sun8i_dwmac_register_mdio_mux() + - net: mdio: Fix ENOMEM return value in BCM6368 mux bus controller + - net: cpsw: add missing of_node_put() in cpsw_probe_dt() + - net: igmp: respect RCU rules in ip_mc_source() and ip_mc_msfilter() + - net: emaclite: Add error handling for of_address_to_resource() + - selftests/net: so_txtime: fix parsing of start time stamp on 32 bit systems + - selftests/net: so_txtime: usage(): fix documentation of default clock + - drm/msm/dp: remove fail safe mode related code + - btrfs: do not BUG_ON() on failure to update inode when setting xattr + - hinic: fix bug of wq out of bound access + - mld: respect RCU rules in ip6_mc_source() and ip6_mc_msfilter() + - rxrpc: Enable IPv6 checksums on transport socket + - selftests: mirror_gre_bridge_1q: Avoid changing PVID while interface is + operational + - bnxt_en: Fix possible bnxt_open() failure caused by wrong RFS flag + - bnxt_en: Fix unnecessary dropping of RX packets + - selftests: ocelot: tc_flower_chains: specify conform-exceed action for + policer + - smsc911x: allow using IRQ0 + - btrfs: force v2 space cache usage for subpage mount + - btrfs: always log symlinks in full mode + - gpio: mvebu: drop pwm base assignment + - kvm: x86/cpuid: Only provide CPUID leaf 0xA if host has architectural PMU + - net/mlx5: Fix slab-out-of-bounds while reading resource dump menu + - net/mlx5e: Lag, Fix use-after-free in fib event handler + - net/mlx5e: Lag, Fix fib_info pointer assignment + - net/mlx5e: Lag, Don't skip fib events on current dst + - iommu/dart: Add missing module owner to ops structure + - kvm: selftests: do not use bitfields larger than 32-bits for PTEs + - KVM: selftests: Silence compiler warning in the kvm_page_table_test + - x86/kvm: Preserve BSP MSR_KVM_POLL_CONTROL across suspend/resume + - KVM: x86: Do not change ICR on write to APIC_SELF_IPI + - KVM: x86/mmu: avoid NULL-pointer dereference on page freeing bugs + - KVM: LAPIC: Enable timer posted-interrupt only when mwait/hlt is advertised + - selftest/vm: verify mmap addr in mremap_test + - selftest/vm: verify remap destination address in mremap_test + - Revert "parisc: Mark sched_clock unstable only if clocks are not + syncronized" + - rcu: Fix callbacks processing time limit retaining cond_resched() + - rcu: Apply callbacks processing time limit only on softirq + - PCI: pci-bridge-emul: Add description for class_revision field + - PCI: pci-bridge-emul: Add definitions for missing capabilities registers + - PCI: aardvark: Add support for DEVCAP2, DEVCTL2, LNKCAP2 and LNKCTL2 + registers on emulated bridge + - PCI: aardvark: Clear all MSIs at setup + - PCI: aardvark: Comment actions in driver remove method + - PCI: aardvark: Disable bus mastering when unbinding driver + - PCI: aardvark: Mask all interrupts when unbinding driver + - PCI: aardvark: Fix memory leak in driver unbind + - PCI: aardvark: Assert PERST# when unbinding driver + - PCI: aardvark: Disable link training when unbinding driver + - PCI: aardvark: Disable common PHY when unbinding driver + - PCI: aardvark: Replace custom PCIE_CORE_INT_* macros with PCI_INTERRUPT_* + - PCI: aardvark: Check return value of generic_handle_domain_irq() when + processing INTx IRQ + - PCI: aardvark: Make MSI irq_chip structures static driver structures + - PCI: aardvark: Make msi_domain_info structure a static driver structure + - PCI: aardvark: Use dev_fwnode() instead of of_node_to_fwnode(dev->of_node) + - PCI: aardvark: Refactor unmasking summary MSI interrupt + - PCI: aardvark: Add support for masking MSI interrupts + - PCI: aardvark: Fix setting MSI address + - PCI: aardvark: Enable MSI-X support + - PCI: aardvark: Add support for ERR interrupt on emulated bridge + - PCI: aardvark: Optimize writing PCI_EXP_RTCTL_PMEIE and PCI_EXP_RTSTA_PME on + emulated bridge + - PCI: aardvark: Add support for PME interrupts + - PCI: aardvark: Fix support for PME requester on emulated bridge + - PCI: aardvark: Use separate INTA interrupt for emulated root bridge + - PCI: aardvark: Remove irq_mask_ack() callback for INTx interrupts + - PCI: aardvark: Don't mask irq when mapping + - PCI: aardvark: Drop __maybe_unused from advk_pcie_disable_phy() + - PCI: aardvark: Update comment about link going down after link-up + - Linux 5.15.39 + + * Jammy update: v5.15.38 upstream stable release (LP: #1978234) + - usb: mtu3: fix USB 3.0 dual-role-switch from device to host + - USB: quirks: add a Realtek card reader + - USB: quirks: add STRING quirk for VCOM device + - USB: serial: whiteheat: fix heap overflow in WHITEHEAT_GET_DTR_RTS + - USB: serial: cp210x: add PIDs for Kamstrup USB Meter Reader + - USB: serial: option: add support for Cinterion MV32-WA/MV32-WB + - USB: serial: option: add Telit 0x1057, 0x1058, 0x1075 compositions + - usb: xhci: tegra:Fix PM usage reference leak of + tegra_xusb_unpowergate_partitions + - xhci: Enable runtime PM on second Alderlake controller + - xhci: stop polling roothubs after shutdown + - xhci: increase usb U3 -> U0 link resume timeout from 100ms to 500ms + - iio: dac: ad5592r: Fix the missing return value. + - iio: dac: ad5446: Fix read_raw not returning set value + - iio: magnetometer: ak8975: Fix the error handling in ak8975_power_on() + - iio: imu: inv_icm42600: Fix I2C init possible nack + - usb: misc: fix improper handling of refcount in uss720_probe() + - usb: core: Don't hold the device lock while sleeping in do_proc_control() + - usb: typec: ucsi: Fix reuse of completion structure + - usb: typec: ucsi: Fix role swapping + - usb: gadget: uvc: Fix crash when encoding data for usb request + - usb: gadget: configfs: clear deactivation flag in + configfs_composite_unbind() + - usb: dwc3: Try usb-role-switch first in dwc3_drd_init + - usb: dwc3: core: Fix tx/rx threshold settings + - usb: dwc3: core: Only handle soft-reset in DCTL + - usb: dwc3: gadget: Return proper request status + - usb: dwc3: pci: add support for the Intel Meteor Lake-P + - usb: cdns3: Fix issue for clear halt endpoint + - usb: phy: generic: Get the vbus supply + - serial: imx: fix overrun interrupts in DMA mode + - serial: amba-pl011: do not time out prematurely when draining tx fifo + - serial: 8250: Also set sticky MCR bits in console restoration + - serial: 8250: Correct the clock for EndRun PTP/1588 PCIe device + - arch_topology: Do not set llc_sibling if llc_id is invalid + - ceph: fix possible NULL pointer dereference for req->r_session + - bus: mhi: host: pci_generic: Add missing poweroff() PM callback + - bus: mhi: host: pci_generic: Flush recovery worker during freeze + - arm64: dts: imx8mm-venice: fix spi2 pin configuration + - pinctrl: samsung: fix missing GPIOLIB on ARM64 Exynos config + - hex2bin: make the function hex_to_bin constant-time + - hex2bin: fix access beyond string end + - riscv: patch_text: Fixup last cpu should be master + - x86/pci/xen: Disable PCI/MSI[-X] masking for XEN_HVM guests + - iocost: don't reset the inuse weight of under-weighted debtors + - virtio_net: fix wrong buf address calculation when using xdp + - cpufreq: qcom-hw: fix the race between LMH worker and cpuhp + - cpufreq: qcom-cpufreq-hw: Fix throttle frequency value on EPSS platforms + - video: fbdev: udlfb: properly check endpoint type + - arm64: dts: meson: remove CPU opps below 1GHz for G12B boards + - arm64: dts: meson: remove CPU opps below 1GHz for SM1 boards + - iio:imu:bmi160: disable regulator in error path + - mtd: rawnand: fix ecc parameters for mt7622 + - xsk: Fix l2fwd for copy mode + busy poll combo + - arm64: dts: imx8qm: Correct SCU clock controller's compatible property + - USB: Fix xhci event ring dequeue pointer ERDP update issue + - ARM: dts: imx6qdl-apalis: Fix sgtl5000 detection issue + - arm64: dts: imx8mn: Fix SAI nodes + - arm64: dts: meson-sm1-bananapi-m5: fix wrong GPIO pin labeling for CON1 + - phy: samsung: Fix missing of_node_put() in exynos_sata_phy_probe + - phy: samsung: exynos5250-sata: fix missing device put in probe error paths + - ARM: OMAP2+: Fix refcount leak in omap_gic_of_init + - bus: ti-sysc: Make omap3 gpt12 quirk handling SoC specific + - ARM: dts: dra7: Fix suspend warning for vpe powerdomain + - phy: ti: omap-usb2: Fix error handling in omap_usb2_enable_clocks + - ARM: dts: at91: Map MCLK for wm8731 on at91sam9g20ek + - ARM: dts: at91: sama5d4_xplained: fix pinctrl phandle name + - ARM: dts: at91: fix pinctrl phandles + - phy: mapphone-mdm6600: Fix PM error handling in phy_mdm6600_probe + - phy: ti: Add missing pm_runtime_disable() in serdes_am654_probe + - interconnect: qcom: sdx55: Drop IP0 interconnects + - ARM: dts: Fix mmc order for omap3-gta04 + - ARM: dts: am3517-evm: Fix misc pinmuxing + - ARM: dts: logicpd-som-lv: Fix wrong pinmuxing on OMAP35 + - ipvs: correctly print the memory size of ip_vs_conn_tab + - phy: amlogic: fix error path in phy_g12a_usb3_pcie_probe() + - pinctrl: mediatek: moore: Fix build error + - mtd: rawnand: Fix return value check of wait_for_completion_timeout + - mtd: fix 'part' field data corruption in mtd_info + - pinctrl: stm32: Do not call stm32_gpio_get() for edge triggered IRQs in EOI + - memory: renesas-rpc-if: Fix HF/OSPI data transfer in Manual Mode + - net: dsa: Add missing of_node_put() in dsa_port_link_register_of + - netfilter: nft_set_rbtree: overlap detection with element re-addition after + deletion + - bpf, lwt: Fix crash when using bpf_skb_set_tunnel_key() from bpf_xmit lwt + hook + - pinctrl: rockchip: fix RK3308 pinmux bits + - tcp: md5: incorrect tcp_header_len for incoming connections + - pinctrl: stm32: Keep pinctrl block clock enabled when LEVEL IRQ requested + - tcp: ensure to use the most recently sent skb when filling the rate sample + - wireguard: device: check for metadata_dst with skb_valid_dst() + - sctp: check asoc strreset_chunk in sctp_generate_reconf_event + - ARM: dts: imx6ull-colibri: fix vqmmc regulator + - arm64: dts: imx8mn-ddr4-evk: Describe the 32.768 kHz PMIC clock + - pinctrl: pistachio: fix use of irq_of_parse_and_map() + - cpufreq: fix memory leak in sun50i_cpufreq_nvmem_probe + - net: hns3: clear inited state and stop client after failed to register + netdev + - net: hns3: modify the return code of hclge_get_ring_chain_from_mbx + - net: hns3: add validity check for message data length + - net: hns3: add return value for mailbox handling in PF + - net/smc: sync err code when tcp connection was refused + - ip_gre: Make o_seqno start from 0 in native mode + - ip6_gre: Make o_seqno start from 0 in native mode + - ip_gre, ip6_gre: Fix race condition on o_seqno in collect_md mode + - tcp: fix potential xmit stalls caused by TCP_NOTSENT_LOWAT + - tcp: make sure treq->af_specific is initialized + - bus: sunxi-rsb: Fix the return value of sunxi_rsb_device_create() + - clk: sunxi: sun9i-mmc: check return value after calling + platform_get_resource() + - cpufreq: qcom-cpufreq-hw: Clear dcvs interrupts + - net: bcmgenet: hide status block before TX timestamping + - net: phy: marvell10g: fix return value on error + - net: dsa: mv88e6xxx: Fix port_hidden_wait to account for port_base_addr + - drm/sun4i: Remove obsolete references to PHYS_OFFSET + - net: dsa: lantiq_gswip: Don't set GSWIP_MII_CFG_RMII_CLK + - io_uring: check reserved fields for send/sendmsg + - io_uring: check reserved fields for recv/recvmsg + - netfilter: conntrack: fix udp offload timeout sysctl + - drm/amdkfd: Fix GWS queue count + - drm/amd/display: Fix memory leak in dcn21_clock_source_create + - tls: Skip tls_append_frag on zero copy size + - bnx2x: fix napi API usage sequence + - net: fec: add missing of_node_put() in fec_enet_init_stop_mode() + - gfs2: Prevent endless loops in gfs2_file_buffered_write + - gfs2: Minor retry logic cleanup + - gfs2: Make sure not to return short direct writes + - gfs2: No short reads or writes upon glock contention + - perf arm-spe: Fix addresses of synthesized SPE events + - ixgbe: ensure IPsec VF<->PF compatibility + - Revert "ibmvnic: Add ethtool private flag for driver-defined queue limits" + - tcp: fix F-RTO may not work correctly when receiving DSACK + - ASoC: Intel: soc-acpi: correct device endpoints for max98373 + - ASoC: wm8731: Disable the regulator when probing fails + - ext4: fix bug_on in start_this_handle during umount filesystem + - arch: xtensa: platforms: Fix deadlock in rs_close() + - ksmbd: increment reference count of parent fp + - ksmbd: set fixed sector size to FS_SECTOR_SIZE_INFORMATION + - bonding: do not discard lowest hash bit for non layer3+4 hashing + - x86: __memcpy_flushcache: fix wrong alignment if size > 2^32 + - cifs: destage any unwritten data to the server before calling + copychunk_write + - drivers: net: hippi: Fix deadlock in rr_close() + - powerpc/perf: Fix 32bit compile + - selftest/vm: verify mmap addr in mremap_test + - selftest/vm: verify remap destination address in mremap_test + - Revert "ACPI: processor: idle: fix lockup regression on 32-bit ThinkPad T40" + - zonefs: Fix management of open zones + - zonefs: Clear inode information flags on inode creation + - kasan: prevent cpu_quarantine corruption when CPU offline and cache shrink + occur at same time + - mtd: rawnand: qcom: fix memory corruption that causes panic + - netfilter: Update ip6_route_me_harder to consider L3 domain + - drm/i915: Check EDID for HDR static metadata when choosing blc + - drm/i915: Fix SEL_FETCH_PLANE_*(PIPE_B+) register addresses + - net: ethernet: stmmac: fix write to sgmii_adapter_base + - ACPI: processor: idle: Avoid falling back to C3 type C-states + - thermal: int340x: Fix attr.show callback prototype + - btrfs: fix leaked plug after failure syncing log on zoned filesystems + - ARM: dts: at91: sama7g5ek: enable pull-up on flexcom3 console lines + - ARM: dts: imx8mm-venice-gw{71xx,72xx,73xx}: fix OTG controller OC mode + - x86/cpu: Load microcode during restore_processor_state() + - perf symbol: Pass is_kallsyms to symbols__fixup_end() + - perf symbol: Update symbols__fixup_end() + - tty: n_gsm: fix restart handling via CLD command + - tty: n_gsm: fix decoupled mux resource + - tty: n_gsm: fix mux cleanup after unregister tty device + - tty: n_gsm: fix wrong signal octet encoding in convergence layer type 2 + - tty: n_gsm: fix malformed counter for out of frame data + - netfilter: nft_socket: only do sk lookups when indev is available + - tty: n_gsm: fix insufficient txframe size + - tty: n_gsm: fix wrong DLCI release order + - tty: n_gsm: fix missing explicit ldisc flush + - tty: n_gsm: fix wrong command retry handling + - tty: n_gsm: fix wrong command frame length field encoding + - tty: n_gsm: fix wrong signal octets encoding in MSC + - tty: n_gsm: fix missing tty wakeup in convergence layer type 2 + - tty: n_gsm: fix reset fifo race condition + - tty: n_gsm: fix incorrect UA handling + - tty: n_gsm: fix software flow control handling + - perf symbol: Remove arch__symbols__fixup_end() + - eeprom: at25: Use DMA safe buffers + - objtool: Fix code relocs vs weak symbols + - objtool: Fix type of reloc::addend + - powerpc/64: Add UADDR64 relocation support + - Linux 5.15.38 + + * Jammy update: v5.15.37 upstream stable release (LP: #1976135) + - floppy: disable FDRAWCMD by default + - [Config] updateconfigs for BLK_DEV_FD_RAWCMD + - bpf: Introduce composable reg, ret and arg types. + - bpf: Replace ARG_XXX_OR_NULL with ARG_XXX | PTR_MAYBE_NULL + - bpf: Replace RET_XXX_OR_NULL with RET_XXX | PTR_MAYBE_NULL + - bpf: Replace PTR_TO_XXX_OR_NULL with PTR_TO_XXX | PTR_MAYBE_NULL + - bpf: Introduce MEM_RDONLY flag + - bpf: Convert PTR_TO_MEM_OR_NULL to composable types. + - bpf: Make per_cpu_ptr return rdonly PTR_TO_MEM. + - bpf: Add MEM_RDONLY for helper args that are pointers to rdonly mem. + - bpf/selftests: Test PTR_TO_RDONLY_MEM + - bpf: Fix crash due to out of bounds access into reg2btf_ids. + - spi: cadence-quadspi: fix write completion support + - ARM: dts: socfpga: change qspi to "intel,socfpga-qspi" + - mm: kfence: fix objcgs vector allocation + - gup: Turn fault_in_pages_{readable,writeable} into + fault_in_{readable,writeable} + - iov_iter: Turn iov_iter_fault_in_readable into fault_in_iov_iter_readable + - iov_iter: Introduce fault_in_iov_iter_writeable + - gfs2: Add wrapper for iomap_file_buffered_write + - gfs2: Clean up function may_grant + - gfs2: Introduce flag for glock holder auto-demotion + - gfs2: Move the inode glock locking to gfs2_file_buffered_write + - gfs2: Eliminate ip->i_gh + - gfs2: Fix mmap + page fault deadlocks for buffered I/O + - iomap: Fix iomap_dio_rw return value for user copies + - iomap: Support partial direct I/O on user copy failures + - iomap: Add done_before argument to iomap_dio_rw + - gup: Introduce FOLL_NOFAULT flag to disable page faults + - iov_iter: Introduce nofault flag to disable page faults + - gfs2: Fix mmap + page fault deadlocks for direct I/O + - btrfs: fix deadlock due to page faults during direct IO reads and writes + - btrfs: fallback to blocking mode when doing async dio over multiple extents + - mm: gup: make fault_in_safe_writeable() use fixup_user_fault() + - selftests/bpf: Add test for reg2btf_ids out of bounds access + - Linux 5.15.37 + + * CVE-2022-1789 + - KVM: x86/mmu: fix NULL pointer dereference on guest INVPCID + + * Jammy update: v5.15.36 upstream stable release (LP: #1972905) + - block: simplify the block device syncing code + - xfs: return errors in xfs_fs_sync_fs + - dma-mapping: remove bogus test for pfn_valid from dma_map_resource + - arm64/mm: drop HAVE_ARCH_PFN_VALID + - etherdevice: Adjust ether_addr* prototypes to silence -Wstringop-overead + - mm: page_alloc: fix building error on -Werror=array-compare + - perf tools: Fix segfault accessing sample_id xyarray + - mm, kfence: support kmem_dump_obj() for KFENCE objects + - gfs2: assign rgrp glock before compute_bitstructs + - scsi: ufs: core: scsi_get_lba() error fix + - ALSA: usb-audio: Clear MIDI port active flag after draining + - ALSA: hda/realtek: Add quirk for Clevo NP70PNP + - ASoC: atmel: Remove system clock tree configuration for at91sam9g20ek + - ASoC: topology: Correct error handling in soc_tplg_dapm_widget_create() + - ASoC: rk817: Use devm_clk_get() in rk817_platform_probe + - ASoC: msm8916-wcd-digital: Check failure for devm_snd_soc_register_component + - ASoC: codecs: wcd934x: do not switch off SIDO Buck when codec is in use + - dmaengine: idxd: fix device cleanup on disable + - dmaengine: imx-sdma: Fix error checking in sdma_event_remap + - dmaengine: mediatek:Fix PM usage reference leak of + mtk_uart_apdma_alloc_chan_resources + - dmaengine: dw-edma: Fix unaligned 64bit access + - spi: spi-mtk-nor: initialize spi controller after resume + - esp: limit skb_page_frag_refill use to a single page + - spi: cadence-quadspi: fix incorrect supports_op() return value + - igc: Fix infinite loop in release_swfw_sync + - igc: Fix BUG: scheduling while atomic + - igc: Fix suspending when PTM is active + - ALSA: hda/hdmi: fix warning about PCM count when used with SOF + - rxrpc: Restore removed timer deletion + - net/smc: Fix sock leak when release after smc_shutdown() + - net/packet: fix packet_sock xmit return value checking + - ip6_gre: Avoid updating tunnel->tun_hlen in __gre6_xmit() + - ip6_gre: Fix skb_under_panic in __gre6_xmit() + - net: restore alpha order to Ethernet devices in config + - net/sched: cls_u32: fix possible leak in u32_init_knode() + - l3mdev: l3mdev_master_upper_ifindex_by_index_rcu should be using + netdev_master_upper_dev_get_rcu + - ipv6: make ip6_rt_gc_expire an atomic_t + - can: isotp: stop timeout monitoring when no first frame was sent + - net: dsa: hellcreek: Calculate checksums in tagger + - net: mscc: ocelot: fix broken IP multicast flooding + - netlink: reset network and mac headers in netlink_dump() + - drm/i915/display/psr: Unset enable_psr2_sel_fetch if other checks in + intel_psr2_config_valid() fails + - net: stmmac: Use readl_poll_timeout_atomic() in atomic state + - dmaengine: idxd: add RO check for wq max_batch_size write + - dmaengine: idxd: add RO check for wq max_transfer_size write + - dmaengine: idxd: skip clearing device context when device is read-only + - selftests: mlxsw: vxlan_flooding: Prevent flooding of unwanted packets + - arm64: mm: fix p?d_leaf() + - ARM: vexpress/spc: Avoid negative array index when !SMP + - reset: renesas: Check return value of reset_control_deassert() + - reset: tegra-bpmp: Restore Handle errors in BPMP response + - platform/x86: samsung-laptop: Fix an unsigned comparison which can never be + negative + - ALSA: usb-audio: Fix undefined behavior due to shift overflowing the + constant + - drm/msm/disp: check the return value of kzalloc() + - arm64: dts: imx: Fix imx8*-var-som touchscreen property sizes + - vxlan: fix error return code in vxlan_fdb_append + - cifs: Check the IOCB_DIRECT flag, not O_DIRECT + - mt76: Fix undefined behavior due to shift overflowing the constant + - brcmfmac: sdio: Fix undefined behavior due to shift overflowing the constant + - dpaa_eth: Fix missing of_node_put in dpaa_get_ts_info() + - drm/msm/mdp5: check the return of kzalloc() + - net: macb: Restart tx only if queue pointer is lagging + - scsi: iscsi: Release endpoint ID when its freed + - scsi: iscsi: Merge suspend fields + - scsi: iscsi: Fix NOP handling during conn recovery + - scsi: qedi: Fix failed disconnect handling + - stat: fix inconsistency between struct stat and struct compat_stat + - VFS: filename_create(): fix incorrect intent. + - nvme: add a quirk to disable namespace identifiers + - nvme-pci: disable namespace identifiers for the MAXIO MAP1002/1202 + - nvme-pci: disable namespace identifiers for Qemu controllers + - EDAC/synopsys: Read the error count from the correct register + - mm/memory-failure.c: skip huge_zero_page in memory_failure() + - memcg: sync flush only if periodic flush is delayed + - mm, hugetlb: allow for "high" userspace addresses + - oom_kill.c: futex: delay the OOM reaper to allow time for proper futex + cleanup + - mm/mmu_notifier.c: fix race in mmu_interval_notifier_remove() + - ata: pata_marvell: Check the 'bmdma_addr' beforing reading + - dma: at_xdmac: fix a missing check on list iterator + - dmaengine: imx-sdma: fix init of uart scripts + - net: atlantic: invert deep par in pm functions, preventing null derefs + - Input: omap4-keypad - fix pm_runtime_get_sync() error checking + - scsi: sr: Do not leak information in ioctl + - sched/pelt: Fix attach_entity_load_avg() corner case + - perf/core: Fix perf_mmap fail when CONFIG_PERF_USE_VMALLOC enabled + - drm/panel/raspberrypi-touchscreen: Avoid NULL deref if not initialised + - drm/panel/raspberrypi-touchscreen: Initialise the bridge in prepare + - KVM: PPC: Fix TCE handling for VFIO + - drm/vc4: Use pm_runtime_resume_and_get to fix pm_runtime_get_sync() usage + - powerpc/perf: Fix power9 event alternatives + - powerpc/perf: Fix power10 event alternatives + - perf script: Always allow field 'data_src' for auxtrace + - perf report: Set PERF_SAMPLE_DATA_SRC bit for Arm SPE event + - xtensa: patch_text: Fixup last cpu should be master + - xtensa: fix a7 clobbering in coprocessor context load/store + - openvswitch: fix OOB access in reserve_sfa_size() + - ASoC: soc-dapm: fix two incorrect uses of list iterator + - e1000e: Fix possible overflow in LTR decoding + - ARC: entry: fix syscall_trace_exit argument + - arm_pmu: Validate single/group leader events + - KVM: x86/pmu: Update AMD PMC sample period to fix guest NMI-watchdog + - KVM: x86: Pend KVM_REQ_APICV_UPDATE during vCPU creation to fix a race + - KVM: nVMX: Defer APICv updates while L2 is active until L1 is active + - KVM: SVM: Flush when freeing encrypted pages even on SME_COHERENT CPUs + - netfilter: conntrack: convert to refcount_t api + - netfilter: conntrack: avoid useless indirection during conntrack destruction + - ext4: fix fallocate to use file_modified to update permissions consistently + - ext4: fix symlink file size not match to file content + - ext4: fix use-after-free in ext4_search_dir + - ext4, doc: fix incorrect h_reserved size + - ext4: fix overhead calculation to account for the reserved gdt blocks + - ext4: force overhead calculation if the s_overhead_cluster makes no sense + - netfilter: nft_ct: fix use after free when attaching zone template + - jbd2: fix a potential race while discarding reserved buffers after an abort + - spi: atmel-quadspi: Fix the buswidth adjustment between spi-mem and + controller + - block/compat_ioctl: fix range check in BLKGETSIZE + - arm64: dts: qcom: add IPA qcom,qmp property + - Linux 5.15.36 + + * Aquantia GbE LAN driver causes UBSAN error during kernel boot + (LP: #1958770) // Jammy update: v5.15.36 upstream stable release + (LP: #1972905) + - net: atlantic: Avoid out-of-bounds indexing + + -- Stefan Bader Wed, 22 Jun 2022 14:42:28 +0200 + linux (5.15.0-40.43) jammy; urgency=medium * jammy/linux: 5.15.0-40.43 -proposed tracker (LP: #1978610) diff -u linux-5.15.0/debian/control linux-5.15.0/debian/control --- linux-5.15.0/debian/control +++ linux-5.15.0/debian/control @@ -83,7 +83,7 @@ you do not want this package. Install the appropriate linux-headers package instead. -Package: linux-headers-5.15.0-40 +Package: linux-headers-5.15.0-41 Build-Profiles: Architecture: all Multi-Arch: foreign @@ -93,7 +93,7 @@ Description: Header files related to Linux kernel version 5.15.0 This package provides kernel header files for version 5.15.0, for sites that want the latest kernel headers. Please read - /usr/share/doc/linux-headers-5.15.0-40/debian.README.gz for details + /usr/share/doc/linux-headers-5.15.0-41/debian.README.gz for details Package: linux-tools-common Build-Profiles: @@ -107,18 +107,18 @@ version locked tools (such as perf and x86_energy_perf_policy) for version 5.15.0. -Package: linux-tools-5.15.0-40 +Package: linux-tools-5.15.0-41 Build-Profiles: Architecture: amd64 armhf arm64 ppc64el s390x Section: devel Priority: optional Depends: ${misc:Depends}, ${shlibs:Depends}, linux-tools-common -Description: Linux kernel version specific tools for version 5.15.0-40 +Description: Linux kernel version specific tools for version 5.15.0-41 This package provides the architecture dependant parts for kernel version locked tools (such as perf and x86_energy_perf_policy) for - version 5.15.0-40 on + version 5.15.0-41 on 64 bit x86. - You probably want to install linux-tools-5.15.0-40-. + You probably want to install linux-tools-5.15.0-41-. Package: linux-cloud-tools-common Build-Profiles: @@ -131,17 +131,17 @@ This package provides the architecture independent parts for kernel version locked tools for cloud tools for version 5.15.0. -Package: linux-cloud-tools-5.15.0-40 +Package: linux-cloud-tools-5.15.0-41 Build-Profiles: Architecture: amd64 armhf Section: devel Priority: optional Depends: ${misc:Depends}, ${shlibs:Depends}, linux-cloud-tools-common -Description: Linux kernel version specific cloud tools for version 5.15.0-40 +Description: Linux kernel version specific cloud tools for version 5.15.0-41 This package provides the architecture dependant parts for kernel - version locked tools for cloud tools for version 5.15.0-40 on + version locked tools for cloud tools for version 5.15.0-41 on 64 bit x86. - You probably want to install linux-cloud-tools-5.15.0-40-. + You probably want to install linux-cloud-tools-5.15.0-41-. Package: linux-tools-host Build-Profiles: @@ -181,17 +181,17 @@ contained in each file. -Package: linux-image-unsigned-5.15.0-40-generic +Package: linux-image-unsigned-5.15.0-41-generic Build-Profiles: Architecture: amd64 armhf arm64 ppc64el s390x Section: kernel Priority: optional Provides: linux-image, fuse-module, kvm-api-4, redhat-cluster-modules, ivtv-modules, virtualbox-guest-modules [amd64], ${linux:rprovides} -Depends: ${misc:Depends}, ${shlibs:Depends}, kmod, linux-base (>= 4.5ubuntu1~16.04.1), linux-modules-5.15.0-40-generic +Depends: ${misc:Depends}, ${shlibs:Depends}, kmod, linux-base (>= 4.5ubuntu1~16.04.1), linux-modules-5.15.0-41-generic Recommends: grub-pc [amd64] | grub-efi-amd64 [amd64] | grub-efi-ia32 [amd64] | grub [amd64] | lilo [amd64] | flash-kernel [armhf arm64] | grub-efi-arm64 [arm64] | grub-efi-arm [armhf] | grub-ieee1275 [ppc64el], initramfs-tools | linux-initramfs-tool Breaks: flash-kernel (<< 3.90ubuntu2) [arm64 armhf], s390-tools (<< 2.3.0-0ubuntu3) [s390x] -Conflicts: linux-image-5.15.0-40-generic -Suggests: fdutils, linux-doc | linux-source-5.15.0, linux-tools, linux-headers-5.15.0-40-generic, linux-modules-extra-5.15.0-40-generic +Conflicts: linux-image-5.15.0-41-generic +Suggests: fdutils, linux-doc | linux-source-5.15.0, linux-tools, linux-headers-5.15.0-41-generic, linux-modules-extra-5.15.0-41-generic Description: Linux kernel image for version 5.15.0 on 64 bit x86 SMP This package contains the unsigned Linux kernel image for version 5.15.0 on 64 bit x86 SMP. @@ -204,12 +204,12 @@ the linux-generic meta-package, which will ensure that upgrades work correctly, and that supporting packages are also installed. -Package: linux-modules-5.15.0-40-generic +Package: linux-modules-5.15.0-41-generic Build-Profiles: Architecture: amd64 armhf arm64 ppc64el s390x Section: kernel Priority: optional -Depends: ${misc:Depends}, ${shlibs:Depends}, linux-image-5.15.0-40-generic | linux-image-unsigned-5.15.0-40-generic +Depends: ${misc:Depends}, ${shlibs:Depends}, linux-image-5.15.0-41-generic | linux-image-unsigned-5.15.0-41-generic Built-Using: ${linux:BuiltUsing} Description: Linux kernel extra modules for version 5.15.0 on 64 bit x86 SMP Contains the corresponding System.map file, the modules built by the @@ -224,12 +224,12 @@ the linux-generic meta-package, which will ensure that upgrades work correctly, and that supporting packages are also installed. -Package: linux-modules-extra-5.15.0-40-generic +Package: linux-modules-extra-5.15.0-41-generic Build-Profiles: Architecture: amd64 armhf arm64 ppc64el s390x Section: kernel Priority: optional -Depends: ${misc:Depends}, ${shlibs:Depends}, linux-image-5.15.0-40-generic | linux-image-unsigned-5.15.0-40-generic, wireless-regdb +Depends: ${misc:Depends}, ${shlibs:Depends}, linux-image-5.15.0-41-generic | linux-image-unsigned-5.15.0-41-generic, wireless-regdb Description: Linux kernel extra modules for version 5.15.0 on 64 bit x86 SMP This package contains the Linux kernel extra modules for version 5.15.0 on 64 bit x86 SMP. @@ -246,21 +246,21 @@ the linux-generic meta-package, which will ensure that upgrades work correctly, and that supporting packages are also installed. -Package: linux-headers-5.15.0-40-generic +Package: linux-headers-5.15.0-41-generic Build-Profiles: Architecture: amd64 armhf arm64 ppc64el s390x Section: devel Priority: optional -Depends: ${misc:Depends}, linux-headers-5.15.0-40, ${shlibs:Depends} +Depends: ${misc:Depends}, linux-headers-5.15.0-41, ${shlibs:Depends} Provides: linux-headers, linux-headers-3.0 Description: Linux kernel headers for version 5.15.0 on 64 bit x86 SMP This package provides kernel header files for version 5.15.0 on 64 bit x86 SMP. . This is for sites that want the latest kernel headers. Please read - /usr/share/doc/linux-headers-5.15.0-40/debian.README.gz for details. + /usr/share/doc/linux-headers-5.15.0-41/debian.README.gz for details. -Package: linux-image-unsigned-5.15.0-40-generic-dbgsym +Package: linux-image-unsigned-5.15.0-41-generic-dbgsym Build-Profiles: Architecture: amd64 armhf arm64 ppc64el s390x Section: devel @@ -277,31 +277,31 @@ is uncompressed, and unstripped. This package also includes the unstripped modules. -Package: linux-tools-5.15.0-40-generic +Package: linux-tools-5.15.0-41-generic Build-Profiles: Architecture: amd64 armhf arm64 ppc64el s390x Section: devel Priority: optional -Depends: ${misc:Depends}, linux-tools-5.15.0-40 -Description: Linux kernel version specific tools for version 5.15.0-40 +Depends: ${misc:Depends}, linux-tools-5.15.0-41 +Description: Linux kernel version specific tools for version 5.15.0-41 This package provides the architecture dependant parts for kernel version locked tools (such as perf and x86_energy_perf_policy) for - version 5.15.0-40 on + version 5.15.0-41 on 64 bit x86. -Package: linux-cloud-tools-5.15.0-40-generic +Package: linux-cloud-tools-5.15.0-41-generic Build-Profiles: Architecture: amd64 armhf arm64 ppc64el s390x Section: devel Priority: optional -Depends: ${misc:Depends}, linux-cloud-tools-5.15.0-40 -Description: Linux kernel version specific cloud tools for version 5.15.0-40 +Depends: ${misc:Depends}, linux-cloud-tools-5.15.0-41 +Description: Linux kernel version specific cloud tools for version 5.15.0-41 This package provides the architecture dependant parts for kernel - version locked tools for cloud for version 5.15.0-40 on + version locked tools for cloud for version 5.15.0-41 on 64 bit x86. -Package: linux-buildinfo-5.15.0-40-generic +Package: linux-buildinfo-5.15.0-41-generic Build-Profiles: Architecture: amd64 armhf arm64 ppc64el s390x Section: kernel @@ -315,18 +315,18 @@ You likely do not want to install this package. -Package: linux-modules-iwlwifi-5.15.0-40-generic +Package: linux-modules-iwlwifi-5.15.0-41-generic Build-Profiles: Architecture: amd64 armhf arm64 ppc64el s390x Section: kernel Priority: optional Depends: ${misc:Depends}, - linux-image-5.15.0-40-generic | linux-image-unsigned-5.15.0-40-generic, + linux-image-5.15.0-41-generic | linux-image-unsigned-5.15.0-41-generic, Built-Using: ${linux:BuiltUsing} -Description: Linux kernel iwlwifi modules for version 5.15.0-40 +Description: Linux kernel iwlwifi modules for version 5.15.0-41 This package provides the Linux kernel iwlwifi modules for version - 5.15.0-40. + 5.15.0-41. . You likely do not want to install this package directly. Instead, install the one of the linux-modules-iwlwifi-generic* meta-packages, @@ -334,17 +334,17 @@ also installed. -Package: linux-image-unsigned-5.15.0-40-generic-64k +Package: linux-image-unsigned-5.15.0-41-generic-64k Build-Profiles: Architecture: arm64 Section: kernel Priority: optional Provides: linux-image, fuse-module, kvm-api-4, redhat-cluster-modules, ivtv-modules, ${linux:rprovides} -Depends: ${misc:Depends}, ${shlibs:Depends}, kmod, linux-base (>= 4.5ubuntu1~16.04.1), linux-modules-5.15.0-40-generic-64k +Depends: ${misc:Depends}, ${shlibs:Depends}, kmod, linux-base (>= 4.5ubuntu1~16.04.1), linux-modules-5.15.0-41-generic-64k Recommends: grub-efi-arm64 [arm64] | flash-kernel [arm64], initramfs-tools | linux-initramfs-tool Breaks: flash-kernel (<< 3.90ubuntu2) [arm64 armhf], s390-tools (<< 2.3.0-0ubuntu3) [s390x] -Conflicts: linux-image-5.15.0-40-generic-64k -Suggests: fdutils, linux-doc | linux-source-5.15.0, linux-tools, linux-headers-5.15.0-40-generic-64k, linux-modules-extra-5.15.0-40-generic-64k +Conflicts: linux-image-5.15.0-41-generic-64k +Suggests: fdutils, linux-doc | linux-source-5.15.0, linux-tools, linux-headers-5.15.0-41-generic-64k, linux-modules-extra-5.15.0-41-generic-64k Description: Linux kernel image for version 5.15.0 on 64 bit x86 SMP This package contains the unsigned Linux kernel image for version 5.15.0 on 64 bit x86 SMP. @@ -357,12 +357,12 @@ the linux-generic-64k meta-package, which will ensure that upgrades work correctly, and that supporting packages are also installed. -Package: linux-modules-5.15.0-40-generic-64k +Package: linux-modules-5.15.0-41-generic-64k Build-Profiles: Architecture: arm64 Section: kernel Priority: optional -Depends: ${misc:Depends}, ${shlibs:Depends}, linux-image-5.15.0-40-generic-64k | linux-image-unsigned-5.15.0-40-generic-64k +Depends: ${misc:Depends}, ${shlibs:Depends}, linux-image-5.15.0-41-generic-64k | linux-image-unsigned-5.15.0-41-generic-64k Built-Using: ${linux:BuiltUsing} Description: Linux kernel extra modules for version 5.15.0 on 64 bit x86 SMP Contains the corresponding System.map file, the modules built by the @@ -377,12 +377,12 @@ the linux-generic-64k meta-package, which will ensure that upgrades work correctly, and that supporting packages are also installed. -Package: linux-modules-extra-5.15.0-40-generic-64k +Package: linux-modules-extra-5.15.0-41-generic-64k Build-Profiles: Architecture: arm64 Section: kernel Priority: optional -Depends: ${misc:Depends}, ${shlibs:Depends}, linux-image-5.15.0-40-generic-64k | linux-image-unsigned-5.15.0-40-generic-64k, wireless-regdb +Depends: ${misc:Depends}, ${shlibs:Depends}, linux-image-5.15.0-41-generic-64k | linux-image-unsigned-5.15.0-41-generic-64k, wireless-regdb Description: Linux kernel extra modules for version 5.15.0 on 64 bit x86 SMP This package contains the Linux kernel extra modules for version 5.15.0 on 64 bit x86 SMP. @@ -399,21 +399,21 @@ the linux-generic-64k meta-package, which will ensure that upgrades work correctly, and that supporting packages are also installed. -Package: linux-headers-5.15.0-40-generic-64k +Package: linux-headers-5.15.0-41-generic-64k Build-Profiles: Architecture: arm64 Section: devel Priority: optional -Depends: ${misc:Depends}, linux-headers-5.15.0-40, ${shlibs:Depends} +Depends: ${misc:Depends}, linux-headers-5.15.0-41, ${shlibs:Depends} Provides: linux-headers, linux-headers-3.0 Description: Linux kernel headers for version 5.15.0 on 64 bit x86 SMP This package provides kernel header files for version 5.15.0 on 64 bit x86 SMP. . This is for sites that want the latest kernel headers. Please read - /usr/share/doc/linux-headers-5.15.0-40/debian.README.gz for details. + /usr/share/doc/linux-headers-5.15.0-41/debian.README.gz for details. -Package: linux-image-unsigned-5.15.0-40-generic-64k-dbgsym +Package: linux-image-unsigned-5.15.0-41-generic-64k-dbgsym Build-Profiles: Architecture: arm64 Section: devel @@ -430,31 +430,31 @@ is uncompressed, and unstripped. This package also includes the unstripped modules. -Package: linux-tools-5.15.0-40-generic-64k +Package: linux-tools-5.15.0-41-generic-64k Build-Profiles: Architecture: arm64 Section: devel Priority: optional -Depends: ${misc:Depends}, linux-tools-5.15.0-40 -Description: Linux kernel version specific tools for version 5.15.0-40 +Depends: ${misc:Depends}, linux-tools-5.15.0-41 +Description: Linux kernel version specific tools for version 5.15.0-41 This package provides the architecture dependant parts for kernel version locked tools (such as perf and x86_energy_perf_policy) for - version 5.15.0-40 on + version 5.15.0-41 on 64 bit x86. -Package: linux-cloud-tools-5.15.0-40-generic-64k +Package: linux-cloud-tools-5.15.0-41-generic-64k Build-Profiles: Architecture: arm64 Section: devel Priority: optional -Depends: ${misc:Depends}, linux-cloud-tools-5.15.0-40 -Description: Linux kernel version specific cloud tools for version 5.15.0-40 +Depends: ${misc:Depends}, linux-cloud-tools-5.15.0-41 +Description: Linux kernel version specific cloud tools for version 5.15.0-41 This package provides the architecture dependant parts for kernel - version locked tools for cloud for version 5.15.0-40 on + version locked tools for cloud for version 5.15.0-41 on 64 bit x86. -Package: linux-buildinfo-5.15.0-40-generic-64k +Package: linux-buildinfo-5.15.0-41-generic-64k Build-Profiles: Architecture: arm64 Section: kernel @@ -468,18 +468,18 @@ You likely do not want to install this package. -Package: linux-modules-iwlwifi-5.15.0-40-generic-64k +Package: linux-modules-iwlwifi-5.15.0-41-generic-64k Build-Profiles: Architecture: arm64 Section: kernel Priority: optional Depends: ${misc:Depends}, - linux-image-5.15.0-40-generic-64k | linux-image-unsigned-5.15.0-40-generic-64k, + linux-image-5.15.0-41-generic-64k | linux-image-unsigned-5.15.0-41-generic-64k, Built-Using: ${linux:BuiltUsing} -Description: Linux kernel iwlwifi modules for version 5.15.0-40 +Description: Linux kernel iwlwifi modules for version 5.15.0-41 This package provides the Linux kernel iwlwifi modules for version - 5.15.0-40. + 5.15.0-41. . You likely do not want to install this package directly. Instead, install the one of the linux-modules-iwlwifi-generic-64k* meta-packages, @@ -487,17 +487,17 @@ also installed. -Package: linux-image-unsigned-5.15.0-40-generic-lpae +Package: linux-image-unsigned-5.15.0-41-generic-lpae Build-Profiles: Architecture: armhf Section: kernel Priority: optional Provides: linux-image, fuse-module, kvm-api-4, redhat-cluster-modules, ivtv-modules, ${linux:rprovides} -Depends: ${misc:Depends}, ${shlibs:Depends}, kmod, linux-base (>= 4.5ubuntu1~16.04.1), linux-modules-5.15.0-40-generic-lpae +Depends: ${misc:Depends}, ${shlibs:Depends}, kmod, linux-base (>= 4.5ubuntu1~16.04.1), linux-modules-5.15.0-41-generic-lpae Recommends: flash-kernel [armhf] | grub-efi-arm [armhf], initramfs-tools | linux-initramfs-tool Breaks: flash-kernel (<< 3.90ubuntu2) [arm64 armhf], s390-tools (<< 2.3.0-0ubuntu3) [s390x] -Conflicts: linux-image-5.15.0-40-generic-lpae -Suggests: fdutils, linux-doc | linux-source-5.15.0, linux-tools, linux-headers-5.15.0-40-generic-lpae, linux-modules-extra-5.15.0-40-generic-lpae +Conflicts: linux-image-5.15.0-41-generic-lpae +Suggests: fdutils, linux-doc | linux-source-5.15.0, linux-tools, linux-headers-5.15.0-41-generic-lpae, linux-modules-extra-5.15.0-41-generic-lpae Description: Linux kernel image for version 5.15.0 on 64 bit x86 SMP This package contains the unsigned Linux kernel image for version 5.15.0 on 64 bit x86 SMP. @@ -510,12 +510,12 @@ the linux-generic-lpae meta-package, which will ensure that upgrades work correctly, and that supporting packages are also installed. -Package: linux-modules-5.15.0-40-generic-lpae +Package: linux-modules-5.15.0-41-generic-lpae Build-Profiles: Architecture: armhf Section: kernel Priority: optional -Depends: ${misc:Depends}, ${shlibs:Depends}, linux-image-5.15.0-40-generic-lpae | linux-image-unsigned-5.15.0-40-generic-lpae +Depends: ${misc:Depends}, ${shlibs:Depends}, linux-image-5.15.0-41-generic-lpae | linux-image-unsigned-5.15.0-41-generic-lpae Built-Using: ${linux:BuiltUsing} Description: Linux kernel extra modules for version 5.15.0 on 64 bit x86 SMP Contains the corresponding System.map file, the modules built by the @@ -530,12 +530,12 @@ the linux-generic-lpae meta-package, which will ensure that upgrades work correctly, and that supporting packages are also installed. -Package: linux-modules-extra-5.15.0-40-generic-lpae +Package: linux-modules-extra-5.15.0-41-generic-lpae Build-Profiles: Architecture: armhf Section: kernel Priority: optional -Depends: ${misc:Depends}, ${shlibs:Depends}, linux-image-5.15.0-40-generic-lpae | linux-image-unsigned-5.15.0-40-generic-lpae, wireless-regdb +Depends: ${misc:Depends}, ${shlibs:Depends}, linux-image-5.15.0-41-generic-lpae | linux-image-unsigned-5.15.0-41-generic-lpae, wireless-regdb Description: Linux kernel extra modules for version 5.15.0 on 64 bit x86 SMP This package contains the Linux kernel extra modules for version 5.15.0 on 64 bit x86 SMP. @@ -552,21 +552,21 @@ the linux-generic-lpae meta-package, which will ensure that upgrades work correctly, and that supporting packages are also installed. -Package: linux-headers-5.15.0-40-generic-lpae +Package: linux-headers-5.15.0-41-generic-lpae Build-Profiles: Architecture: armhf Section: devel Priority: optional -Depends: ${misc:Depends}, linux-headers-5.15.0-40, ${shlibs:Depends} +Depends: ${misc:Depends}, linux-headers-5.15.0-41, ${shlibs:Depends} Provides: linux-headers, linux-headers-3.0 Description: Linux kernel headers for version 5.15.0 on 64 bit x86 SMP This package provides kernel header files for version 5.15.0 on 64 bit x86 SMP. . This is for sites that want the latest kernel headers. Please read - /usr/share/doc/linux-headers-5.15.0-40/debian.README.gz for details. + /usr/share/doc/linux-headers-5.15.0-41/debian.README.gz for details. -Package: linux-image-unsigned-5.15.0-40-generic-lpae-dbgsym +Package: linux-image-unsigned-5.15.0-41-generic-lpae-dbgsym Build-Profiles: Architecture: armhf Section: devel @@ -583,31 +583,31 @@ is uncompressed, and unstripped. This package also includes the unstripped modules. -Package: linux-tools-5.15.0-40-generic-lpae +Package: linux-tools-5.15.0-41-generic-lpae Build-Profiles: Architecture: armhf Section: devel Priority: optional -Depends: ${misc:Depends}, linux-tools-5.15.0-40 -Description: Linux kernel version specific tools for version 5.15.0-40 +Depends: ${misc:Depends}, linux-tools-5.15.0-41 +Description: Linux kernel version specific tools for version 5.15.0-41 This package provides the architecture dependant parts for kernel version locked tools (such as perf and x86_energy_perf_policy) for - version 5.15.0-40 on + version 5.15.0-41 on 64 bit x86. -Package: linux-cloud-tools-5.15.0-40-generic-lpae +Package: linux-cloud-tools-5.15.0-41-generic-lpae Build-Profiles: Architecture: armhf Section: devel Priority: optional -Depends: ${misc:Depends}, linux-cloud-tools-5.15.0-40 -Description: Linux kernel version specific cloud tools for version 5.15.0-40 +Depends: ${misc:Depends}, linux-cloud-tools-5.15.0-41 +Description: Linux kernel version specific cloud tools for version 5.15.0-41 This package provides the architecture dependant parts for kernel - version locked tools for cloud for version 5.15.0-40 on + version locked tools for cloud for version 5.15.0-41 on 64 bit x86. -Package: linux-buildinfo-5.15.0-40-generic-lpae +Package: linux-buildinfo-5.15.0-41-generic-lpae Build-Profiles: Architecture: armhf Section: kernel @@ -621,18 +621,18 @@ You likely do not want to install this package. -Package: linux-modules-iwlwifi-5.15.0-40-generic-lpae +Package: linux-modules-iwlwifi-5.15.0-41-generic-lpae Build-Profiles: Architecture: armhf Section: kernel Priority: optional Depends: ${misc:Depends}, - linux-image-5.15.0-40-generic-lpae | linux-image-unsigned-5.15.0-40-generic-lpae, + linux-image-5.15.0-41-generic-lpae | linux-image-unsigned-5.15.0-41-generic-lpae, Built-Using: ${linux:BuiltUsing} -Description: Linux kernel iwlwifi modules for version 5.15.0-40 +Description: Linux kernel iwlwifi modules for version 5.15.0-41 This package provides the Linux kernel iwlwifi modules for version - 5.15.0-40. + 5.15.0-41. . You likely do not want to install this package directly. Instead, install the one of the linux-modules-iwlwifi-generic-lpae* meta-packages, diff -u linux-5.15.0/drivers/acpi/processor_idle.c linux-5.15.0/drivers/acpi/processor_idle.c --- linux-5.15.0/drivers/acpi/processor_idle.c +++ linux-5.15.0/drivers/acpi/processor_idle.c @@ -95,11 +95,6 @@ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), DMI_MATCH(DMI_PRODUCT_NAME,"L8400B series Notebook PC")}, (void *)1}, - /* T40 can not handle C3 idle state */ - { set_max_cstate, "IBM ThinkPad T40", { - DMI_MATCH(DMI_SYS_VENDOR, "IBM"), - DMI_MATCH(DMI_PRODUCT_NAME, "23737CU")}, - (void *)2}, {}, }; @@ -797,7 +792,8 @@ if (cx->type == ACPI_STATE_C1 || cx->type == ACPI_STATE_C2 || cx->type == ACPI_STATE_C3) { state->enter_dead = acpi_idle_play_dead; - drv->safe_state_index = count; + if (cx->type != ACPI_STATE_C3) + drv->safe_state_index = count; } /* * Halt-induced C1 is not good for ->enter_s2idle, because it diff -u linux-5.15.0/drivers/block/floppy.c linux-5.15.0/drivers/block/floppy.c --- linux-5.15.0/drivers/block/floppy.c +++ linux-5.15.0/drivers/block/floppy.c @@ -2984,6 +2984,8 @@ return "(null)"; } +#ifdef CONFIG_BLK_DEV_FD_RAWCMD + /* raw commands */ static void raw_cmd_done(int flag) { @@ -3183,6 +3185,35 @@ return ret; } +static int floppy_raw_cmd_ioctl(int type, int drive, int cmd, + void __user *param) +{ + int ret; + + pr_warn_once("Note: FDRAWCMD is deprecated and will be removed from the kernel in the near future.\n"); + + if (type) + return -EINVAL; + if (lock_fdc(drive)) + return -EINTR; + set_floppy(drive); + ret = raw_cmd_ioctl(cmd, param); + if (ret == -EINTR) + return -EINTR; + process_fd_request(); + return ret; +} + +#else /* CONFIG_BLK_DEV_FD_RAWCMD */ + +static int floppy_raw_cmd_ioctl(int type, int drive, int cmd, + void __user *param) +{ + return -EOPNOTSUPP; +} + +#endif + static int invalidate_drive(struct block_device *bdev) { /* invalidate the buffer track to force a reread */ @@ -3371,7 +3402,6 @@ { int drive = (long)bdev->bd_disk->private_data; int type = ITYPE(drive_state[drive].fd_device); - int i; int ret; int size; union inparam { @@ -3522,16 +3552,7 @@ outparam = &write_errors[drive]; break; case FDRAWCMD: - if (type) - return -EINVAL; - if (lock_fdc(drive)) - return -EINTR; - set_floppy(drive); - i = raw_cmd_ioctl(cmd, (void __user *)param); - if (i == -EINTR) - return -EINTR; - process_fd_request(); - return i; + return floppy_raw_cmd_ioctl(type, drive, cmd, (void __user *)param); case FDTWADDLE: if (lock_fdc(drive)) return -EINTR; diff -u linux-5.15.0/drivers/bus/mhi/pci_generic.c linux-5.15.0/drivers/bus/mhi/pci_generic.c --- linux-5.15.0/drivers/bus/mhi/pci_generic.c +++ linux-5.15.0/drivers/bus/mhi/pci_generic.c @@ -1020,6 +1020,7 @@ * the intermediate restore kernel reinitializes MHI device with new * context. */ + flush_work(&mhi_pdev->recovery_work); if (test_and_clear_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status)) { mhi_power_down(mhi_cntrl, true); mhi_unprepare_after_power_down(mhi_cntrl); @@ -1045,6 +1046,7 @@ .resume = mhi_pci_resume, .freeze = mhi_pci_freeze, .thaw = mhi_pci_restore, + .poweroff = mhi_pci_freeze, .restore = mhi_pci_restore, #endif }; diff -u linux-5.15.0/drivers/bus/sunxi-rsb.c linux-5.15.0/drivers/bus/sunxi-rsb.c --- linux-5.15.0/drivers/bus/sunxi-rsb.c +++ linux-5.15.0/drivers/bus/sunxi-rsb.c @@ -227,6 +227,8 @@ dev_dbg(&rdev->dev, "device %s registered\n", dev_name(&rdev->dev)); + return rdev; + err_device_add: put_device(&rdev->dev); diff -u linux-5.15.0/drivers/bus/ti-sysc.c linux-5.15.0/drivers/bus/ti-sysc.c --- linux-5.15.0/drivers/bus/ti-sysc.c +++ linux-5.15.0/drivers/bus/ti-sysc.c @@ -3162,13 +3162,27 @@ */ static int sysc_check_active_timer(struct sysc *ddata) { + int error; + if (ddata->cap->type != TI_SYSC_OMAP2_TIMER && ddata->cap->type != TI_SYSC_OMAP4_TIMER) return 0; + /* + * Quirk for omap3 beagleboard revision A to B4 to use gpt12. + * Revision C and later are fixed with commit 23885389dbbb ("ARM: + * dts: Fix timer regression for beagleboard revision c"). This all + * can be dropped if we stop supporting old beagleboard revisions + * A to B4 at some point. + */ + if (sysc_soc->soc == SOC_3430) + error = -ENXIO; + else + error = -EBUSY; + if ((ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT) && (ddata->cfg.quirks & SYSC_QUIRK_NO_IDLE)) - return -ENXIO; + return error; return 0; } diff -u linux-5.15.0/drivers/cpufreq/qcom-cpufreq-hw.c linux-5.15.0/drivers/cpufreq/qcom-cpufreq-hw.c --- linux-5.15.0/drivers/cpufreq/qcom-cpufreq-hw.c +++ linux-5.15.0/drivers/cpufreq/qcom-cpufreq-hw.c @@ -24,12 +24,16 @@ #define CLK_HW_DIV 2 #define LUT_TURBO_IND 1 +#define GT_IRQ_STATUS BIT(2) + #define HZ_PER_KHZ 1000 struct qcom_cpufreq_soc_data { u32 reg_enable; + u32 reg_domain_state; u32 reg_freq_lut; u32 reg_volt_lut; + u32 reg_intr_clr; u32 reg_current_vote; u32 reg_perf_state; u8 lut_row_size; @@ -266,28 +270,31 @@ } } -static unsigned int qcom_lmh_get_throttle_freq(struct qcom_cpufreq_data *data) +static unsigned long qcom_lmh_get_throttle_freq(struct qcom_cpufreq_data *data) { - unsigned int val = readl_relaxed(data->base + data->soc_data->reg_current_vote); + unsigned int lval; + + if (data->soc_data->reg_current_vote) + lval = readl_relaxed(data->base + data->soc_data->reg_current_vote) & 0x3ff; + else + lval = readl_relaxed(data->base + data->soc_data->reg_domain_state) & 0xff; - return (val & 0x3FF) * 19200; + return lval * xo_rate; } static void qcom_lmh_dcvs_notify(struct qcom_cpufreq_data *data) { unsigned long max_capacity, capacity, freq_hz, throttled_freq; struct cpufreq_policy *policy = data->policy; - int cpu = cpumask_first(policy->cpus); + int cpu = cpumask_first(policy->related_cpus); struct device *dev = get_cpu_device(cpu); struct dev_pm_opp *opp; - unsigned int freq; /* * Get the h/w throttled frequency, normalize it using the * registered opp table and use it to calculate thermal pressure. */ - freq = qcom_lmh_get_throttle_freq(data); - freq_hz = freq * HZ_PER_KHZ; + freq_hz = qcom_lmh_get_throttle_freq(data); opp = dev_pm_opp_find_freq_floor(dev, &freq_hz); if (IS_ERR(opp) && PTR_ERR(opp) == -ERANGE) @@ -345,6 +352,10 @@ disable_irq_nosync(c_data->throttle_irq); schedule_delayed_work(&c_data->throttle_work, 0); + if (c_data->soc_data->reg_intr_clr) + writel_relaxed(GT_IRQ_STATUS, + c_data->base + c_data->soc_data->reg_intr_clr); + return IRQ_HANDLED; } @@ -359,8 +370,10 @@ static const struct qcom_cpufreq_soc_data epss_soc_data = { .reg_enable = 0x0, + .reg_domain_state = 0x20, .reg_freq_lut = 0x100, .reg_volt_lut = 0x200, + .reg_intr_clr = 0x308, .reg_perf_state = 0x320, .lut_row_size = 4, }; diff -u linux-5.15.0/drivers/dma/at_xdmac.c linux-5.15.0/drivers/dma/at_xdmac.c --- linux-5.15.0/drivers/dma/at_xdmac.c +++ linux-5.15.0/drivers/dma/at_xdmac.c @@ -1450,7 +1450,7 @@ { struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan); struct at_xdmac *atxdmac = to_at_xdmac(atchan->chan.device); - struct at_xdmac_desc *desc, *_desc; + struct at_xdmac_desc *desc, *_desc, *iter; struct list_head *descs_list; enum dma_status ret; int residue, retry; @@ -1565,11 +1565,13 @@ * microblock. */ descs_list = &desc->descs_list; - list_for_each_entry_safe(desc, _desc, descs_list, desc_node) { - dwidth = at_xdmac_get_dwidth(desc->lld.mbr_cfg); - residue -= (desc->lld.mbr_ubc & 0xffffff) << dwidth; - if ((desc->lld.mbr_nda & 0xfffffffc) == cur_nda) + list_for_each_entry_safe(iter, _desc, descs_list, desc_node) { + dwidth = at_xdmac_get_dwidth(iter->lld.mbr_cfg); + residue -= (iter->lld.mbr_ubc & 0xffffff) << dwidth; + if ((iter->lld.mbr_nda & 0xfffffffc) == cur_nda) { + desc = iter; break; + } } residue += cur_ubc << dwidth; diff -u linux-5.15.0/drivers/dma/idxd/device.c linux-5.15.0/drivers/dma/idxd/device.c --- linux-5.15.0/drivers/dma/idxd/device.c +++ linux-5.15.0/drivers/dma/idxd/device.c @@ -406,7 +406,6 @@ { lockdep_assert_held(&wq->wq_lock); - idxd_wq_disable_cleanup(wq); wq->size = 0; wq->group = NULL; } @@ -723,14 +722,17 @@ if (wq->state == IDXD_WQ_ENABLED) { idxd_wq_disable_cleanup(wq); - idxd_wq_device_reset_cleanup(wq); wq->state = IDXD_WQ_DISABLED; } + idxd_wq_device_reset_cleanup(wq); } } void idxd_device_clear_state(struct idxd_device *idxd) { + if (!test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags)) + return; + idxd_groups_clear_state(idxd); idxd_engines_clear_state(idxd); idxd_device_wqs_clear_state(idxd); diff -u linux-5.15.0/drivers/dma/idxd/sysfs.c linux-5.15.0/drivers/dma/idxd/sysfs.c --- linux-5.15.0/drivers/dma/idxd/sysfs.c +++ linux-5.15.0/drivers/dma/idxd/sysfs.c @@ -842,6 +842,9 @@ u64 xfer_size; int rc; + if (!test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags)) + return -EPERM; + if (wq->state != IDXD_WQ_DISABLED) return -EPERM; @@ -876,6 +879,9 @@ u64 batch_size; int rc; + if (!test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags)) + return -EPERM; + if (wq->state != IDXD_WQ_DISABLED) return -EPERM; diff -u linux-5.15.0/drivers/edac/synopsys_edac.c linux-5.15.0/drivers/edac/synopsys_edac.c --- linux-5.15.0/drivers/edac/synopsys_edac.c +++ linux-5.15.0/drivers/edac/synopsys_edac.c @@ -163,6 +163,11 @@ #define ECC_STAT_CECNT_SHIFT 8 #define ECC_STAT_BITNUM_MASK 0x7F +/* ECC error count register definitions */ +#define ECC_ERRCNT_UECNT_MASK 0xFFFF0000 +#define ECC_ERRCNT_UECNT_SHIFT 16 +#define ECC_ERRCNT_CECNT_MASK 0xFFFF + /* DDR QOS Interrupt register definitions */ #define DDR_QOS_IRQ_STAT_OFST 0x20200 #define DDR_QOSUE_MASK 0x4 @@ -418,15 +423,16 @@ base = priv->baseaddr; p = &priv->stat; + regval = readl(base + ECC_ERRCNT_OFST); + p->ce_cnt = regval & ECC_ERRCNT_CECNT_MASK; + p->ue_cnt = (regval & ECC_ERRCNT_UECNT_MASK) >> ECC_ERRCNT_UECNT_SHIFT; + if (!p->ce_cnt) + goto ue_err; + regval = readl(base + ECC_STAT_OFST); if (!regval) return 1; - p->ce_cnt = (regval & ECC_STAT_CECNT_MASK) >> ECC_STAT_CECNT_SHIFT; - p->ue_cnt = (regval & ECC_STAT_UECNT_MASK) >> ECC_STAT_UECNT_SHIFT; - if (!p->ce_cnt) - goto ue_err; - p->ceinfo.bitpos = (regval & ECC_STAT_BITNUM_MASK); regval = readl(base + ECC_CEADDR0_OFST); diff -u linux-5.15.0/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c linux-5.15.0/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c --- linux-5.15.0/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ linux-5.15.0/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -138,19 +138,33 @@ } static void increment_queue_count(struct device_queue_manager *dqm, - enum kfd_queue_type type) + struct qcm_process_device *qpd, + struct queue *q) { dqm->active_queue_count++; - if (type == KFD_QUEUE_TYPE_COMPUTE || type == KFD_QUEUE_TYPE_DIQ) + if (q->properties.type == KFD_QUEUE_TYPE_COMPUTE || + q->properties.type == KFD_QUEUE_TYPE_DIQ) dqm->active_cp_queue_count++; + + if (q->properties.is_gws) { + dqm->gws_queue_count++; + qpd->mapped_gws_queue = true; + } } static void decrement_queue_count(struct device_queue_manager *dqm, - enum kfd_queue_type type) + struct qcm_process_device *qpd, + struct queue *q) { dqm->active_queue_count--; - if (type == KFD_QUEUE_TYPE_COMPUTE || type == KFD_QUEUE_TYPE_DIQ) + if (q->properties.type == KFD_QUEUE_TYPE_COMPUTE || + q->properties.type == KFD_QUEUE_TYPE_DIQ) dqm->active_cp_queue_count--; + + if (q->properties.is_gws) { + dqm->gws_queue_count--; + qpd->mapped_gws_queue = false; + } } static int allocate_doorbell(struct qcm_process_device *qpd, struct queue *q) @@ -390,7 +404,7 @@ list_add(&q->list, &qpd->queues_list); qpd->queue_count++; if (q->properties.is_active) - increment_queue_count(dqm, q->properties.type); + increment_queue_count(dqm, qpd, q); /* * Unconditionally increment this counter, regardless of the queue's @@ -515,13 +529,8 @@ deallocate_vmid(dqm, qpd, q); } qpd->queue_count--; - if (q->properties.is_active) { - decrement_queue_count(dqm, q->properties.type); - if (q->properties.is_gws) { - dqm->gws_queue_count--; - qpd->mapped_gws_queue = false; - } - } + if (q->properties.is_active) + decrement_queue_count(dqm, qpd, q); return retval; } @@ -613,12 +622,11 @@ * dqm->active_queue_count to determine whether a new runlist must be * uploaded. */ - if (q->properties.is_active && !prev_active) - increment_queue_count(dqm, q->properties.type); - else if (!q->properties.is_active && prev_active) - decrement_queue_count(dqm, q->properties.type); - - if (q->gws && !q->properties.is_gws) { + if (q->properties.is_active && !prev_active) { + increment_queue_count(dqm, &pdd->qpd, q); + } else if (!q->properties.is_active && prev_active) { + decrement_queue_count(dqm, &pdd->qpd, q); + } else if (q->gws && !q->properties.is_gws) { if (q->properties.is_active) { dqm->gws_queue_count++; pdd->qpd.mapped_gws_queue = true; @@ -680,11 +688,7 @@ mqd_mgr = dqm->mqd_mgrs[get_mqd_type_from_queue_type( q->properties.type)]; q->properties.is_active = false; - decrement_queue_count(dqm, q->properties.type); - if (q->properties.is_gws) { - dqm->gws_queue_count--; - qpd->mapped_gws_queue = false; - } + decrement_queue_count(dqm, qpd, q); if (WARN_ONCE(!dqm->sched_running, "Evict when stopped\n")) continue; @@ -730,7 +734,7 @@ continue; q->properties.is_active = false; - decrement_queue_count(dqm, q->properties.type); + decrement_queue_count(dqm, qpd, q); } pdd->last_evict_timestamp = get_jiffies_64(); retval = execute_queues_cpsch(dqm, @@ -801,11 +805,7 @@ mqd_mgr = dqm->mqd_mgrs[get_mqd_type_from_queue_type( q->properties.type)]; q->properties.is_active = true; - increment_queue_count(dqm, q->properties.type); - if (q->properties.is_gws) { - dqm->gws_queue_count++; - qpd->mapped_gws_queue = true; - } + increment_queue_count(dqm, qpd, q); if (WARN_ONCE(!dqm->sched_running, "Restore when stopped\n")) continue; @@ -863,7 +863,7 @@ continue; q->properties.is_active = true; - increment_queue_count(dqm, q->properties.type); + increment_queue_count(dqm, &pdd->qpd, q); } retval = execute_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0); @@ -1265,7 +1265,7 @@ dqm->total_queue_count); list_add(&kq->list, &qpd->priv_queue_list); - increment_queue_count(dqm, kq->queue->properties.type); + increment_queue_count(dqm, qpd, kq->queue); qpd->is_debug = true; execute_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0); dqm_unlock(dqm); @@ -1279,7 +1279,7 @@ { dqm_lock(dqm); list_del(&kq->list); - decrement_queue_count(dqm, kq->queue->properties.type); + decrement_queue_count(dqm, qpd, kq->queue); qpd->is_debug = false; execute_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES, 0); /* @@ -1346,7 +1346,7 @@ qpd->queue_count++; if (q->properties.is_active) { - increment_queue_count(dqm, q->properties.type); + increment_queue_count(dqm, qpd, q); execute_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0); @@ -1548,15 +1548,11 @@ list_del(&q->list); qpd->queue_count--; if (q->properties.is_active) { - decrement_queue_count(dqm, q->properties.type); + decrement_queue_count(dqm, qpd, q); retval = execute_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0); if (retval == -ETIME) qpd->reset_wavefronts = true; - if (q->properties.is_gws) { - dqm->gws_queue_count--; - qpd->mapped_gws_queue = false; - } } /* @@ -1747,7 +1743,7 @@ /* Clean all kernel queues */ list_for_each_entry_safe(kq, kq_next, &qpd->priv_queue_list, list) { list_del(&kq->list); - decrement_queue_count(dqm, kq->queue->properties.type); + decrement_queue_count(dqm, qpd, kq->queue); qpd->is_debug = false; dqm->total_queue_count--; filter = KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES; @@ -1760,13 +1756,8 @@ else if (q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI) deallocate_sdma_queue(dqm, q); - if (q->properties.is_active) { - decrement_queue_count(dqm, q->properties.type); - if (q->properties.is_gws) { - dqm->gws_queue_count--; - qpd->mapped_gws_queue = false; - } - } + if (q->properties.is_active) + decrement_queue_count(dqm, qpd, q); dqm->total_queue_count--; } diff -u linux-5.15.0/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c linux-5.15.0/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c --- linux-5.15.0/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ linux-5.15.0/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1152,6 +1152,32 @@ return 0; } +static void dm_dmub_hw_resume(struct amdgpu_device *adev) +{ + struct dmub_srv *dmub_srv = adev->dm.dmub_srv; + enum dmub_status status; + bool init; + + if (!dmub_srv) { + /* DMUB isn't supported on the ASIC. */ + return; + } + + status = dmub_srv_is_hw_init(dmub_srv, &init); + if (status != DMUB_STATUS_OK) + DRM_WARN("DMUB hardware init check failed: %d\n", status); + + if (status == DMUB_STATUS_OK && init) { + /* Wait for firmware load to finish. */ + status = dmub_srv_wait_for_auto_load(dmub_srv, 100000); + if (status != DMUB_STATUS_OK) + DRM_WARN("Wait for DMUB auto-load failed: %d\n", status); + } else { + /* Perform the full hardware initialization. */ + dm_dmub_hw_init(adev); + } +} + #if defined(CONFIG_DRM_AMD_DC_DCN) static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_addr_space_config *pa_config) { @@ -2455,9 +2481,7 @@ amdgpu_dm_outbox_init(adev); /* Before powering on DC we need to re-initialize DMUB. */ - r = dm_dmub_hw_init(adev); - if (r) - DRM_ERROR("DMUB interface failed to initialize: status=%d\n", r); + dm_dmub_hw_resume(adev); /* power on hardware */ dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D0); diff -u linux-5.15.0/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c linux-5.15.0/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c --- linux-5.15.0/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ linux-5.15.0/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -3185,7 +3185,7 @@ &dpcd_pattern_type.value, sizeof(dpcd_pattern_type)); - channel_count = dpcd_test_mode.bits.channel_count + 1; + channel_count = min(dpcd_test_mode.bits.channel_count + 1, AUDIO_CHANNELS_COUNT); // read pattern periods for requested channels when sawTooth pattern is requested if (dpcd_pattern_type.value == AUDIO_TEST_PATTERN_SAWTOOTH || diff -u linux-5.15.0/drivers/gpu/drm/i915/display/intel_bios.c linux-5.15.0/drivers/gpu/drm/i915/display/intel_bios.c --- linux-5.15.0/drivers/gpu/drm/i915/display/intel_bios.c +++ linux-5.15.0/drivers/gpu/drm/i915/display/intel_bios.c @@ -2013,6 +2013,15 @@ case HDMI_MAX_DATA_RATE_PLATFORM: max_tmds_clock = 0; break; + case HDMI_MAX_DATA_RATE_594: + max_tmds_clock = 594000; + break; + case HDMI_MAX_DATA_RATE_340: + max_tmds_clock = 340000; + break; + case HDMI_MAX_DATA_RATE_300: + max_tmds_clock = 300000; + break; case HDMI_MAX_DATA_RATE_297: max_tmds_clock = 297000; break; diff -u linux-5.15.0/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c linux-5.15.0/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c --- linux-5.15.0/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ linux-5.15.0/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -96,6 +96,14 @@ #define INTEL_EDP_BRIGHTNESS_OPTIMIZATION_1 0x359 +enum intel_dp_aux_backlight_modparam { + INTEL_DP_AUX_BACKLIGHT_AUTO = -1, + INTEL_DP_AUX_BACKLIGHT_OFF = 0, + INTEL_DP_AUX_BACKLIGHT_ON = 1, + INTEL_DP_AUX_BACKLIGHT_FORCE_VESA = 2, + INTEL_DP_AUX_BACKLIGHT_FORCE_INTEL = 3, +}; + /* Intel EDP backlight callbacks */ static bool intel_dp_aux_supports_hdr_backlight(struct intel_connector *connector) @@ -125,6 +133,24 @@ return false; } + /* + * If we don't have HDR static metadata there is no way to + * runtime detect used range for nits based control. For now + * do not use Intel proprietary eDP backlight control if we + * don't have this data in panel EDID. In case we find panel + * which supports only nits based control, but doesn't provide + * HDR static metadata we need to start maintaining table of + * ranges for such panels. + */ + if (i915->params.enable_dpcd_backlight != INTEL_DP_AUX_BACKLIGHT_FORCE_INTEL && + !(connector->base.hdr_sink_metadata.hdmi_type1.metadata_type & + BIT(HDMI_STATIC_METADATA_TYPE1))) { + drm_info(&i915->drm, + "Panel is missing HDR static metadata. Possible support for Intel HDR backlight interface is not used. If your backlight controls don't work try booting with i915.enable_dpcd_backlight=%d. needs this, please file a _new_ bug report on drm/i915, see " FDO_BUG_URL " for details.\n", + INTEL_DP_AUX_BACKLIGHT_FORCE_INTEL); + return false; + } + panel->backlight.edp.intel.sdr_uses_aux = tcon_cap[2] & INTEL_EDP_SDR_TCON_BRIGHTNESS_AUX_CAP; @@ -373,14 +399,6 @@ .get = intel_dp_aux_vesa_get_backlight, }; -enum intel_dp_aux_backlight_modparam { - INTEL_DP_AUX_BACKLIGHT_AUTO = -1, - INTEL_DP_AUX_BACKLIGHT_OFF = 0, - INTEL_DP_AUX_BACKLIGHT_ON = 1, - INTEL_DP_AUX_BACKLIGHT_FORCE_VESA = 2, - INTEL_DP_AUX_BACKLIGHT_FORCE_INTEL = 3, -}; - int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector) { struct drm_device *dev = connector->base.dev; diff -u linux-5.15.0/drivers/gpu/drm/i915/i915_reg.h linux-5.15.0/drivers/gpu/drm/i915/i915_reg.h --- linux-5.15.0/drivers/gpu/drm/i915/i915_reg.h +++ linux-5.15.0/drivers/gpu/drm/i915/i915_reg.h @@ -7458,7 +7458,7 @@ #define _SEL_FETCH_PLANE_BASE_6_A 0x70940 #define _SEL_FETCH_PLANE_BASE_7_A 0x70960 #define _SEL_FETCH_PLANE_BASE_CUR_A 0x70880 -#define _SEL_FETCH_PLANE_BASE_1_B 0x70990 +#define _SEL_FETCH_PLANE_BASE_1_B 0x71890 #define _SEL_FETCH_PLANE_BASE_A(plane) _PICK(plane, \ _SEL_FETCH_PLANE_BASE_1_A, \ diff -u linux-5.15.0/drivers/gpu/drm/msm/dp/dp_display.c linux-5.15.0/drivers/gpu/drm/msm/dp/dp_display.c --- linux-5.15.0/drivers/gpu/drm/msm/dp/dp_display.c +++ linux-5.15.0/drivers/gpu/drm/msm/dp/dp_display.c @@ -551,12 +551,6 @@ mutex_unlock(&dp->event_mutex); - /* - * add fail safe mode outside event_mutex scope - * to avoid potiential circular lock with drm thread - */ - dp_panel_add_fail_safe_mode(dp->dp_display.connector); - /* uevent will complete connection part */ return 0; }; diff -u linux-5.15.0/drivers/gpu/drm/msm/dp/dp_panel.c linux-5.15.0/drivers/gpu/drm/msm/dp/dp_panel.c --- linux-5.15.0/drivers/gpu/drm/msm/dp/dp_panel.c +++ linux-5.15.0/drivers/gpu/drm/msm/dp/dp_panel.c @@ -151,15 +151,6 @@ return rc; } -void dp_panel_add_fail_safe_mode(struct drm_connector *connector) -{ - /* fail safe edid */ - mutex_lock(&connector->dev->mode_config.mutex); - if (drm_add_modes_noedid(connector, 640, 480)) - drm_set_preferred_mode(connector, 640, 480); - mutex_unlock(&connector->dev->mode_config.mutex); -} - int dp_panel_read_sink_caps(struct dp_panel *dp_panel, struct drm_connector *connector) { @@ -215,8 +206,6 @@ rc = -ETIMEDOUT; goto end; } - - dp_panel_add_fail_safe_mode(connector); } if (panel->aux_cfg_update_done) { reverted: --- linux-5.15.0/drivers/gpu/drm/msm/dp/dp_panel.h +++ linux-5.15.0.orig/drivers/gpu/drm/msm/dp/dp_panel.h @@ -59,7 +59,6 @@ int dp_panel_deinit(struct dp_panel *dp_panel); int dp_panel_timing_cfg(struct dp_panel *dp_panel); void dp_panel_dump_regs(struct dp_panel *dp_panel); -void dp_panel_add_fail_safe_mode(struct drm_connector *connector); int dp_panel_read_sink_caps(struct dp_panel *dp_panel, struct drm_connector *connector); u32 dp_panel_get_mode_bpp(struct dp_panel *dp_panel, u32 mode_max_bpp, diff -u linux-5.15.0/drivers/gpu/drm/vc4/vc4_dsi.c linux-5.15.0/drivers/gpu/drm/vc4/vc4_dsi.c --- linux-5.15.0/drivers/gpu/drm/vc4/vc4_dsi.c +++ linux-5.15.0/drivers/gpu/drm/vc4/vc4_dsi.c @@ -846,7 +846,7 @@ unsigned long phy_clock; int ret; - ret = pm_runtime_get_sync(dev); + ret = pm_runtime_resume_and_get(dev); if (ret) { DRM_ERROR("Failed to runtime PM enable on DSI%d\n", dsi->variant->port); return; diff -u linux-5.15.0/drivers/hwmon/adt7470.c linux-5.15.0/drivers/hwmon/adt7470.c --- linux-5.15.0/drivers/hwmon/adt7470.c +++ linux-5.15.0/drivers/hwmon/adt7470.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -294,11 +295,10 @@ adt7470_read_temperatures(data); mutex_unlock(&data->lock); - set_current_state(TASK_INTERRUPTIBLE); if (kthread_should_stop()) break; - schedule_timeout(msecs_to_jiffies(data->auto_update_interval)); + schedule_timeout_interruptible(msecs_to_jiffies(data->auto_update_interval)); } return 0; diff -u linux-5.15.0/drivers/hwmon/pmbus/pmbus_core.c linux-5.15.0/drivers/hwmon/pmbus/pmbus_core.c --- linux-5.15.0/drivers/hwmon/pmbus/pmbus_core.c +++ linux-5.15.0/drivers/hwmon/pmbus/pmbus_core.c @@ -2326,6 +2326,9 @@ data->has_status_word = true; } + /* Make sure PEC is disabled, will be enabled later if needed */ + client->flags &= ~I2C_CLIENT_PEC; + /* Enable PEC if the controller and bus supports it */ if (!(data->flags & PMBUS_NO_CAPABILITY)) { ret = i2c_smbus_read_byte_data(client, PMBUS_CAPABILITY); diff -u linux-5.15.0/drivers/iio/dac/ad5446.c linux-5.15.0/drivers/iio/dac/ad5446.c --- linux-5.15.0/drivers/iio/dac/ad5446.c +++ linux-5.15.0/drivers/iio/dac/ad5446.c @@ -178,7 +178,7 @@ switch (m) { case IIO_CHAN_INFO_RAW: - *val = st->cached_val; + *val = st->cached_val >> chan->scan_type.shift; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: *val = st->vref_mv; diff -u linux-5.15.0/drivers/infiniband/hw/irdma/utils.c linux-5.15.0/drivers/infiniband/hw/irdma/utils.c --- linux-5.15.0/drivers/infiniband/hw/irdma/utils.c +++ linux-5.15.0/drivers/infiniband/hw/irdma/utils.c @@ -258,18 +258,16 @@ u32 local_ipaddr[4] = {}; bool ipv4 = true; - real_dev = rdma_vlan_dev_real_dev(netdev); - if (!real_dev) - real_dev = netdev; - - ibdev = ib_device_get_by_netdev(real_dev, RDMA_DRIVER_IRDMA); - if (!ibdev) - return NOTIFY_DONE; - - iwdev = to_iwdev(ibdev); - switch (event) { case NETEVENT_NEIGH_UPDATE: + real_dev = rdma_vlan_dev_real_dev(netdev); + if (!real_dev) + real_dev = netdev; + ibdev = ib_device_get_by_netdev(real_dev, RDMA_DRIVER_IRDMA); + if (!ibdev) + return NOTIFY_DONE; + + iwdev = to_iwdev(ibdev); p = (__be32 *)neigh->primary_key; if (neigh->tbl->family == AF_INET6) { ipv4 = false; @@ -290,13 +288,12 @@ irdma_manage_arp_cache(iwdev->rf, neigh->ha, local_ipaddr, ipv4, IRDMA_ARP_DELETE); + ib_device_put(ibdev); break; default: break; } - ib_device_put(ibdev); - return NOTIFY_DONE; } diff -u linux-5.15.0/drivers/infiniband/hw/irdma/verbs.c linux-5.15.0/drivers/infiniband/hw/irdma/verbs.c --- linux-5.15.0/drivers/infiniband/hw/irdma/verbs.c +++ linux-5.15.0/drivers/infiniband/hw/irdma/verbs.c @@ -1617,13 +1617,13 @@ if (issue_modify_qp && iwqp->ibqp_state > IB_QPS_RTS) { if (dont_wait) { - if (iwqp->cm_id && iwqp->hw_tcp_state) { + if (iwqp->hw_tcp_state) { spin_lock_irqsave(&iwqp->lock, flags); iwqp->hw_tcp_state = IRDMA_TCP_STATE_CLOSED; iwqp->last_aeq = IRDMA_AE_RESET_SENT; spin_unlock_irqrestore(&iwqp->lock, flags); - irdma_cm_disconn(iwqp); } + irdma_cm_disconn(iwqp); } else { int close_timer_started; diff -u linux-5.15.0/drivers/iommu/apple-dart.c linux-5.15.0/drivers/iommu/apple-dart.c --- linux-5.15.0/drivers/iommu/apple-dart.c +++ linux-5.15.0/drivers/iommu/apple-dart.c @@ -757,6 +757,7 @@ .of_xlate = apple_dart_of_xlate, .def_domain_type = apple_dart_def_domain_type, .pgsize_bitmap = -1UL, /* Restricted during dart probe */ + .owner = THIS_MODULE, }; static irqreturn_t apple_dart_irq(int irq, void *dev) @@ -832,16 +833,15 @@ dart->dev = dev; spin_lock_init(&dart->lock); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + dart->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res); + if (IS_ERR(dart->regs)) + return PTR_ERR(dart->regs); + if (resource_size(res) < 0x4000) { dev_err(dev, "MMIO region too small (%pr)\n", res); return -EINVAL; } - dart->regs = devm_ioremap_resource(dev, res); - if (IS_ERR(dart->regs)) - return PTR_ERR(dart->regs); - dart->irq = platform_get_irq(pdev, 0); if (dart->irq < 0) return -ENODEV; diff -u linux-5.15.0/drivers/iommu/intel/iommu.c linux-5.15.0/drivers/iommu/intel/iommu.c --- linux-5.15.0/drivers/iommu/intel/iommu.c +++ linux-5.15.0/drivers/iommu/intel/iommu.c @@ -1645,7 +1645,8 @@ unsigned long pfn, unsigned int pages, int ih, int map) { - unsigned int mask = ilog2(__roundup_pow_of_two(pages)); + unsigned int aligned_pages = __roundup_pow_of_two(pages); + unsigned int mask = ilog2(aligned_pages); uint64_t addr = (uint64_t)pfn << VTD_PAGE_SHIFT; u16 did = domain->iommu_did[iommu->seq_id]; @@ -1657,10 +1658,30 @@ if (domain_use_first_level(domain)) { domain_flush_piotlb(iommu, domain, addr, pages, ih); } else { + unsigned long bitmask = aligned_pages - 1; + + /* + * PSI masks the low order bits of the base address. If the + * address isn't aligned to the mask, then compute a mask value + * needed to ensure the target range is flushed. + */ + if (unlikely(bitmask & pfn)) { + unsigned long end_pfn = pfn + pages - 1, shared_bits; + + /* + * Since end_pfn <= pfn + bitmask, the only way bits + * higher than bitmask can differ in pfn and end_pfn is + * by carrying. This means after masking out bitmask, + * high bits starting with the first set bit in + * shared_bits are all equal in both pfn and end_pfn. + */ + shared_bits = ~(pfn ^ end_pfn) & ~bitmask; + mask = shared_bits ? __ffs(shared_bits) : BITS_PER_LONG; + } + /* * Fallback to domain selective flush if no PSI support or - * the size is too big. PSI requires page size to be 2 ^ x, - * and the base address is naturally aligned to the size. + * the size is too big. */ if (!cap_pgsel_inv(iommu->cap) || mask > cap_max_amask_val(iommu->cap)) diff -u linux-5.15.0/drivers/memory/renesas-rpc-if.c linux-5.15.0/drivers/memory/renesas-rpc-if.c --- linux-5.15.0/drivers/memory/renesas-rpc-if.c +++ linux-5.15.0/drivers/memory/renesas-rpc-if.c @@ -162,25 +162,39 @@ /* - * Custom accessor functions to ensure SMRDR0 and SMWDR0 are always accessed - * with proper width. Requires SMENR_SPIDE to be correctly set before! + * Custom accessor functions to ensure SM[RW]DR[01] are always accessed with + * proper width. Requires rpcif.xfer_size to be correctly set before! */ static int rpcif_reg_read(void *context, unsigned int reg, unsigned int *val) { struct rpcif *rpc = context; - if (reg == RPCIF_SMRDR0 || reg == RPCIF_SMWDR0) { - u32 spide = readl(rpc->base + RPCIF_SMENR) & RPCIF_SMENR_SPIDE(0xF); - - if (spide == 0x8) { + switch (reg) { + case RPCIF_SMRDR0: + case RPCIF_SMWDR0: + switch (rpc->xfer_size) { + case 1: *val = readb(rpc->base + reg); return 0; - } else if (spide == 0xC) { + + case 2: *val = readw(rpc->base + reg); return 0; - } else if (spide != 0xF) { + + case 4: + case 8: + *val = readl(rpc->base + reg); + return 0; + + default: return -EILSEQ; } + + case RPCIF_SMRDR1: + case RPCIF_SMWDR1: + if (rpc->xfer_size != 8) + return -EILSEQ; + break; } *val = readl(rpc->base + reg); @@ -192,18 +206,34 @@ { struct rpcif *rpc = context; - if (reg == RPCIF_SMRDR0 || reg == RPCIF_SMWDR0) { - u32 spide = readl(rpc->base + RPCIF_SMENR) & RPCIF_SMENR_SPIDE(0xF); - - if (spide == 0x8) { + switch (reg) { + case RPCIF_SMWDR0: + switch (rpc->xfer_size) { + case 1: writeb(val, rpc->base + reg); return 0; - } else if (spide == 0xC) { + + case 2: writew(val, rpc->base + reg); return 0; - } else if (spide != 0xF) { + + case 4: + case 8: + writel(val, rpc->base + reg); + return 0; + + default: return -EILSEQ; } + + case RPCIF_SMWDR1: + if (rpc->xfer_size != 8) + return -EILSEQ; + break; + + case RPCIF_SMRDR0: + case RPCIF_SMRDR1: + return -EPERM; } writel(val, rpc->base + reg); @@ -442,6 +472,7 @@ smenr |= RPCIF_SMENR_SPIDE(rpcif_bits_set(rpc, nbytes)); regmap_write(rpc->regmap, RPCIF_SMENR, smenr); + rpc->xfer_size = nbytes; memcpy(data, rpc->buffer + pos, nbytes); if (nbytes == 8) { @@ -506,6 +537,7 @@ regmap_write(rpc->regmap, RPCIF_SMENR, smenr); regmap_write(rpc->regmap, RPCIF_SMCR, rpc->smcr | RPCIF_SMCR_SPIE); + rpc->xfer_size = nbytes; ret = wait_msg_xfer_end(rpc); if (ret) goto err_out; diff -u linux-5.15.0/drivers/misc/eeprom/at25.c linux-5.15.0/drivers/misc/eeprom/at25.c --- linux-5.15.0/drivers/misc/eeprom/at25.c +++ linux-5.15.0/drivers/misc/eeprom/at25.c @@ -30,6 +30,8 @@ */ #define FM25_SN_LEN 8 /* serial number length */ +#define EE_MAXADDRLEN 3 /* 24 bit addresses, up to 2 MBytes */ + struct at25_data { struct spi_device *spi; struct mutex lock; @@ -38,6 +40,7 @@ struct nvmem_config nvmem_config; struct nvmem_device *nvmem; u8 sernum[FM25_SN_LEN]; + u8 command[EE_MAXADDRLEN + 1]; }; #define AT25_WREN 0x06 /* latch the write enable */ @@ -60,8 +63,6 @@ #define FM25_ID_LEN 9 /* ID length */ -#define EE_MAXADDRLEN 3 /* 24 bit addresses, up to 2 MBytes */ - /* Specs often allow 5 msec for a page write, sometimes 20 msec; * it's important to recover from write timeouts. */ @@ -76,7 +77,6 @@ { struct at25_data *at25 = priv; char *buf = val; - u8 command[EE_MAXADDRLEN + 1]; u8 *cp; ssize_t status; struct spi_transfer t[2]; @@ -90,12 +90,15 @@ if (unlikely(!count)) return -EINVAL; - cp = command; + cp = at25->command; instr = AT25_READ; if (at25->chip.flags & EE_INSTR_BIT3_IS_ADDR) if (offset >= (1U << (at25->addrlen * 8))) instr |= AT25_INSTR_BIT3; + + mutex_lock(&at25->lock); + *cp++ = instr; /* 8/16/24-bit address is written MSB first */ @@ -114,7 +117,7 @@ spi_message_init(&m); memset(t, 0, sizeof(t)); - t[0].tx_buf = command; + t[0].tx_buf = at25->command; t[0].len = at25->addrlen + 1; spi_message_add_tail(&t[0], &m); @@ -122,8 +125,6 @@ t[1].len = count; spi_message_add_tail(&t[1], &m); - mutex_lock(&at25->lock); - /* Read it all at once. * * REVISIT that's potentially a problem with large chips, if @@ -151,7 +152,7 @@ spi_message_init(&m); memset(t, 0, sizeof(t)); - t[0].tx_buf = &command; + t[0].tx_buf = at25->command; t[0].len = 1; spi_message_add_tail(&t[0], &m); @@ -161,6 +162,8 @@ mutex_lock(&at25->lock); + at25->command[0] = command; + status = spi_sync(at25->spi, &m); dev_dbg(&at25->spi->dev, "read %d aux bytes --> %d\n", len, status); diff -u linux-5.15.0/drivers/mtd/nand/raw/qcom_nandc.c linux-5.15.0/drivers/mtd/nand/raw/qcom_nandc.c --- linux-5.15.0/drivers/mtd/nand/raw/qcom_nandc.c +++ linux-5.15.0/drivers/mtd/nand/raw/qcom_nandc.c @@ -2641,10 +2641,23 @@ ecc->engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; mtd_set_ooblayout(mtd, &qcom_nand_ooblayout_ops); + /* Free the initially allocated BAM transaction for reading the ONFI params */ + if (nandc->props->is_bam) + free_bam_transaction(nandc); nandc->max_cwperpage = max_t(unsigned int, nandc->max_cwperpage, cwperpage); + /* Now allocate the BAM transaction based on updated max_cwperpage */ + if (nandc->props->is_bam) { + nandc->bam_txn = alloc_bam_transaction(nandc); + if (!nandc->bam_txn) { + dev_err(nandc->dev, + "failed to allocate bam transaction\n"); + return -ENOMEM; + } + } + /* * DATA_UD_BYTES varies based on whether the read/write command protects * spare data with ECC too. We protect spare data by default, so we set @@ -2945,17 +2958,6 @@ if (ret) return ret; - if (nandc->props->is_bam) { - free_bam_transaction(nandc); - nandc->bam_txn = alloc_bam_transaction(nandc); - if (!nandc->bam_txn) { - dev_err(nandc->dev, - "failed to allocate bam transaction\n"); - nand_cleanup(chip); - return -ENOMEM; - } - } - ret = mtd_device_parse_register(mtd, probes, NULL, NULL, 0); if (ret) nand_cleanup(chip); diff -u linux-5.15.0/drivers/net/bonding/bond_main.c linux-5.15.0/drivers/net/bonding/bond_main.c --- linux-5.15.0/drivers/net/bonding/bond_main.c +++ linux-5.15.0/drivers/net/bonding/bond_main.c @@ -3817,14 +3817,19 @@ return true; } -static u32 bond_ip_hash(u32 hash, struct flow_keys *flow) +static u32 bond_ip_hash(u32 hash, struct flow_keys *flow, int xmit_policy) { hash ^= (__force u32)flow_get_u32_dst(flow) ^ (__force u32)flow_get_u32_src(flow); hash ^= (hash >> 16); hash ^= (hash >> 8); + /* discard lowest hash bit to deal with the common even ports pattern */ - return hash >> 1; + if (xmit_policy == BOND_XMIT_POLICY_LAYER34 || + xmit_policy == BOND_XMIT_POLICY_ENCAP34) + return hash >> 1; + + return hash; } /* Generate hash based on xmit policy. If @skb is given it is used to linearize @@ -3854,7 +3859,7 @@ memcpy(&hash, &flow.ports.ports, sizeof(hash)); } - return bond_ip_hash(hash, &flow); + return bond_ip_hash(hash, &flow, bond->params.xmit_policy); } /** @@ -5012,7 +5017,7 @@ /* L4 */ memcpy(&hash, &flow.ports.ports, sizeof(hash)); /* L3 */ - return bond_ip_hash(hash, &flow); + return bond_ip_hash(hash, &flow, BOND_XMIT_POLICY_LAYER34); } static struct net_device *__bond_sk_get_lower_dev(struct bonding *bond, diff -u linux-5.15.0/drivers/net/dsa/lantiq_gswip.c linux-5.15.0/drivers/net/dsa/lantiq_gswip.c --- linux-5.15.0/drivers/net/dsa/lantiq_gswip.c +++ linux-5.15.0/drivers/net/dsa/lantiq_gswip.c @@ -1663,9 +1663,6 @@ break; case PHY_INTERFACE_MODE_RMII: miicfg |= GSWIP_MII_CFG_MODE_RMIIM; - - /* Configure the RMII clock as output: */ - miicfg |= GSWIP_MII_CFG_RMII_CLK; break; case PHY_INTERFACE_MODE_RGMII: case PHY_INTERFACE_MODE_RGMII_ID: diff -u linux-5.15.0/drivers/net/dsa/mt7530.c linux-5.15.0/drivers/net/dsa/mt7530.c --- linux-5.15.0/drivers/net/dsa/mt7530.c +++ linux-5.15.0/drivers/net/dsa/mt7530.c @@ -2216,6 +2216,7 @@ ret = of_get_phy_mode(mac_np, &interface); if (ret && ret != -ENODEV) { of_node_put(mac_np); + of_node_put(phy_node); return ret; } id = of_mdio_parse_addr(ds->dev, phy_node); diff -u linux-5.15.0/drivers/net/ethernet/aquantia/atlantic/aq_nic.c linux-5.15.0/drivers/net/ethernet/aquantia/atlantic/aq_nic.c --- linux-5.15.0/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +++ linux-5.15.0/drivers/net/ethernet/aquantia/atlantic/aq_nic.c @@ -480,8 +480,8 @@ if (err < 0) goto err_exit; - for (i = 0U, aq_vec = self->aq_vec[0]; - self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i]) { + for (i = 0U; self->aq_vecs > i; ++i) { + aq_vec = self->aq_vec[i]; err = aq_vec_start(aq_vec); if (err < 0) goto err_exit; @@ -511,8 +511,8 @@ mod_timer(&self->polling_timer, jiffies + AQ_CFG_POLLING_TIMER_INTERVAL); } else { - for (i = 0U, aq_vec = self->aq_vec[0]; - self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i]) { + for (i = 0U; self->aq_vecs > i; ++i) { + aq_vec = self->aq_vec[i]; err = aq_pci_func_alloc_irq(self, i, self->ndev->name, aq_vec_isr, aq_vec, aq_vec_get_affinity_mask(aq_vec)); diff -u linux-5.15.0/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c linux-5.15.0/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c --- linux-5.15.0/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c +++ linux-5.15.0/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c @@ -444,22 +444,22 @@ static int aq_pm_freeze(struct device *dev) { - return aq_suspend_common(dev, false); + return aq_suspend_common(dev, true); } static int aq_pm_suspend_poweroff(struct device *dev) { - return aq_suspend_common(dev, true); + return aq_suspend_common(dev, false); } static int aq_pm_thaw(struct device *dev) { - return atl_resume_common(dev, false); + return atl_resume_common(dev, true); } static int aq_pm_resume_restore(struct device *dev) { - return atl_resume_common(dev, true); + return atl_resume_common(dev, false); } static const struct dev_pm_ops aq_pm_ops = { diff -u linux-5.15.0/drivers/net/ethernet/aquantia/atlantic/aq_vec.c linux-5.15.0/drivers/net/ethernet/aquantia/atlantic/aq_vec.c --- linux-5.15.0/drivers/net/ethernet/aquantia/atlantic/aq_vec.c +++ linux-5.15.0/drivers/net/ethernet/aquantia/atlantic/aq_vec.c @@ -43,8 +43,8 @@ if (!self) { err = -EINVAL; } else { - for (i = 0U, ring = self->ring[0]; - self->tx_rings > i; ++i, ring = self->ring[i]) { + for (i = 0U; self->tx_rings > i; ++i) { + ring = self->ring[i]; u64_stats_update_begin(&ring[AQ_VEC_RX_ID].stats.rx.syncp); ring[AQ_VEC_RX_ID].stats.rx.polls++; u64_stats_update_end(&ring[AQ_VEC_RX_ID].stats.rx.syncp); @@ -182,8 +182,8 @@ self->aq_hw_ops = aq_hw_ops; self->aq_hw = aq_hw; - for (i = 0U, ring = self->ring[0]; - self->tx_rings > i; ++i, ring = self->ring[i]) { + for (i = 0U; self->tx_rings > i; ++i) { + ring = self->ring[i]; err = aq_ring_init(&ring[AQ_VEC_TX_ID], ATL_RING_TX); if (err < 0) goto err_exit; @@ -224,8 +224,8 @@ unsigned int i = 0U; int err = 0; - for (i = 0U, ring = self->ring[0]; - self->tx_rings > i; ++i, ring = self->ring[i]) { + for (i = 0U; self->tx_rings > i; ++i) { + ring = self->ring[i]; err = self->aq_hw_ops->hw_ring_tx_start(self->aq_hw, &ring[AQ_VEC_TX_ID]); if (err < 0) @@ -248,8 +248,8 @@ struct aq_ring_s *ring = NULL; unsigned int i = 0U; - for (i = 0U, ring = self->ring[0]; - self->tx_rings > i; ++i, ring = self->ring[i]) { + for (i = 0U; self->tx_rings > i; ++i) { + ring = self->ring[i]; self->aq_hw_ops->hw_ring_tx_stop(self->aq_hw, &ring[AQ_VEC_TX_ID]); @@ -268,8 +268,8 @@ if (!self) goto err_exit; - for (i = 0U, ring = self->ring[0]; - self->tx_rings > i; ++i, ring = self->ring[i]) { + for (i = 0U; self->tx_rings > i; ++i) { + ring = self->ring[i]; aq_ring_tx_clean(&ring[AQ_VEC_TX_ID]); aq_ring_rx_deinit(&ring[AQ_VEC_RX_ID]); } @@ -297,8 +297,8 @@ if (!self) goto err_exit; - for (i = 0U, ring = self->ring[0]; - self->tx_rings > i; ++i, ring = self->ring[i]) { + for (i = 0U; self->tx_rings > i; ++i) { + ring = self->ring[i]; aq_ring_free(&ring[AQ_VEC_TX_ID]); if (i < self->rx_rings) aq_ring_free(&ring[AQ_VEC_RX_ID]); diff -u linux-5.15.0/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c linux-5.15.0/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c --- linux-5.15.0/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ linux-5.15.0/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -14158,10 +14158,6 @@ /* Stop Tx */ bnx2x_tx_disable(bp); - /* Delete all NAPI objects */ - bnx2x_del_all_napi(bp); - if (CNIC_LOADED(bp)) - bnx2x_del_all_napi_cnic(bp); netdev_reset_tc(bp->dev); del_timer_sync(&bp->timer); @@ -14266,6 +14262,11 @@ bnx2x_drain_tx_queues(bp); bnx2x_send_unload_req(bp, UNLOAD_RECOVERY); bnx2x_netif_stop(bp, 1); + bnx2x_del_all_napi(bp); + + if (CNIC_LOADED(bp)) + bnx2x_del_all_napi_cnic(bp); + bnx2x_free_irq(bp); /* Report UNLOAD_DONE to MCP */ diff -u linux-5.15.0/drivers/net/ethernet/broadcom/bnxt/bnxt.c linux-5.15.0/drivers/net/ethernet/broadcom/bnxt/bnxt.c --- linux-5.15.0/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ linux-5.15.0/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -2699,6 +2699,10 @@ u32 idx = le32_to_cpu(nqcmp->cq_handle_low); struct bnxt_cp_ring_info *cpr2; + /* No more budget for RX work */ + if (budget && work_done >= budget && idx == BNXT_RX_HDL) + break; + cpr2 = cpr->cp_ring_arr[idx]; work_done += __bnxt_poll_work(bp, cpr2, budget - work_done); @@ -10881,7 +10885,7 @@ if (bp->flags & BNXT_FLAG_CHIP_P5) return bnxt_rfs_supported(bp); - if (!(bp->flags & BNXT_FLAG_MSIX_CAP) || !bnxt_can_reserve_rings(bp)) + if (!(bp->flags & BNXT_FLAG_MSIX_CAP) || !bnxt_can_reserve_rings(bp) || !bp->rx_nr_rings) return false; vnics = 1 + bp->rx_nr_rings; @@ -13087,10 +13091,9 @@ goto init_dflt_ring_err; bp->tx_nr_rings_per_tc = bp->tx_nr_rings; - if (bnxt_rfs_supported(bp) && bnxt_rfs_capable(bp)) { - bp->flags |= BNXT_FLAG_RFS; - bp->dev->features |= NETIF_F_NTUPLE; - } + + bnxt_set_dflt_rfs(bp); + init_dflt_ring_err: bnxt_ulp_irq_restart(bp, rc); return rc; diff -u linux-5.15.0/drivers/net/ethernet/broadcom/genet/bcmgenet.c linux-5.15.0/drivers/net/ethernet/broadcom/genet/bcmgenet.c --- linux-5.15.0/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ linux-5.15.0/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -1991,6 +1991,11 @@ return skb; } +static void bcmgenet_hide_tsb(struct sk_buff *skb) +{ + __skb_pull(skb, sizeof(struct status_64)); +} + static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev) { struct bcmgenet_priv *priv = netdev_priv(dev); @@ -2097,6 +2102,8 @@ } GENET_CB(skb)->last_cb = tx_cb_ptr; + + bcmgenet_hide_tsb(skb); skb_tx_timestamp(skb); /* Decrement total BD count and advance our write pointer */ diff -u linux-5.15.0/drivers/net/ethernet/cadence/macb_main.c linux-5.15.0/drivers/net/ethernet/cadence/macb_main.c --- linux-5.15.0/drivers/net/ethernet/cadence/macb_main.c +++ linux-5.15.0/drivers/net/ethernet/cadence/macb_main.c @@ -1689,6 +1689,7 @@ unsigned int head = queue->tx_head; unsigned int tail = queue->tx_tail; struct macb *bp = queue->bp; + unsigned int head_idx, tbqp; if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) queue_writel(queue, ISR, MACB_BIT(TXUBR)); @@ -1696,6 +1697,13 @@ if (head == tail) return; + tbqp = queue_readl(queue, TBQP) / macb_dma_desc_get_size(bp); + tbqp = macb_adj_dma_desc_idx(bp, macb_tx_ring_wrap(bp, tbqp)); + head_idx = macb_adj_dma_desc_idx(bp, macb_tx_ring_wrap(bp, head)); + + if (tbqp == head_idx) + return; + macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART)); } diff -u linux-5.15.0/drivers/net/ethernet/freescale/fec_main.c linux-5.15.0/drivers/net/ethernet/freescale/fec_main.c --- linux-5.15.0/drivers/net/ethernet/freescale/fec_main.c +++ linux-5.15.0/drivers/net/ethernet/freescale/fec_main.c @@ -3726,7 +3726,7 @@ ARRAY_SIZE(out_val)); if (ret) { dev_dbg(&fep->pdev->dev, "no stop mode property\n"); - return ret; + goto out; } fep->stop_gpr.gpr = syscon_node_to_regmap(gpr_np); diff -u linux-5.15.0/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c linux-5.15.0/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c --- linux-5.15.0/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ linux-5.15.0/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -5092,6 +5092,13 @@ set_bit(HNS3_NIC_STATE_RXD_ADV_LAYOUT_ENABLE, &priv->state); } +static void hns3_state_uninit(struct hnae3_handle *handle) +{ + struct hns3_nic_priv *priv = handle->priv; + + clear_bit(HNS3_NIC_STATE_INITED, &priv->state); +} + static int hns3_client_init(struct hnae3_handle *handle) { struct pci_dev *pdev = handle->pdev; @@ -5209,7 +5216,9 @@ return ret; out_reg_netdev_fail: + hns3_state_uninit(handle); hns3_dbg_uninit(handle); + hns3_client_stop(handle); out_client_start: hns3_free_rx_cpu_rmap(netdev); hns3_nic_uninit_irq(priv); diff -u linux-5.15.0/drivers/net/ethernet/ibm/ibmvnic.c linux-5.15.0/drivers/net/ethernet/ibm/ibmvnic.c --- linux-5.15.0/drivers/net/ethernet/ibm/ibmvnic.c +++ linux-5.15.0/drivers/net/ethernet/ibm/ibmvnic.c @@ -2961,13 +2961,8 @@ { struct ibmvnic_adapter *adapter = netdev_priv(netdev); - if (adapter->priv_flags & IBMVNIC_USE_SERVER_MAXES) { - ring->rx_max_pending = adapter->max_rx_add_entries_per_subcrq; - ring->tx_max_pending = adapter->max_tx_entries_per_subcrq; - } else { - ring->rx_max_pending = IBMVNIC_MAX_QUEUE_SZ; - ring->tx_max_pending = IBMVNIC_MAX_QUEUE_SZ; - } + ring->rx_max_pending = adapter->max_rx_add_entries_per_subcrq; + ring->tx_max_pending = adapter->max_tx_entries_per_subcrq; ring->rx_mini_max_pending = 0; ring->rx_jumbo_max_pending = 0; ring->rx_pending = adapter->req_rx_add_entries_per_subcrq; @@ -2980,23 +2975,21 @@ struct ethtool_ringparam *ring) { struct ibmvnic_adapter *adapter = netdev_priv(netdev); - int ret; - ret = 0; + if (ring->rx_pending > adapter->max_rx_add_entries_per_subcrq || + ring->tx_pending > adapter->max_tx_entries_per_subcrq) { + netdev_err(netdev, "Invalid request.\n"); + netdev_err(netdev, "Max tx buffers = %llu\n", + adapter->max_rx_add_entries_per_subcrq); + netdev_err(netdev, "Max rx buffers = %llu\n", + adapter->max_tx_entries_per_subcrq); + return -EINVAL; + } + adapter->desired.rx_entries = ring->rx_pending; adapter->desired.tx_entries = ring->tx_pending; - ret = wait_for_reset(adapter); - - if (!ret && - (adapter->req_rx_add_entries_per_subcrq != ring->rx_pending || - adapter->req_tx_entries_per_subcrq != ring->tx_pending)) - netdev_info(netdev, - "Could not match full ringsize request. Requested: RX %d, TX %d; Allowed: RX %llu, TX %llu\n", - ring->rx_pending, ring->tx_pending, - adapter->req_rx_add_entries_per_subcrq, - adapter->req_tx_entries_per_subcrq); - return ret; + return wait_for_reset(adapter); } static void ibmvnic_get_channels(struct net_device *netdev, @@ -3004,14 +2997,8 @@ { struct ibmvnic_adapter *adapter = netdev_priv(netdev); - if (adapter->priv_flags & IBMVNIC_USE_SERVER_MAXES) { - channels->max_rx = adapter->max_rx_queues; - channels->max_tx = adapter->max_tx_queues; - } else { - channels->max_rx = IBMVNIC_MAX_QUEUES; - channels->max_tx = IBMVNIC_MAX_QUEUES; - } - + channels->max_rx = adapter->max_rx_queues; + channels->max_tx = adapter->max_tx_queues; channels->max_other = 0; channels->max_combined = 0; channels->rx_count = adapter->req_rx_queues; @@ -3024,22 +3011,11 @@ struct ethtool_channels *channels) { struct ibmvnic_adapter *adapter = netdev_priv(netdev); - int ret; - ret = 0; adapter->desired.rx_queues = channels->rx_count; adapter->desired.tx_queues = channels->tx_count; - ret = wait_for_reset(adapter); - - if (!ret && - (adapter->req_rx_queues != channels->rx_count || - adapter->req_tx_queues != channels->tx_count)) - netdev_info(netdev, - "Could not match full channels request. Requested: RX %d, TX %d; Allowed: RX %llu, TX %llu\n", - channels->rx_count, channels->tx_count, - adapter->req_rx_queues, adapter->req_tx_queues); - return ret; + return wait_for_reset(adapter); } static void ibmvnic_get_strings(struct net_device *dev, u32 stringset, u8 *data) @@ -3047,43 +3023,32 @@ struct ibmvnic_adapter *adapter = netdev_priv(dev); int i; - switch (stringset) { - case ETH_SS_STATS: - for (i = 0; i < ARRAY_SIZE(ibmvnic_stats); - i++, data += ETH_GSTRING_LEN) - memcpy(data, ibmvnic_stats[i].name, ETH_GSTRING_LEN); - - for (i = 0; i < adapter->req_tx_queues; i++) { - snprintf(data, ETH_GSTRING_LEN, "tx%d_packets", i); - data += ETH_GSTRING_LEN; - - snprintf(data, ETH_GSTRING_LEN, "tx%d_bytes", i); - data += ETH_GSTRING_LEN; - - snprintf(data, ETH_GSTRING_LEN, - "tx%d_dropped_packets", i); - data += ETH_GSTRING_LEN; - } - - for (i = 0; i < adapter->req_rx_queues; i++) { - snprintf(data, ETH_GSTRING_LEN, "rx%d_packets", i); - data += ETH_GSTRING_LEN; - - snprintf(data, ETH_GSTRING_LEN, "rx%d_bytes", i); - data += ETH_GSTRING_LEN; - - snprintf(data, ETH_GSTRING_LEN, "rx%d_interrupts", i); - data += ETH_GSTRING_LEN; - } - break; - - case ETH_SS_PRIV_FLAGS: - for (i = 0; i < ARRAY_SIZE(ibmvnic_priv_flags); i++) - strcpy(data + i * ETH_GSTRING_LEN, - ibmvnic_priv_flags[i]); - break; - default: + if (stringset != ETH_SS_STATS) return; + + for (i = 0; i < ARRAY_SIZE(ibmvnic_stats); i++, data += ETH_GSTRING_LEN) + memcpy(data, ibmvnic_stats[i].name, ETH_GSTRING_LEN); + + for (i = 0; i < adapter->req_tx_queues; i++) { + snprintf(data, ETH_GSTRING_LEN, "tx%d_packets", i); + data += ETH_GSTRING_LEN; + + snprintf(data, ETH_GSTRING_LEN, "tx%d_bytes", i); + data += ETH_GSTRING_LEN; + + snprintf(data, ETH_GSTRING_LEN, "tx%d_dropped_packets", i); + data += ETH_GSTRING_LEN; + } + + for (i = 0; i < adapter->req_rx_queues; i++) { + snprintf(data, ETH_GSTRING_LEN, "rx%d_packets", i); + data += ETH_GSTRING_LEN; + + snprintf(data, ETH_GSTRING_LEN, "rx%d_bytes", i); + data += ETH_GSTRING_LEN; + + snprintf(data, ETH_GSTRING_LEN, "rx%d_interrupts", i); + data += ETH_GSTRING_LEN; } } @@ -3096,8 +3061,6 @@ return ARRAY_SIZE(ibmvnic_stats) + adapter->req_tx_queues * NUM_TX_STATS + adapter->req_rx_queues * NUM_RX_STATS; - case ETH_SS_PRIV_FLAGS: - return ARRAY_SIZE(ibmvnic_priv_flags); default: return -EOPNOTSUPP; } @@ -3150,26 +3113,6 @@ } } -static u32 ibmvnic_get_priv_flags(struct net_device *netdev) -{ - struct ibmvnic_adapter *adapter = netdev_priv(netdev); - - return adapter->priv_flags; -} - -static int ibmvnic_set_priv_flags(struct net_device *netdev, u32 flags) -{ - struct ibmvnic_adapter *adapter = netdev_priv(netdev); - bool which_maxes = !!(flags & IBMVNIC_USE_SERVER_MAXES); - - if (which_maxes) - adapter->priv_flags |= IBMVNIC_USE_SERVER_MAXES; - else - adapter->priv_flags &= ~IBMVNIC_USE_SERVER_MAXES; - - return 0; -} - static const struct ethtool_ops ibmvnic_ethtool_ops = { .get_drvinfo = ibmvnic_get_drvinfo, .get_msglevel = ibmvnic_get_msglevel, @@ -3183,8 +3126,6 @@ .get_sset_count = ibmvnic_get_sset_count, .get_ethtool_stats = ibmvnic_get_ethtool_stats, .get_link_ksettings = ibmvnic_get_link_ksettings, - .get_priv_flags = ibmvnic_get_priv_flags, - .set_priv_flags = ibmvnic_set_priv_flags, }; /* Routines for managing CRQs/sCRQs */ diff -u linux-5.15.0/drivers/net/ethernet/ibm/ibmvnic.h linux-5.15.0/drivers/net/ethernet/ibm/ibmvnic.h --- linux-5.15.0/drivers/net/ethernet/ibm/ibmvnic.h +++ linux-5.15.0/drivers/net/ethernet/ibm/ibmvnic.h @@ -43,11 +43,6 @@ #define IBMVNIC_RESET_DELAY 100 -static const char ibmvnic_priv_flags[][ETH_GSTRING_LEN] = { -#define IBMVNIC_USE_SERVER_MAXES 0x1 - "use-server-maxes" -}; - struct ibmvnic_login_buffer { __be32 len; __be32 version; @@ -885,7 +880,6 @@ struct ibmvnic_control_ip_offload_buffer ip_offload_ctrl; dma_addr_t ip_offload_ctrl_tok; u32 msg_enable; - u32 priv_flags; /* Vital Product Data (VPD) */ struct ibmvnic_vpd *vpd; diff -u linux-5.15.0/drivers/net/ethernet/intel/e1000e/ich8lan.c linux-5.15.0/drivers/net/ethernet/intel/e1000e/ich8lan.c --- linux-5.15.0/drivers/net/ethernet/intel/e1000e/ich8lan.c +++ linux-5.15.0/drivers/net/ethernet/intel/e1000e/ich8lan.c @@ -1009,8 +1009,8 @@ { u32 reg = link << (E1000_LTRV_REQ_SHIFT + E1000_LTRV_NOSNOOP_SHIFT) | link << E1000_LTRV_REQ_SHIFT | E1000_LTRV_SEND; - u16 max_ltr_enc_d = 0; /* maximum LTR decoded by platform */ - u16 lat_enc_d = 0; /* latency decoded */ + u32 max_ltr_enc_d = 0; /* maximum LTR decoded by platform */ + u32 lat_enc_d = 0; /* latency decoded */ u16 lat_enc = 0; /* latency encoded */ if (link) { diff -u linux-5.15.0/drivers/net/ethernet/intel/igc/igc_i225.c linux-5.15.0/drivers/net/ethernet/intel/igc/igc_i225.c --- linux-5.15.0/drivers/net/ethernet/intel/igc/igc_i225.c +++ linux-5.15.0/drivers/net/ethernet/intel/igc/igc_i225.c @@ -156,8 +156,15 @@ { u32 swfw_sync; - while (igc_get_hw_semaphore_i225(hw)) - ; /* Empty */ + /* Releasing the resource requires first getting the HW semaphore. + * If we fail to get the semaphore, there is nothing we can do, + * except log an error and quit. We are not allowed to hang here + * indefinitely, as it may cause denial of service or system crash. + */ + if (igc_get_hw_semaphore_i225(hw)) { + hw_dbg("Failed to release SW_FW_SYNC.\n"); + return; + } swfw_sync = rd32(IGC_SW_FW_SYNC); swfw_sync &= ~mask; diff -u linux-5.15.0/drivers/net/ethernet/intel/igc/igc_phy.c linux-5.15.0/drivers/net/ethernet/intel/igc/igc_phy.c --- linux-5.15.0/drivers/net/ethernet/intel/igc/igc_phy.c +++ linux-5.15.0/drivers/net/ethernet/intel/igc/igc_phy.c @@ -581,7 +581,7 @@ * the lower time out */ for (i = 0; i < IGC_GEN_POLL_TIMEOUT; i++) { - usleep_range(500, 1000); + udelay(50); mdic = rd32(IGC_MDIC); if (mdic & IGC_MDIC_READY) break; @@ -638,7 +638,7 @@ * the lower time out */ for (i = 0; i < IGC_GEN_POLL_TIMEOUT; i++) { - usleep_range(500, 1000); + udelay(50); mdic = rd32(IGC_MDIC); if (mdic & IGC_MDIC_READY) break; diff -u linux-5.15.0/drivers/net/ethernet/intel/igc/igc_ptp.c linux-5.15.0/drivers/net/ethernet/intel/igc/igc_ptp.c --- linux-5.15.0/drivers/net/ethernet/intel/igc/igc_ptp.c +++ linux-5.15.0/drivers/net/ethernet/intel/igc/igc_ptp.c @@ -996,6 +996,17 @@ igc_ptp_write_i225(adapter, &ts); } +static void igc_ptm_stop(struct igc_adapter *adapter) +{ + struct igc_hw *hw = &adapter->hw; + u32 ctrl; + + ctrl = rd32(IGC_PTM_CTRL); + ctrl &= ~IGC_PTM_CTRL_EN; + + wr32(IGC_PTM_CTRL, ctrl); +} + /** * igc_ptp_suspend - Disable PTP work items and prepare for suspend * @adapter: Board private structure @@ -1013,8 +1024,10 @@ adapter->ptp_tx_skb = NULL; clear_bit_unlock(__IGC_PTP_TX_IN_PROGRESS, &adapter->state); - if (pci_device_is_present(adapter->pdev)) + if (pci_device_is_present(adapter->pdev)) { igc_ptp_time_save(adapter); + igc_ptm_stop(adapter); + } } /** diff -u linux-5.15.0/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c linux-5.15.0/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c --- linux-5.15.0/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c +++ linux-5.15.0/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c @@ -1699,6 +1699,8 @@ static void mlx5_tc_ct_del_ft_cb(struct mlx5_tc_ct_priv *ct_priv, struct mlx5_ct_ft *ft) { + struct mlx5e_priv *priv; + if (!refcount_dec_and_test(&ft->refcount)) return; @@ -1708,6 +1710,8 @@ rhashtable_free_and_destroy(&ft->ct_entries_ht, mlx5_tc_ct_flush_ft_entry, ct_priv); + priv = netdev_priv(ct_priv->netdev); + flush_workqueue(priv->wq); mlx5_tc_ct_free_pre_ct_tables(ft); mapping_remove(ct_priv->zone_mapping, ft->zone_restore_id); kfree(ft); diff -u linux-5.15.0/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c linux-5.15.0/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c --- linux-5.15.0/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ linux-5.15.0/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -2291,6 +2291,17 @@ match.key->vlan_priority); *match_level = MLX5_MATCH_L2; + + if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CVLAN) && + match.mask->vlan_eth_type && + MLX5_CAP_FLOWTABLE_TYPE(priv->mdev, + ft_field_support.outer_second_vid, + fs_type)) { + MLX5_SET(fte_match_set_misc, misc_c, + outer_second_cvlan_tag, 1); + spec->match_criteria_enable |= + MLX5_MATCH_MISC_PARAMETERS; + } } } else if (*match_level != MLX5_MATCH_NONE) { /* cvlan_tag enabled in match criteria and diff -u linux-5.15.0/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c linux-5.15.0/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c --- linux-5.15.0/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +++ linux-5.15.0/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c @@ -111,6 +111,28 @@ } } +static void mlx5_stop_sync_reset_poll(struct mlx5_core_dev *dev) +{ + struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset; + + del_timer_sync(&fw_reset->timer); +} + +static int mlx5_sync_reset_clear_reset_requested(struct mlx5_core_dev *dev, bool poll_health) +{ + struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset; + + if (!test_and_clear_bit(MLX5_FW_RESET_FLAGS_RESET_REQUESTED, &fw_reset->reset_flags)) { + mlx5_core_warn(dev, "Reset request was already cleared\n"); + return -EALREADY; + } + + mlx5_stop_sync_reset_poll(dev); + if (poll_health) + mlx5_start_health_poll(dev); + return 0; +} + static void mlx5_sync_reset_reload_work(struct work_struct *work) { struct mlx5_fw_reset *fw_reset = container_of(work, struct mlx5_fw_reset, @@ -118,6 +140,7 @@ struct mlx5_core_dev *dev = fw_reset->dev; int err; + mlx5_sync_reset_clear_reset_requested(dev, false); mlx5_enter_error_state(dev, true); mlx5_unload_one(dev); err = mlx5_health_wait_pci_up(dev); @@ -127,23 +150,6 @@ mlx5_fw_reset_complete_reload(dev); } -static void mlx5_stop_sync_reset_poll(struct mlx5_core_dev *dev) -{ - struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset; - - del_timer_sync(&fw_reset->timer); -} - -static void mlx5_sync_reset_clear_reset_requested(struct mlx5_core_dev *dev, bool poll_health) -{ - struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset; - - mlx5_stop_sync_reset_poll(dev); - clear_bit(MLX5_FW_RESET_FLAGS_RESET_REQUESTED, &fw_reset->reset_flags); - if (poll_health) - mlx5_start_health_poll(dev); -} - #define MLX5_RESET_POLL_INTERVAL (HZ / 10) static void poll_sync_reset(struct timer_list *t) { @@ -158,7 +164,6 @@ if (fatal_error) { mlx5_core_warn(dev, "Got Device Reset\n"); - mlx5_sync_reset_clear_reset_requested(dev, false); queue_work(fw_reset->wq, &fw_reset->reset_reload_work); return; } @@ -185,13 +190,17 @@ return mlx5_reg_mfrl_set(dev, MLX5_MFRL_REG_RESET_LEVEL3, 0, 2, false); } -static void mlx5_sync_reset_set_reset_requested(struct mlx5_core_dev *dev) +static int mlx5_sync_reset_set_reset_requested(struct mlx5_core_dev *dev) { struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset; + if (test_and_set_bit(MLX5_FW_RESET_FLAGS_RESET_REQUESTED, &fw_reset->reset_flags)) { + mlx5_core_warn(dev, "Reset request was already set\n"); + return -EALREADY; + } mlx5_stop_health_poll(dev, true); - set_bit(MLX5_FW_RESET_FLAGS_RESET_REQUESTED, &fw_reset->reset_flags); mlx5_start_sync_reset_poll(dev); + return 0; } static void mlx5_fw_live_patch_event(struct work_struct *work) @@ -220,7 +229,9 @@ err ? "Failed" : "Sent"); return; } - mlx5_sync_reset_set_reset_requested(dev); + if (mlx5_sync_reset_set_reset_requested(dev)) + return; + err = mlx5_fw_reset_set_reset_sync_ack(dev); if (err) mlx5_core_warn(dev, "PCI Sync FW Update Reset Ack Failed. Error code: %d\n", err); @@ -320,7 +331,8 @@ struct mlx5_core_dev *dev = fw_reset->dev; int err; - mlx5_sync_reset_clear_reset_requested(dev, false); + if (mlx5_sync_reset_clear_reset_requested(dev, false)) + return; mlx5_core_warn(dev, "Sync Reset now. Device is going to reset.\n"); @@ -349,10 +361,8 @@ reset_abort_work); struct mlx5_core_dev *dev = fw_reset->dev; - if (!test_bit(MLX5_FW_RESET_FLAGS_RESET_REQUESTED, &fw_reset->reset_flags)) + if (mlx5_sync_reset_clear_reset_requested(dev, true)) return; - - mlx5_sync_reset_clear_reset_requested(dev, true); mlx5_core_warn(dev, "PCI Sync FW Update Reset Aborted.\n"); } diff -u linux-5.15.0/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c linux-5.15.0/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c --- linux-5.15.0/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c +++ linux-5.15.0/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c @@ -100,6 +100,14 @@ flush_workqueue(mp->wq); } +static void mlx5_lag_fib_set(struct lag_mp *mp, struct fib_info *fi, u32 dst, int dst_len) +{ + mp->fib.mfi = fi; + mp->fib.priority = fi->fib_priority; + mp->fib.dst = dst; + mp->fib.dst_len = dst_len; +} + struct mlx5_fib_event_work { struct work_struct work; struct mlx5_lag *ldev; @@ -110,10 +118,10 @@ }; }; -static void mlx5_lag_fib_route_event(struct mlx5_lag *ldev, - unsigned long event, - struct fib_info *fi) +static void mlx5_lag_fib_route_event(struct mlx5_lag *ldev, unsigned long event, + struct fib_entry_notifier_info *fen_info) { + struct fib_info *fi = fen_info->fi; struct lag_mp *mp = &ldev->lag_mp; struct fib_nh *fib_nh0, *fib_nh1; unsigned int nhs; @@ -121,13 +129,15 @@ /* Handle delete event */ if (event == FIB_EVENT_ENTRY_DEL) { /* stop track */ - if (mp->mfi == fi) - mp->mfi = NULL; + if (mp->fib.mfi == fi) + mp->fib.mfi = NULL; return; } /* Handle multipath entry with lower priority value */ - if (mp->mfi && mp->mfi != fi && fi->fib_priority >= mp->mfi->fib_priority) + if (mp->fib.mfi && mp->fib.mfi != fi && + (mp->fib.dst != fen_info->dst || mp->fib.dst_len != fen_info->dst_len) && + fi->fib_priority >= mp->fib.priority) return; /* Handle add/replace event */ @@ -143,9 +153,9 @@ i++; mlx5_lag_set_port_affinity(ldev, i); + mlx5_lag_fib_set(mp, fi, fen_info->dst, fen_info->dst_len); } - mp->mfi = fi; return; } @@ -165,7 +175,7 @@ } /* First time we see multipath route */ - if (!mp->mfi && !__mlx5_lag_is_active(ldev)) { + if (!mp->fib.mfi && !__mlx5_lag_is_active(ldev)) { struct lag_tracker tracker; tracker = ldev->tracker; @@ -173,7 +183,7 @@ } mlx5_lag_set_port_affinity(ldev, MLX5_LAG_NORMAL_AFFINITY); - mp->mfi = fi; + mlx5_lag_fib_set(mp, fi, fen_info->dst, fen_info->dst_len); } static void mlx5_lag_fib_nexthop_event(struct mlx5_lag *ldev, @@ -184,7 +194,7 @@ struct lag_mp *mp = &ldev->lag_mp; /* Check the nh event is related to the route */ - if (!mp->mfi || mp->mfi != fi) + if (!mp->fib.mfi || mp->fib.mfi != fi) return; /* nh added/removed */ @@ -214,7 +224,7 @@ case FIB_EVENT_ENTRY_REPLACE: case FIB_EVENT_ENTRY_DEL: mlx5_lag_fib_route_event(ldev, fib_work->event, - fib_work->fen_info.fi); + &fib_work->fen_info); fib_info_put(fib_work->fen_info.fi); break; case FIB_EVENT_NH_ADD: @@ -313,7 +323,7 @@ /* Clear mfi, as it might become stale when a route delete event * has been missed, see mlx5_lag_fib_route_event(). */ - ldev->lag_mp.mfi = NULL; + ldev->lag_mp.fib.mfi = NULL; } int mlx5_lag_mp_init(struct mlx5_lag *ldev) @@ -324,7 +334,7 @@ /* always clear mfi, as it might become stale when a route delete event * has been missed */ - mp->mfi = NULL; + mp->fib.mfi = NULL; if (mp->fib_nb.notifier_call) return 0; @@ -356,3 +366,3 @@ mp->fib_nb.notifier_call = NULL; - mp->mfi = NULL; + mp->fib.mfi = NULL; } diff -u linux-5.15.0/drivers/net/ethernet/mscc/ocelot.c linux-5.15.0/drivers/net/ethernet/mscc/ocelot.c --- linux-5.15.0/drivers/net/ethernet/mscc/ocelot.c +++ linux-5.15.0/drivers/net/ethernet/mscc/ocelot.c @@ -1932,6 +1932,8 @@ val = BIT(port); ocelot_rmw_rix(ocelot, val, BIT(port), ANA_PGID_PGID, PGID_MC); + ocelot_rmw_rix(ocelot, val, BIT(port), ANA_PGID_PGID, PGID_MCIPV4); + ocelot_rmw_rix(ocelot, val, BIT(port), ANA_PGID_PGID, PGID_MCIPV6); } static void ocelot_port_set_bcast_flood(struct ocelot *ocelot, int port, diff -u linux-5.15.0/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c linux-5.15.0/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c --- linux-5.15.0/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c +++ linux-5.15.0/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c @@ -65,8 +65,9 @@ struct phy_device *phy_dev = ndev->phydev; u32 val; - writew(SGMII_ADAPTER_DISABLE, - sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG); + if (sgmii_adapter_base) + writew(SGMII_ADAPTER_DISABLE, + sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG); if (splitter_base) { val = readl(splitter_base + EMAC_SPLITTER_CTRL_REG); @@ -88,10 +89,11 @@ writel(val, splitter_base + EMAC_SPLITTER_CTRL_REG); } - writew(SGMII_ADAPTER_ENABLE, - sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG); - if (phy_dev) + if (phy_dev && sgmii_adapter_base) { + writew(SGMII_ADAPTER_ENABLE, + sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG); tse_pcs_fix_mac_speed(&dwmac->pcs, phy_dev, speed); + } } static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device *dev) diff -u linux-5.15.0/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c linux-5.15.0/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c --- linux-5.15.0/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +++ linux-5.15.0/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c @@ -916,6 +916,7 @@ ret = mdio_mux_init(priv->device, mdio_mux, mdio_mux_syscon_switch_fn, &gmac->mux_handle, priv, priv->mii); + of_node_put(mdio_mux); return ret; } diff -u linux-5.15.0/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c linux-5.15.0/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c --- linux-5.15.0/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c +++ linux-5.15.0/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c @@ -71,9 +71,9 @@ writel(value, ioaddr + PTP_TCR); /* wait for present system time initialize to complete */ - return readl_poll_timeout(ioaddr + PTP_TCR, value, + return readl_poll_timeout_atomic(ioaddr + PTP_TCR, value, !(value & PTP_TCR_TSINIT), - 10000, 100000); + 10, 100000); } static int config_addend(void __iomem *ioaddr, u32 addend) diff -u linux-5.15.0/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c linux-5.15.0/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c --- linux-5.15.0/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ linux-5.15.0/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -7081,7 +7081,7 @@ dev_info(priv->device, "TSO feature enabled\n"); } - if (priv->dma_cap.sphen) { + if (priv->dma_cap.sphen && !priv->plat->sph_disable) { ndev->hw_features |= NETIF_F_GRO; priv->sph_cap = true; priv->sph = priv->sph_cap; diff -u linux-5.15.0/drivers/net/ethernet/ti/cpsw_new.c linux-5.15.0/drivers/net/ethernet/ti/cpsw_new.c --- linux-5.15.0/drivers/net/ethernet/ti/cpsw_new.c +++ linux-5.15.0/drivers/net/ethernet/ti/cpsw_new.c @@ -1246,8 +1246,10 @@ data->slave_data = devm_kcalloc(dev, CPSW_SLAVE_PORTS_NUM, sizeof(struct cpsw_slave_data), GFP_KERNEL); - if (!data->slave_data) + if (!data->slave_data) { + of_node_put(tmp_node); return -ENOMEM; + } /* Populate all the child nodes here... */ @@ -1341,6 +1343,7 @@ err_node_put: of_node_put(port_np); + of_node_put(tmp_node); return ret; } diff -u linux-5.15.0/drivers/net/ethernet/xilinx/xilinx_emaclite.c linux-5.15.0/drivers/net/ethernet/xilinx/xilinx_emaclite.c --- linux-5.15.0/drivers/net/ethernet/xilinx/xilinx_emaclite.c +++ linux-5.15.0/drivers/net/ethernet/xilinx/xilinx_emaclite.c @@ -822,10 +822,10 @@ static int xemaclite_mdio_setup(struct net_local *lp, struct device *dev) { struct mii_bus *bus; - int rc; struct resource res; struct device_node *np = of_get_parent(lp->phy_node); struct device_node *npp; + int rc, ret; /* Don't register the MDIO bus if the phy_node or its parent node * can't be found. @@ -835,8 +835,14 @@ return -ENODEV; } npp = of_get_parent(np); - - of_address_to_resource(npp, 0, &res); + ret = of_address_to_resource(npp, 0, &res); + of_node_put(npp); + if (ret) { + dev_err(dev, "%s resource error!\n", + dev->of_node->full_name); + of_node_put(np); + return ret; + } if (lp->ndev->mem_start != res.start) { struct phy_device *phydev; phydev = of_phy_find_device(lp->phy_node); @@ -845,6 +851,7 @@ "MDIO of the phy is not registered yet\n"); else put_device(&phydev->mdio.dev); + of_node_put(np); return 0; } @@ -857,6 +864,7 @@ bus = mdiobus_alloc(); if (!bus) { dev_err(dev, "Failed to allocate mdiobus\n"); + of_node_put(np); return -ENOMEM; } @@ -869,6 +877,7 @@ bus->parent = dev; rc = of_mdiobus_register(bus, np); + of_node_put(np); if (rc) { dev_err(dev, "Failed to register mdio bus.\n"); goto err_register; diff -u linux-5.15.0/drivers/net/vxlan.c linux-5.15.0/drivers/net/vxlan.c --- linux-5.15.0/drivers/net/vxlan.c +++ linux-5.15.0/drivers/net/vxlan.c @@ -873,11 +873,11 @@ rd = kmalloc(sizeof(*rd), GFP_ATOMIC); if (rd == NULL) - return -ENOBUFS; + return -ENOMEM; if (dst_cache_init(&rd->dst_cache, GFP_ATOMIC)) { kfree(rd); - return -ENOBUFS; + return -ENOMEM; } rd->remote_ip = *ip; diff -u linux-5.15.0/drivers/net/wireguard/device.c linux-5.15.0/drivers/net/wireguard/device.c --- linux-5.15.0/drivers/net/wireguard/device.c +++ linux-5.15.0/drivers/net/wireguard/device.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -152,7 +153,7 @@ goto err_peer; } - mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu; + mtu = skb_valid_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu; __skb_queue_head_init(&packets); if (!skb_is_gso(skb)) { diff -u linux-5.15.0/drivers/net/wireless/ath/ath10k/txrx.c linux-5.15.0/drivers/net/wireless/ath/ath10k/txrx.c --- linux-5.15.0/drivers/net/wireless/ath/ath10k/txrx.c +++ linux-5.15.0/drivers/net/wireless/ath/ath10k/txrx.c @@ -125,7 +125,7 @@ tx_done->ack_rssi != ATH10K_INVALID_RSSI) { info->status.ack_signal = ATH10K_DEFAULT_NOISE_FLOOR + tx_done->ack_rssi; - info->status.is_valid_ack_signal = true; + info->status.flags |= IEEE80211_TX_STATUS_ACK_SIGNAL_VALID; } ieee80211_tx_status(htt->ar->hw, msdu); diff -u linux-5.15.0/drivers/net/wireless/ath/ath10k/wmi.c linux-5.15.0/drivers/net/wireless/ath/ath10k/wmi.c --- linux-5.15.0/drivers/net/wireless/ath/ath10k/wmi.c +++ linux-5.15.0/drivers/net/wireless/ath/ath10k/wmi.c @@ -2427,7 +2427,7 @@ info->flags |= IEEE80211_TX_STAT_ACK; info->status.ack_signal = ATH10K_DEFAULT_NOISE_FLOOR + param->ack_rssi; - info->status.is_valid_ack_signal = true; + info->status.flags |= IEEE80211_TX_STATUS_ACK_SIGNAL_VALID; } ieee80211_tx_status_irqsafe(ar->hw, msdu); diff -u linux-5.15.0/drivers/net/wireless/ath/ath11k/dp_tx.c linux-5.15.0/drivers/net/wireless/ath/ath11k/dp_tx.c --- linux-5.15.0/drivers/net/wireless/ath/ath11k/dp_tx.c +++ linux-5.15.0/drivers/net/wireless/ath/ath11k/dp_tx.c @@ -349,7 +349,8 @@ info->flags |= IEEE80211_TX_STAT_ACK; info->status.ack_signal = ATH11K_DEFAULT_NOISE_FLOOR + ts->ack_rssi; - info->status.is_valid_ack_signal = true; + info->status.flags |= + IEEE80211_TX_STATUS_ACK_SIGNAL_VALID; } else { info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; } @@ -453,7 +454,7 @@ info->flags |= IEEE80211_TX_STAT_ACK; info->status.ack_signal = ATH11K_DEFAULT_NOISE_FLOOR + ts->ack_rssi; - info->status.is_valid_ack_signal = true; + info->status.flags |= IEEE80211_TX_STATUS_ACK_SIGNAL_VALID; } if (ts->status == HAL_WBM_TQM_REL_REASON_CMD_REMOVE_TX && diff -u linux-5.15.0/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c linux-5.15.0/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c --- linux-5.15.0/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ linux-5.15.0/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -557,7 +557,7 @@ BRCMF_SDIO_FT_SUB, }; -#define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu)) +#define SDIOD_DRVSTR_KEY(chip, pmu) (((unsigned int)(chip) << 16) | (pmu)) /* SDIO Pad drive strength to select value mappings */ struct sdiod_drive_str { diff -u linux-5.15.0/drivers/nvme/host/core.c linux-5.15.0/drivers/nvme/host/core.c --- linux-5.15.0/drivers/nvme/host/core.c +++ linux-5.15.0/drivers/nvme/host/core.c @@ -1354,6 +1354,8 @@ warn_str, cur->nidl); return -1; } + if (ctrl->quirks & NVME_QUIRK_BOGUS_NID) + return NVME_NIDT_EUI64_LEN; memcpy(ids->eui64, data + sizeof(*cur), NVME_NIDT_EUI64_LEN); return NVME_NIDT_EUI64_LEN; case NVME_NIDT_NGUID: @@ -1362,6 +1364,8 @@ warn_str, cur->nidl); return -1; } + if (ctrl->quirks & NVME_QUIRK_BOGUS_NID) + return NVME_NIDT_NGUID_LEN; memcpy(ids->nguid, data + sizeof(*cur), NVME_NIDT_NGUID_LEN); return NVME_NIDT_NGUID_LEN; case NVME_NIDT_UUID: @@ -1370,6 +1374,8 @@ warn_str, cur->nidl); return -1; } + if (ctrl->quirks & NVME_QUIRK_BOGUS_NID) + return NVME_NIDT_UUID_LEN; uuid_copy(&ids->uuid, data + sizeof(*cur)); return NVME_NIDT_UUID_LEN; case NVME_NIDT_CSI: @@ -1466,12 +1472,18 @@ if ((*id)->ncap == 0) /* namespace not allocated or attached */ goto out_free_id; - if (ctrl->vs >= NVME_VS(1, 1, 0) && - !memchr_inv(ids->eui64, 0, sizeof(ids->eui64))) - memcpy(ids->eui64, (*id)->eui64, sizeof(ids->eui64)); - if (ctrl->vs >= NVME_VS(1, 2, 0) && - !memchr_inv(ids->nguid, 0, sizeof(ids->nguid))) - memcpy(ids->nguid, (*id)->nguid, sizeof(ids->nguid)); + + if (ctrl->quirks & NVME_QUIRK_BOGUS_NID) { + dev_info(ctrl->device, + "Ignoring bogus Namespace Identifiers\n"); + } else { + if (ctrl->vs >= NVME_VS(1, 1, 0) && + !memchr_inv(ids->eui64, 0, sizeof(ids->eui64))) + memcpy(ids->eui64, (*id)->eui64, sizeof(ids->eui64)); + if (ctrl->vs >= NVME_VS(1, 2, 0) && + !memchr_inv(ids->nguid, 0, sizeof(ids->nguid))) + memcpy(ids->nguid, (*id)->nguid, sizeof(ids->nguid)); + } return 0; diff -u linux-5.15.0/drivers/nvme/host/nvme.h linux-5.15.0/drivers/nvme/host/nvme.h --- linux-5.15.0/drivers/nvme/host/nvme.h +++ linux-5.15.0/drivers/nvme/host/nvme.h @@ -144,6 +144,11 @@ * encoding the generation sequence number. */ NVME_QUIRK_SKIP_CID_GEN = (1 << 17), + + /* + * Reports garbage in the namespace identifiers (eui64, nguid, uuid). + */ + NVME_QUIRK_BOGUS_NID = (1 << 18), }; /* diff -u linux-5.15.0/drivers/nvme/host/pci.c linux-5.15.0/drivers/nvme/host/pci.c --- linux-5.15.0/drivers/nvme/host/pci.c +++ linux-5.15.0/drivers/nvme/host/pci.c @@ -3314,7 +3314,10 @@ .driver_data = NVME_QUIRK_IGNORE_DEV_SUBNQN, }, { PCI_VDEVICE(INTEL, 0x5845), /* Qemu emulated controller */ .driver_data = NVME_QUIRK_IDENTIFY_CNS | - NVME_QUIRK_DISABLE_WRITE_ZEROES, }, + NVME_QUIRK_DISABLE_WRITE_ZEROES | + NVME_QUIRK_BOGUS_NID, }, + { PCI_VDEVICE(REDHAT, 0x0010), /* Qemu emulated controller */ + .driver_data = NVME_QUIRK_BOGUS_NID, }, { PCI_DEVICE(0x126f, 0x2263), /* Silicon Motion unidentified */ .driver_data = NVME_QUIRK_NO_NS_DESC_LIST, }, { PCI_DEVICE(0x1bb1, 0x0100), /* Seagate Nytro Flash Storage */ @@ -3352,6 +3355,10 @@ .driver_data = NVME_QUIRK_NO_DEEPEST_PS, }, { PCI_DEVICE(0x2646, 0x2263), /* KINGSTON A2000 NVMe SSD */ .driver_data = NVME_QUIRK_NO_DEEPEST_PS, }, + { PCI_DEVICE(0x1e4B, 0x1002), /* MAXIO MAP1002 */ + .driver_data = NVME_QUIRK_BOGUS_NID, }, + { PCI_DEVICE(0x1e4B, 0x1202), /* MAXIO MAP1202 */ + .driver_data = NVME_QUIRK_BOGUS_NID, }, { PCI_DEVICE(PCI_VENDOR_ID_AMAZON, 0x0061), .driver_data = NVME_QUIRK_DMA_ADDRESS_BITS_48, }, { PCI_DEVICE(PCI_VENDOR_ID_AMAZON, 0x0065), diff -u linux-5.15.0/drivers/pci/controller/pci-aardvark.c linux-5.15.0/drivers/pci/controller/pci-aardvark.c --- linux-5.15.0/drivers/pci/controller/pci-aardvark.c +++ linux-5.15.0/drivers/pci/controller/pci-aardvark.c @@ -38,10 +38,6 @@ #define PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX_EN BIT(6) #define PCIE_CORE_ERR_CAPCTL_ECRC_CHCK BIT(7) #define PCIE_CORE_ERR_CAPCTL_ECRC_CHCK_RCV BIT(8) -#define PCIE_CORE_INT_A_ASSERT_ENABLE 1 -#define PCIE_CORE_INT_B_ASSERT_ENABLE 2 -#define PCIE_CORE_INT_C_ASSERT_ENABLE 3 -#define PCIE_CORE_INT_D_ASSERT_ENABLE 4 /* PIO registers base address and register offsets */ #define PIO_BASE_ADDR 0x4000 #define PIO_CTRL (PIO_BASE_ADDR + 0x0) @@ -102,6 +98,10 @@ #define PCIE_MSG_PM_PME_MASK BIT(7) #define PCIE_ISR0_MASK_REG (CONTROL_BASE_ADDR + 0x44) #define PCIE_ISR0_MSI_INT_PENDING BIT(24) +#define PCIE_ISR0_CORR_ERR BIT(11) +#define PCIE_ISR0_NFAT_ERR BIT(12) +#define PCIE_ISR0_FAT_ERR BIT(13) +#define PCIE_ISR0_ERR_MASK GENMASK(13, 11) #define PCIE_ISR0_INTX_ASSERT(val) BIT(16 + (val)) #define PCIE_ISR0_INTX_DEASSERT(val) BIT(20 + (val)) #define PCIE_ISR0_ALL_MASK GENMASK(31, 0) @@ -115,6 +115,7 @@ #define PCIE_MSI_ADDR_HIGH_REG (CONTROL_BASE_ADDR + 0x54) #define PCIE_MSI_STATUS_REG (CONTROL_BASE_ADDR + 0x58) #define PCIE_MSI_MASK_REG (CONTROL_BASE_ADDR + 0x5C) +#define PCIE_MSI_ALL_MASK GENMASK(31, 0) #define PCIE_MSI_PAYLOAD_REG (CONTROL_BASE_ADDR + 0x9C) #define PCIE_MSI_DATA_MASK GENMASK(15, 0) @@ -271,17 +272,15 @@ u32 actions; } wins[OB_WIN_COUNT]; u8 wins_count; + struct irq_domain *rp_irq_domain; struct irq_domain *irq_domain; struct irq_chip irq_chip; raw_spinlock_t irq_lock; struct irq_domain *msi_domain; struct irq_domain *msi_inner_domain; - struct irq_chip msi_bottom_irq_chip; - struct irq_chip msi_irq_chip; - struct msi_domain_info msi_domain_info; + raw_spinlock_t msi_irq_lock; DECLARE_BITMAP(msi_used, MSI_IRQ_NUM); struct mutex msi_used_lock; - u16 msi_msg; int link_gen; struct pci_bridge_emul bridge; struct gpio_desc *reset_gpio; @@ -476,6 +475,7 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie) { + phys_addr_t msi_addr; u32 reg; int i; @@ -564,25 +564,36 @@ reg |= LANE_COUNT_1; advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG); + /* Set MSI address */ + msi_addr = virt_to_phys(pcie); + advk_writel(pcie, lower_32_bits(msi_addr), PCIE_MSI_ADDR_LOW_REG); + advk_writel(pcie, upper_32_bits(msi_addr), PCIE_MSI_ADDR_HIGH_REG); + /* Enable MSI */ reg = advk_readl(pcie, PCIE_CORE_CTRL2_REG); reg |= PCIE_CORE_CTRL2_MSI_ENABLE; advk_writel(pcie, reg, PCIE_CORE_CTRL2_REG); /* Clear all interrupts */ + advk_writel(pcie, PCIE_MSI_ALL_MASK, PCIE_MSI_STATUS_REG); advk_writel(pcie, PCIE_ISR0_ALL_MASK, PCIE_ISR0_REG); advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_REG); advk_writel(pcie, PCIE_IRQ_ALL_MASK, HOST_CTRL_INT_STATUS_REG); - /* Disable All ISR0/1 Sources */ - reg = PCIE_ISR0_ALL_MASK; + /* Disable All ISR0/1 and MSI Sources */ + advk_writel(pcie, PCIE_ISR0_ALL_MASK, PCIE_ISR0_MASK_REG); + advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_MASK_REG); + advk_writel(pcie, PCIE_MSI_ALL_MASK, PCIE_MSI_MASK_REG); + + /* Unmask summary MSI interrupt */ + reg = advk_readl(pcie, PCIE_ISR0_MASK_REG); reg &= ~PCIE_ISR0_MSI_INT_PENDING; advk_writel(pcie, reg, PCIE_ISR0_MASK_REG); - advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_MASK_REG); - - /* Unmask all MSIs */ - advk_writel(pcie, 0, PCIE_MSI_MASK_REG); + /* Unmask PME interrupt for processing of PME requester */ + reg = advk_readl(pcie, PCIE_ISR0_MASK_REG); + reg &= ~PCIE_MSG_PM_PME_MASK; + advk_writel(pcie, reg, PCIE_ISR0_MASK_REG); /* Enable summary interrupt for GIC SPI source */ reg = PCIE_IRQ_ALL_MASK & (~PCIE_IRQ_ENABLE_INTS_MASK); @@ -776,11 +787,15 @@ case PCI_INTERRUPT_LINE: { /* * From the whole 32bit register we support reading from HW only - * one bit: PCI_BRIDGE_CTL_BUS_RESET. + * two bits: PCI_BRIDGE_CTL_BUS_RESET and PCI_BRIDGE_CTL_SERR. * Other bits are retrieved only from emulated config buffer. */ __le32 *cfgspace = (__le32 *)&bridge->conf; u32 val = le32_to_cpu(cfgspace[PCI_INTERRUPT_LINE / 4]); + if (advk_readl(pcie, PCIE_ISR0_MASK_REG) & PCIE_ISR0_ERR_MASK) + val &= ~(PCI_BRIDGE_CTL_SERR << 16); + else + val |= PCI_BRIDGE_CTL_SERR << 16; if (advk_readl(pcie, PCIE_CORE_CTRL1_REG) & HOT_RESET_GEN) val |= PCI_BRIDGE_CTL_BUS_RESET << 16; else @@ -806,6 +821,19 @@ break; case PCI_INTERRUPT_LINE: + /* + * According to Figure 6-3: Pseudo Logic Diagram for Error + * Message Controls in PCIe base specification, SERR# Enable bit + * in Bridge Control register enable receiving of ERR_* messages + */ + if (mask & (PCI_BRIDGE_CTL_SERR << 16)) { + u32 val = advk_readl(pcie, PCIE_ISR0_MASK_REG); + if (new & (PCI_BRIDGE_CTL_SERR << 16)) + val &= ~PCIE_ISR0_ERR_MASK; + else + val |= PCIE_ISR0_ERR_MASK; + advk_writel(pcie, val, PCIE_ISR0_MASK_REG); + } if (mask & (PCI_BRIDGE_CTL_BUS_RESET << 16)) { u32 val = advk_readl(pcie, PCIE_CORE_CTRL1_REG); if (new & (PCI_BRIDGE_CTL_BUS_RESET << 16)) @@ -833,22 +861,11 @@ *value = PCI_EXP_SLTSTA_PDS << 16; return PCI_BRIDGE_EMUL_HANDLED; - case PCI_EXP_RTCTL: { - u32 val = advk_readl(pcie, PCIE_ISR0_MASK_REG); - *value = (val & PCIE_MSG_PM_PME_MASK) ? 0 : PCI_EXP_RTCTL_PMEIE; - *value |= le16_to_cpu(bridge->pcie_conf.rootctl) & PCI_EXP_RTCTL_CRSSVE; - *value |= PCI_EXP_RTCAP_CRSVIS << 16; - return PCI_BRIDGE_EMUL_HANDLED; - } - - case PCI_EXP_RTSTA: { - u32 isr0 = advk_readl(pcie, PCIE_ISR0_REG); - u32 msglog = advk_readl(pcie, PCIE_MSG_LOG_REG); - *value = msglog >> 16; - if (isr0 & PCIE_MSG_PM_PME_MASK) - *value |= PCI_EXP_RTSTA_PME; - return PCI_BRIDGE_EMUL_HANDLED; - } + /* + * PCI_EXP_RTCTL and PCI_EXP_RTSTA are also supported, but do not need + * to be handled here, because their values are stored in emulated + * config space buffer, and we read them from there when needed. + */ case PCI_EXP_LNKCAP: { u32 val = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + reg); @@ -876,8 +893,13 @@ case PCI_EXP_DEVCAP: case PCI_EXP_DEVCTL: + case PCI_EXP_DEVCAP2: + case PCI_EXP_DEVCTL2: + case PCI_EXP_LNKCAP2: + case PCI_EXP_LNKCTL2: *value = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + reg); return PCI_BRIDGE_EMUL_HANDLED; + default: return PCI_BRIDGE_EMUL_NOT_HANDLED; } @@ -891,10 +913,6 @@ struct advk_pcie *pcie = bridge->data; switch (reg) { - case PCI_EXP_DEVCTL: - advk_writel(pcie, new, PCIE_CORE_PCIEXP_CAP + reg); - break; - case PCI_EXP_LNKCTL: advk_writel(pcie, new, PCIE_CORE_PCIEXP_CAP + reg); if (new & PCI_EXP_LNKCTL_RL) @@ -902,18 +920,23 @@ break; case PCI_EXP_RTCTL: { - /* Only mask/unmask PME interrupt */ - u32 val = advk_readl(pcie, PCIE_ISR0_MASK_REG) & - ~PCIE_MSG_PM_PME_MASK; - if ((new & PCI_EXP_RTCTL_PMEIE) == 0) - val |= PCIE_MSG_PM_PME_MASK; - advk_writel(pcie, val, PCIE_ISR0_MASK_REG); + u16 rootctl = le16_to_cpu(bridge->pcie_conf.rootctl); + /* Only emulation of PMEIE and CRSSVE bits is provided */ + rootctl &= PCI_EXP_RTCTL_PMEIE | PCI_EXP_RTCTL_CRSSVE; + bridge->pcie_conf.rootctl = cpu_to_le16(rootctl); break; } - case PCI_EXP_RTSTA: - new = (new & PCI_EXP_RTSTA_PME) >> 9; - advk_writel(pcie, new, PCIE_ISR0_REG); + /* + * PCI_EXP_RTSTA is also supported, but does not need to be handled + * here, because its value is stored in emulated config space buffer, + * and we write it there when needed. + */ + + case PCI_EXP_DEVCTL: + case PCI_EXP_DEVCTL2: + case PCI_EXP_LNKCTL2: + advk_writel(pcie, new, PCIE_CORE_PCIEXP_CAP + reg); break; default: @@ -952,7 +975,7 @@ bridge->conf.pref_mem_limit = cpu_to_le16(PCI_PREF_RANGE_TYPE_64); /* Support interrupt A for MSI feature */ - bridge->conf.intpin = PCIE_CORE_INT_A_ASSERT_ENABLE; + bridge->conf.intpin = PCI_INTERRUPT_INTA; /* Aardvark HW provides PCIe Capability structure in version 2 */ bridge->pcie_conf.cap = cpu_to_le16(2); @@ -974,8 +997,12 @@ return false; /* - * If the link goes down after we check for link-up, nothing bad - * happens but the config access times out. + * If the link goes down after we check for link-up, we have a problem: + * if a PIO request is executed while link-down, the whole controller + * gets stuck in a non-functional state, and even after link comes up + * again, PIO requests won't work anymore, and a reset of the whole PCIe + * controller is needed. Therefore we need to prevent sending PIO + * requests while the link is down. */ if (!pci_is_root_bus(bus) && !advk_pcie_link_up(pcie)) return false; @@ -1175,10 +1202,10 @@ struct msi_msg *msg) { struct advk_pcie *pcie = irq_data_get_irq_chip_data(data); - phys_addr_t msi_msg = virt_to_phys(&pcie->msi_msg); + phys_addr_t msi_addr = virt_to_phys(pcie); - msg->address_lo = lower_32_bits(msi_msg); - msg->address_hi = upper_32_bits(msi_msg); + msg->address_lo = lower_32_bits(msi_addr); + msg->address_hi = upper_32_bits(msi_addr); msg->data = data->hwirq; } @@ -1188,6 +1215,54 @@ return -EINVAL; } +static void advk_msi_irq_mask(struct irq_data *d) +{ + struct advk_pcie *pcie = d->domain->host_data; + irq_hw_number_t hwirq = irqd_to_hwirq(d); + unsigned long flags; + u32 mask; + + raw_spin_lock_irqsave(&pcie->msi_irq_lock, flags); + mask = advk_readl(pcie, PCIE_MSI_MASK_REG); + mask |= BIT(hwirq); + advk_writel(pcie, mask, PCIE_MSI_MASK_REG); + raw_spin_unlock_irqrestore(&pcie->msi_irq_lock, flags); +} + +static void advk_msi_irq_unmask(struct irq_data *d) +{ + struct advk_pcie *pcie = d->domain->host_data; + irq_hw_number_t hwirq = irqd_to_hwirq(d); + unsigned long flags; + u32 mask; + + raw_spin_lock_irqsave(&pcie->msi_irq_lock, flags); + mask = advk_readl(pcie, PCIE_MSI_MASK_REG); + mask &= ~BIT(hwirq); + advk_writel(pcie, mask, PCIE_MSI_MASK_REG); + raw_spin_unlock_irqrestore(&pcie->msi_irq_lock, flags); +} + +static void advk_msi_top_irq_mask(struct irq_data *d) +{ + pci_msi_mask_irq(d); + irq_chip_mask_parent(d); +} + +static void advk_msi_top_irq_unmask(struct irq_data *d) +{ + pci_msi_unmask_irq(d); + irq_chip_unmask_parent(d); +} + +static struct irq_chip advk_msi_bottom_irq_chip = { + .name = "MSI", + .irq_compose_msi_msg = advk_msi_irq_compose_msi_msg, + .irq_set_affinity = advk_msi_set_affinity, + .irq_mask = advk_msi_irq_mask, + .irq_unmask = advk_msi_irq_unmask, +}; + static int advk_msi_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, unsigned int nr_irqs, void *args) @@ -1204,7 +1279,7 @@ for (i = 0; i < nr_irqs; i++) irq_domain_set_info(domain, virq + i, hwirq + i, - &pcie->msi_bottom_irq_chip, + &advk_msi_bottom_irq_chip, domain->host_data, handle_simple_irq, NULL, NULL); @@ -1260,7 +1335,6 @@ { struct advk_pcie *pcie = h->host_data; - advk_pcie_irq_mask(irq_get_irq_data(virq)); irq_set_status_flags(virq, IRQ_LEVEL); irq_set_chip_and_handler(virq, &pcie->irq_chip, handle_level_irq); @@ -1274,37 +1348,25 @@ .xlate = irq_domain_xlate_onecell, }; +static struct irq_chip advk_msi_irq_chip = { + .name = "advk-MSI", + .irq_mask = advk_msi_top_irq_mask, + .irq_unmask = advk_msi_top_irq_unmask, +}; + +static struct msi_domain_info advk_msi_domain_info = { + .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | + MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX, + .chip = &advk_msi_irq_chip, +}; + static int advk_pcie_init_msi_irq_domain(struct advk_pcie *pcie) { struct device *dev = &pcie->pdev->dev; - struct device_node *node = dev->of_node; - struct irq_chip *bottom_ic, *msi_ic; - struct msi_domain_info *msi_di; - phys_addr_t msi_msg_phys; + raw_spin_lock_init(&pcie->msi_irq_lock); mutex_init(&pcie->msi_used_lock); - bottom_ic = &pcie->msi_bottom_irq_chip; - - bottom_ic->name = "MSI"; - bottom_ic->irq_compose_msi_msg = advk_msi_irq_compose_msi_msg; - bottom_ic->irq_set_affinity = advk_msi_set_affinity; - - msi_ic = &pcie->msi_irq_chip; - msi_ic->name = "advk-MSI"; - - msi_di = &pcie->msi_domain_info; - msi_di->flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | - MSI_FLAG_MULTI_PCI_MSI; - msi_di->chip = msi_ic; - - msi_msg_phys = virt_to_phys(&pcie->msi_msg); - - advk_writel(pcie, lower_32_bits(msi_msg_phys), - PCIE_MSI_ADDR_LOW_REG); - advk_writel(pcie, upper_32_bits(msi_msg_phys), - PCIE_MSI_ADDR_HIGH_REG); - pcie->msi_inner_domain = irq_domain_add_linear(NULL, MSI_IRQ_NUM, &advk_msi_domain_ops, pcie); @@ -1312,8 +1374,9 @@ return -ENOMEM; pcie->msi_domain = - pci_msi_create_irq_domain(of_node_to_fwnode(node), - msi_di, pcie->msi_inner_domain); + pci_msi_create_irq_domain(dev_fwnode(dev), + &advk_msi_domain_info, + pcie->msi_inner_domain); if (!pcie->msi_domain) { irq_domain_remove(pcie->msi_inner_domain); return -ENOMEM; @@ -1354,7 +1417,6 @@ } irq_chip->irq_mask = advk_pcie_irq_mask; - irq_chip->irq_mask_ack = advk_pcie_irq_mask; irq_chip->irq_unmask = advk_pcie_irq_unmask; pcie->irq_domain = @@ -1376,13 +1438,77 @@ irq_domain_remove(pcie->irq_domain); } +static struct irq_chip advk_rp_irq_chip = { + .name = "advk-RP", +}; + +static int advk_pcie_rp_irq_map(struct irq_domain *h, + unsigned int virq, irq_hw_number_t hwirq) +{ + struct advk_pcie *pcie = h->host_data; + + irq_set_chip_and_handler(virq, &advk_rp_irq_chip, handle_simple_irq); + irq_set_chip_data(virq, pcie); + + return 0; +} + +static const struct irq_domain_ops advk_pcie_rp_irq_domain_ops = { + .map = advk_pcie_rp_irq_map, + .xlate = irq_domain_xlate_onecell, +}; + +static int advk_pcie_init_rp_irq_domain(struct advk_pcie *pcie) +{ + pcie->rp_irq_domain = irq_domain_add_linear(NULL, 1, + &advk_pcie_rp_irq_domain_ops, + pcie); + if (!pcie->rp_irq_domain) { + dev_err(&pcie->pdev->dev, "Failed to add Root Port IRQ domain\n"); + return -ENOMEM; + } + + return 0; +} + +static void advk_pcie_remove_rp_irq_domain(struct advk_pcie *pcie) +{ + irq_domain_remove(pcie->rp_irq_domain); +} + +static void advk_pcie_handle_pme(struct advk_pcie *pcie) +{ + u32 requester = advk_readl(pcie, PCIE_MSG_LOG_REG) >> 16; + + advk_writel(pcie, PCIE_MSG_PM_PME_MASK, PCIE_ISR0_REG); + + /* + * PCIE_MSG_LOG_REG contains the last inbound message, so store + * the requester ID only when PME was not asserted yet. + * Also do not trigger PME interrupt when PME is still asserted. + */ + if (!(le32_to_cpu(pcie->bridge.pcie_conf.rootsta) & PCI_EXP_RTSTA_PME)) { + pcie->bridge.pcie_conf.rootsta = cpu_to_le32(requester | PCI_EXP_RTSTA_PME); + + /* + * Trigger PME interrupt only if PMEIE bit in Root Control is set. + * Aardvark HW returns zero for PCI_EXP_FLAGS_IRQ, so use PCIe interrupt 0. + */ + if (!(le16_to_cpu(pcie->bridge.pcie_conf.rootctl) & PCI_EXP_RTCTL_PMEIE)) + return; + + if (generic_handle_domain_irq(pcie->rp_irq_domain, 0) == -EINVAL) + dev_err_ratelimited(&pcie->pdev->dev, "unhandled PME IRQ\n"); + } +} + static void advk_pcie_handle_msi(struct advk_pcie *pcie) { u32 msi_val, msi_mask, msi_status, msi_idx; msi_mask = advk_readl(pcie, PCIE_MSI_MASK_REG); msi_val = advk_readl(pcie, PCIE_MSI_STATUS_REG); - msi_status = msi_val & ~msi_mask; + msi_status = msi_val & ((~msi_mask) & PCIE_MSI_ALL_MASK); for (msi_idx = 0; msi_idx < MSI_IRQ_NUM; msi_idx++) { if (!(BIT(msi_idx) & msi_status)) @@ -1411,6 +1537,22 @@ isr1_mask = advk_readl(pcie, PCIE_ISR1_MASK_REG); isr1_status = isr1_val & ((~isr1_mask) & PCIE_ISR1_ALL_MASK); + /* Process PME interrupt as the first one to do not miss PME requester id */ + if (isr0_status & PCIE_MSG_PM_PME_MASK) + advk_pcie_handle_pme(pcie); + + /* Process ERR interrupt */ + if (isr0_status & PCIE_ISR0_ERR_MASK) { + advk_writel(pcie, PCIE_ISR0_ERR_MASK, PCIE_ISR0_REG); + + /* + * Aardvark HW returns zero for PCI_ERR_ROOT_AER_IRQ, so use + * PCIe interrupt 0 + */ + if (generic_handle_domain_irq(pcie->rp_irq_domain, 0) == -EINVAL) + dev_err_ratelimited(&pcie->pdev->dev, "unhandled ERR IRQ\n"); + } + /* Process MSI interrupts */ if (isr0_status & PCIE_ISR0_MSI_INT_PENDING) advk_pcie_handle_msi(pcie); @@ -1423,7 +1565,9 @@ advk_writel(pcie, PCIE_ISR1_INTX_ASSERT(i), PCIE_ISR1_REG); - generic_handle_domain_irq(pcie->irq_domain, i); + if (generic_handle_domain_irq(pcie->irq_domain, i) == -EINVAL) + dev_err_ratelimited(&pcie->pdev->dev, "unexpected INT%c IRQ\n", + (char)i + 'A'); } } @@ -1444,7 +1588,22 @@ return IRQ_HANDLED; } -static void __maybe_unused advk_pcie_disable_phy(struct advk_pcie *pcie) +static int advk_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +{ + struct advk_pcie *pcie = dev->bus->sysdata; + + /* + * Emulated root bridge has its own emulated irq chip and irq domain. + * Argument pin is the INTx pin (1=INTA, 2=INTB, 3=INTC, 4=INTD) and + * hwirq for irq_create_mapping() is indexed from zero. + */ + if (pci_is_root_bus(dev->bus)) + return irq_create_mapping(pcie->rp_irq_domain, pin - 1); + else + return of_irq_parse_and_map_pci(dev, slot, pin); +} + +static void advk_pcie_disable_phy(struct advk_pcie *pcie) { phy_power_off(pcie->phy); phy_exit(pcie->phy); @@ -1653,11 +1812,21 @@ return ret; } + ret = advk_pcie_init_rp_irq_domain(pcie); + if (ret) { + dev_err(dev, "Failed to initialize irq\n"); + advk_pcie_remove_msi_irq_domain(pcie); + advk_pcie_remove_irq_domain(pcie); + return ret; + } + bridge->sysdata = pcie; bridge->ops = &advk_pcie_ops; + bridge->map_irq = advk_pcie_map_irq; ret = pci_host_probe(bridge); if (ret < 0) { + advk_pcie_remove_rp_irq_domain(pcie); advk_pcie_remove_msi_irq_domain(pcie); advk_pcie_remove_irq_domain(pcie); return ret; @@ -1670,20 +1839,65 @@ { struct advk_pcie *pcie = platform_get_drvdata(pdev); struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie); + u32 val; int i; + /* Remove PCI bus with all devices */ pci_lock_rescan_remove(); pci_stop_root_bus(bridge->bus); pci_remove_root_bus(bridge->bus); pci_unlock_rescan_remove(); + /* Disable Root Bridge I/O space, memory space and bus mastering */ + val = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG); + val &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + advk_writel(pcie, val, PCIE_CORE_CMD_STATUS_REG); + + /* Disable MSI */ + val = advk_readl(pcie, PCIE_CORE_CTRL2_REG); + val &= ~PCIE_CORE_CTRL2_MSI_ENABLE; + advk_writel(pcie, val, PCIE_CORE_CTRL2_REG); + + /* Clear MSI address */ + advk_writel(pcie, 0, PCIE_MSI_ADDR_LOW_REG); + advk_writel(pcie, 0, PCIE_MSI_ADDR_HIGH_REG); + + /* Mask all interrupts */ + advk_writel(pcie, PCIE_MSI_ALL_MASK, PCIE_MSI_MASK_REG); + advk_writel(pcie, PCIE_ISR0_ALL_MASK, PCIE_ISR0_MASK_REG); + advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_MASK_REG); + advk_writel(pcie, PCIE_IRQ_ALL_MASK, HOST_CTRL_INT_MASK_REG); + + /* Clear all interrupts */ + advk_writel(pcie, PCIE_MSI_ALL_MASK, PCIE_MSI_STATUS_REG); + advk_writel(pcie, PCIE_ISR0_ALL_MASK, PCIE_ISR0_REG); + advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_REG); + advk_writel(pcie, PCIE_IRQ_ALL_MASK, HOST_CTRL_INT_STATUS_REG); + + /* Remove IRQ domains */ + advk_pcie_remove_rp_irq_domain(pcie); advk_pcie_remove_msi_irq_domain(pcie); advk_pcie_remove_irq_domain(pcie); + /* Free config space for emulated root bridge */ + pci_bridge_emul_cleanup(&pcie->bridge); + + /* Assert PERST# signal which prepares PCIe card for power down */ + if (pcie->reset_gpio) + gpiod_set_value_cansleep(pcie->reset_gpio, 1); + + /* Disable link training */ + val = advk_readl(pcie, PCIE_CORE_CTRL0_REG); + val &= ~LINK_TRAINING_EN; + advk_writel(pcie, val, PCIE_CORE_CTRL0_REG); + /* Disable outbound address windows mapping */ for (i = 0; i < OB_WIN_COUNT; i++) advk_pcie_disable_ob_win(pcie, i); + /* Disable phy */ + advk_pcie_disable_phy(pcie); + return 0; } diff -u linux-5.15.0/drivers/pci/controller/vmd.c linux-5.15.0/drivers/pci/controller/vmd.c --- linux-5.15.0/drivers/pci/controller/vmd.c +++ linux-5.15.0/drivers/pci/controller/vmd.c @@ -6,7 +6,6 @@ #include #include -#include #include #include #include @@ -777,8 +776,7 @@ * acceptable because the guest is usually CPU-limited and MSI * remapping doesn't become a performance bottleneck. */ - if (iommu_capable(vmd->dev->dev.bus, IOMMU_CAP_INTR_REMAP) || - !(features & VMD_FEAT_CAN_BYPASS_MSI_REMAP) || + if (!(features & VMD_FEAT_CAN_BYPASS_MSI_REMAP) || offset[0] || offset[1]) { ret = vmd_alloc_irqs(vmd); if (ret) @@ -817,6 +815,9 @@ vmd_attach_resources(vmd); if (vmd->irq_domain) dev_set_msi_domain(&vmd->bus->dev, vmd->irq_domain); + else + dev_set_msi_domain(&vmd->bus->dev, + dev_get_msi_domain(&vmd->dev->dev)); vmd_acpi_begin(); diff -u linux-5.15.0/drivers/pci/pci-bridge-emul.c linux-5.15.0/drivers/pci/pci-bridge-emul.c --- linux-5.15.0/drivers/pci/pci-bridge-emul.c +++ linux-5.15.0/drivers/pci/pci-bridge-emul.c @@ -270,6 +270,49 @@ .ro = GENMASK(15, 0) | PCI_EXP_RTSTA_PENDING, .w1c = PCI_EXP_RTSTA_PME, }, + + [PCI_EXP_DEVCAP2 / 4] = { + /* + * Device capabilities 2 register has reserved bits [30:27]. + * Also bits [26:24] are reserved for non-upstream ports. + */ + .ro = BIT(31) | GENMASK(23, 0), + }, + + [PCI_EXP_DEVCTL2 / 4] = { + /* + * Device control 2 register is RW. Bit 11 is reserved for + * non-upstream ports. + * + * Device status 2 register is reserved. + */ + .rw = GENMASK(15, 12) | GENMASK(10, 0), + }, + + [PCI_EXP_LNKCAP2 / 4] = { + /* Link capabilities 2 register has reserved bits [30:25] and 0. */ + .ro = BIT(31) | GENMASK(24, 1), + }, + + [PCI_EXP_LNKCTL2 / 4] = { + /* + * Link control 2 register is RW. + * + * Link status 2 register has bits 5, 15 W1C; + * bits 10, 11 reserved and others are RO. + */ + .rw = GENMASK(15, 0), + .w1c = (BIT(15) | BIT(5)) << 16, + .ro = (GENMASK(14, 12) | GENMASK(9, 6) | GENMASK(4, 0)) << 16, + }, + + [PCI_EXP_SLTCAP2 / 4] = { + /* Slot capabilities 2 register is reserved. */ + }, + + [PCI_EXP_SLTCTL2 / 4] = { + /* Both Slot control 2 and Slot status 2 registers are reserved. */ + }, }; /* @@ -284,7 +327,11 @@ { BUILD_BUG_ON(sizeof(bridge->conf) != PCI_BRIDGE_CONF_END); - bridge->conf.class_revision |= cpu_to_le32(PCI_CLASS_BRIDGE_PCI << 16); + /* + * class_revision: Class is high 24 bits and revision is low 8 bit of this member, + * while class for PCI Bridge Normal Decode has the 24-bit value: PCI_CLASS_BRIDGE_PCI << 8 + */ + bridge->conf.class_revision |= cpu_to_le32((PCI_CLASS_BRIDGE_PCI << 8) << 8); bridge->conf.header_type = PCI_HEADER_TYPE_BRIDGE; bridge->conf.cache_line_size = 0x10; bridge->conf.status = cpu_to_le16(PCI_STATUS_CAP_LIST); diff -u linux-5.15.0/drivers/pinctrl/pinctrl-rockchip.c linux-5.15.0/drivers/pinctrl/pinctrl-rockchip.c --- linux-5.15.0/drivers/pinctrl/pinctrl-rockchip.c +++ linux-5.15.0/drivers/pinctrl/pinctrl-rockchip.c @@ -455,95 +455,110 @@ static struct rockchip_mux_recalced_data rk3308_mux_recalced_data[] = { { + /* gpio1b6_sel */ .num = 1, .pin = 14, .reg = 0x28, .bit = 12, .mask = 0xf }, { + /* gpio1b7_sel */ .num = 1, .pin = 15, .reg = 0x2c, .bit = 0, .mask = 0x3 }, { + /* gpio1c2_sel */ .num = 1, .pin = 18, .reg = 0x30, .bit = 4, .mask = 0xf }, { + /* gpio1c3_sel */ .num = 1, .pin = 19, .reg = 0x30, .bit = 8, .mask = 0xf }, { + /* gpio1c4_sel */ .num = 1, .pin = 20, .reg = 0x30, .bit = 12, .mask = 0xf }, { + /* gpio1c5_sel */ .num = 1, .pin = 21, .reg = 0x34, .bit = 0, .mask = 0xf }, { + /* gpio1c6_sel */ .num = 1, .pin = 22, .reg = 0x34, .bit = 4, .mask = 0xf }, { + /* gpio1c7_sel */ .num = 1, .pin = 23, .reg = 0x34, .bit = 8, .mask = 0xf }, { + /* gpio3b4_sel */ .num = 3, .pin = 12, .reg = 0x68, .bit = 8, .mask = 0xf }, { + /* gpio3b5_sel */ .num = 3, .pin = 13, .reg = 0x68, .bit = 12, .mask = 0xf }, { + /* gpio2a2_sel */ .num = 2, .pin = 2, - .reg = 0x608, - .bit = 0, - .mask = 0x7 + .reg = 0x40, + .bit = 4, + .mask = 0x3 }, { + /* gpio2a3_sel */ .num = 2, .pin = 3, - .reg = 0x608, - .bit = 4, - .mask = 0x7 + .reg = 0x40, + .bit = 6, + .mask = 0x3 }, { + /* gpio2c0_sel */ .num = 2, .pin = 16, - .reg = 0x610, - .bit = 8, - .mask = 0x7 + .reg = 0x50, + .bit = 0, + .mask = 0x3 }, { + /* gpio3b2_sel */ .num = 3, .pin = 10, - .reg = 0x610, - .bit = 0, - .mask = 0x7 + .reg = 0x68, + .bit = 4, + .mask = 0x3 }, { + /* gpio3b3_sel */ .num = 3, .pin = 11, - .reg = 0x610, - .bit = 4, - .mask = 0x7 + .reg = 0x68, + .bit = 6, + .mask = 0x3 }, }; diff -u linux-5.15.0/drivers/pinctrl/stm32/pinctrl-stm32.c linux-5.15.0/drivers/pinctrl/stm32/pinctrl-stm32.c --- linux-5.15.0/drivers/pinctrl/stm32/pinctrl-stm32.c +++ linux-5.15.0/drivers/pinctrl/stm32/pinctrl-stm32.c @@ -225,6 +225,13 @@ pinctrl_gpio_free(chip->base + offset); } +static int stm32_gpio_get_noclk(struct gpio_chip *chip, unsigned int offset) +{ + struct stm32_gpio_bank *bank = gpiochip_get_data(chip); + + return !!(readl_relaxed(bank->base + STM32_GPIO_IDR) & BIT(offset)); +} + static int stm32_gpio_get(struct gpio_chip *chip, unsigned offset) { struct stm32_gpio_bank *bank = gpiochip_get_data(chip); @@ -232,7 +239,7 @@ clk_enable(bank->clk); - ret = !!(readl_relaxed(bank->base + STM32_GPIO_IDR) & BIT(offset)); + ret = stm32_gpio_get_noclk(chip, offset); clk_disable(bank->clk); @@ -311,8 +318,12 @@ struct stm32_gpio_bank *bank = d->domain->host_data; int level; + /* Do not access the GPIO if this is not LEVEL triggered IRQ. */ + if (!(bank->irq_type[d->hwirq] & IRQ_TYPE_LEVEL_MASK)) + return; + /* If level interrupt type then retrig */ - level = stm32_gpio_get(&bank->gpio_chip, d->hwirq); + level = stm32_gpio_get_noclk(&bank->gpio_chip, d->hwirq); if ((level == 0 && bank->irq_type[d->hwirq] == IRQ_TYPE_LEVEL_LOW) || (level == 1 && bank->irq_type[d->hwirq] == IRQ_TYPE_LEVEL_HIGH)) irq_chip_retrigger_hierarchy(d); @@ -354,6 +365,7 @@ { struct stm32_gpio_bank *bank = irq_data->domain->host_data; struct stm32_pinctrl *pctl = dev_get_drvdata(bank->gpio_chip.parent); + unsigned long flags; int ret; ret = stm32_gpio_direction_input(&bank->gpio_chip, irq_data->hwirq); @@ -367,6 +379,10 @@ return ret; } + flags = irqd_get_trigger_type(irq_data); + if (flags & IRQ_TYPE_LEVEL_MASK) + clk_enable(bank->clk); + return 0; } @@ -374,6 +390,9 @@ { struct stm32_gpio_bank *bank = irq_data->domain->host_data; + if (bank->irq_type[irq_data->hwirq] & IRQ_TYPE_LEVEL_MASK) + clk_disable(bank->clk); + gpiochip_unlock_as_irq(&bank->gpio_chip, irq_data->hwirq); } diff -u linux-5.15.0/drivers/reset/reset-rzg2l-usbphy-ctrl.c linux-5.15.0/drivers/reset/reset-rzg2l-usbphy-ctrl.c --- linux-5.15.0/drivers/reset/reset-rzg2l-usbphy-ctrl.c +++ linux-5.15.0/drivers/reset/reset-rzg2l-usbphy-ctrl.c @@ -121,7 +121,9 @@ return dev_err_probe(dev, PTR_ERR(priv->rstc), "failed to get reset\n"); - reset_control_deassert(priv->rstc); + error = reset_control_deassert(priv->rstc); + if (error) + return error; priv->rcdev.ops = &rzg2l_usbphy_ctrl_reset_ops; priv->rcdev.of_reset_n_cells = 1; reverted: --- linux-5.15.0/drivers/reset/tegra/reset-bpmp.c +++ linux-5.15.0.orig/drivers/reset/tegra/reset-bpmp.c @@ -20,6 +20,7 @@ struct tegra_bpmp *bpmp = to_tegra_bpmp(rstc); struct mrq_reset_request request; struct tegra_bpmp_message msg; + int err; memset(&request, 0, sizeof(request)); request.cmd = command; @@ -30,7 +31,13 @@ msg.tx.data = &request; msg.tx.size = sizeof(request); + err = tegra_bpmp_transfer(bpmp, &msg); + if (err) + return err; + if (msg.rx.ret) + return -EINVAL; + + return 0; - return tegra_bpmp_transfer(bpmp, &msg); } static int tegra_bpmp_reset_module(struct reset_controller_dev *rstc, diff -u linux-5.15.0/drivers/scsi/libiscsi.c linux-5.15.0/drivers/scsi/libiscsi.c --- linux-5.15.0/drivers/scsi/libiscsi.c +++ linux-5.15.0/drivers/scsi/libiscsi.c @@ -678,7 +678,8 @@ struct iscsi_task *task; itt_t itt; - if (session->state == ISCSI_STATE_TERMINATE) + if (session->state == ISCSI_STATE_TERMINATE || + !test_bit(ISCSI_CONN_FLAG_BOUND, &conn->flags)) return NULL; if (opcode == ISCSI_OP_LOGIN || opcode == ISCSI_OP_TEXT) { @@ -1392,8 +1393,8 @@ if (conn->stop_stage == 0) session->state = ISCSI_STATE_FAILED; - set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); - set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx); + set_bit(ISCSI_CONN_FLAG_SUSPEND_TX, &conn->flags); + set_bit(ISCSI_CONN_FLAG_SUSPEND_RX, &conn->flags); return true; } @@ -1454,7 +1455,7 @@ * Do this after dropping the extra ref because if this was a requeue * it's removed from that list and cleanup_queued_task would miss it. */ - if (test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx)) { + if (test_bit(ISCSI_CONN_FLAG_SUSPEND_TX, &conn->flags)) { /* * Save the task and ref in case we weren't cleaning up this * task and get woken up again. @@ -1532,7 +1533,7 @@ int rc = 0; spin_lock_bh(&conn->session->frwd_lock); - if (test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx)) { + if (test_bit(ISCSI_CONN_FLAG_SUSPEND_TX, &conn->flags)) { ISCSI_DBG_SESSION(conn->session, "Tx suspended!\n"); spin_unlock_bh(&conn->session->frwd_lock); return -ENODATA; @@ -1746,7 +1747,7 @@ goto fault; } - if (test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx)) { + if (test_bit(ISCSI_CONN_FLAG_SUSPEND_TX, &conn->flags)) { reason = FAILURE_SESSION_IN_RECOVERY; sc->result = DID_REQUEUE << 16; goto fault; @@ -1935,7 +1936,7 @@ void iscsi_suspend_queue(struct iscsi_conn *conn) { spin_lock_bh(&conn->session->frwd_lock); - set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); + set_bit(ISCSI_CONN_FLAG_SUSPEND_TX, &conn->flags); spin_unlock_bh(&conn->session->frwd_lock); } EXPORT_SYMBOL_GPL(iscsi_suspend_queue); @@ -1953,7 +1954,7 @@ struct Scsi_Host *shost = conn->session->host; struct iscsi_host *ihost = shost_priv(shost); - set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); + set_bit(ISCSI_CONN_FLAG_SUSPEND_TX, &conn->flags); if (ihost->workq) flush_workqueue(ihost->workq); } @@ -1961,7 +1962,7 @@ static void iscsi_start_tx(struct iscsi_conn *conn) { - clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); + clear_bit(ISCSI_CONN_FLAG_SUSPEND_TX, &conn->flags); iscsi_conn_queue_work(conn); } @@ -2214,6 +2215,8 @@ iscsi_suspend_tx(conn); spin_lock_bh(&session->frwd_lock); + clear_bit(ISCSI_CONN_FLAG_BOUND, &conn->flags); + if (!is_active) { /* * if logout timed out before userspace could even send a PDU @@ -3312,6 +3315,8 @@ spin_lock_bh(&session->frwd_lock); if (is_leading) session->leadconn = conn; + + set_bit(ISCSI_CONN_FLAG_BOUND, &conn->flags); spin_unlock_bh(&session->frwd_lock); /* @@ -3324,8 +3329,8 @@ /* * Unblock xmitworker(), Login Phase will pass through. */ - clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx); - clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); + clear_bit(ISCSI_CONN_FLAG_SUSPEND_RX, &conn->flags); + clear_bit(ISCSI_CONN_FLAG_SUSPEND_TX, &conn->flags); return 0; } EXPORT_SYMBOL_GPL(iscsi_conn_bind); diff -u linux-5.15.0/drivers/scsi/scsi_transport_iscsi.c linux-5.15.0/drivers/scsi/scsi_transport_iscsi.c --- linux-5.15.0/drivers/scsi/scsi_transport_iscsi.c +++ linux-5.15.0/drivers/scsi/scsi_transport_iscsi.c @@ -86,6 +86,9 @@ struct transport_container session_cont; }; +static DEFINE_IDR(iscsi_ep_idr); +static DEFINE_MUTEX(iscsi_ep_idr_mutex); + static atomic_t iscsi_session_nr; /* sysfs session id for next new session */ static struct workqueue_struct *iscsi_eh_timer_workq; @@ -169,6 +172,11 @@ static void iscsi_endpoint_release(struct device *dev) { struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev); + + mutex_lock(&iscsi_ep_idr_mutex); + idr_remove(&iscsi_ep_idr, ep->id); + mutex_unlock(&iscsi_ep_idr_mutex); + kfree(ep); } @@ -181,7 +189,7 @@ show_ep_handle(struct device *dev, struct device_attribute *attr, char *buf) { struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev); - return sysfs_emit(buf, "%llu\n", (unsigned long long) ep->id); + return sysfs_emit(buf, "%d\n", ep->id); } static ISCSI_ATTR(ep, handle, S_IRUGO, show_ep_handle, NULL); @@ -194,48 +202,32 @@ .attrs = iscsi_endpoint_attrs, }; -#define ISCSI_MAX_EPID -1 - -static int iscsi_match_epid(struct device *dev, const void *data) -{ - struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev); - const uint64_t *epid = data; - - return *epid == ep->id; -} - struct iscsi_endpoint * iscsi_create_endpoint(int dd_size) { - struct device *dev; struct iscsi_endpoint *ep; - uint64_t id; - int err; - - for (id = 1; id < ISCSI_MAX_EPID; id++) { - dev = class_find_device(&iscsi_endpoint_class, NULL, &id, - iscsi_match_epid); - if (!dev) - break; - else - put_device(dev); - } - if (id == ISCSI_MAX_EPID) { - printk(KERN_ERR "Too many connections. Max supported %u\n", - ISCSI_MAX_EPID - 1); - return NULL; - } + int err, id; ep = kzalloc(sizeof(*ep) + dd_size, GFP_KERNEL); if (!ep) return NULL; + mutex_lock(&iscsi_ep_idr_mutex); + id = idr_alloc(&iscsi_ep_idr, ep, 0, -1, GFP_NOIO); + if (id < 0) { + mutex_unlock(&iscsi_ep_idr_mutex); + printk(KERN_ERR "Could not allocate endpoint ID. Error %d.\n", + id); + goto free_ep; + } + mutex_unlock(&iscsi_ep_idr_mutex); + ep->id = id; ep->dev.class = &iscsi_endpoint_class; - dev_set_name(&ep->dev, "ep-%llu", (unsigned long long) id); + dev_set_name(&ep->dev, "ep-%d", id); err = device_register(&ep->dev); if (err) - goto free_ep; + goto free_id; err = sysfs_create_group(&ep->dev.kobj, &iscsi_endpoint_group); if (err) @@ -249,6 +241,10 @@ device_unregister(&ep->dev); return NULL; +free_id: + mutex_lock(&iscsi_ep_idr_mutex); + idr_remove(&iscsi_ep_idr, id); + mutex_unlock(&iscsi_ep_idr_mutex); free_ep: kfree(ep); return NULL; @@ -276,14 +272,17 @@ */ struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle) { - struct device *dev; + struct iscsi_endpoint *ep; - dev = class_find_device(&iscsi_endpoint_class, NULL, &handle, - iscsi_match_epid); - if (!dev) - return NULL; + mutex_lock(&iscsi_ep_idr_mutex); + ep = idr_find(&iscsi_ep_idr, handle); + if (!ep) + goto unlock; - return iscsi_dev_to_endpoint(dev); + get_device(&ep->dev); +unlock: + mutex_unlock(&iscsi_ep_idr_mutex); + return ep; } EXPORT_SYMBOL_GPL(iscsi_lookup_endpoint); diff -u linux-5.15.0/drivers/scsi/ufs/ufshcd.c linux-5.15.0/drivers/scsi/ufs/ufshcd.c --- linux-5.15.0/drivers/scsi/ufs/ufshcd.c +++ linux-5.15.0/drivers/scsi/ufs/ufshcd.c @@ -358,7 +358,7 @@ static void ufshcd_add_command_trace(struct ufs_hba *hba, unsigned int tag, enum ufs_trace_str_t str_t) { - u64 lba; + u64 lba = 0; u8 opcode = 0, group_id = 0; u32 intr, doorbell; struct ufshcd_lrb *lrbp = &hba->lrb[tag]; @@ -375,7 +375,6 @@ return; opcode = cmd->cmnd[0]; - lba = scsi_get_lba(cmd); if (opcode == READ_10 || opcode == WRITE_10) { /* @@ -383,6 +382,7 @@ */ transfer_len = be32_to_cpu(lrbp->ucd_req_ptr->sc.exp_data_transfer_len); + lba = scsi_get_lba(cmd); if (opcode == WRITE_10) group_id = lrbp->cmd->cmnd[6]; } else if (opcode == UNMAP) { @@ -390,6 +390,7 @@ * The number of Bytes to be unmapped beginning with the lba. */ transfer_len = blk_rq_bytes(rq); + lba = scsi_get_lba(cmd); } intr = ufshcd_readl(hba, REG_INTERRUPT_STATUS); diff -u linux-5.15.0/drivers/spi/atmel-quadspi.c linux-5.15.0/drivers/spi/atmel-quadspi.c --- linux-5.15.0/drivers/spi/atmel-quadspi.c +++ linux-5.15.0/drivers/spi/atmel-quadspi.c @@ -277,6 +277,9 @@ static bool atmel_qspi_supports_op(struct spi_mem *mem, const struct spi_mem_op *op) { + if (!spi_mem_default_supports_op(mem, op)) + return false; + if (atmel_qspi_find_mode(op) < 0) return false; diff -u linux-5.15.0/drivers/spi/spi-cadence-quadspi.c linux-5.15.0/drivers/spi/spi-cadence-quadspi.c --- linux-5.15.0/drivers/spi/spi-cadence-quadspi.c +++ linux-5.15.0/drivers/spi/spi-cadence-quadspi.c @@ -36,6 +36,7 @@ /* Quirks */ #define CQSPI_NEEDS_WR_DELAY BIT(0) #define CQSPI_DISABLE_DAC_MODE BIT(1) +#define CQSPI_NO_SUPPORT_WR_COMPLETION BIT(3) /* Capabilities */ #define CQSPI_SUPPORTS_OCTAL BIT(0) @@ -83,6 +84,7 @@ u32 wr_delay; bool use_direct_mode; struct cqspi_flash_pdata f_pdata[CQSPI_MAX_CHIPSELECT]; + bool wr_completion; }; struct cqspi_driver_platdata { @@ -797,9 +799,11 @@ * polling on the controller's side. spinand and spi-nor will take * care of polling the status register. */ - reg = readl(reg_base + CQSPI_REG_WR_COMPLETION_CTRL); - reg |= CQSPI_REG_WR_DISABLE_AUTO_POLL; - writel(reg, reg_base + CQSPI_REG_WR_COMPLETION_CTRL); + if (cqspi->wr_completion) { + reg = readl(reg_base + CQSPI_REG_WR_COMPLETION_CTRL); + reg |= CQSPI_REG_WR_DISABLE_AUTO_POLL; + writel(reg, reg_base + CQSPI_REG_WR_COMPLETION_CTRL); + } reg = readl(reg_base + CQSPI_REG_SIZE); reg &= ~CQSPI_REG_SIZE_ADDRESS_MASK; @@ -1226,9 +1230,24 @@ all_false = !op->cmd.dtr && !op->addr.dtr && !op->dummy.dtr && !op->data.dtr; - /* Mixed DTR modes not supported. */ - if (!(all_true || all_false)) + if (all_true) { + /* Right now we only support 8-8-8 DTR mode. */ + if (op->cmd.nbytes && op->cmd.buswidth != 8) + return false; + if (op->addr.nbytes && op->addr.buswidth != 8) + return false; + if (op->data.nbytes && op->data.buswidth != 8) + return false; + } else if (all_false) { + /* Only 1-1-X ops are supported without DTR */ + if (op->cmd.nbytes && op->cmd.buswidth > 1) + return false; + if (op->addr.nbytes && op->addr.buswidth > 1) + return false; + } else { + /* Mixed DTR modes are not supported. */ return false; + } if (all_true) return spi_mem_dtr_supports_op(mem, op); @@ -1517,6 +1536,10 @@ cqspi->master_ref_clk_hz = clk_get_rate(cqspi->clk); master->max_speed_hz = cqspi->master_ref_clk_hz; + + /* write completion is supported by default */ + cqspi->wr_completion = true; + ddata = of_device_get_match_data(dev); if (ddata) { if (ddata->quirks & CQSPI_NEEDS_WR_DELAY) @@ -1526,6 +1549,8 @@ master->mode_bits |= SPI_RX_OCTAL | SPI_TX_OCTAL; if (!(ddata->quirks & CQSPI_DISABLE_DAC_MODE)) cqspi->use_direct_mode = true; + if (ddata->quirks & CQSPI_NO_SUPPORT_WR_COMPLETION) + cqspi->wr_completion = false; } ret = devm_request_irq(dev, irq, cqspi_irq_handler, 0, @@ -1634,6 +1659,10 @@ .quirks = CQSPI_DISABLE_DAC_MODE, }; +static const struct cqspi_driver_platdata socfpga_qspi = { + .quirks = CQSPI_NO_SUPPORT_WR_COMPLETION, +}; + static const struct of_device_id cqspi_dt_ids[] = { { .compatible = "cdns,qspi-nor", @@ -1651,6 +1680,10 @@ .compatible = "intel,lgm-qspi", .data = &intel_lgm_qspi, }, + { + .compatible = "intel,socfpga-qspi", + .data = (void *)&socfpga_qspi, + }, { /* end of table */ } }; diff -u linux-5.15.0/drivers/spi/spi-mtk-nor.c linux-5.15.0/drivers/spi/spi-mtk-nor.c --- linux-5.15.0/drivers/spi/spi-mtk-nor.c +++ linux-5.15.0/drivers/spi/spi-mtk-nor.c @@ -909,7 +909,17 @@ static int __maybe_unused mtk_nor_resume(struct device *dev) { - return pm_runtime_force_resume(dev); + struct spi_controller *ctlr = dev_get_drvdata(dev); + struct mtk_nor *sp = spi_controller_get_devdata(ctlr); + int ret; + + ret = pm_runtime_force_resume(dev); + if (ret) + return ret; + + mtk_nor_init(sp); + + return 0; } static const struct dev_pm_ops mtk_nor_pm_ops = { diff -u linux-5.15.0/drivers/thermal/intel/int340x_thermal/int3400_thermal.c linux-5.15.0/drivers/thermal/intel/int340x_thermal/int3400_thermal.c --- linux-5.15.0/drivers/thermal/intel/int340x_thermal/int3400_thermal.c +++ linux-5.15.0/drivers/thermal/intel/int340x_thermal/int3400_thermal.c @@ -68,7 +68,7 @@ struct odvp_attr { int odvp; struct int3400_thermal_priv *priv; - struct kobj_attribute attr; + struct device_attribute attr; }; static ssize_t data_vault_read(struct file *file, struct kobject *kobj, @@ -312,7 +312,7 @@ return result; } -static ssize_t odvp_show(struct kobject *kobj, struct kobj_attribute *attr, +static ssize_t odvp_show(struct device *dev, struct device_attribute *attr, char *buf) { struct odvp_attr *odvp_attr; diff -u linux-5.15.0/drivers/tty/n_gsm.c linux-5.15.0/drivers/tty/n_gsm.c --- linux-5.15.0/drivers/tty/n_gsm.c +++ linux-5.15.0/drivers/tty/n_gsm.c @@ -73,6 +73,8 @@ */ #define MAX_MRU 1500 #define MAX_MTU 1500 +/* SOF, ADDR, CTRL, LEN1, LEN2, ..., FCS, EOF */ +#define PROT_OVERHEAD 7 #define GSM_NET_TX_TIMEOUT (HZ*10) /* @@ -231,6 +233,7 @@ int initiator; /* Did we initiate connection */ bool dead; /* Has the mux been shut down */ struct gsm_dlci *dlci[NUM_DLCI]; + int old_c_iflag; /* termios c_iflag value before attach */ bool constipated; /* Asked by remote to shut up */ spinlock_t tx_lock; @@ -820,7 +823,7 @@ break; case 2: /* Unstructed with modem bits. Always one byte as we never send inline break data */ - *dp++ = gsm_encode_modem(dlci); + *dp++ = (gsm_encode_modem(dlci) << 1) | EA; break; } WARN_ON(kfifo_out_locked(&dlci->fifo, dp , len, &dlci->lock) != len); @@ -1081,7 +1084,6 @@ { unsigned int addr = 0; unsigned int modem = 0; - unsigned int brk = 0; struct gsm_dlci *dlci; int len = clen; int slen; @@ -1111,17 +1113,8 @@ return; } len--; - if (len > 0) { - while (gsm_read_ea(&brk, *dp++) == 0) { - len--; - if (len == 0) - return; - } - modem <<= 7; - modem |= (brk & 0x7f); - } tty = tty_port_tty_get(&dlci->port); - gsm_process_modem(tty, dlci, modem, slen); + gsm_process_modem(tty, dlci, modem, slen - len); if (tty) { tty_wakeup(tty); tty_kref_put(tty); @@ -1300,11 +1293,12 @@ static void gsm_control_transmit(struct gsm_mux *gsm, struct gsm_control *ctrl) { - struct gsm_msg *msg = gsm_data_alloc(gsm, 0, ctrl->len + 1, gsm->ftype); + struct gsm_msg *msg = gsm_data_alloc(gsm, 0, ctrl->len + 2, gsm->ftype); if (msg == NULL) return; - msg->data[0] = (ctrl->cmd << 1) | 2 | EA; /* command */ - memcpy(msg->data + 1, ctrl->data, ctrl->len); + msg->data[0] = (ctrl->cmd << 1) | CR | EA; /* command */ + msg->data[1] = (ctrl->len << 1) | EA; + memcpy(msg->data + 2, ctrl->data, ctrl->len); gsm_data_queue(gsm->dlci[0], msg); } @@ -1327,7 +1321,6 @@ spin_lock_irqsave(&gsm->control_lock, flags); ctrl = gsm->pending_cmd; if (ctrl) { - gsm->cretries--; if (gsm->cretries == 0) { gsm->pending_cmd = NULL; ctrl->error = -ETIMEDOUT; @@ -1336,6 +1329,7 @@ wake_up(&gsm->event); return; } + gsm->cretries--; gsm_control_transmit(gsm, ctrl); mod_timer(&gsm->t2_timer, jiffies + gsm->t2 * HZ / 100); } @@ -1376,7 +1370,7 @@ /* If DLCI0 is in ADM mode skip retries, it won't respond */ if (gsm->dlci[0]->mode == DLCI_MODE_ADM) - gsm->cretries = 1; + gsm->cretries = 0; else gsm->cretries = gsm->n2; @@ -1424,13 +1418,17 @@ static void gsm_dlci_close(struct gsm_dlci *dlci) { + unsigned long flags; + del_timer(&dlci->t1); if (debug & 8) pr_debug("DLCI %d goes closed.\n", dlci->addr); dlci->state = DLCI_CLOSED; if (dlci->addr != 0) { tty_port_tty_hangup(&dlci->port, false); + spin_lock_irqsave(&dlci->lock, flags); kfifo_reset(&dlci->fifo); + spin_unlock_irqrestore(&dlci->lock, flags); /* Ensure that gsmtty_open() can return. */ tty_port_set_initialized(&dlci->port, 0); wake_up_interruptible(&dlci->port.open_wait); @@ -1593,6 +1591,7 @@ tty = tty_port_tty_get(port); if (tty) { gsm_process_modem(tty, dlci, modem, slen); + tty_wakeup(tty); tty_kref_put(tty); } fallthrough; @@ -1818,7 +1817,6 @@ gsm_response(gsm, address, UA); gsm_dlci_close(dlci); break; - case UA: case UA|PF: if (cr == 0 || dlci == NULL) break; @@ -1962,6 +1960,16 @@ static void gsm1_receive(struct gsm_mux *gsm, unsigned char c) { + /* handle XON/XOFF */ + if ((c & ISO_IEC_646_MASK) == XON) { + gsm->constipated = true; + return; + } else if ((c & ISO_IEC_646_MASK) == XOFF) { + gsm->constipated = false; + /* Kick the link in case it is idling */ + gsm_data_kick(gsm, NULL); + return; + } if (c == GSM1_SOF) { /* EOF is only valid in frame if we have got to the data state and received at least one byte (the FCS) */ @@ -1976,7 +1984,8 @@ } /* Any partial frame was a runt so go back to start */ if (gsm->state != GSM_START) { - gsm->malformed++; + if (gsm->state != GSM_SEARCH) + gsm->malformed++; gsm->state = GSM_START; } /* A SOF in GSM_START means we are still reading idling or @@ -2048,74 +2057,43 @@ gsm->io_error++; } -static int gsm_disconnect(struct gsm_mux *gsm) -{ - struct gsm_dlci *dlci = gsm->dlci[0]; - struct gsm_control *gc; - - if (!dlci) - return 0; - - /* In theory disconnecting DLCI 0 is sufficient but for some - modems this is apparently not the case. */ - gc = gsm_control_send(gsm, CMD_CLD, NULL, 0); - if (gc) - gsm_control_wait(gsm, gc); - - del_timer_sync(&gsm->t2_timer); - /* Now we are sure T2 has stopped */ - - gsm_dlci_begin_close(dlci); - wait_event_interruptible(gsm->event, - dlci->state == DLCI_CLOSED); - - if (signal_pending(current)) - return -EINTR; - - return 0; -} - /** * gsm_cleanup_mux - generic GSM protocol cleanup * @gsm: our mux + * @disc: disconnect link? * * Clean up the bits of the mux which are the same for all framing * protocols. Remove the mux from the mux table, stop all the timers * and then shut down each device hanging up the channels as we go. */ -static void gsm_cleanup_mux(struct gsm_mux *gsm) +static void gsm_cleanup_mux(struct gsm_mux *gsm, bool disc) { int i; struct gsm_dlci *dlci = gsm->dlci[0]; struct gsm_msg *txq, *ntxq; gsm->dead = true; + mutex_lock(&gsm->mutex); - spin_lock(&gsm_mux_lock); - for (i = 0; i < MAX_MUX; i++) { - if (gsm_mux[i] == gsm) { - gsm_mux[i] = NULL; - break; + if (dlci) { + if (disc && dlci->state != DLCI_CLOSED) { + gsm_dlci_begin_close(dlci); + wait_event(gsm->event, dlci->state == DLCI_CLOSED); } + dlci->dead = true; } - spin_unlock(&gsm_mux_lock); - /* open failed before registering => nothing to do */ - if (i == MAX_MUX) - return; + /* Finish outstanding timers, making sure they are done */ del_timer_sync(&gsm->t2_timer); - /* Now we are sure T2 has stopped */ - if (dlci) - dlci->dead = true; - /* Free up any link layer users */ - mutex_lock(&gsm->mutex); - for (i = 0; i < NUM_DLCI; i++) + /* Free up any link layer users and finally the control channel */ + for (i = NUM_DLCI - 1; i >= 0; i--) if (gsm->dlci[i]) gsm_dlci_release(gsm->dlci[i]); mutex_unlock(&gsm->mutex); /* Now wipe the queues */ + tty_ldisc_flush(gsm->tty); list_for_each_entry_safe(txq, ntxq, &gsm->tx_list, list) kfree(txq); INIT_LIST_HEAD(&gsm->tx_list); @@ -2133,7 +2111,6 @@ static int gsm_activate_mux(struct gsm_mux *gsm) { struct gsm_dlci *dlci; - int i = 0; timer_setup(&gsm->t2_timer, gsm_control_retransmit, 0); init_waitqueue_head(&gsm->event); @@ -2145,18 +2122,6 @@ else gsm->receive = gsm1_receive; - spin_lock(&gsm_mux_lock); - for (i = 0; i < MAX_MUX; i++) { - if (gsm_mux[i] == NULL) { - gsm->num = i; - gsm_mux[i] = gsm; - break; - } - } - spin_unlock(&gsm_mux_lock); - if (i == MAX_MUX) - return -EBUSY; - dlci = gsm_dlci_alloc(gsm, 0); if (dlci == NULL) return -ENOMEM; @@ -2172,6 +2137,15 @@ */ static void gsm_free_mux(struct gsm_mux *gsm) { + int i; + + for (i = 0; i < MAX_MUX; i++) { + if (gsm == gsm_mux[i]) { + gsm_mux[i] = NULL; + break; + } + } + mutex_destroy(&gsm->mutex); kfree(gsm->txframe); kfree(gsm->buf); kfree(gsm); @@ -2191,12 +2165,20 @@ static inline void mux_get(struct gsm_mux *gsm) { + unsigned long flags; + + spin_lock_irqsave(&gsm_mux_lock, flags); kref_get(&gsm->ref); + spin_unlock_irqrestore(&gsm_mux_lock, flags); } static inline void mux_put(struct gsm_mux *gsm) { + unsigned long flags; + + spin_lock_irqsave(&gsm_mux_lock, flags); kref_put(&gsm->ref, gsm_free_muxr); + spin_unlock_irqrestore(&gsm_mux_lock, flags); } static inline unsigned int mux_num_to_base(struct gsm_mux *gsm) @@ -2217,6 +2199,7 @@ static struct gsm_mux *gsm_alloc_mux(void) { + int i; struct gsm_mux *gsm = kzalloc(sizeof(struct gsm_mux), GFP_KERNEL); if (gsm == NULL) return NULL; @@ -2225,7 +2208,7 @@ kfree(gsm); return NULL; } - gsm->txframe = kmalloc(2 * MAX_MRU + 2, GFP_KERNEL); + gsm->txframe = kmalloc(2 * (MAX_MTU + PROT_OVERHEAD - 1), GFP_KERNEL); if (gsm->txframe == NULL) { kfree(gsm->buf); kfree(gsm); @@ -2246,6 +2229,26 @@ gsm->mtu = 64; gsm->dead = true; /* Avoid early tty opens */ + /* Store the instance to the mux array or abort if no space is + * available. + */ + spin_lock(&gsm_mux_lock); + for (i = 0; i < MAX_MUX; i++) { + if (!gsm_mux[i]) { + gsm_mux[i] = gsm; + gsm->num = i; + break; + } + } + spin_unlock(&gsm_mux_lock); + if (i == MAX_MUX) { + mutex_destroy(&gsm->mutex); + kfree(gsm->txframe); + kfree(gsm->buf); + kfree(gsm); + return NULL; + } + return gsm; } @@ -2281,7 +2284,7 @@ /* Check the MRU/MTU range looks sane */ if (c->mru > MAX_MRU || c->mtu > MAX_MTU || c->mru < 8 || c->mtu < 8) return -EINVAL; - if (c->n2 < 3) + if (c->n2 > 255) return -EINVAL; if (c->encapsulation > 1) /* Basic, advanced, no I */ return -EINVAL; @@ -2312,19 +2315,11 @@ /* * Close down what is needed, restart and initiate the new - * configuration + * configuration. On the first time there is no DLCI[0] + * and closing or cleaning up is not necessary. */ - - if (need_close || need_restart) { - int ret; - - ret = gsm_disconnect(gsm); - - if (ret) - return ret; - } - if (need_restart) - gsm_cleanup_mux(gsm); + if (need_close || need_restart) + gsm_cleanup_mux(gsm, true); gsm->initiator = c->initiator; gsm->mru = c->mru; @@ -2393,6 +2388,9 @@ int ret, i; gsm->tty = tty_kref_get(tty); + /* Turn off tty XON/XOFF handling to handle it explicitly. */ + gsm->old_c_iflag = tty->termios.c_iflag; + tty->termios.c_iflag &= (IXON | IXOFF); ret = gsm_activate_mux(gsm); if (ret != 0) tty_kref_put(gsm->tty); @@ -2433,7 +2431,8 @@ WARN_ON(tty != gsm->tty); for (i = 1; i < NUM_DLCI; i++) tty_unregister_device(gsm_tty_driver, base + i); - gsm_cleanup_mux(gsm); + /* Restore tty XON/XOFF handling. */ + gsm->tty->termios.c_iflag = gsm->old_c_iflag; tty_kref_put(gsm->tty); gsm->tty = NULL; } @@ -2498,6 +2497,12 @@ { struct gsm_mux *gsm = tty->disc_data; + /* The ldisc locks and closes the port before calling our close. This + * means we have no way to do a proper disconnect. We will not bother + * to do one. + */ + gsm_cleanup_mux(gsm, false); + gsmld_detach_gsm(tty, gsm); gsmld_flush_buffer(tty); @@ -2536,7 +2541,7 @@ ret = gsmld_attach_gsm(tty, gsm); if (ret != 0) { - gsm_cleanup_mux(gsm); + gsm_cleanup_mux(gsm, false); mux_put(gsm); } return ret; @@ -2895,19 +2900,19 @@ static int gsmtty_modem_update(struct gsm_dlci *dlci, u8 brk) { - u8 modembits[5]; + u8 modembits[3]; struct gsm_control *ctrl; int len = 2; - if (brk) + modembits[0] = (dlci->addr << 2) | 2 | EA; /* DLCI, Valid, EA */ + if (!brk) { + modembits[1] = (gsm_encode_modem(dlci) << 1) | EA; + } else { + modembits[1] = gsm_encode_modem(dlci) << 1; + modembits[2] = (brk << 4) | 2 | EA; /* Length, Break, EA */ len++; - - modembits[0] = len << 1 | EA; /* Data bytes */ - modembits[1] = dlci->addr << 2 | 3; /* DLCI, EA, 1 */ - modembits[2] = gsm_encode_modem(dlci) << 1 | EA; - if (brk) - modembits[3] = brk << 4 | 2 | EA; /* Valid, EA */ - ctrl = gsm_control_send(dlci->gsm, CMD_MSC, modembits, len + 1); + } + ctrl = gsm_control_send(dlci->gsm, CMD_MSC, modembits, len); if (ctrl == NULL) return -ENOMEM; return gsm_control_wait(dlci->gsm, ctrl); @@ -3092,13 +3097,17 @@ static void gsmtty_flush_buffer(struct tty_struct *tty) { struct gsm_dlci *dlci = tty->driver_data; + unsigned long flags; + if (dlci->state == DLCI_CLOSED) return; /* Caution needed: If we implement reliable transport classes then the data being transmitted can't simply be junked once it has first hit the stack. Until then we can just blow it away */ + spin_lock_irqsave(&dlci->lock, flags); kfifo_reset(&dlci->fifo); + spin_unlock_irqrestore(&dlci->lock, flags); /* Need to unhook this DLCI from the transmit queue logic */ } diff -u linux-5.15.0/drivers/tty/serial/8250/8250_pci.c linux-5.15.0/drivers/tty/serial/8250/8250_pci.c --- linux-5.15.0/drivers/tty/serial/8250/8250_pci.c +++ linux-5.15.0/drivers/tty/serial/8250/8250_pci.c @@ -2940,7 +2940,7 @@ pbn_panacom2, pbn_panacom4, pbn_plx_romulus, - pbn_endrun_2_4000000, + pbn_endrun_2_3906250, pbn_oxsemi, pbn_oxsemi_1_3906250, pbn_oxsemi_2_3906250, @@ -3472,10 +3472,10 @@ * signal now many ports are available * 2 port 952 Uart support */ - [pbn_endrun_2_4000000] = { + [pbn_endrun_2_3906250] = { .flags = FL_BASE0, .num_ports = 2, - .base_baud = 4000000, + .base_baud = 3906250, .uart_offset = 0x200, .first_offset = 0x1000, }, @@ -4418,7 +4418,7 @@ */ { PCI_VENDOR_ID_ENDRUN, PCI_DEVICE_ID_ENDRUN_1588, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_endrun_2_4000000 }, + pbn_endrun_2_3906250 }, /* * Quatech cards. These actually have configurable clocks but for * now we just use the default. diff -u linux-5.15.0/drivers/tty/serial/8250/8250_port.c linux-5.15.0/drivers/tty/serial/8250/8250_port.c --- linux-5.15.0/drivers/tty/serial/8250/8250_port.c +++ linux-5.15.0/drivers/tty/serial/8250/8250_port.c @@ -3340,7 +3340,7 @@ serial8250_set_divisor(port, baud, quot, frac); serial_port_out(port, UART_LCR, up->lcr); - serial8250_out_MCR(up, UART_MCR_DTR | UART_MCR_RTS); + serial8250_out_MCR(up, up->mcr | UART_MCR_DTR | UART_MCR_RTS); } /* diff -u linux-5.15.0/drivers/tty/serial/amba-pl011.c linux-5.15.0/drivers/tty/serial/amba-pl011.c --- linux-5.15.0/drivers/tty/serial/amba-pl011.c +++ linux-5.15.0/drivers/tty/serial/amba-pl011.c @@ -1288,13 +1288,18 @@ static void pl011_rs485_tx_stop(struct uart_amba_port *uap) { + /* + * To be on the safe side only time out after twice as many iterations + * as fifo size. + */ + const int MAX_TX_DRAIN_ITERS = uap->port.fifosize * 2; struct uart_port *port = &uap->port; int i = 0; u32 cr; /* Wait until hardware tx queue is empty */ while (!pl011_tx_empty(port)) { - if (i == port->fifosize) { + if (i > MAX_TX_DRAIN_ITERS) { dev_warn(port->dev, "timeout while draining hardware tx queue\n"); break; @@ -2099,7 +2104,7 @@ * with the given baud rate. We use this as the poll interval when we * wait for the tx queue to empty. */ - uap->rs485_tx_drain_interval = (bits * 1000 * 1000) / baud; + uap->rs485_tx_drain_interval = DIV_ROUND_UP(bits * 1000 * 1000, baud); pl011_setup_status_masks(port, termios); diff -u linux-5.15.0/drivers/tty/serial/imx.c linux-5.15.0/drivers/tty/serial/imx.c --- linux-5.15.0/drivers/tty/serial/imx.c +++ linux-5.15.0/drivers/tty/serial/imx.c @@ -1438,7 +1438,7 @@ imx_uart_writel(sport, ucr1, UCR1); ucr4 = imx_uart_readl(sport, UCR4) & ~(UCR4_OREN | UCR4_INVR); - if (!sport->dma_is_enabled) + if (!dma_is_inited) ucr4 |= UCR4_OREN; if (sport->inverted_rx) ucr4 |= UCR4_INVR; diff -u linux-5.15.0/drivers/usb/cdns3/cdns3-gadget.c linux-5.15.0/drivers/usb/cdns3/cdns3-gadget.c --- linux-5.15.0/drivers/usb/cdns3/cdns3-gadget.c +++ linux-5.15.0/drivers/usb/cdns3/cdns3-gadget.c @@ -2684,6 +2684,7 @@ struct usb_request *request; struct cdns3_request *priv_req; struct cdns3_trb *trb = NULL; + struct cdns3_trb trb_tmp; int ret; int val; @@ -2693,8 +2694,10 @@ if (request) { priv_req = to_cdns3_request(request); trb = priv_req->trb; - if (trb) + if (trb) { + trb_tmp = *trb; trb->control = trb->control ^ cpu_to_le32(TRB_CYCLE); + } } writel(EP_CMD_CSTALL | EP_CMD_EPRST, &priv_dev->regs->ep_cmd); @@ -2709,7 +2712,7 @@ if (request) { if (trb) - trb->control = trb->control ^ cpu_to_le32(TRB_CYCLE); + *trb = trb_tmp; cdns3_rearm_transfer(priv_ep, 1); } diff -u linux-5.15.0/drivers/usb/core/devio.c linux-5.15.0/drivers/usb/core/devio.c --- linux-5.15.0/drivers/usb/core/devio.c +++ linux-5.15.0/drivers/usb/core/devio.c @@ -1197,12 +1197,16 @@ usb_unlock_device(dev); i = usbfs_start_wait_urb(urb, tmo, &actlen); + + /* Linger a bit, prior to the next control message. */ + if (dev->quirks & USB_QUIRK_DELAY_CTRL_MSG) + msleep(200); usb_lock_device(dev); snoop_urb(dev, NULL, pipe, actlen, i, COMPLETE, tbuf, actlen); if (!i && actlen) { if (copy_to_user(ctrl->data, tbuf, actlen)) { ret = -EFAULT; - goto recv_fault; + goto done; } } } else { @@ -1219,6 +1223,10 @@ usb_unlock_device(dev); i = usbfs_start_wait_urb(urb, tmo, &actlen); + + /* Linger a bit, prior to the next control message. */ + if (dev->quirks & USB_QUIRK_DELAY_CTRL_MSG) + msleep(200); usb_lock_device(dev); snoop_urb(dev, NULL, pipe, actlen, i, COMPLETE, NULL, 0); } @@ -1230,10 +1238,6 @@ } ret = (i < 0 ? i : actlen); - recv_fault: - /* Linger a bit, prior to the next control message. */ - if (dev->quirks & USB_QUIRK_DELAY_CTRL_MSG) - msleep(200); done: kfree(dr); usb_free_urb(urb); diff -u linux-5.15.0/drivers/usb/core/quirks.c linux-5.15.0/drivers/usb/core/quirks.c --- linux-5.15.0/drivers/usb/core/quirks.c +++ linux-5.15.0/drivers/usb/core/quirks.c @@ -404,6 +404,9 @@ { USB_DEVICE(0x0b05, 0x17e0), .driver_info = USB_QUIRK_IGNORE_REMOTE_WAKEUP }, + /* Realtek Semiconductor Corp. Mass Storage Device (Multicard Reader)*/ + { USB_DEVICE(0x0bda, 0x0151), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS }, + /* Realtek hub in Dell WD19 (Type-C) */ { USB_DEVICE(0x0bda, 0x0487), .driver_info = USB_QUIRK_NO_LPM }, @@ -507,6 +510,9 @@ /* DJI CineSSD */ { USB_DEVICE(0x2ca3, 0x0031), .driver_info = USB_QUIRK_NO_LPM }, + /* VCOM device */ + { USB_DEVICE(0x4296, 0x7570), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS }, + /* INTEL VALUE SSD */ { USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME }, diff -u linux-5.15.0/drivers/usb/dwc3/core.c linux-5.15.0/drivers/usb/dwc3/core.c --- linux-5.15.0/drivers/usb/dwc3/core.c +++ linux-5.15.0/drivers/usb/dwc3/core.c @@ -275,7 +275,8 @@ reg = dwc3_readl(dwc->regs, DWC3_DCTL); reg |= DWC3_DCTL_CSFTRST; - dwc3_writel(dwc->regs, DWC3_DCTL, reg); + reg &= ~DWC3_DCTL_RUN_STOP; + dwc3_gadget_dctl_write_safe(dwc, reg); /* * For DWC_usb31 controller 1.90a and later, the DCTL.CSFRST bit @@ -1268,10 +1269,10 @@ u8 lpm_nyet_threshold; u8 tx_de_emphasis; u8 hird_threshold; - u8 rx_thr_num_pkt_prd; - u8 rx_max_burst_prd; - u8 tx_thr_num_pkt_prd; - u8 tx_max_burst_prd; + u8 rx_thr_num_pkt_prd = 0; + u8 rx_max_burst_prd = 0; + u8 tx_thr_num_pkt_prd = 0; + u8 tx_max_burst_prd = 0; u8 tx_fifo_resize_max_num; const char *usb_psy_name; int ret; diff -u linux-5.15.0/drivers/usb/dwc3/dwc3-pci.c linux-5.15.0/drivers/usb/dwc3/dwc3-pci.c --- linux-5.15.0/drivers/usb/dwc3/dwc3-pci.c +++ linux-5.15.0/drivers/usb/dwc3/dwc3-pci.c @@ -44,6 +44,8 @@ #define PCI_DEVICE_ID_INTEL_ADLM 0x54ee #define PCI_DEVICE_ID_INTEL_ADLS 0x7ae1 #define PCI_DEVICE_ID_INTEL_RPLS 0x7a61 +#define PCI_DEVICE_ID_INTEL_MTLP 0x7ec1 +#define PCI_DEVICE_ID_INTEL_MTL 0x7e7e #define PCI_DEVICE_ID_INTEL_TGL 0x9a15 #define PCI_DEVICE_ID_AMD_MR 0x163a @@ -421,6 +423,12 @@ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_RPLS), (kernel_ulong_t) &dwc3_pci_intel_swnode, }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MTLP), + (kernel_ulong_t) &dwc3_pci_intel_swnode, }, + + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MTL), + (kernel_ulong_t) &dwc3_pci_intel_swnode, }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_TGL), (kernel_ulong_t) &dwc3_pci_intel_swnode, }, diff -u linux-5.15.0/drivers/usb/dwc3/gadget.c linux-5.15.0/drivers/usb/dwc3/gadget.c --- linux-5.15.0/drivers/usb/dwc3/gadget.c +++ linux-5.15.0/drivers/usb/dwc3/gadget.c @@ -3199,6 +3199,7 @@ const struct dwc3_event_depevt *event, struct dwc3_request *req, int status) { + int request_status; int ret; if (req->request.num_mapped_sgs) @@ -3219,7 +3220,35 @@ req->needs_extra_trb = false; } - dwc3_gadget_giveback(dep, req, status); + /* + * The event status only reflects the status of the TRB with IOC set. + * For the requests that don't set interrupt on completion, the driver + * needs to check and return the status of the completed TRBs associated + * with the request. Use the status of the last TRB of the request. + */ + if (req->request.no_interrupt) { + struct dwc3_trb *trb; + + trb = dwc3_ep_prev_trb(dep, dep->trb_dequeue); + switch (DWC3_TRB_SIZE_TRBSTS(trb->size)) { + case DWC3_TRBSTS_MISSED_ISOC: + /* Isoc endpoint only */ + request_status = -EXDEV; + break; + case DWC3_TRB_STS_XFER_IN_PROG: + /* Applicable when End Transfer with ForceRM=0 */ + case DWC3_TRBSTS_SETUP_PENDING: + /* Control endpoint only */ + case DWC3_TRBSTS_OK: + default: + request_status = 0; + break; + } + } else { + request_status = status; + } + + dwc3_gadget_giveback(dep, req, request_status); out: return ret; diff -u linux-5.15.0/drivers/usb/host/xhci-hub.c linux-5.15.0/drivers/usb/host/xhci-hub.c --- linux-5.15.0/drivers/usb/host/xhci-hub.c +++ linux-5.15.0/drivers/usb/host/xhci-hub.c @@ -1434,7 +1434,7 @@ } spin_unlock_irqrestore(&xhci->lock, flags); if (!wait_for_completion_timeout(&bus_state->u3exit_done[wIndex], - msecs_to_jiffies(100))) + msecs_to_jiffies(500))) xhci_dbg(xhci, "missing U0 port change event for port %d-%d\n", hcd->self.busnum, wIndex + 1); spin_lock_irqsave(&xhci->lock, flags); diff -u linux-5.15.0/drivers/usb/host/xhci-pci.c linux-5.15.0/drivers/usb/host/xhci-pci.c --- linux-5.15.0/drivers/usb/host/xhci-pci.c +++ linux-5.15.0/drivers/usb/host/xhci-pci.c @@ -59,6 +59,7 @@ #define PCI_DEVICE_ID_INTEL_TIGER_LAKE_XHCI 0x9a13 #define PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_XHCI 0x1138 #define PCI_DEVICE_ID_INTEL_ALDER_LAKE_XHCI 0x461e +#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI 0x51ed #define PCI_DEVICE_ID_AMD_RENOIR_XHCI 0x1639 #define PCI_DEVICE_ID_AMD_PROMONTORYA_4 0x43b9 @@ -266,7 +267,8 @@ pdev->device == PCI_DEVICE_ID_INTEL_ICE_LAKE_XHCI || pdev->device == PCI_DEVICE_ID_INTEL_TIGER_LAKE_XHCI || pdev->device == PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_XHCI || - pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_XHCI)) + pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_XHCI || + pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI)) xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW; if (pdev->vendor == PCI_VENDOR_ID_ETRON && diff -u linux-5.15.0/drivers/usb/host/xhci-ring.c linux-5.15.0/drivers/usb/host/xhci-ring.c --- linux-5.15.0/drivers/usb/host/xhci-ring.c +++ linux-5.15.0/drivers/usb/host/xhci-ring.c @@ -3141,6 +3141,7 @@ if (event_loop++ < TRBS_PER_SEGMENT / 2) continue; xhci_update_erst_dequeue(xhci, event_ring_deq); + event_ring_deq = xhci->event_ring->dequeue; /* ring is half-full, force isoc trbs to interrupt more often */ if (xhci->isoc_bei_interval > AVOID_BEI_INTERVAL_MIN) diff -u linux-5.15.0/drivers/usb/host/xhci-tegra.c linux-5.15.0/drivers/usb/host/xhci-tegra.c --- linux-5.15.0/drivers/usb/host/xhci-tegra.c +++ linux-5.15.0/drivers/usb/host/xhci-tegra.c @@ -1034,13 +1034,13 @@ int rc; if (tegra->use_genpd) { - rc = pm_runtime_get_sync(tegra->genpd_dev_ss); + rc = pm_runtime_resume_and_get(tegra->genpd_dev_ss); if (rc < 0) { dev_err(dev, "failed to enable XUSB SS partition\n"); return rc; } - rc = pm_runtime_get_sync(tegra->genpd_dev_host); + rc = pm_runtime_resume_and_get(tegra->genpd_dev_host); if (rc < 0) { dev_err(dev, "failed to enable XUSB Host partition\n"); pm_runtime_put_sync(tegra->genpd_dev_ss); diff -u linux-5.15.0/drivers/usb/host/xhci.c linux-5.15.0/drivers/usb/host/xhci.c --- linux-5.15.0/drivers/usb/host/xhci.c +++ linux-5.15.0/drivers/usb/host/xhci.c @@ -778,6 +778,17 @@ if (xhci->quirks & XHCI_SPURIOUS_REBOOT) usb_disable_xhci_ports(to_pci_dev(hcd->self.sysdev)); + /* Don't poll the roothubs after shutdown. */ + xhci_dbg(xhci, "%s: stopping usb%d port polling.\n", + __func__, hcd->self.busnum); + clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); + del_timer_sync(&hcd->rh_timer); + + if (xhci->shared_hcd) { + clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags); + del_timer_sync(&xhci->shared_hcd->rh_timer); + } + spin_lock_irq(&xhci->lock); xhci_halt(xhci); /* Workaround for spurious wakeups at shutdown with HSW */ diff -u linux-5.15.0/drivers/usb/serial/cp210x.c linux-5.15.0/drivers/usb/serial/cp210x.c --- linux-5.15.0/drivers/usb/serial/cp210x.c +++ linux-5.15.0/drivers/usb/serial/cp210x.c @@ -194,6 +194,8 @@ { USB_DEVICE(0x16DC, 0x0015) }, /* W-IE-NE-R Plein & Baus GmbH CML Control, Monitoring and Data Logger */ { USB_DEVICE(0x17A8, 0x0001) }, /* Kamstrup Optical Eye/3-wire */ { USB_DEVICE(0x17A8, 0x0005) }, /* Kamstrup M-Bus Master MultiPort 250D */ + { USB_DEVICE(0x17A8, 0x0101) }, /* Kamstrup 868 MHz wM-Bus C-Mode Meter Reader (Int Ant) */ + { USB_DEVICE(0x17A8, 0x0102) }, /* Kamstrup 868 MHz wM-Bus C-Mode Meter Reader (Ext Ant) */ { USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */ { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */ { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ diff -u linux-5.15.0/drivers/usb/serial/option.c linux-5.15.0/drivers/usb/serial/option.c --- linux-5.15.0/drivers/usb/serial/option.c +++ linux-5.15.0/drivers/usb/serial/option.c @@ -432,6 +432,8 @@ #define CINTERION_PRODUCT_CLS8 0x00b0 #define CINTERION_PRODUCT_MV31_MBIM 0x00b3 #define CINTERION_PRODUCT_MV31_RMNET 0x00b7 +#define CINTERION_PRODUCT_MV32_WA 0x00f1 +#define CINTERION_PRODUCT_MV32_WB 0x00f2 /* Olivetti products */ #define OLIVETTI_VENDOR_ID 0x0b3c @@ -1217,6 +1219,10 @@ .driver_info = NCTRL(0) | RSVD(1) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1056, 0xff), /* Telit FD980 */ .driver_info = NCTRL(2) | RSVD(3) }, + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1057, 0xff), /* Telit FN980 */ + .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) }, + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1058, 0xff), /* Telit FN980 (PCIe) */ + .driver_info = NCTRL(0) | RSVD(1) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1060, 0xff), /* Telit LN920 (rmnet) */ .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1061, 0xff), /* Telit LN920 (MBIM) */ @@ -1233,6 +1239,8 @@ .driver_info = NCTRL(2) | RSVD(3) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1073, 0xff), /* Telit FN990 (ECM) */ .driver_info = NCTRL(0) | RSVD(1) }, + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1075, 0xff), /* Telit FN990 (PCIe) */ + .driver_info = RSVD(0) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910), .driver_info = NCTRL(0) | RSVD(1) | RSVD(3) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910_DUAL_MODEM), @@ -1969,6 +1977,10 @@ .driver_info = RSVD(3)}, { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV31_RMNET, 0xff), .driver_info = RSVD(0)}, + { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV32_WA, 0xff), + .driver_info = RSVD(3)}, + { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV32_WB, 0xff), + .driver_info = RSVD(3)}, { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100), .driver_info = RSVD(4) }, { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD120), diff -u linux-5.15.0/drivers/usb/serial/pl2303.c linux-5.15.0/drivers/usb/serial/pl2303.c --- linux-5.15.0/drivers/usb/serial/pl2303.c +++ linux-5.15.0/drivers/usb/serial/pl2303.c @@ -420,6 +420,9 @@ bcdUSB = le16_to_cpu(desc->bcdUSB); switch (bcdUSB) { + case 0x101: + /* USB 1.0.1? Let's assume they meant 1.1... */ + fallthrough; case 0x110: switch (bcdDevice) { case 0x300: diff -u linux-5.15.0/drivers/usb/typec/ucsi/ucsi.c linux-5.15.0/drivers/usb/typec/ucsi/ucsi.c --- linux-5.15.0/drivers/usb/typec/ucsi/ucsi.c +++ linux-5.15.0/drivers/usb/typec/ucsi/ucsi.c @@ -935,6 +935,8 @@ role == TYPEC_HOST)) goto out_unlock; + reinit_completion(&con->complete); + command = UCSI_SET_UOR | UCSI_CONNECTOR_NUMBER(con->num); command |= UCSI_SET_UOR_ROLE(role); command |= UCSI_SET_UOR_ACCEPT_ROLE_SWAPS; @@ -942,14 +944,18 @@ if (ret < 0) goto out_unlock; + mutex_unlock(&con->lock); + if (!wait_for_completion_timeout(&con->complete, - msecs_to_jiffies(UCSI_SWAP_TIMEOUT_MS))) - ret = -ETIMEDOUT; + msecs_to_jiffies(UCSI_SWAP_TIMEOUT_MS))) + return -ETIMEDOUT; + + return 0; out_unlock: mutex_unlock(&con->lock); - return ret < 0 ? ret : 0; + return ret; } static int ucsi_pr_swap(struct typec_port *port, enum typec_role role) @@ -971,6 +977,8 @@ if (cur_role == role) goto out_unlock; + reinit_completion(&con->complete); + command = UCSI_SET_PDR | UCSI_CONNECTOR_NUMBER(con->num); command |= UCSI_SET_PDR_ROLE(role); command |= UCSI_SET_PDR_ACCEPT_ROLE_SWAPS; @@ -978,11 +986,13 @@ if (ret < 0) goto out_unlock; + mutex_unlock(&con->lock); + if (!wait_for_completion_timeout(&con->complete, - msecs_to_jiffies(UCSI_SWAP_TIMEOUT_MS))) { - ret = -ETIMEDOUT; - goto out_unlock; - } + msecs_to_jiffies(UCSI_SWAP_TIMEOUT_MS))) + return -ETIMEDOUT; + + mutex_lock(&con->lock); /* Something has gone wrong while swapping the role */ if (UCSI_CONSTAT_PWR_OPMODE(con->status.flags) != diff -u linux-5.15.0/drivers/video/fbdev/udlfb.c linux-5.15.0/drivers/video/fbdev/udlfb.c --- linux-5.15.0/drivers/video/fbdev/udlfb.c +++ linux-5.15.0/drivers/video/fbdev/udlfb.c @@ -1649,8 +1649,9 @@ const struct device_attribute *attr; struct dlfb_data *dlfb; struct fb_info *info; - int retval = -ENOMEM; + int retval; struct usb_device *usbdev = interface_to_usbdev(intf); + struct usb_endpoint_descriptor *out; /* usb initialization */ dlfb = kzalloc(sizeof(*dlfb), GFP_KERNEL); @@ -1664,6 +1665,12 @@ dlfb->udev = usb_get_dev(usbdev); usb_set_intfdata(intf, dlfb); + retval = usb_find_common_endpoints(intf->cur_altsetting, NULL, &out, NULL, NULL); + if (retval) { + dev_err(&intf->dev, "Device should have at lease 1 bulk endpoint!\n"); + goto error; + } + dev_dbg(&intf->dev, "console enable=%d\n", console); dev_dbg(&intf->dev, "fb_defio enable=%d\n", fb_defio); dev_dbg(&intf->dev, "shadow enable=%d\n", shadow); @@ -1673,6 +1680,7 @@ if (!dlfb_parse_vendor_descriptor(dlfb, intf)) { dev_err(&intf->dev, "firmware not recognized, incompatible device?\n"); + retval = -ENODEV; goto error; } @@ -1686,8 +1694,10 @@ /* allocates framebuffer driver structure, not framebuffer memory */ info = framebuffer_alloc(0, &dlfb->udev->dev); - if (!info) + if (!info) { + retval = -ENOMEM; goto error; + } dlfb->info = info; info->par = dlfb; diff -u linux-5.15.0/fs/btrfs/disk-io.c linux-5.15.0/fs/btrfs/disk-io.c --- linux-5.15.0/fs/btrfs/disk-io.c +++ linux-5.15.0/fs/btrfs/disk-io.c @@ -3415,6 +3415,17 @@ } if (sectorsize != PAGE_SIZE) { + /* + * V1 space cache has some hardcoded PAGE_SIZE usage, and is + * going to be deprecated. + * + * Force to use v2 cache for subpage case. + */ + btrfs_clear_opt(fs_info->mount_opt, SPACE_CACHE); + btrfs_set_and_info(fs_info, FREE_SPACE_TREE, + "forcing free space tree for sector size %u with page size %lu", + sectorsize, PAGE_SIZE); + btrfs_warn(fs_info, "read-write for sector size %u with page size %lu is experimental", sectorsize, PAGE_SIZE); diff -u linux-5.15.0/fs/btrfs/file.c linux-5.15.0/fs/btrfs/file.c --- linux-5.15.0/fs/btrfs/file.c +++ linux-5.15.0/fs/btrfs/file.c @@ -1709,7 +1709,7 @@ * Fault pages before locking them in prepare_pages * to avoid recursive lock */ - if (unlikely(iov_iter_fault_in_readable(i, write_bytes))) { + if (unlikely(fault_in_iov_iter_readable(i, write_bytes))) { ret = -EFAULT; break; } @@ -1903,16 +1903,17 @@ static ssize_t btrfs_direct_write(struct kiocb *iocb, struct iov_iter *from) { + const bool is_sync_write = (iocb->ki_flags & IOCB_DSYNC); struct file *file = iocb->ki_filp; struct inode *inode = file_inode(file); struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); loff_t pos; ssize_t written = 0; ssize_t written_buffered; + size_t prev_left = 0; loff_t endbyte; ssize_t err; unsigned int ilock_flags = 0; - struct iomap_dio *dio = NULL; if (iocb->ki_flags & IOCB_NOWAIT) ilock_flags |= BTRFS_ILOCK_TRY; @@ -1955,23 +1956,80 @@ goto buffered; } - dio = __iomap_dio_rw(iocb, from, &btrfs_dio_iomap_ops, &btrfs_dio_ops, - 0); + /* + * We remove IOCB_DSYNC so that we don't deadlock when iomap_dio_rw() + * calls generic_write_sync() (through iomap_dio_complete()), because + * that results in calling fsync (btrfs_sync_file()) which will try to + * lock the inode in exclusive/write mode. + */ + if (is_sync_write) + iocb->ki_flags &= ~IOCB_DSYNC; - btrfs_inode_unlock(inode, ilock_flags); + /* + * The iov_iter can be mapped to the same file range we are writing to. + * If that's the case, then we will deadlock in the iomap code, because + * it first calls our callback btrfs_dio_iomap_begin(), which will create + * an ordered extent, and after that it will fault in the pages that the + * iov_iter refers to. During the fault in we end up in the readahead + * pages code (starting at btrfs_readahead()), which will lock the range, + * find that ordered extent and then wait for it to complete (at + * btrfs_lock_and_flush_ordered_range()), resulting in a deadlock since + * obviously the ordered extent can never complete as we didn't submit + * yet the respective bio(s). This always happens when the buffer is + * memory mapped to the same file range, since the iomap DIO code always + * invalidates pages in the target file range (after starting and waiting + * for any writeback). + * + * So here we disable page faults in the iov_iter and then retry if we + * got -EFAULT, faulting in the pages before the retry. + */ +again: + from->nofault = true; + err = iomap_dio_rw(iocb, from, &btrfs_dio_iomap_ops, &btrfs_dio_ops, + IOMAP_DIO_PARTIAL, written); + from->nofault = false; - if (IS_ERR_OR_NULL(dio)) { - err = PTR_ERR_OR_ZERO(dio); - if (err < 0 && err != -ENOTBLK) - goto out; - } else { - written = iomap_dio_complete(dio); + /* No increment (+=) because iomap returns a cumulative value. */ + if (err > 0) + written = err; + + if (iov_iter_count(from) > 0 && (err == -EFAULT || err > 0)) { + const size_t left = iov_iter_count(from); + /* + * We have more data left to write. Try to fault in as many as + * possible of the remainder pages and retry. We do this without + * releasing and locking again the inode, to prevent races with + * truncate. + * + * Also, in case the iov refers to pages in the file range of the + * file we want to write to (due to a mmap), we could enter an + * infinite loop if we retry after faulting the pages in, since + * iomap will invalidate any pages in the range early on, before + * it tries to fault in the pages of the iov. So we keep track of + * how much was left of iov in the previous EFAULT and fallback + * to buffered IO in case we haven't made any progress. + */ + if (left == prev_left) { + err = -ENOTBLK; + } else { + fault_in_iov_iter_readable(from, left); + prev_left = left; + goto again; + } } - if (written < 0 || !iov_iter_count(from)) { - err = written; + btrfs_inode_unlock(inode, ilock_flags); + + /* + * Add back IOCB_DSYNC. Our caller, btrfs_file_write_iter(), will do + * the fsync (call generic_write_sync()). + */ + if (is_sync_write) + iocb->ki_flags |= IOCB_DSYNC; + + /* If 'err' is -ENOTBLK then it means we must fallback to buffered IO. */ + if ((err < 0 && err != -ENOTBLK) || !iov_iter_count(from)) goto out; - } buffered: pos = iocb->ki_pos; @@ -1996,7 +2054,7 @@ invalidate_mapping_pages(file->f_mapping, pos >> PAGE_SHIFT, endbyte >> PAGE_SHIFT); out: - return written ? written : err; + return err < 0 ? err : written; } static ssize_t btrfs_file_write_iter(struct kiocb *iocb, @@ -3659,6 +3717,8 @@ static ssize_t btrfs_direct_read(struct kiocb *iocb, struct iov_iter *to) { struct inode *inode = file_inode(iocb->ki_filp); + size_t prev_left = 0; + ssize_t read = 0; ssize_t ret; if (fsverity_active(inode)) @@ -3668,9 +3728,57 @@ return 0; btrfs_inode_lock(inode, BTRFS_ILOCK_SHARED); - ret = iomap_dio_rw(iocb, to, &btrfs_dio_iomap_ops, &btrfs_dio_ops, 0); +again: + /* + * This is similar to what we do for direct IO writes, see the comment + * at btrfs_direct_write(), but we also disable page faults in addition + * to disabling them only at the iov_iter level. This is because when + * reading from a hole or prealloc extent, iomap calls iov_iter_zero(), + * which can still trigger page fault ins despite having set ->nofault + * to true of our 'to' iov_iter. + * + * The difference to direct IO writes is that we deadlock when trying + * to lock the extent range in the inode's tree during he page reads + * triggered by the fault in (while for writes it is due to waiting for + * our own ordered extent). This is because for direct IO reads, + * btrfs_dio_iomap_begin() returns with the extent range locked, which + * is only unlocked in the endio callback (end_bio_extent_readpage()). + */ + pagefault_disable(); + to->nofault = true; + ret = iomap_dio_rw(iocb, to, &btrfs_dio_iomap_ops, &btrfs_dio_ops, + IOMAP_DIO_PARTIAL, read); + to->nofault = false; + pagefault_enable(); + + /* No increment (+=) because iomap returns a cumulative value. */ + if (ret > 0) + read = ret; + + if (iov_iter_count(to) > 0 && (ret == -EFAULT || ret > 0)) { + const size_t left = iov_iter_count(to); + + if (left == prev_left) { + /* + * We didn't make any progress since the last attempt, + * fallback to a buffered read for the remainder of the + * range. This is just to avoid any possibility of looping + * for too long. + */ + ret = read; + } else { + /* + * We made some progress since the last retry or this is + * the first time we are retrying. Fault in as many pages + * as possible and retry. + */ + fault_in_iov_iter_writeable(to, left); + prev_left = left; + goto again; + } + } btrfs_inode_unlock(inode, BTRFS_ILOCK_SHARED); - return ret; + return ret < 0 ? ret : read; } static ssize_t btrfs_file_read_iter(struct kiocb *iocb, struct iov_iter *to) diff -u linux-5.15.0/fs/btrfs/inode.c linux-5.15.0/fs/btrfs/inode.c --- linux-5.15.0/fs/btrfs/inode.c +++ linux-5.15.0/fs/btrfs/inode.c @@ -7961,6 +7961,34 @@ } len = min(len, em->len - (start - em->start)); + + /* + * If we have a NOWAIT request and the range contains multiple extents + * (or a mix of extents and holes), then we return -EAGAIN to make the + * caller fallback to a context where it can do a blocking (without + * NOWAIT) request. This way we avoid doing partial IO and returning + * success to the caller, which is not optimal for writes and for reads + * it can result in unexpected behaviour for an application. + * + * When doing a read, because we use IOMAP_DIO_PARTIAL when calling + * iomap_dio_rw(), we can end up returning less data then what the caller + * asked for, resulting in an unexpected, and incorrect, short read. + * That is, the caller asked to read N bytes and we return less than that, + * which is wrong unless we are crossing EOF. This happens if we get a + * page fault error when trying to fault in pages for the buffer that is + * associated to the struct iov_iter passed to iomap_dio_rw(), and we + * have previously submitted bios for other extents in the range, in + * which case iomap_dio_rw() may return us EIOCBQUEUED if not all of + * those bios have completed by the time we get the page fault error, + * which we return back to our caller - we should only return EIOCBQUEUED + * after we have submitted bios for all the extents in the range. + */ + if ((flags & IOMAP_NOWAIT) && len < length) { + free_extent_map(em); + ret = -EAGAIN; + goto unlock_err; + } + if (write) { ret = btrfs_get_blocks_direct_write(&em, inode, dio_data, start, len); diff -u linux-5.15.0/fs/btrfs/ioctl.c linux-5.15.0/fs/btrfs/ioctl.c --- linux-5.15.0/fs/btrfs/ioctl.c +++ linux-5.15.0/fs/btrfs/ioctl.c @@ -2258,9 +2258,8 @@ key.offset = sk->min_offset; while (1) { - ret = fault_in_pages_writeable(ubuf + sk_offset, - *buf_size - sk_offset); - if (ret) + ret = -EFAULT; + if (fault_in_writeable(ubuf + sk_offset, *buf_size - sk_offset)) break; ret = btrfs_search_forward(root, &key, path, sk->min_transid); diff -u linux-5.15.0/fs/btrfs/tree-log.c linux-5.15.0/fs/btrfs/tree-log.c --- linux-5.15.0/fs/btrfs/tree-log.c +++ linux-5.15.0/fs/btrfs/tree-log.c @@ -3216,6 +3216,7 @@ ret = btrfs_alloc_log_tree_node(trans, log_root_tree); if (ret) { mutex_unlock(&fs_info->tree_root->log_mutex); + blk_finish_plug(&plug); goto out; } } @@ -5483,6 +5484,18 @@ } /* + * For symlinks, we must always log their content, which is stored in an + * inline extent, otherwise we could end up with an empty symlink after + * log replay, which is invalid on linux (symlink(2) returns -ENOENT if + * one attempts to create an empty symlink). + * We don't need to worry about flushing delalloc, because when we create + * the inline extent when the symlink is created (we never have delalloc + * for symlinks). + */ + if (S_ISLNK(inode->vfs_inode.i_mode)) + inode_only = LOG_INODE_ALL; + + /* * This is for cases where logging a directory could result in losing a * a file after replaying the log. For example, if we move a file from a * directory A to a directory B, then fsync directory A, we have no way @@ -5852,7 +5865,7 @@ } ctx->log_new_dentries = false; - if (type == BTRFS_FT_DIR || type == BTRFS_FT_SYMLINK) + if (type == BTRFS_FT_DIR) log_mode = LOG_INODE_ALL; ret = btrfs_log_inode(trans, root, BTRFS_I(di_inode), log_mode, ctx); diff -u linux-5.15.0/fs/ceph/caps.c linux-5.15.0/fs/ceph/caps.c --- linux-5.15.0/fs/ceph/caps.c +++ linux-5.15.0/fs/ceph/caps.c @@ -2266,6 +2266,8 @@ list_for_each_entry(req, &ci->i_unsafe_dirops, r_unsafe_dir_item) { s = req->r_session; + if (!s) + continue; if (unlikely(s->s_mds >= max_sessions)) { spin_unlock(&ci->i_unsafe_lock); for (i = 0; i < max_sessions; i++) { @@ -2286,6 +2288,8 @@ list_for_each_entry(req, &ci->i_unsafe_iops, r_unsafe_target_item) { s = req->r_session; + if (!s) + continue; if (unlikely(s->s_mds >= max_sessions)) { spin_unlock(&ci->i_unsafe_lock); for (i = 0; i < max_sessions; i++) { diff -u linux-5.15.0/fs/cifs/cifsfs.c linux-5.15.0/fs/cifs/cifsfs.c --- linux-5.15.0/fs/cifs/cifsfs.c +++ linux-5.15.0/fs/cifs/cifsfs.c @@ -936,7 +936,7 @@ ssize_t rc; struct inode *inode = file_inode(iocb->ki_filp); - if (iocb->ki_filp->f_flags & O_DIRECT) + if (iocb->ki_flags & IOCB_DIRECT) return cifs_user_readv(iocb, iter); rc = cifs_revalidate_mapping(inode); diff -u linux-5.15.0/fs/cifs/smb2ops.c linux-5.15.0/fs/cifs/smb2ops.c --- linux-5.15.0/fs/cifs/smb2ops.c +++ linux-5.15.0/fs/cifs/smb2ops.c @@ -1849,9 +1849,17 @@ int chunks_copied = 0; bool chunk_sizes_updated = false; ssize_t bytes_written, total_bytes_written = 0; + struct inode *inode; pcchunk = kmalloc(sizeof(struct copychunk_ioctl), GFP_KERNEL); + /* + * We need to flush all unwritten data before we can send the + * copychunk ioctl to the server. + */ + inode = d_inode(trgtfile->dentry); + filemap_write_and_wait(inode->i_mapping); + if (pcchunk == NULL) return -ENOMEM; diff -u linux-5.15.0/fs/ext4/ext4.h linux-5.15.0/fs/ext4/ext4.h --- linux-5.15.0/fs/ext4/ext4.h +++ linux-5.15.0/fs/ext4/ext4.h @@ -2267,6 +2267,10 @@ * Structure of a directory entry */ #define EXT4_NAME_LEN 255 +/* + * Base length of the ext4 directory entry excluding the name length + */ +#define EXT4_BASE_DIR_LEN (sizeof(struct ext4_dir_entry_2) - EXT4_NAME_LEN) struct ext4_dir_entry { __le32 inode; /* Inode number */ @@ -3027,7 +3031,7 @@ extern int ext4_can_truncate(struct inode *inode); extern int ext4_truncate(struct inode *); extern int ext4_break_layouts(struct inode *); -extern int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length); +extern int ext4_punch_hole(struct file *file, loff_t offset, loff_t length); extern void ext4_set_inode_flags(struct inode *, bool init); extern int ext4_alloc_da_blocks(struct inode *inode); extern void ext4_set_aops(struct inode *inode); diff -u linux-5.15.0/fs/ext4/extents.c linux-5.15.0/fs/ext4/extents.c --- linux-5.15.0/fs/ext4/extents.c +++ linux-5.15.0/fs/ext4/extents.c @@ -4504,9 +4504,9 @@ return ret > 0 ? ret2 : ret; } -static int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len); +static int ext4_collapse_range(struct file *file, loff_t offset, loff_t len); -static int ext4_insert_range(struct inode *inode, loff_t offset, loff_t len); +static int ext4_insert_range(struct file *file, loff_t offset, loff_t len); static long ext4_zero_range(struct file *file, loff_t offset, loff_t len, int mode) @@ -4578,6 +4578,10 @@ /* Wait all existing dio workers, newcomers will block on i_mutex */ inode_dio_wait(inode); + ret = file_modified(file); + if (ret) + goto out_mutex; + /* Preallocate the range including the unaligned edges */ if (partial_begin || partial_end) { ret = ext4_alloc_file_blocks(file, @@ -4696,7 +4700,7 @@ ext4_fc_start_update(inode); if (mode & FALLOC_FL_PUNCH_HOLE) { - ret = ext4_punch_hole(inode, offset, len); + ret = ext4_punch_hole(file, offset, len); goto exit; } @@ -4705,12 +4709,12 @@ goto exit; if (mode & FALLOC_FL_COLLAPSE_RANGE) { - ret = ext4_collapse_range(inode, offset, len); + ret = ext4_collapse_range(file, offset, len); goto exit; } if (mode & FALLOC_FL_INSERT_RANGE) { - ret = ext4_insert_range(inode, offset, len); + ret = ext4_insert_range(file, offset, len); goto exit; } @@ -4746,6 +4750,10 @@ /* Wait all existing dio workers, newcomers will block on i_mutex */ inode_dio_wait(inode); + ret = file_modified(file); + if (ret) + goto out; + ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size, flags); if (ret) goto out; @@ -5248,8 +5256,9 @@ * This implements the fallocate's collapse range functionality for ext4 * Returns: 0 and non-zero on error. */ -static int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len) +static int ext4_collapse_range(struct file *file, loff_t offset, loff_t len) { + struct inode *inode = file_inode(file); struct super_block *sb = inode->i_sb; struct address_space *mapping = inode->i_mapping; ext4_lblk_t punch_start, punch_stop; @@ -5301,6 +5310,10 @@ /* Wait for existing dio to complete */ inode_dio_wait(inode); + ret = file_modified(file); + if (ret) + goto out_mutex; + /* * Prevent page faults from reinstantiating pages we have released from * page cache. @@ -5394,8 +5407,9 @@ * by len bytes. * Returns 0 on success, error otherwise. */ -static int ext4_insert_range(struct inode *inode, loff_t offset, loff_t len) +static int ext4_insert_range(struct file *file, loff_t offset, loff_t len) { + struct inode *inode = file_inode(file); struct super_block *sb = inode->i_sb; struct address_space *mapping = inode->i_mapping; handle_t *handle; @@ -5452,6 +5466,10 @@ /* Wait for existing dio to complete */ inode_dio_wait(inode); + ret = file_modified(file); + if (ret) + goto out_mutex; + /* * Prevent page faults from reinstantiating pages we have released from * page cache. diff -u linux-5.15.0/fs/ext4/inode.c linux-5.15.0/fs/ext4/inode.c --- linux-5.15.0/fs/ext4/inode.c +++ linux-5.15.0/fs/ext4/inode.c @@ -3939,8 +3939,9 @@ * Returns: 0 on success or negative on failure */ -int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length) +int ext4_punch_hole(struct file *file, loff_t offset, loff_t length) { + struct inode *inode = file_inode(file); struct super_block *sb = inode->i_sb; ext4_lblk_t first_block, stop_block; struct address_space *mapping = inode->i_mapping; @@ -4011,6 +4012,10 @@ /* Wait all existing dio workers, newcomers will block on i_mutex */ inode_dio_wait(inode); + ret = file_modified(file); + if (ret) + goto out_mutex; + /* * Prevent page faults from reinstantiating pages we have released from * page cache. diff -u linux-5.15.0/fs/ext4/namei.c linux-5.15.0/fs/ext4/namei.c --- linux-5.15.0/fs/ext4/namei.c +++ linux-5.15.0/fs/ext4/namei.c @@ -1466,10 +1466,10 @@ de = (struct ext4_dir_entry_2 *)search_buf; dlimit = search_buf + buf_size; - while ((char *) de < dlimit) { + while ((char *) de < dlimit - EXT4_BASE_DIR_LEN) { /* this code is executed quadratically often */ /* do minimal checking `by hand' */ - if ((char *) de + de->name_len <= dlimit && + if (de->name + de->name_len <= dlimit && ext4_match(dir, fname, de)) { /* found a match - just to be sure, do * a full check */ diff -u linux-5.15.0/fs/ext4/super.c linux-5.15.0/fs/ext4/super.c --- linux-5.15.0/fs/ext4/super.c +++ linux-5.15.0/fs/ext4/super.c @@ -1167,20 +1167,25 @@ int aborted = 0; int i, err; - ext4_unregister_li_request(sb); - ext4_quota_off_umount(sb); - - flush_work(&sbi->s_error_work); - destroy_workqueue(sbi->rsv_conversion_wq); - ext4_release_orphan_info(sb); - /* * Unregister sysfs before destroying jbd2 journal. * Since we could still access attr_journal_task attribute via sysfs * path which could have sbi->s_journal->j_task as NULL + * Unregister sysfs before flush sbi->s_error_work. + * Since user may read /proc/fs/ext4/xx/mb_groups during umount, If + * read metadata verify failed then will queue error work. + * flush_stashed_error_work will call start_this_handle may trigger + * BUG_ON. */ ext4_unregister_sysfs(sb); + ext4_unregister_li_request(sb); + ext4_quota_off_umount(sb); + + flush_work(&sbi->s_error_work); + destroy_workqueue(sbi->rsv_conversion_wq); + ext4_release_orphan_info(sb); + if (sbi->s_journal) { aborted = is_journal_aborted(sbi->s_journal); err = jbd2_journal_destroy(sbi->s_journal); @@ -3697,9 +3702,11 @@ ext4_fsblk_t first_block, last_block, b; ext4_group_t i, ngroups = ext4_get_groups_count(sb); int s, j, count = 0; + int has_super = ext4_bg_has_super(sb, grp); if (!ext4_has_feature_bigalloc(sb)) - return (ext4_bg_has_super(sb, grp) + ext4_bg_num_gdb(sb, grp) + + return (has_super + ext4_bg_num_gdb(sb, grp) + + (has_super ? le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) : 0) + sbi->s_itb_per_group + 2); first_block = le32_to_cpu(sbi->s_es->s_first_data_block) + @@ -4786,9 +4793,18 @@ * Get the # of file system overhead blocks from the * superblock if present. */ - if (es->s_overhead_clusters) - sbi->s_overhead = le32_to_cpu(es->s_overhead_clusters); - else { + sbi->s_overhead = le32_to_cpu(es->s_overhead_clusters); + /* ignore the precalculated value if it is ridiculous */ + if (sbi->s_overhead > ext4_blocks_count(es)) + sbi->s_overhead = 0; + /* + * If the bigalloc feature is not enabled recalculating the + * overhead doesn't take long, so we might as well just redo + * it to make sure we are using the correct value. + */ + if (!ext4_has_feature_bigalloc(sb)) + sbi->s_overhead = 0; + if (sbi->s_overhead == 0) { err = ext4_calculate_overhead(sb); if (err) goto failed_mount_wq; diff -u linux-5.15.0/fs/f2fs/file.c linux-5.15.0/fs/f2fs/file.c --- linux-5.15.0/fs/f2fs/file.c +++ linux-5.15.0/fs/f2fs/file.c @@ -4279,7 +4279,7 @@ size_t target_size = 0; int err; - if (iov_iter_fault_in_readable(from, iov_iter_count(from))) + if (fault_in_iov_iter_readable(from, iov_iter_count(from))) set_inode_flag(inode, FI_NO_PREALLOC); if ((iocb->ki_flags & IOCB_NOWAIT)) { diff -u linux-5.15.0/fs/fuse/file.c linux-5.15.0/fs/fuse/file.c --- linux-5.15.0/fs/fuse/file.c +++ linux-5.15.0/fs/fuse/file.c @@ -1164,7 +1164,7 @@ again: err = -EFAULT; - if (iov_iter_fault_in_readable(ii, bytes)) + if (fault_in_iov_iter_readable(ii, bytes)) break; err = -ENOMEM; diff -u linux-5.15.0/fs/gfs2/bmap.c linux-5.15.0/fs/gfs2/bmap.c --- linux-5.15.0/fs/gfs2/bmap.c +++ linux-5.15.0/fs/gfs2/bmap.c @@ -961,46 +961,6 @@ goto out; } -static int gfs2_write_lock(struct inode *inode) -{ - struct gfs2_inode *ip = GFS2_I(inode); - struct gfs2_sbd *sdp = GFS2_SB(inode); - int error; - - gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &ip->i_gh); - error = gfs2_glock_nq(&ip->i_gh); - if (error) - goto out_uninit; - if (&ip->i_inode == sdp->sd_rindex) { - struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); - - error = gfs2_glock_nq_init(m_ip->i_gl, LM_ST_EXCLUSIVE, - GL_NOCACHE, &m_ip->i_gh); - if (error) - goto out_unlock; - } - return 0; - -out_unlock: - gfs2_glock_dq(&ip->i_gh); -out_uninit: - gfs2_holder_uninit(&ip->i_gh); - return error; -} - -static void gfs2_write_unlock(struct inode *inode) -{ - struct gfs2_inode *ip = GFS2_I(inode); - struct gfs2_sbd *sdp = GFS2_SB(inode); - - if (&ip->i_inode == sdp->sd_rindex) { - struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); - - gfs2_glock_dq_uninit(&m_ip->i_gh); - } - gfs2_glock_dq_uninit(&ip->i_gh); -} - static int gfs2_iomap_page_prepare(struct inode *inode, loff_t pos, unsigned len) { @@ -1118,11 +1078,6 @@ return ret; } -static inline bool gfs2_iomap_need_write_lock(unsigned flags) -{ - return (flags & IOMAP_WRITE) && !(flags & IOMAP_DIRECT); -} - static int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length, unsigned flags, struct iomap *iomap, struct iomap *srcmap) @@ -1135,12 +1090,6 @@ iomap->flags |= IOMAP_F_BUFFER_HEAD; trace_gfs2_iomap_start(ip, pos, length, flags); - if (gfs2_iomap_need_write_lock(flags)) { - ret = gfs2_write_lock(inode); - if (ret) - goto out; - } - ret = __gfs2_iomap_get(inode, pos, length, flags, iomap, &mp); if (ret) goto out_unlock; @@ -1168,10 +1117,7 @@ ret = gfs2_iomap_begin_write(inode, pos, length, flags, iomap, &mp); out_unlock: - if (ret && gfs2_iomap_need_write_lock(flags)) - gfs2_write_unlock(inode); release_metapath(&mp); -out: trace_gfs2_iomap_end(ip, iomap, ret); return ret; } @@ -1219,15 +1165,11 @@ } if (unlikely(!written)) - goto out_unlock; + return 0; if (iomap->flags & IOMAP_F_SIZE_CHANGED) mark_inode_dirty(inode); set_bit(GLF_DIRTY, &ip->i_gl->gl_flags); - -out_unlock: - if (gfs2_iomap_need_write_lock(flags)) - gfs2_write_unlock(inode); return 0; } diff -u linux-5.15.0/fs/gfs2/file.c linux-5.15.0/fs/gfs2/file.c --- linux-5.15.0/fs/gfs2/file.c +++ linux-5.15.0/fs/gfs2/file.c @@ -777,27 +777,99 @@ return ret ? ret : ret1; } +static inline bool should_fault_in_pages(ssize_t ret, struct iov_iter *i, + size_t *prev_count, + size_t *window_size) +{ + char __user *p = i->iov[0].iov_base + i->iov_offset; + size_t count = iov_iter_count(i); + int pages = 1; + + if (likely(!count)) + return false; + if (ret <= 0 && ret != -EFAULT) + return false; + if (!iter_is_iovec(i)) + return false; + + if (*prev_count != count || !*window_size) { + int pages, nr_dirtied; + + pages = min_t(int, BIO_MAX_VECS, + DIV_ROUND_UP(iov_iter_count(i), PAGE_SIZE)); + nr_dirtied = max(current->nr_dirtied_pause - + current->nr_dirtied, 1); + pages = min(pages, nr_dirtied); + } + + *prev_count = count; + *window_size = (size_t)PAGE_SIZE * pages - offset_in_page(p); + return true; +} + static ssize_t gfs2_file_direct_read(struct kiocb *iocb, struct iov_iter *to, struct gfs2_holder *gh) { struct file *file = iocb->ki_filp; struct gfs2_inode *ip = GFS2_I(file->f_mapping->host); - size_t count = iov_iter_count(to); + size_t prev_count = 0, window_size = 0; + size_t written = 0; ssize_t ret; - if (!count) + /* + * In this function, we disable page faults when we're holding the + * inode glock while doing I/O. If a page fault occurs, we indicate + * that the inode glock may be dropped, fault in the pages manually, + * and retry. + * + * Unlike generic_file_read_iter, for reads, iomap_dio_rw can trigger + * physical as well as manual page faults, and we need to disable both + * kinds. + * + * For direct I/O, gfs2 takes the inode glock in deferred mode. This + * locking mode is compatible with other deferred holders, so multiple + * processes and nodes can do direct I/O to a file at the same time. + * There's no guarantee that reads or writes will be atomic. Any + * coordination among readers and writers needs to happen externally. + */ + + if (!iov_iter_count(to)) return 0; /* skip atime */ gfs2_holder_init(ip->i_gl, LM_ST_DEFERRED, 0, gh); +retry: ret = gfs2_glock_nq(gh); if (ret) goto out_uninit; +retry_under_glock: + pagefault_disable(); + to->nofault = true; + ret = iomap_dio_rw(iocb, to, &gfs2_iomap_ops, NULL, + IOMAP_DIO_PARTIAL, written); + to->nofault = false; + pagefault_enable(); + if (ret > 0) + written = ret; - ret = iomap_dio_rw(iocb, to, &gfs2_iomap_ops, NULL, 0); - gfs2_glock_dq(gh); + if (should_fault_in_pages(ret, to, &prev_count, &window_size)) { + size_t leftover; + + gfs2_holder_allow_demote(gh); + leftover = fault_in_iov_iter_writeable(to, window_size); + gfs2_holder_disallow_demote(gh); + if (leftover != window_size) { + if (gfs2_holder_queued(gh)) + goto retry_under_glock; + goto retry; + } + } + if (gfs2_holder_queued(gh)) + gfs2_glock_dq(gh); out_uninit: gfs2_holder_uninit(gh); - return ret; + if (ret < 0) + return ret; + return written; } static ssize_t gfs2_file_direct_write(struct kiocb *iocb, struct iov_iter *from, @@ -806,11 +878,21 @@ struct file *file = iocb->ki_filp; struct inode *inode = file->f_mapping->host; struct gfs2_inode *ip = GFS2_I(inode); - size_t len = iov_iter_count(from); - loff_t offset = iocb->ki_pos; + size_t prev_count = 0, window_size = 0; + size_t read = 0; ssize_t ret; /* + * In this function, we disable page faults when we're holding the + * inode glock while doing I/O. If a page fault occurs, we indicate + * that the inode glock may be dropped, fault in the pages manually, + * and retry. + * + * For writes, iomap_dio_rw only triggers manual page faults, so we + * don't need to disable physical ones. + */ + + /* * Deferred lock, even if its a write, since we do no allocation on * this path. All we need to change is the atime, and this lock mode * ensures that other nodes have flushed their buffered read caches @@ -819,31 +901,62 @@ * VFS does. */ gfs2_holder_init(ip->i_gl, LM_ST_DEFERRED, 0, gh); +retry: ret = gfs2_glock_nq(gh); if (ret) goto out_uninit; - +retry_under_glock: /* Silently fall back to buffered I/O when writing beyond EOF */ - if (offset + len > i_size_read(&ip->i_inode)) + if (iocb->ki_pos + iov_iter_count(from) > i_size_read(&ip->i_inode)) goto out; - ret = iomap_dio_rw(iocb, from, &gfs2_iomap_ops, NULL, 0); + from->nofault = true; + ret = iomap_dio_rw(iocb, from, &gfs2_iomap_ops, NULL, + IOMAP_DIO_PARTIAL, read); + from->nofault = false; + if (ret == -ENOTBLK) ret = 0; + if (ret > 0) + read = ret; + + if (should_fault_in_pages(ret, from, &prev_count, &window_size)) { + size_t leftover; + + gfs2_holder_allow_demote(gh); + leftover = fault_in_iov_iter_readable(from, window_size); + gfs2_holder_disallow_demote(gh); + if (leftover != window_size) { + if (gfs2_holder_queued(gh)) + goto retry_under_glock; + goto retry; + } + } out: - gfs2_glock_dq(gh); + if (gfs2_holder_queued(gh)) + gfs2_glock_dq(gh); out_uninit: gfs2_holder_uninit(gh); - return ret; + if (ret < 0) + return ret; + return read; } static ssize_t gfs2_file_read_iter(struct kiocb *iocb, struct iov_iter *to) { struct gfs2_inode *ip; struct gfs2_holder gh; + size_t prev_count = 0, window_size = 0; size_t written = 0; ssize_t ret; + /* + * In this function, we disable page faults when we're holding the + * inode glock while doing I/O. If a page fault occurs, we indicate + * that the inode glock may be dropped, fault in the pages manually, + * and retry. + */ + if (iocb->ki_flags & IOCB_DIRECT) { ret = gfs2_file_direct_read(iocb, to, &gh); if (likely(ret != -ENOTBLK)) @@ -865,18 +978,115 @@ } ip = GFS2_I(iocb->ki_filp->f_mapping->host); gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh); +retry: ret = gfs2_glock_nq(&gh); if (ret) goto out_uninit; +retry_under_glock: + pagefault_disable(); ret = generic_file_read_iter(iocb, to); + pagefault_enable(); if (ret > 0) written += ret; - gfs2_glock_dq(&gh); + + if (should_fault_in_pages(ret, to, &prev_count, &window_size)) { + size_t leftover; + + gfs2_holder_allow_demote(&gh); + leftover = fault_in_iov_iter_writeable(to, window_size); + gfs2_holder_disallow_demote(&gh); + if (leftover != window_size) { + if (gfs2_holder_queued(&gh)) + goto retry_under_glock; + goto retry; + } + } + if (gfs2_holder_queued(&gh)) + gfs2_glock_dq(&gh); out_uninit: gfs2_holder_uninit(&gh); return written ? written : ret; } +static ssize_t gfs2_file_buffered_write(struct kiocb *iocb, + struct iov_iter *from, + struct gfs2_holder *gh) +{ + struct file *file = iocb->ki_filp; + struct inode *inode = file_inode(file); + struct gfs2_inode *ip = GFS2_I(inode); + struct gfs2_sbd *sdp = GFS2_SB(inode); + struct gfs2_holder *statfs_gh = NULL; + size_t prev_count = 0, window_size = 0; + size_t orig_count = iov_iter_count(from); + size_t read = 0; + ssize_t ret; + + /* + * In this function, we disable page faults when we're holding the + * inode glock while doing I/O. If a page fault occurs, we indicate + * that the inode glock may be dropped, fault in the pages manually, + * and retry. + */ + + if (inode == sdp->sd_rindex) { + statfs_gh = kmalloc(sizeof(*statfs_gh), GFP_NOFS); + if (!statfs_gh) + return -ENOMEM; + } + + gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, gh); +retry: + ret = gfs2_glock_nq(gh); + if (ret) + goto out_uninit; +retry_under_glock: + if (inode == sdp->sd_rindex) { + struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); + + ret = gfs2_glock_nq_init(m_ip->i_gl, LM_ST_EXCLUSIVE, + GL_NOCACHE, statfs_gh); + if (ret) + goto out_unlock; + } + + current->backing_dev_info = inode_to_bdi(inode); + pagefault_disable(); + ret = iomap_file_buffered_write(iocb, from, &gfs2_iomap_ops); + pagefault_enable(); + current->backing_dev_info = NULL; + if (ret > 0) { + iocb->ki_pos += ret; + read += ret; + } + + if (inode == sdp->sd_rindex) + gfs2_glock_dq_uninit(statfs_gh); + + from->count = orig_count - read; + if (should_fault_in_pages(ret, from, &prev_count, &window_size)) { + size_t leftover; + + gfs2_holder_allow_demote(gh); + leftover = fault_in_iov_iter_readable(from, window_size); + gfs2_holder_disallow_demote(gh); + if (leftover != window_size) { + from->count = min(from->count, window_size - leftover); + if (gfs2_holder_queued(gh)) + goto retry_under_glock; + goto retry; + } + } +out_unlock: + if (gfs2_holder_queued(gh)) + gfs2_glock_dq(gh); +out_uninit: + gfs2_holder_uninit(gh); + if (statfs_gh) + kfree(statfs_gh); + return read ? read : ret; +} + /** * gfs2_file_write_iter - Perform a write to a file * @iocb: The io context @@ -928,9 +1138,7 @@ goto out_unlock; iocb->ki_flags |= IOCB_DSYNC; - current->backing_dev_info = inode_to_bdi(inode); - buffered = iomap_file_buffered_write(iocb, from, &gfs2_iomap_ops); - current->backing_dev_info = NULL; + buffered = gfs2_file_buffered_write(iocb, from, &gh); if (unlikely(buffered <= 0)) { if (!ret) ret = buffered; @@ -944,7 +1152,6 @@ * the direct I/O range as we don't know if the buffered pages * made it to disk. */ - iocb->ki_pos += buffered; ret2 = generic_write_sync(iocb, buffered); invalidate_mapping_pages(mapping, (iocb->ki_pos - buffered) >> PAGE_SHIFT, @@ -952,13 +1159,9 @@ if (!ret || ret2 > 0) ret += ret2; } else { - current->backing_dev_info = inode_to_bdi(inode); - ret = iomap_file_buffered_write(iocb, from, &gfs2_iomap_ops); - current->backing_dev_info = NULL; - if (likely(ret > 0)) { - iocb->ki_pos += ret; + ret = gfs2_file_buffered_write(iocb, from, &gh); + if (likely(ret > 0)) ret = generic_write_sync(iocb, ret); - } } out_unlock: diff -u linux-5.15.0/fs/gfs2/glock.c linux-5.15.0/fs/gfs2/glock.c --- linux-5.15.0/fs/gfs2/glock.c +++ linux-5.15.0/fs/gfs2/glock.c @@ -58,6 +58,7 @@ typedef void (*glock_examiner) (struct gfs2_glock * gl); static void do_xmote(struct gfs2_glock *gl, struct gfs2_holder *gh, unsigned int target); +static void __gfs2_glock_dq(struct gfs2_holder *gh); static struct dentry *gfs2_root; static struct workqueue_struct *glock_workqueue; @@ -197,6 +198,12 @@ if (gl->gl_state == LM_ST_UNLOCKED) return 0; + /* + * Note that demote_ok is used for the lru process of disposing of + * glocks. For this purpose, we don't care if the glock's holders + * have the HIF_MAY_DEMOTE flag set or not. If someone is using + * them, don't demote. + */ if (!list_empty(&gl->gl_holders)) return 0; if (glops->go_demote_ok) @@ -301,46 +308,59 @@ } /** - * may_grant - check if its ok to grant a new lock + * may_grant - check if it's ok to grant a new lock * @gl: The glock + * @current_gh: One of the current holders of @gl * @gh: The lock request which we wish to grant * - * Returns: true if its ok to grant the lock + * With our current compatibility rules, if a glock has one or more active + * holders (HIF_HOLDER flag set), any of those holders can be passed in as + * @current_gh; they are all the same as far as compatibility with the new @gh + * goes. + * + * Returns true if it's ok to grant the lock. */ -static inline int may_grant(const struct gfs2_glock *gl, const struct gfs2_holder *gh) +static inline bool may_grant(struct gfs2_glock *gl, + struct gfs2_holder *current_gh, + struct gfs2_holder *gh) { - const struct gfs2_holder *gh_head = list_first_entry(&gl->gl_holders, const struct gfs2_holder, gh_list); + if (current_gh) { + GLOCK_BUG_ON(gl, !test_bit(HIF_HOLDER, ¤t_gh->gh_iflags)); - if (gh != gh_head) { - /** - * Here we make a special exception to grant holders who agree - * to share the EX lock with other holders who also have the - * bit set. If the original holder has the LM_FLAG_NODE_SCOPE bit - * is set, we grant more holders with the bit set. - */ - if (gh_head->gh_state == LM_ST_EXCLUSIVE && - (gh_head->gh_flags & LM_FLAG_NODE_SCOPE) && - gh->gh_state == LM_ST_EXCLUSIVE && - (gh->gh_flags & LM_FLAG_NODE_SCOPE)) - return 1; - if ((gh->gh_state == LM_ST_EXCLUSIVE || - gh_head->gh_state == LM_ST_EXCLUSIVE)) - return 0; + switch(current_gh->gh_state) { + case LM_ST_EXCLUSIVE: + /* + * Here we make a special exception to grant holders + * who agree to share the EX lock with other holders + * who also have the bit set. If the original holder + * has the LM_FLAG_NODE_SCOPE bit set, we grant more + * holders with the bit set. + */ + return gh->gh_state == LM_ST_EXCLUSIVE && + (current_gh->gh_flags & LM_FLAG_NODE_SCOPE) && + (gh->gh_flags & LM_FLAG_NODE_SCOPE); + + case LM_ST_SHARED: + case LM_ST_DEFERRED: + return gh->gh_state == current_gh->gh_state; + + default: + return false; + } } + if (gl->gl_state == gh->gh_state) - return 1; + return true; if (gh->gh_flags & GL_EXACT) - return 0; + return false; if (gl->gl_state == LM_ST_EXCLUSIVE) { - if (gh->gh_state == LM_ST_SHARED && gh_head->gh_state == LM_ST_SHARED) - return 1; - if (gh->gh_state == LM_ST_DEFERRED && gh_head->gh_state == LM_ST_DEFERRED) - return 1; + return gh->gh_state == LM_ST_SHARED || + gh->gh_state == LM_ST_DEFERRED; } - if (gl->gl_state != LM_ST_UNLOCKED && (gh->gh_flags & LM_FLAG_ANY)) - return 1; - return 0; + if (gh->gh_flags & LM_FLAG_ANY) + return gl->gl_state != LM_ST_UNLOCKED; + return false; } static void gfs2_holder_wake(struct gfs2_holder *gh) @@ -366,7 +386,7 @@ struct gfs2_holder *gh, *tmp; list_for_each_entry_safe(gh, tmp, &gl->gl_holders, gh_list) { - if (test_bit(HIF_HOLDER, &gh->gh_iflags)) + if (!test_bit(HIF_WAIT, &gh->gh_iflags)) continue; if (ret & LM_OUT_ERROR) gh->gh_error = -EIO; @@ -381,6 +401,78 @@ } /** + * demote_incompat_holders - demote incompatible demoteable holders + * @gl: the glock we want to promote + * @new_gh: the new holder to be promoted + */ +static void demote_incompat_holders(struct gfs2_glock *gl, + struct gfs2_holder *new_gh) +{ + struct gfs2_holder *gh; + + /* + * Demote incompatible holders before we make ourselves eligible. + * (This holder may or may not allow auto-demoting, but we don't want + * to demote the new holder before it's even granted.) + */ + list_for_each_entry(gh, &gl->gl_holders, gh_list) { + /* + * Since holders are at the front of the list, we stop when we + * find the first non-holder. + */ + if (!test_bit(HIF_HOLDER, &gh->gh_iflags)) + return; + if (test_bit(HIF_MAY_DEMOTE, &gh->gh_iflags) && + !may_grant(gl, new_gh, gh)) { + /* + * We should not recurse into do_promote because + * __gfs2_glock_dq only calls handle_callback, + * gfs2_glock_add_to_lru and __gfs2_glock_queue_work. + */ + __gfs2_glock_dq(gh); + } + } +} + +/** + * find_first_holder - find the first "holder" gh + * @gl: the glock + */ + +static inline struct gfs2_holder *find_first_holder(const struct gfs2_glock *gl) +{ + struct gfs2_holder *gh; + + if (!list_empty(&gl->gl_holders)) { + gh = list_first_entry(&gl->gl_holders, struct gfs2_holder, + gh_list); + if (test_bit(HIF_HOLDER, &gh->gh_iflags)) + return gh; + } + return NULL; +} + +/** + * find_first_strong_holder - find the first non-demoteable holder + * @gl: the glock + * + * Find the first holder that doesn't have the HIF_MAY_DEMOTE flag set. + */ +static inline struct gfs2_holder * +find_first_strong_holder(struct gfs2_glock *gl) +{ + struct gfs2_holder *gh; + + list_for_each_entry(gh, &gl->gl_holders, gh_list) { + if (!test_bit(HIF_HOLDER, &gh->gh_iflags)) + return NULL; + if (!test_bit(HIF_MAY_DEMOTE, &gh->gh_iflags)) + return gh; + } + return NULL; +} + +/** * do_promote - promote as many requests as possible on the current queue * @gl: The glock * @@ -393,14 +485,21 @@ __acquires(&gl->gl_lockref.lock) { const struct gfs2_glock_operations *glops = gl->gl_ops; - struct gfs2_holder *gh, *tmp; + struct gfs2_holder *gh, *tmp, *first_gh; + bool incompat_holders_demoted = false; int ret; restart: + first_gh = find_first_strong_holder(gl); list_for_each_entry_safe(gh, tmp, &gl->gl_holders, gh_list) { - if (test_bit(HIF_HOLDER, &gh->gh_iflags)) + if (!test_bit(HIF_WAIT, &gh->gh_iflags)) continue; - if (may_grant(gl, gh)) { + if (may_grant(gl, first_gh, gh)) { + if (!incompat_holders_demoted) { + demote_incompat_holders(gl, first_gh); + incompat_holders_demoted = true; + first_gh = gh; + } if (gh->gh_list.prev == &gl->gl_holders && glops->go_lock) { spin_unlock(&gl->gl_lockref.lock); @@ -426,6 +525,11 @@ gfs2_holder_wake(gh); continue; } + /* + * If we get here, it means we may not grant this holder for + * some reason. If this holder is the head of the list, it + * means we have a blocked holder at the head, so return 1. + */ if (gh->gh_list.prev == &gl->gl_holders) return 1; do_error(gl, 0); @@ -723,23 +827,6 @@ } /** - * find_first_holder - find the first "holder" gh - * @gl: the glock - */ - -static inline struct gfs2_holder *find_first_holder(const struct gfs2_glock *gl) -{ - struct gfs2_holder *gh; - - if (!list_empty(&gl->gl_holders)) { - gh = list_first_entry(&gl->gl_holders, struct gfs2_holder, gh_list); - if (test_bit(HIF_HOLDER, &gh->gh_iflags)) - return gh; - } - return NULL; -} - -/** * run_queue - do all outstanding tasks related to a glock * @gl: The glock in question * @nonblock: True if we must not block in run_queue @@ -1354,15 +1441,20 @@ GLOCK_BUG_ON(gl, true); if (gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)) { - if (test_bit(GLF_LOCK, &gl->gl_flags)) - try_futile = !may_grant(gl, gh); + if (test_bit(GLF_LOCK, &gl->gl_flags)) { + struct gfs2_holder *first_gh; + + first_gh = find_first_strong_holder(gl); + try_futile = !may_grant(gl, first_gh, gh); + } if (test_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags)) goto fail; } list_for_each_entry(gh2, &gl->gl_holders, gh_list) { if (unlikely(gh2->gh_owner_pid == gh->gh_owner_pid && - (gh->gh_gl->gl_ops->go_type != LM_TYPE_FLOCK))) + (gh->gh_gl->gl_ops->go_type != LM_TYPE_FLOCK) && + !test_bit(HIF_MAY_DEMOTE, &gh2->gh_iflags))) goto trap_recursive; if (try_futile && !(gh2->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB))) { @@ -1458,51 +1550,83 @@ return test_bit(HIF_WAIT, &gh->gh_iflags) ? 0 : 1; } -/** - * gfs2_glock_dq - dequeue a struct gfs2_holder from a glock (release a glock) - * @gh: the glock holder - * - */ +static inline bool needs_demote(struct gfs2_glock *gl) +{ + return (test_bit(GLF_DEMOTE, &gl->gl_flags) || + test_bit(GLF_PENDING_DEMOTE, &gl->gl_flags)); +} -void gfs2_glock_dq(struct gfs2_holder *gh) +static void __gfs2_glock_dq(struct gfs2_holder *gh) { struct gfs2_glock *gl = gh->gh_gl; struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; unsigned delay = 0; int fast_path = 0; - spin_lock(&gl->gl_lockref.lock); /* - * If we're in the process of file system withdraw, we cannot just - * dequeue any glocks until our journal is recovered, lest we - * introduce file system corruption. We need two exceptions to this - * rule: We need to allow unlocking of nondisk glocks and the glock - * for our own journal that needs recovery. + * This while loop is similar to function demote_incompat_holders: + * If the glock is due to be demoted (which may be from another node + * or even if this holder is GL_NOCACHE), the weak holders are + * demoted as well, allowing the glock to be demoted. */ - if (test_bit(SDF_WITHDRAW_RECOVERY, &sdp->sd_flags) && - glock_blocked_by_withdraw(gl) && - gh->gh_gl != sdp->sd_jinode_gl) { - sdp->sd_glock_dqs_held++; - spin_unlock(&gl->gl_lockref.lock); - might_sleep(); - wait_on_bit(&sdp->sd_flags, SDF_WITHDRAW_RECOVERY, - TASK_UNINTERRUPTIBLE); - spin_lock(&gl->gl_lockref.lock); - } - if (gh->gh_flags & GL_NOCACHE) - handle_callback(gl, LM_ST_UNLOCKED, 0, false); + while (gh) { + /* + * If we're in the process of file system withdraw, we cannot + * just dequeue any glocks until our journal is recovered, lest + * we introduce file system corruption. We need two exceptions + * to this rule: We need to allow unlocking of nondisk glocks + * and the glock for our own journal that needs recovery. + */ + if (test_bit(SDF_WITHDRAW_RECOVERY, &sdp->sd_flags) && + glock_blocked_by_withdraw(gl) && + gh->gh_gl != sdp->sd_jinode_gl) { + sdp->sd_glock_dqs_held++; + spin_unlock(&gl->gl_lockref.lock); + might_sleep(); + wait_on_bit(&sdp->sd_flags, SDF_WITHDRAW_RECOVERY, + TASK_UNINTERRUPTIBLE); + spin_lock(&gl->gl_lockref.lock); + } + + /* + * This holder should not be cached, so mark it for demote. + * Note: this should be done before the check for needs_demote + * below. + */ + if (gh->gh_flags & GL_NOCACHE) + handle_callback(gl, LM_ST_UNLOCKED, 0, false); + + list_del_init(&gh->gh_list); + clear_bit(HIF_HOLDER, &gh->gh_iflags); + trace_gfs2_glock_queue(gh, 0); + + /* + * If there hasn't been a demote request we are done. + * (Let the remaining holders, if any, keep holding it.) + */ + if (!needs_demote(gl)) { + if (list_empty(&gl->gl_holders)) + fast_path = 1; + break; + } + /* + * If we have another strong holder (we cannot auto-demote) + * we are done. It keeps holding it until it is done. + */ + if (find_first_strong_holder(gl)) + break; - list_del_init(&gh->gh_list); - clear_bit(HIF_HOLDER, &gh->gh_iflags); - if (list_empty(&gl->gl_holders) && - !test_bit(GLF_PENDING_DEMOTE, &gl->gl_flags) && - !test_bit(GLF_DEMOTE, &gl->gl_flags)) - fast_path = 1; + /* + * If we have a weak holder at the head of the list, it + * (and all others like it) must be auto-demoted. If there + * are no more weak holders, we exit the while loop. + */ + gh = find_first_holder(gl); + } if (!test_bit(GLF_LFLUSH, &gl->gl_flags) && demote_ok(gl)) gfs2_glock_add_to_lru(gl); - trace_gfs2_glock_queue(gh, 0); if (unlikely(!fast_path)) { gl->gl_lockref.count++; if (test_bit(GLF_PENDING_DEMOTE, &gl->gl_flags) && @@ -1511,6 +1635,19 @@ delay = gl->gl_hold_time; __gfs2_glock_queue_work(gl, delay); } +} + +/** + * gfs2_glock_dq - dequeue a struct gfs2_holder from a glock (release a glock) + * @gh: the glock holder + * + */ +void gfs2_glock_dq(struct gfs2_holder *gh) +{ + struct gfs2_glock *gl = gh->gh_gl; + + spin_lock(&gl->gl_lockref.lock); + __gfs2_glock_dq(gh); spin_unlock(&gl->gl_lockref.lock); } @@ -1673,6 +1810,7 @@ void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state) { + struct gfs2_holder mock_gh = { .gh_gl = gl, .gh_state = state, }; unsigned long delay = 0; unsigned long holdtime; unsigned long now = jiffies; @@ -1687,6 +1825,28 @@ if (test_bit(GLF_REPLY_PENDING, &gl->gl_flags)) delay = gl->gl_hold_time; } + /* + * Note 1: We cannot call demote_incompat_holders from handle_callback + * or gfs2_set_demote due to recursion problems like: gfs2_glock_dq -> + * handle_callback -> demote_incompat_holders -> gfs2_glock_dq + * Plus, we only want to demote the holders if the request comes from + * a remote cluster node because local holder conflicts are resolved + * elsewhere. + * + * Note 2: if a remote node wants this glock in EX mode, lock_dlm will + * request that we set our state to UNLOCKED. Here we mock up a holder + * to make it look like someone wants the lock EX locally. Any SH + * and DF requests should be able to share the lock without demoting. + * + * Note 3: We only want to demote the demoteable holders when there + * are no more strong holders. The demoteable holders might as well + * keep the glock until the last strong holder is done with it. + */ + if (!find_first_strong_holder(gl)) { + if (state == LM_ST_UNLOCKED) + mock_gh.gh_state = LM_ST_EXCLUSIVE; + demote_incompat_holders(gl, &mock_gh); + } handle_callback(gl, state, delay, true); __gfs2_glock_queue_work(gl, delay); spin_unlock(&gl->gl_lockref.lock); @@ -2078,6 +2238,8 @@ *p++ = 'H'; if (test_bit(HIF_WAIT, &iflags)) *p++ = 'W'; + if (test_bit(HIF_MAY_DEMOTE, &iflags)) + *p++ = 'D'; *p = 0; return buf; } diff -u linux-5.15.0/fs/gfs2/rgrp.c linux-5.15.0/fs/gfs2/rgrp.c --- linux-5.15.0/fs/gfs2/rgrp.c +++ linux-5.15.0/fs/gfs2/rgrp.c @@ -923,15 +923,15 @@ spin_lock_init(&rgd->rd_rsspin); mutex_init(&rgd->rd_mutex); - error = compute_bitstructs(rgd); - if (error) - goto fail; - error = gfs2_glock_get(sdp, rgd->rd_addr, &gfs2_rgrp_glops, CREATE, &rgd->rd_gl); if (error) goto fail; + error = compute_bitstructs(rgd); + if (error) + goto fail_glock; + rgd->rd_rgl = (struct gfs2_rgrp_lvb *)rgd->rd_gl->gl_lksb.sb_lvbptr; rgd->rd_flags &= ~(GFS2_RDF_UPTODATE | GFS2_RDF_PREFERRED); if (rgd->rd_data > sdp->sd_max_rg_data) @@ -945,6 +945,7 @@ } error = 0; /* someone else read in the rgrp; free it and ignore it */ +fail_glock: gfs2_glock_put(rgd->rd_gl); fail: diff -u linux-5.15.0/fs/hugetlbfs/inode.c linux-5.15.0/fs/hugetlbfs/inode.c --- linux-5.15.0/fs/hugetlbfs/inode.c +++ linux-5.15.0/fs/hugetlbfs/inode.c @@ -206,7 +206,7 @@ info.flags = 0; info.length = len; info.low_limit = current->mm->mmap_base; - info.high_limit = TASK_SIZE; + info.high_limit = arch_get_mmap_end(addr); info.align_mask = PAGE_MASK & ~huge_page_mask(h); info.align_offset = 0; return vm_unmapped_area(&info); @@ -222,7 +222,7 @@ info.flags = VM_UNMAPPED_AREA_TOPDOWN; info.length = len; info.low_limit = max(PAGE_SIZE, mmap_min_addr); - info.high_limit = current->mm->mmap_base; + info.high_limit = arch_get_mmap_base(addr, current->mm->mmap_base); info.align_mask = PAGE_MASK & ~huge_page_mask(h); info.align_offset = 0; addr = vm_unmapped_area(&info); @@ -237,7 +237,7 @@ VM_BUG_ON(addr != -ENOMEM); info.flags = 0; info.low_limit = current->mm->mmap_base; - info.high_limit = TASK_SIZE; + info.high_limit = arch_get_mmap_end(addr); addr = vm_unmapped_area(&info); } @@ -251,6 +251,7 @@ struct mm_struct *mm = current->mm; struct vm_area_struct *vma; struct hstate *h = hstate_file(file); + const unsigned long mmap_end = arch_get_mmap_end(addr); if (len & ~huge_page_mask(h)) return -EINVAL; @@ -266,7 +267,7 @@ if (addr) { addr = ALIGN(addr, huge_page_size(h)); vma = find_vma(mm, addr); - if (TASK_SIZE - len >= addr && + if (mmap_end - len >= addr && (!vma || addr + len <= vm_start_gap(vma))) return addr; } diff -u linux-5.15.0/fs/io_uring.c linux-5.15.0/fs/io_uring.c --- linux-5.15.0/fs/io_uring.c +++ linux-5.15.0/fs/io_uring.c @@ -4786,6 +4786,8 @@ if (unlikely(req->ctx->flags & IORING_SETUP_IOPOLL)) return -EINVAL; + if (unlikely(sqe->addr2 || sqe->file_index)) + return -EINVAL; sr->umsg = u64_to_user_ptr(READ_ONCE(sqe->addr)); sr->len = READ_ONCE(sqe->len); @@ -5007,6 +5009,8 @@ if (unlikely(req->ctx->flags & IORING_SETUP_IOPOLL)) return -EINVAL; + if (unlikely(sqe->addr2 || sqe->file_index)) + return -EINVAL; sr->umsg = u64_to_user_ptr(READ_ONCE(sqe->addr)); sr->len = READ_ONCE(sqe->len); diff -u linux-5.15.0/fs/iomap/buffered-io.c linux-5.15.0/fs/iomap/buffered-io.c --- linux-5.15.0/fs/iomap/buffered-io.c +++ linux-5.15.0/fs/iomap/buffered-io.c @@ -757,7 +757,7 @@ * same page as we're writing to, without it being marked * up-to-date. */ - if (unlikely(iov_iter_fault_in_readable(i, bytes))) { + if (unlikely(fault_in_iov_iter_readable(i, bytes))) { status = -EFAULT; break; } diff -u linux-5.15.0/fs/jbd2/commit.c linux-5.15.0/fs/jbd2/commit.c --- linux-5.15.0/fs/jbd2/commit.c +++ linux-5.15.0/fs/jbd2/commit.c @@ -501,7 +501,6 @@ } spin_unlock(&commit_transaction->t_handle_lock); commit_transaction->t_state = T_SWITCH; - write_unlock(&journal->j_state_lock); J_ASSERT (atomic_read(&commit_transaction->t_outstanding_credits) <= journal->j_max_transaction_buffers); @@ -521,6 +520,8 @@ * has reserved. This is consistent with the existing behaviour * that multiple jbd2_journal_get_write_access() calls to the same * buffer are perfectly permissible. + * We use journal->j_state_lock here to serialize processing of + * t_reserved_list with eviction of buffers from journal_unmap_buffer(). */ while (commit_transaction->t_reserved_list) { jh = commit_transaction->t_reserved_list; @@ -540,6 +541,7 @@ jbd2_journal_refile_buffer(journal, jh); } + write_unlock(&journal->j_state_lock); /* * Now try to drop any written-back buffers from the journal's * checkpoint lists. We do this *before* commit because it potentially diff -u linux-5.15.0/fs/ksmbd/smb2pdu.c linux-5.15.0/fs/ksmbd/smb2pdu.c --- linux-5.15.0/fs/ksmbd/smb2pdu.c +++ linux-5.15.0/fs/ksmbd/smb2pdu.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "glob.h" #include "smb2pdu.h" @@ -4997,15 +4998,17 @@ case FS_SECTOR_SIZE_INFORMATION: { struct smb3_fs_ss_info *info; + unsigned int sector_size = + min_t(unsigned int, path.mnt->mnt_sb->s_blocksize, 4096); info = (struct smb3_fs_ss_info *)(rsp->Buffer); - info->LogicalBytesPerSector = cpu_to_le32(stfs.f_bsize); + info->LogicalBytesPerSector = cpu_to_le32(sector_size); info->PhysicalBytesPerSectorForAtomicity = - cpu_to_le32(stfs.f_bsize); - info->PhysicalBytesPerSectorForPerf = cpu_to_le32(stfs.f_bsize); + cpu_to_le32(sector_size); + info->PhysicalBytesPerSectorForPerf = cpu_to_le32(sector_size); info->FSEffPhysicalBytesPerSectorForAtomicity = - cpu_to_le32(stfs.f_bsize); + cpu_to_le32(sector_size); info->Flags = cpu_to_le32(SSINFO_FLAGS_ALIGNED_DEVICE | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE); info->ByteOffsetForSectorAlignment = 0; @@ -5768,8 +5771,10 @@ if (parent_fp) { if (parent_fp->daccess & FILE_DELETE_LE) { pr_err("parent dir is opened with delete access\n"); + ksmbd_fd_put(work, parent_fp); return -ESHARE; } + ksmbd_fd_put(work, parent_fp); } next: return smb2_rename(work, fp, user_ns, rename_info, diff -u linux-5.15.0/fs/namei.c linux-5.15.0/fs/namei.c --- linux-5.15.0/fs/namei.c +++ linux-5.15.0/fs/namei.c @@ -3625,18 +3625,14 @@ { struct dentry *dentry = ERR_PTR(-EEXIST); struct qstr last; + bool want_dir = lookup_flags & LOOKUP_DIRECTORY; + unsigned int reval_flag = lookup_flags & LOOKUP_REVAL; + unsigned int create_flags = LOOKUP_CREATE | LOOKUP_EXCL; int type; int err2; int error; - bool is_dir = (lookup_flags & LOOKUP_DIRECTORY); - /* - * Note that only LOOKUP_REVAL and LOOKUP_DIRECTORY matter here. Any - * other flags passed in are ignored! - */ - lookup_flags &= LOOKUP_REVAL; - - error = filename_parentat(dfd, name, lookup_flags, path, &last, &type); + error = filename_parentat(dfd, name, reval_flag, path, &last, &type); if (error) return ERR_PTR(error); @@ -3650,11 +3646,13 @@ /* don't fail immediately if it's r/o, at least try to report other errors */ err2 = mnt_want_write(path->mnt); /* - * Do the final lookup. + * Do the final lookup. Suppress 'create' if there is a trailing + * '/', and a directory wasn't requested. */ - lookup_flags |= LOOKUP_CREATE | LOOKUP_EXCL; + if (last.name[last.len] && !want_dir) + create_flags = 0; inode_lock_nested(path->dentry->d_inode, I_MUTEX_PARENT); - dentry = __lookup_hash(&last, path->dentry, lookup_flags); + dentry = __lookup_hash(&last, path->dentry, reval_flag | create_flags); if (IS_ERR(dentry)) goto unlock; @@ -3668,7 +3666,7 @@ * all is fine. Let's be bastards - you had / on the end, you've * been asking for (non-existent) directory. -ENOENT for you. */ - if (unlikely(!is_dir && last.name[last.len])) { + if (unlikely(!create_flags)) { error = -ENOENT; goto fail; } diff -u linux-5.15.0/fs/nfs/nfs4proc.c linux-5.15.0/fs/nfs/nfs4proc.c --- linux-5.15.0/fs/nfs/nfs4proc.c +++ linux-5.15.0/fs/nfs/nfs4proc.c @@ -370,6 +370,14 @@ kunmap_atomic(start); } +static void nfs4_fattr_set_prechange(struct nfs_fattr *fattr, u64 version) +{ + if (!(fattr->valid & NFS_ATTR_FATTR_PRECHANGE)) { + fattr->pre_change_attr = version; + fattr->valid |= NFS_ATTR_FATTR_PRECHANGE; + } +} + static void nfs4_test_and_free_stateid(struct nfs_server *server, nfs4_stateid *stateid, const struct cred *cred) @@ -6562,7 +6570,9 @@ pnfs_roc_release(&data->lr.arg, &data->lr.res, data->res.lr_ret); if (inode) { - nfs_post_op_update_inode_force_wcc(inode, &data->fattr); + nfs4_fattr_set_prechange(&data->fattr, + inode_peek_iversion_raw(inode)); + nfs_refresh_inode(inode, &data->fattr); nfs_iput_and_deactive(inode); } kfree(calldata); diff -u linux-5.15.0/fs/sync.c linux-5.15.0/fs/sync.c --- linux-5.15.0/fs/sync.c +++ linux-5.15.0/fs/sync.c @@ -82,21 +82,6 @@ sb->s_op->sync_fs(sb, *(int *)arg); } -static void fdatawrite_one_bdev(struct block_device *bdev, void *arg) -{ - filemap_fdatawrite(bdev->bd_inode->i_mapping); -} - -static void fdatawait_one_bdev(struct block_device *bdev, void *arg) -{ - /* - * We keep the error status of individual mapping so that - * applications can catch the writeback error using fsync(2). - * See filemap_fdatawait_keep_errors() for details. - */ - filemap_fdatawait_keep_errors(bdev->bd_inode->i_mapping); -} - /* * Sync everything. We start by waking flusher threads so that most of * writeback runs on all devices in parallel. Then we sync all inodes reliably @@ -115,8 +100,8 @@ iterate_supers(sync_inodes_one_sb, NULL); iterate_supers(sync_fs_one_sb, &nowait); iterate_supers(sync_fs_one_sb, &wait); - iterate_bdevs(fdatawrite_one_bdev, NULL); - iterate_bdevs(fdatawait_one_bdev, NULL); + sync_bdevs(false); + sync_bdevs(true); if (unlikely(laptop_mode)) laptop_sync_completion(); } @@ -137,10 +122,10 @@ */ iterate_supers(sync_inodes_one_sb, &nowait); iterate_supers(sync_fs_one_sb, &nowait); - iterate_bdevs(fdatawrite_one_bdev, NULL); + sync_bdevs(false); iterate_supers(sync_inodes_one_sb, &nowait); iterate_supers(sync_fs_one_sb, &nowait); - iterate_bdevs(fdatawrite_one_bdev, NULL); + sync_bdevs(false); printk("Emergency Sync complete\n"); kfree(work); } diff -u linux-5.15.0/fs/zonefs/super.c linux-5.15.0/fs/zonefs/super.c --- linux-5.15.0/fs/zonefs/super.c +++ linux-5.15.0/fs/zonefs/super.c @@ -35,6 +35,17 @@ lockdep_assert_held(&zi->i_truncate_mutex); + /* + * With ZNS drives, closing an explicitly open zone that has not been + * written will change the zone state to "closed", that is, the zone + * will remain active. Since this can then cause failure of explicit + * open operation on other zones if the drive active zone resources + * are exceeded, make sure that the zone does not remain active by + * resetting it. + */ + if (op == REQ_OP_ZONE_CLOSE && !zi->i_wpoffset) + op = REQ_OP_ZONE_RESET; + trace_zonefs_zone_mgmt(inode, op); ret = blkdev_zone_mgmt(inode->i_sb->s_bdev, op, zi->i_zsector, zi->i_zone_size >> SECTOR_SHIFT, GFP_NOFS); @@ -852,7 +863,7 @@ ret = zonefs_file_dio_append(iocb, from); else ret = iomap_dio_rw(iocb, from, &zonefs_iomap_ops, - &zonefs_write_dio_ops, 0); + &zonefs_write_dio_ops, 0, 0); if (zi->i_ztype == ZONEFS_ZTYPE_SEQ && (ret > 0 || ret == -EIOCBQUEUED)) { if (ret > 0) @@ -987,7 +998,7 @@ } file_accessed(iocb->ki_filp); ret = iomap_dio_rw(iocb, to, &zonefs_iomap_ops, - &zonefs_read_dio_ops, 0); + &zonefs_read_dio_ops, 0, 0); } else { ret = generic_file_read_iter(iocb, to); if (ret == -EIO) @@ -1144,6 +1155,7 @@ inode_init_once(&zi->i_vnode); mutex_init(&zi->i_truncate_mutex); zi->i_wr_refcnt = 0; + zi->i_flags = 0; return &zi->i_vnode; } @@ -1295,12 +1307,13 @@ inc_nlink(parent); } -static void zonefs_init_file_inode(struct inode *inode, struct blk_zone *zone, - enum zonefs_ztype type) +static int zonefs_init_file_inode(struct inode *inode, struct blk_zone *zone, + enum zonefs_ztype type) { struct super_block *sb = inode->i_sb; struct zonefs_sb_info *sbi = ZONEFS_SB(sb); struct zonefs_inode_info *zi = ZONEFS_I(inode); + int ret = 0; inode->i_ino = zone->start >> sbi->s_zone_sectors_shift; inode->i_mode = S_IFREG | sbi->s_perm; @@ -1325,6 +1338,22 @@ sb->s_maxbytes = max(zi->i_max_size, sb->s_maxbytes); sbi->s_blocks += zi->i_max_size >> sb->s_blocksize_bits; sbi->s_used_blocks += zi->i_wpoffset >> sb->s_blocksize_bits; + + /* + * For sequential zones, make sure that any open zone is closed first + * to ensure that the initial number of open zones is 0, in sync with + * the open zone accounting done when the mount option + * ZONEFS_MNTOPT_EXPLICIT_OPEN is used. + */ + if (type == ZONEFS_ZTYPE_SEQ && + (zone->cond == BLK_ZONE_COND_IMP_OPEN || + zone->cond == BLK_ZONE_COND_EXP_OPEN)) { + mutex_lock(&zi->i_truncate_mutex); + ret = zonefs_zone_mgmt(inode, REQ_OP_ZONE_CLOSE); + mutex_unlock(&zi->i_truncate_mutex); + } + + return ret; } static struct dentry *zonefs_create_inode(struct dentry *parent, @@ -1334,6 +1363,7 @@ struct inode *dir = d_inode(parent); struct dentry *dentry; struct inode *inode; + int ret; dentry = d_alloc_name(parent, name); if (!dentry) @@ -1344,10 +1374,16 @@ goto dput; inode->i_ctime = inode->i_mtime = inode->i_atime = dir->i_ctime; - if (zone) - zonefs_init_file_inode(inode, zone, type); - else + if (zone) { + ret = zonefs_init_file_inode(inode, zone, type); + if (ret) { + iput(inode); + goto dput; + } + } else { zonefs_init_dir_inode(dir, inode, type); + } + d_add(dentry, inode); dir->i_size++; diff -u linux-5.15.0/include/linux/blkdev.h linux-5.15.0/include/linux/blkdev.h --- linux-5.15.0/include/linux/blkdev.h +++ linux-5.15.0/include/linux/blkdev.h @@ -1999,6 +1999,7 @@ #ifdef CONFIG_BLOCK void invalidate_bdev(struct block_device *bdev); int sync_blockdev(struct block_device *bdev); +void sync_bdevs(bool wait); #else static inline void invalidate_bdev(struct block_device *bdev) { @@ -2007,6 +2008,9 @@ { return 0; } +static inline void sync_bdevs(bool wait) +{ +} #endif int fsync_bdev(struct block_device *bdev); diff -u linux-5.15.0/include/linux/bpf.h linux-5.15.0/include/linux/bpf.h --- linux-5.15.0/include/linux/bpf.h +++ linux-5.15.0/include/linux/bpf.h @@ -293,6 +293,34 @@ extern const struct bpf_map_ops bpf_map_offload_ops; +/* bpf_type_flag contains a set of flags that are applicable to the values of + * arg_type, ret_type and reg_type. For example, a pointer value may be null, + * or a memory is read-only. We classify types into two categories: base types + * and extended types. Extended types are base types combined with a type flag. + * + * Currently there are no more than 32 base types in arg_type, ret_type and + * reg_types. + */ +#define BPF_BASE_TYPE_BITS 8 + +enum bpf_type_flag { + /* PTR may be NULL. */ + PTR_MAYBE_NULL = BIT(0 + BPF_BASE_TYPE_BITS), + + /* MEM is read-only. When applied on bpf_arg, it indicates the arg is + * compatible with both mutable and immutable memory. + */ + MEM_RDONLY = BIT(1 + BPF_BASE_TYPE_BITS), + + __BPF_TYPE_LAST_FLAG = MEM_RDONLY, +}; + +/* Max number of base types. */ +#define BPF_BASE_TYPE_LIMIT (1UL << BPF_BASE_TYPE_BITS) + +/* Max number of all types. */ +#define BPF_TYPE_LIMIT (__BPF_TYPE_LAST_FLAG | (__BPF_TYPE_LAST_FLAG - 1)) + /* function argument constraints */ enum bpf_arg_type { ARG_DONTCARE = 0, /* unused argument in helper function */ @@ -304,13 +332,11 @@ ARG_PTR_TO_MAP_KEY, /* pointer to stack used as map key */ ARG_PTR_TO_MAP_VALUE, /* pointer to stack used as map value */ ARG_PTR_TO_UNINIT_MAP_VALUE, /* pointer to valid memory used to store a map value */ - ARG_PTR_TO_MAP_VALUE_OR_NULL, /* pointer to stack used as map value or NULL */ /* the following constraints used to prototype bpf_memcmp() and other * functions that access data on eBPF program stack */ ARG_PTR_TO_MEM, /* pointer to valid memory (stack, packet, map value) */ - ARG_PTR_TO_MEM_OR_NULL, /* pointer to valid memory or NULL */ ARG_PTR_TO_UNINIT_MEM, /* pointer to memory does not need to be initialized, * helper function must fill all bytes or clear * them in error case. @@ -320,42 +346,65 @@ ARG_CONST_SIZE_OR_ZERO, /* number of bytes accessed from memory or 0 */ ARG_PTR_TO_CTX, /* pointer to context */ - ARG_PTR_TO_CTX_OR_NULL, /* pointer to context or NULL */ ARG_ANYTHING, /* any (initialized) argument is ok */ ARG_PTR_TO_SPIN_LOCK, /* pointer to bpf_spin_lock */ ARG_PTR_TO_SOCK_COMMON, /* pointer to sock_common */ ARG_PTR_TO_INT, /* pointer to int */ ARG_PTR_TO_LONG, /* pointer to long */ ARG_PTR_TO_SOCKET, /* pointer to bpf_sock (fullsock) */ - ARG_PTR_TO_SOCKET_OR_NULL, /* pointer to bpf_sock (fullsock) or NULL */ ARG_PTR_TO_BTF_ID, /* pointer to in-kernel struct */ ARG_PTR_TO_ALLOC_MEM, /* pointer to dynamically allocated memory */ - ARG_PTR_TO_ALLOC_MEM_OR_NULL, /* pointer to dynamically allocated memory or NULL */ ARG_CONST_ALLOC_SIZE_OR_ZERO, /* number of allocated bytes requested */ ARG_PTR_TO_BTF_ID_SOCK_COMMON, /* pointer to in-kernel sock_common or bpf-mirrored bpf_sock */ ARG_PTR_TO_PERCPU_BTF_ID, /* pointer to in-kernel percpu type */ ARG_PTR_TO_FUNC, /* pointer to a bpf program function */ - ARG_PTR_TO_STACK_OR_NULL, /* pointer to stack or NULL */ + ARG_PTR_TO_STACK, /* pointer to stack */ ARG_PTR_TO_CONST_STR, /* pointer to a null terminated read-only string */ ARG_PTR_TO_TIMER, /* pointer to bpf_timer */ __BPF_ARG_TYPE_MAX, + + /* Extended arg_types. */ + ARG_PTR_TO_MAP_VALUE_OR_NULL = PTR_MAYBE_NULL | ARG_PTR_TO_MAP_VALUE, + ARG_PTR_TO_MEM_OR_NULL = PTR_MAYBE_NULL | ARG_PTR_TO_MEM, + ARG_PTR_TO_CTX_OR_NULL = PTR_MAYBE_NULL | ARG_PTR_TO_CTX, + ARG_PTR_TO_SOCKET_OR_NULL = PTR_MAYBE_NULL | ARG_PTR_TO_SOCKET, + ARG_PTR_TO_ALLOC_MEM_OR_NULL = PTR_MAYBE_NULL | ARG_PTR_TO_ALLOC_MEM, + ARG_PTR_TO_STACK_OR_NULL = PTR_MAYBE_NULL | ARG_PTR_TO_STACK, + + /* This must be the last entry. Its purpose is to ensure the enum is + * wide enough to hold the higher bits reserved for bpf_type_flag. + */ + __BPF_ARG_TYPE_LIMIT = BPF_TYPE_LIMIT, }; +static_assert(__BPF_ARG_TYPE_MAX <= BPF_BASE_TYPE_LIMIT); /* type of values returned from helper functions */ enum bpf_return_type { RET_INTEGER, /* function returns integer */ RET_VOID, /* function doesn't return anything */ RET_PTR_TO_MAP_VALUE, /* returns a pointer to map elem value */ - RET_PTR_TO_MAP_VALUE_OR_NULL, /* returns a pointer to map elem value or NULL */ - RET_PTR_TO_SOCKET_OR_NULL, /* returns a pointer to a socket or NULL */ - RET_PTR_TO_TCP_SOCK_OR_NULL, /* returns a pointer to a tcp_sock or NULL */ - RET_PTR_TO_SOCK_COMMON_OR_NULL, /* returns a pointer to a sock_common or NULL */ - RET_PTR_TO_ALLOC_MEM_OR_NULL, /* returns a pointer to dynamically allocated memory or NULL */ - RET_PTR_TO_BTF_ID_OR_NULL, /* returns a pointer to a btf_id or NULL */ - RET_PTR_TO_MEM_OR_BTF_ID_OR_NULL, /* returns a pointer to a valid memory or a btf_id or NULL */ + RET_PTR_TO_SOCKET, /* returns a pointer to a socket */ + RET_PTR_TO_TCP_SOCK, /* returns a pointer to a tcp_sock */ + RET_PTR_TO_SOCK_COMMON, /* returns a pointer to a sock_common */ + RET_PTR_TO_ALLOC_MEM, /* returns a pointer to dynamically allocated memory */ RET_PTR_TO_MEM_OR_BTF_ID, /* returns a pointer to a valid memory or a btf_id */ RET_PTR_TO_BTF_ID, /* returns a pointer to a btf_id */ + __BPF_RET_TYPE_MAX, + + /* Extended ret_types. */ + RET_PTR_TO_MAP_VALUE_OR_NULL = PTR_MAYBE_NULL | RET_PTR_TO_MAP_VALUE, + RET_PTR_TO_SOCKET_OR_NULL = PTR_MAYBE_NULL | RET_PTR_TO_SOCKET, + RET_PTR_TO_TCP_SOCK_OR_NULL = PTR_MAYBE_NULL | RET_PTR_TO_TCP_SOCK, + RET_PTR_TO_SOCK_COMMON_OR_NULL = PTR_MAYBE_NULL | RET_PTR_TO_SOCK_COMMON, + RET_PTR_TO_ALLOC_MEM_OR_NULL = PTR_MAYBE_NULL | RET_PTR_TO_ALLOC_MEM, + RET_PTR_TO_BTF_ID_OR_NULL = PTR_MAYBE_NULL | RET_PTR_TO_BTF_ID, + + /* This must be the last entry. Its purpose is to ensure the enum is + * wide enough to hold the higher bits reserved for bpf_type_flag. + */ + __BPF_RET_TYPE_LIMIT = BPF_TYPE_LIMIT, }; +static_assert(__BPF_RET_TYPE_MAX <= BPF_BASE_TYPE_LIMIT); /* eBPF function prototype used by verifier to allow BPF_CALLs from eBPF programs * to in-kernel helper functions and for adjusting imm32 field in BPF_CALL @@ -417,18 +466,15 @@ PTR_TO_CTX, /* reg points to bpf_context */ CONST_PTR_TO_MAP, /* reg points to struct bpf_map */ PTR_TO_MAP_VALUE, /* reg points to map element value */ - PTR_TO_MAP_VALUE_OR_NULL,/* points to map elem value or NULL */ + PTR_TO_MAP_KEY, /* reg points to a map element key */ PTR_TO_STACK, /* reg == frame_pointer + offset */ PTR_TO_PACKET_META, /* skb->data - meta_len */ PTR_TO_PACKET, /* reg points to skb->data */ PTR_TO_PACKET_END, /* skb->data + headlen */ PTR_TO_FLOW_KEYS, /* reg points to bpf_flow_keys */ PTR_TO_SOCKET, /* reg points to struct bpf_sock */ - PTR_TO_SOCKET_OR_NULL, /* reg points to struct bpf_sock or NULL */ PTR_TO_SOCK_COMMON, /* reg points to sock_common */ - PTR_TO_SOCK_COMMON_OR_NULL, /* reg points to sock_common or NULL */ PTR_TO_TCP_SOCK, /* reg points to struct tcp_sock */ - PTR_TO_TCP_SOCK_OR_NULL, /* reg points to struct tcp_sock or NULL */ PTR_TO_TP_BUFFER, /* reg points to a writable raw tp's buffer */ PTR_TO_XDP_SOCK, /* reg points to struct xdp_sock */ /* PTR_TO_BTF_ID points to a kernel struct that does not need @@ -446,18 +492,25 @@ * been checked for null. Used primarily to inform the verifier * an explicit null check is required for this struct. */ - PTR_TO_BTF_ID_OR_NULL, PTR_TO_MEM, /* reg points to valid memory region */ - PTR_TO_MEM_OR_NULL, /* reg points to valid memory region or NULL */ - PTR_TO_RDONLY_BUF, /* reg points to a readonly buffer */ - PTR_TO_RDONLY_BUF_OR_NULL, /* reg points to a readonly buffer or NULL */ - PTR_TO_RDWR_BUF, /* reg points to a read/write buffer */ - PTR_TO_RDWR_BUF_OR_NULL, /* reg points to a read/write buffer or NULL */ + PTR_TO_BUF, /* reg points to a read/write buffer */ PTR_TO_PERCPU_BTF_ID, /* reg points to a percpu kernel variable */ PTR_TO_FUNC, /* reg points to a bpf program function */ - PTR_TO_MAP_KEY, /* reg points to a map element key */ __BPF_REG_TYPE_MAX, + + /* Extended reg_types. */ + PTR_TO_MAP_VALUE_OR_NULL = PTR_MAYBE_NULL | PTR_TO_MAP_VALUE, + PTR_TO_SOCKET_OR_NULL = PTR_MAYBE_NULL | PTR_TO_SOCKET, + PTR_TO_SOCK_COMMON_OR_NULL = PTR_MAYBE_NULL | PTR_TO_SOCK_COMMON, + PTR_TO_TCP_SOCK_OR_NULL = PTR_MAYBE_NULL | PTR_TO_TCP_SOCK, + PTR_TO_BTF_ID_OR_NULL = PTR_MAYBE_NULL | PTR_TO_BTF_ID, + + /* This must be the last entry. Its purpose is to ensure the enum is + * wide enough to hold the higher bits reserved for bpf_type_flag. + */ + __BPF_REG_TYPE_LIMIT = BPF_TYPE_LIMIT, }; +static_assert(__BPF_REG_TYPE_MAX <= BPF_BASE_TYPE_LIMIT); /* The information passed from prog-specific *_is_valid_access * back to the verifier. diff -u linux-5.15.0/include/linux/bpf_verifier.h linux-5.15.0/include/linux/bpf_verifier.h --- linux-5.15.0/include/linux/bpf_verifier.h +++ linux-5.15.0/include/linux/bpf_verifier.h @@ -18,6 +18,8 @@ * that converting umax_value to int cannot overflow. */ #define BPF_MAX_VAR_SIZ (1 << 29) +/* size of type_str_buf in bpf_verifier. */ +#define TYPE_STR_BUF_LEN 64 /* Liveness marks, used for registers and spilled-regs (in stack slots). * Read marks propagate upwards until they find a write mark; they record that @@ -474,6 +476,8 @@ /* longest register parentage chain walked for liveness marking */ u32 longest_mark_read_walk; bpfptr_t fd_array; + /* buffer used in reg_type_str() to generate reg_type string */ + char type_str_buf[TYPE_STR_BUF_LEN]; }; __printf(2, 0) void bpf_verifier_vlog(struct bpf_verifier_log *log, @@ -537,2 +541,16 @@ +#define BPF_BASE_TYPE_MASK GENMASK(BPF_BASE_TYPE_BITS - 1, 0) + +/* extract base type from bpf_{arg, return, reg}_type. */ +static inline u32 base_type(u32 type) +{ + return type & BPF_BASE_TYPE_MASK; +} + +/* extract flags from an extended type. See bpf_type_flag in bpf.h. */ +static inline u32 type_flag(u32 type) +{ + return type & ~BPF_BASE_TYPE_MASK; +} + #endif /* _LINUX_BPF_VERIFIER_H */ diff -u linux-5.15.0/include/linux/kfence.h linux-5.15.0/include/linux/kfence.h --- linux-5.15.0/include/linux/kfence.h +++ linux-5.15.0/include/linux/kfence.h @@ -202,6 +202,22 @@ */ bool __must_check kfence_handle_page_fault(unsigned long addr, bool is_write, struct pt_regs *regs); +#ifdef CONFIG_PRINTK +struct kmem_obj_info; +/** + * __kfence_obj_info() - fill kmem_obj_info struct + * @kpp: kmem_obj_info to be filled + * @object: the object + * + * Return: + * * false - not a KFENCE object + * * true - a KFENCE object, filled @kpp + * + * Copies information to @kpp for KFENCE objects. + */ +bool __kfence_obj_info(struct kmem_obj_info *kpp, void *object, struct page *page); +#endif + #else /* CONFIG_KFENCE */ static inline bool is_kfence_address(const void *addr) { return false; } @@ -219,6 +235,14 @@ return false; } +#ifdef CONFIG_PRINTK +struct kmem_obj_info; +static inline bool __kfence_obj_info(struct kmem_obj_info *kpp, void *object, struct page *page) +{ + return false; +} +#endif + #endif #endif /* _LINUX_KFENCE_H */ diff -u linux-5.15.0/include/linux/memcontrol.h linux-5.15.0/include/linux/memcontrol.h --- linux-5.15.0/include/linux/memcontrol.h +++ linux-5.15.0/include/linux/memcontrol.h @@ -1002,6 +1002,7 @@ } void mem_cgroup_flush_stats(void); +void mem_cgroup_flush_stats_delayed(void); void __mod_memcg_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx, int val); @@ -1422,6 +1423,10 @@ { } +static inline void mem_cgroup_flush_stats_delayed(void) +{ +} + static inline void __mod_memcg_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx, int val) { diff -u linux-5.15.0/include/linux/mm.h linux-5.15.0/include/linux/mm.h --- linux-5.15.0/include/linux/mm.h +++ linux-5.15.0/include/linux/mm.h @@ -2880,7 +2880,8 @@ #define FOLL_FORCE 0x10 /* get_user_pages read/write w/o permission */ #define FOLL_NOWAIT 0x20 /* if a disk transfer is needed, start the IO * and return without waiting upon it */ -#define FOLL_POPULATE 0x40 /* fault in page */ +#define FOLL_POPULATE 0x40 /* fault in pages (with FOLL_MLOCK) */ +#define FOLL_NOFAULT 0x80 /* do not fault in pages */ #define FOLL_HWPOISON 0x100 /* check page is hwpoisoned */ #define FOLL_NUMA 0x200 /* force NUMA hinting page fault */ #define FOLL_MIGRATION 0x400 /* wait for page to replace migration entry */ diff -u linux-5.15.0/include/linux/sched.h linux-5.15.0/include/linux/sched.h --- linux-5.15.0/include/linux/sched.h +++ linux-5.15.0/include/linux/sched.h @@ -1436,6 +1436,7 @@ int pagefault_disabled; #ifdef CONFIG_MMU struct task_struct *oom_reaper_list; + struct timer_list oom_reaper_timer; #endif #ifdef CONFIG_VMAP_STACK struct vm_struct *stack_vm_area; diff -u linux-5.15.0/include/linux/stmmac.h linux-5.15.0/include/linux/stmmac.h --- linux-5.15.0/include/linux/stmmac.h +++ linux-5.15.0/include/linux/stmmac.h @@ -270,4 +270,5 @@ int msi_tx_base_vec; bool use_phy_wol; + bool sph_disable; }; #endif diff -u linux-5.15.0/include/memory/renesas-rpc-if.h linux-5.15.0/include/memory/renesas-rpc-if.h --- linux-5.15.0/include/memory/renesas-rpc-if.h +++ linux-5.15.0/include/memory/renesas-rpc-if.h @@ -66,6 +66,7 @@ size_t size; enum rpcif_data_dir dir; u8 bus_size; + u8 xfer_size; void *buffer; u32 xferlen; u32 smcr; reverted: --- linux-5.15.0/include/net/esp.h +++ linux-5.15.0.orig/include/net/esp.h @@ -4,8 +4,6 @@ #include -#define ESP_SKB_FRAG_MAXSIZE (PAGE_SIZE << SKB_FRAG_PAGE_ORDER) - struct ip_esp_hdr; static inline struct ip_esp_hdr *ip_esp_hdr(const struct sk_buff *skb) diff -u linux-5.15.0/include/net/ip_tunnels.h linux-5.15.0/include/net/ip_tunnels.h --- linux-5.15.0/include/net/ip_tunnels.h +++ linux-5.15.0/include/net/ip_tunnels.h @@ -135,7 +135,7 @@ /* These four fields used only by GRE */ u32 i_seqno; /* The last seen seqno */ - u32 o_seqno; /* The last output seqno */ + atomic_t o_seqno; /* The last output seqno */ int tun_hlen; /* Precalculated header length */ /* These four fields used only by ERSPAN */ diff -u linux-5.15.0/include/net/netfilter/nf_conntrack.h linux-5.15.0/include/net/netfilter/nf_conntrack.h --- linux-5.15.0/include/net/netfilter/nf_conntrack.h +++ linux-5.15.0/include/net/netfilter/nf_conntrack.h @@ -76,6 +76,8 @@ * Hint, SKB address this struct and refcnt via skb->_nfct and * helpers nf_conntrack_get() and nf_conntrack_put(). * Helper nf_ct_put() equals nf_conntrack_put() by dec refcnt, + * except that the latter uses internal indirection and does not + * result in a conntrack module dependency. * beware nf_ct_get() is different and don't inc refcnt. */ struct nf_conntrack ct_general; @@ -169,11 +171,13 @@ return (struct nf_conn *)(nfct & NFCT_PTRMASK); } +void nf_ct_destroy(struct nf_conntrack *nfct); + /* decrement reference count on a conntrack */ static inline void nf_ct_put(struct nf_conn *ct) { - WARN_ON(!ct); - nf_conntrack_put(&ct->ct_general); + if (ct && refcount_dec_and_test(&ct->ct_general.use)) + nf_ct_destroy(&ct->ct_general); } /* Protocol module loading */ diff -u linux-5.15.0/include/net/netns/ipv6.h linux-5.15.0/include/net/netns/ipv6.h --- linux-5.15.0/include/net/netns/ipv6.h +++ linux-5.15.0/include/net/netns/ipv6.h @@ -75,8 +75,8 @@ struct list_head fib6_walkers; rwlock_t fib6_walker_lock; spinlock_t fib6_gc_lock; - unsigned int ip6_rt_gc_expire; - unsigned long ip6_rt_last_gc; + atomic_t ip6_rt_gc_expire; + unsigned long ip6_rt_last_gc; unsigned char flowlabel_has_excl; #ifdef CONFIG_IPV6_MULTIPLE_TABLES bool fib6_has_custom_rules; diff -u linux-5.15.0/include/net/tcp.h linux-5.15.0/include/net/tcp.h --- linux-5.15.0/include/net/tcp.h +++ linux-5.15.0/include/net/tcp.h @@ -470,6 +470,7 @@ u32 cookie); struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb); struct request_sock *cookie_tcp_reqsk_alloc(const struct request_sock_ops *ops, + const struct tcp_request_sock_ops *af_ops, struct sock *sk, struct sk_buff *skb); #ifdef CONFIG_SYN_COOKIES @@ -608,6 +609,7 @@ void tcp_reset(struct sock *sk, struct sk_buff *skb); void tcp_skb_mark_lost_uncond_verify(struct tcp_sock *tp, struct sk_buff *skb); void tcp_fin(struct sock *sk); +void tcp_check_space(struct sock *sk); /* tcp_timer.c */ void tcp_init_xmit_timers(struct sock *); @@ -1026,6 +1028,7 @@ int losses; /* number of packets marked lost upon ACK */ u32 acked_sacked; /* number of packets newly (S)ACKed upon ACK */ u32 prior_in_flight; /* in flight before this ACK */ + u32 last_end_seq; /* end_seq of most recently ACKed packet */ bool is_app_limited; /* is sample from packet with bubble in pipe? */ bool is_retrans; /* is sample from retransmission? */ bool is_ack_delayed; /* is this (likely) a delayed ACK? */ @@ -1148,6 +1151,11 @@ bool is_sack_reneg, struct rate_sample *rs); void tcp_rate_check_app_limited(struct sock *sk); +static inline bool tcp_skb_sent_after(u64 t1, u64 t2, u32 seq1, u32 seq2) +{ + return t1 > t2 || (t1 == t2 && after(seq1, seq2)); +} + /* These functions determine how the current flow behaves in respect of SACK * handling. SACK is negotiated with the peer, and therefore it can vary * between different flows. diff -u linux-5.15.0/include/scsi/scsi_transport_iscsi.h linux-5.15.0/include/scsi/scsi_transport_iscsi.h --- linux-5.15.0/include/scsi/scsi_transport_iscsi.h +++ linux-5.15.0/include/scsi/scsi_transport_iscsi.h @@ -296,7 +296,7 @@ struct iscsi_endpoint { void *dd_data; /* LLD private data */ struct device dev; - uint64_t id; + int id; struct iscsi_cls_conn *conn; }; diff -u linux-5.15.0/kernel/bpf/btf.c linux-5.15.0/kernel/bpf/btf.c --- linux-5.15.0/kernel/bpf/btf.c +++ linux-5.15.0/kernel/bpf/btf.c @@ -4800,10 +4800,12 @@ /* check for PTR_TO_RDONLY_BUF_OR_NULL or PTR_TO_RDWR_BUF_OR_NULL */ for (i = 0; i < prog->aux->ctx_arg_info_size; i++) { const struct bpf_ctx_arg_aux *ctx_arg_info = &prog->aux->ctx_arg_info[i]; + u32 type, flag; - if (ctx_arg_info->offset == off && - (ctx_arg_info->reg_type == PTR_TO_RDONLY_BUF_OR_NULL || - ctx_arg_info->reg_type == PTR_TO_RDWR_BUF_OR_NULL)) { + type = base_type(ctx_arg_info->reg_type); + flag = type_flag(ctx_arg_info->reg_type); + if (ctx_arg_info->offset == off && type == PTR_TO_BUF && + (flag & PTR_MAYBE_NULL)) { info->reg_type = ctx_arg_info->reg_type; return true; } @@ -5508,9 +5510,9 @@ if (reg->type == PTR_TO_BTF_ID) { reg_btf = reg->btf; reg_ref_id = reg->btf_id; - } else if (reg2btf_ids[reg->type]) { + } else if (reg2btf_ids[base_type(reg->type)]) { reg_btf = btf_vmlinux; - reg_ref_id = *reg2btf_ids[reg->type]; + reg_ref_id = *reg2btf_ids[base_type(reg->type)]; } else { bpf_log(log, "kernel function %s args#%d expected pointer to %s %s but R%d is not a pointer to btf_id\n", func_name, i, @@ -5717,7 +5719,7 @@ return -EINVAL; } - reg->type = PTR_TO_MEM_OR_NULL; + reg->type = PTR_TO_MEM | PTR_MAYBE_NULL; reg->id = ++env->id_gen; continue; @@ -6229,7 +6231,7 @@ .func = bpf_btf_find_by_name_kind, .gpl_only = false, .ret_type = RET_INTEGER, - .arg1_type = ARG_PTR_TO_MEM, + .arg1_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg2_type = ARG_CONST_SIZE, .arg3_type = ARG_ANYTHING, .arg4_type = ARG_ANYTHING, diff -u linux-5.15.0/kernel/bpf/cgroup.c linux-5.15.0/kernel/bpf/cgroup.c --- linux-5.15.0/kernel/bpf/cgroup.c +++ linux-5.15.0/kernel/bpf/cgroup.c @@ -1753,7 +1753,7 @@ .gpl_only = false, .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE, }; diff -u linux-5.15.0/kernel/bpf/helpers.c linux-5.15.0/kernel/bpf/helpers.c --- linux-5.15.0/kernel/bpf/helpers.c +++ linux-5.15.0/kernel/bpf/helpers.c @@ -530,7 +530,7 @@ .func = bpf_strtol, .gpl_only = false, .ret_type = RET_INTEGER, - .arg1_type = ARG_PTR_TO_MEM, + .arg1_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg2_type = ARG_CONST_SIZE, .arg3_type = ARG_ANYTHING, .arg4_type = ARG_PTR_TO_LONG, @@ -558,7 +558,7 @@ .func = bpf_strtoul, .gpl_only = false, .ret_type = RET_INTEGER, - .arg1_type = ARG_PTR_TO_MEM, + .arg1_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg2_type = ARG_CONST_SIZE, .arg3_type = ARG_ANYTHING, .arg4_type = ARG_PTR_TO_LONG, @@ -630,7 +630,7 @@ .arg1_type = ARG_PTR_TO_CTX, .arg2_type = ARG_CONST_MAP_PTR, .arg3_type = ARG_ANYTHING, - .arg4_type = ARG_PTR_TO_MEM, + .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg5_type = ARG_CONST_SIZE_OR_ZERO, }; @@ -667,7 +667,7 @@ const struct bpf_func_proto bpf_per_cpu_ptr_proto = { .func = bpf_per_cpu_ptr, .gpl_only = false, - .ret_type = RET_PTR_TO_MEM_OR_BTF_ID_OR_NULL, + .ret_type = RET_PTR_TO_MEM_OR_BTF_ID | PTR_MAYBE_NULL | MEM_RDONLY, .arg1_type = ARG_PTR_TO_PERCPU_BTF_ID, .arg2_type = ARG_ANYTHING, }; @@ -680,7 +680,7 @@ const struct bpf_func_proto bpf_this_cpu_ptr_proto = { .func = bpf_this_cpu_ptr, .gpl_only = false, - .ret_type = RET_PTR_TO_MEM_OR_BTF_ID, + .ret_type = RET_PTR_TO_MEM_OR_BTF_ID | MEM_RDONLY, .arg1_type = ARG_PTR_TO_PERCPU_BTF_ID, }; @@ -1013,7 +1013,7 @@ .arg1_type = ARG_PTR_TO_MEM_OR_NULL, .arg2_type = ARG_CONST_SIZE_OR_ZERO, .arg3_type = ARG_PTR_TO_CONST_STR, - .arg4_type = ARG_PTR_TO_MEM_OR_NULL, + .arg4_type = ARG_PTR_TO_MEM | PTR_MAYBE_NULL | MEM_RDONLY, .arg5_type = ARG_CONST_SIZE_OR_ZERO, }; diff -u linux-5.15.0/kernel/bpf/ringbuf.c linux-5.15.0/kernel/bpf/ringbuf.c --- linux-5.15.0/kernel/bpf/ringbuf.c +++ linux-5.15.0/kernel/bpf/ringbuf.c @@ -444,7 +444,7 @@ .func = bpf_ringbuf_output, .ret_type = RET_INTEGER, .arg1_type = ARG_CONST_MAP_PTR, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE_OR_ZERO, .arg4_type = ARG_ANYTHING, }; diff -u linux-5.15.0/kernel/bpf/syscall.c linux-5.15.0/kernel/bpf/syscall.c --- linux-5.15.0/kernel/bpf/syscall.c +++ linux-5.15.0/kernel/bpf/syscall.c @@ -4753,7 +4753,7 @@ .gpl_only = false, .ret_type = RET_INTEGER, .arg1_type = ARG_ANYTHING, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE, }; diff -u linux-5.15.0/kernel/bpf/verifier.c linux-5.15.0/kernel/bpf/verifier.c --- linux-5.15.0/kernel/bpf/verifier.c +++ linux-5.15.0/kernel/bpf/verifier.c @@ -445,18 +445,6 @@ type == PTR_TO_SOCK_COMMON; } -static bool reg_type_may_be_null(enum bpf_reg_type type) -{ - return type == PTR_TO_MAP_VALUE_OR_NULL || - type == PTR_TO_SOCKET_OR_NULL || - type == PTR_TO_SOCK_COMMON_OR_NULL || - type == PTR_TO_TCP_SOCK_OR_NULL || - type == PTR_TO_BTF_ID_OR_NULL || - type == PTR_TO_MEM_OR_NULL || - type == PTR_TO_RDONLY_BUF_OR_NULL || - type == PTR_TO_RDWR_BUF_OR_NULL; -} - static bool reg_may_point_to_spin_lock(const struct bpf_reg_state *reg) { return reg->type == PTR_TO_MAP_VALUE && @@ -465,12 +453,14 @@ static bool reg_type_may_be_refcounted_or_null(enum bpf_reg_type type) { - return type == PTR_TO_SOCKET || - type == PTR_TO_SOCKET_OR_NULL || - type == PTR_TO_TCP_SOCK || - type == PTR_TO_TCP_SOCK_OR_NULL || - type == PTR_TO_MEM || - type == PTR_TO_MEM_OR_NULL; + return base_type(type) == PTR_TO_SOCKET || + base_type(type) == PTR_TO_TCP_SOCK || + base_type(type) == PTR_TO_MEM; +} + +static bool type_is_rdonly_mem(u32 type) +{ + return type & MEM_RDONLY; } static bool arg_type_may_be_refcounted(enum bpf_arg_type type) @@ -478,14 +468,9 @@ return type == ARG_PTR_TO_SOCK_COMMON; } -static bool arg_type_may_be_null(enum bpf_arg_type type) +static bool type_may_be_null(u32 type) { - return type == ARG_PTR_TO_MAP_VALUE_OR_NULL || - type == ARG_PTR_TO_MEM_OR_NULL || - type == ARG_PTR_TO_CTX_OR_NULL || - type == ARG_PTR_TO_SOCKET_OR_NULL || - type == ARG_PTR_TO_ALLOC_MEM_OR_NULL || - type == ARG_PTR_TO_STACK_OR_NULL; + return type & PTR_MAYBE_NULL; } /* Determine whether the function releases some resources allocated by another @@ -545,39 +530,54 @@ insn->imm == BPF_CMPXCHG; } -/* string representation of 'enum bpf_reg_type' */ -static const char * const reg_type_str[] = { - [NOT_INIT] = "?", - [SCALAR_VALUE] = "inv", - [PTR_TO_CTX] = "ctx", - [CONST_PTR_TO_MAP] = "map_ptr", - [PTR_TO_MAP_VALUE] = "map_value", - [PTR_TO_MAP_VALUE_OR_NULL] = "map_value_or_null", - [PTR_TO_STACK] = "fp", - [PTR_TO_PACKET] = "pkt", - [PTR_TO_PACKET_META] = "pkt_meta", - [PTR_TO_PACKET_END] = "pkt_end", - [PTR_TO_FLOW_KEYS] = "flow_keys", - [PTR_TO_SOCKET] = "sock", - [PTR_TO_SOCKET_OR_NULL] = "sock_or_null", - [PTR_TO_SOCK_COMMON] = "sock_common", - [PTR_TO_SOCK_COMMON_OR_NULL] = "sock_common_or_null", - [PTR_TO_TCP_SOCK] = "tcp_sock", - [PTR_TO_TCP_SOCK_OR_NULL] = "tcp_sock_or_null", - [PTR_TO_TP_BUFFER] = "tp_buffer", - [PTR_TO_XDP_SOCK] = "xdp_sock", - [PTR_TO_BTF_ID] = "ptr_", - [PTR_TO_BTF_ID_OR_NULL] = "ptr_or_null_", - [PTR_TO_PERCPU_BTF_ID] = "percpu_ptr_", - [PTR_TO_MEM] = "mem", - [PTR_TO_MEM_OR_NULL] = "mem_or_null", - [PTR_TO_RDONLY_BUF] = "rdonly_buf", - [PTR_TO_RDONLY_BUF_OR_NULL] = "rdonly_buf_or_null", - [PTR_TO_RDWR_BUF] = "rdwr_buf", - [PTR_TO_RDWR_BUF_OR_NULL] = "rdwr_buf_or_null", - [PTR_TO_FUNC] = "func", - [PTR_TO_MAP_KEY] = "map_key", -}; +/* string representation of 'enum bpf_reg_type' + * + * Note that reg_type_str() can not appear more than once in a single verbose() + * statement. + */ +static const char *reg_type_str(struct bpf_verifier_env *env, + enum bpf_reg_type type) +{ + char postfix[16] = {0}, prefix[16] = {0}; + static const char * const str[] = { + [NOT_INIT] = "?", + [SCALAR_VALUE] = "inv", + [PTR_TO_CTX] = "ctx", + [CONST_PTR_TO_MAP] = "map_ptr", + [PTR_TO_MAP_VALUE] = "map_value", + [PTR_TO_STACK] = "fp", + [PTR_TO_PACKET] = "pkt", + [PTR_TO_PACKET_META] = "pkt_meta", + [PTR_TO_PACKET_END] = "pkt_end", + [PTR_TO_FLOW_KEYS] = "flow_keys", + [PTR_TO_SOCKET] = "sock", + [PTR_TO_SOCK_COMMON] = "sock_common", + [PTR_TO_TCP_SOCK] = "tcp_sock", + [PTR_TO_TP_BUFFER] = "tp_buffer", + [PTR_TO_XDP_SOCK] = "xdp_sock", + [PTR_TO_BTF_ID] = "ptr_", + [PTR_TO_PERCPU_BTF_ID] = "percpu_ptr_", + [PTR_TO_MEM] = "mem", + [PTR_TO_BUF] = "buf", + [PTR_TO_FUNC] = "func", + [PTR_TO_MAP_KEY] = "map_key", + }; + + if (type & PTR_MAYBE_NULL) { + if (base_type(type) == PTR_TO_BTF_ID || + base_type(type) == PTR_TO_PERCPU_BTF_ID) + strncpy(postfix, "or_null_", 16); + else + strncpy(postfix, "_or_null", 16); + } + + if (type & MEM_RDONLY) + strncpy(prefix, "rdonly_", 16); + + snprintf(env->type_str_buf, TYPE_STR_BUF_LEN, "%s%s%s", + prefix, str[base_type(type)], postfix); + return env->type_str_buf; +} static char slot_type_char[] = { [STACK_INVALID] = '?', @@ -628,7 +628,7 @@ continue; verbose(env, " R%d", i); print_liveness(env, reg->live); - verbose(env, "=%s", reg_type_str[t]); + verbose(env, "=%s", reg_type_str(env, t)); if (t == SCALAR_VALUE && reg->precise) verbose(env, "P"); if ((t == SCALAR_VALUE || t == PTR_TO_STACK) && @@ -636,9 +636,8 @@ /* reg->off should be 0 for SCALAR_VALUE */ verbose(env, "%lld", reg->var_off.value + reg->off); } else { - if (t == PTR_TO_BTF_ID || - t == PTR_TO_BTF_ID_OR_NULL || - t == PTR_TO_PERCPU_BTF_ID) + if (base_type(t) == PTR_TO_BTF_ID || + base_type(t) == PTR_TO_PERCPU_BTF_ID) verbose(env, "%s", kernel_type_name(reg->btf, reg->btf_id)); verbose(env, "(id=%d", reg->id); if (reg_type_may_be_refcounted_or_null(t)) @@ -647,10 +646,9 @@ verbose(env, ",off=%d", reg->off); if (type_is_pkt_pointer(t)) verbose(env, ",r=%d", reg->range); - else if (t == CONST_PTR_TO_MAP || - t == PTR_TO_MAP_KEY || - t == PTR_TO_MAP_VALUE || - t == PTR_TO_MAP_VALUE_OR_NULL) + else if (base_type(t) == CONST_PTR_TO_MAP || + base_type(t) == PTR_TO_MAP_KEY || + base_type(t) == PTR_TO_MAP_VALUE) verbose(env, ",ks=%d,vs=%d", reg->map_ptr->key_size, reg->map_ptr->value_size); @@ -720,7 +718,7 @@ if (state->stack[i].slot_type[0] == STACK_SPILL) { reg = &state->stack[i].spilled_ptr; t = reg->type; - verbose(env, "=%s", reg_type_str[t]); + verbose(env, "=%s", reg_type_str(env, t)); if (t == SCALAR_VALUE && reg->precise) verbose(env, "P"); if (t == SCALAR_VALUE && tnum_is_const(reg->var_off)) @@ -1133,8 +1131,7 @@ static void mark_ptr_not_null_reg(struct bpf_reg_state *reg) { - switch (reg->type) { - case PTR_TO_MAP_VALUE_OR_NULL: { + if (base_type(reg->type) == PTR_TO_MAP_VALUE) { const struct bpf_map *map = reg->map_ptr; if (map->inner_map_meta) { @@ -1153,32 +1150,10 @@ } else { reg->type = PTR_TO_MAP_VALUE; } - break; - } - case PTR_TO_SOCKET_OR_NULL: - reg->type = PTR_TO_SOCKET; - break; - case PTR_TO_SOCK_COMMON_OR_NULL: - reg->type = PTR_TO_SOCK_COMMON; - break; - case PTR_TO_TCP_SOCK_OR_NULL: - reg->type = PTR_TO_TCP_SOCK; - break; - case PTR_TO_BTF_ID_OR_NULL: - reg->type = PTR_TO_BTF_ID; - break; - case PTR_TO_MEM_OR_NULL: - reg->type = PTR_TO_MEM; - break; - case PTR_TO_RDONLY_BUF_OR_NULL: - reg->type = PTR_TO_RDONLY_BUF; - break; - case PTR_TO_RDWR_BUF_OR_NULL: - reg->type = PTR_TO_RDWR_BUF; - break; - default: - WARN_ONCE(1, "unknown nullable register type"); + return; } + + reg->type &= ~PTR_MAYBE_NULL; } static bool reg_is_pkt_pointer(const struct bpf_reg_state *reg) @@ -1906,7 +1881,7 @@ break; if (parent->live & REG_LIVE_DONE) { verbose(env, "verifier BUG type %s var_off %lld off %d\n", - reg_type_str[parent->type], + reg_type_str(env, parent->type), parent->var_off.value, parent->off); return -EFAULT; } @@ -2564,9 +2539,8 @@ static bool is_spillable_regtype(enum bpf_reg_type type) { - switch (type) { + switch (base_type(type)) { case PTR_TO_MAP_VALUE: - case PTR_TO_MAP_VALUE_OR_NULL: case PTR_TO_STACK: case PTR_TO_CTX: case PTR_TO_PACKET: @@ -2575,21 +2549,13 @@ case PTR_TO_FLOW_KEYS: case CONST_PTR_TO_MAP: case PTR_TO_SOCKET: - case PTR_TO_SOCKET_OR_NULL: case PTR_TO_SOCK_COMMON: - case PTR_TO_SOCK_COMMON_OR_NULL: case PTR_TO_TCP_SOCK: - case PTR_TO_TCP_SOCK_OR_NULL: case PTR_TO_XDP_SOCK: case PTR_TO_BTF_ID: - case PTR_TO_BTF_ID_OR_NULL: - case PTR_TO_RDONLY_BUF: - case PTR_TO_RDONLY_BUF_OR_NULL: - case PTR_TO_RDWR_BUF: - case PTR_TO_RDWR_BUF_OR_NULL: + case PTR_TO_BUF: case PTR_TO_PERCPU_BTF_ID: case PTR_TO_MEM: - case PTR_TO_MEM_OR_NULL: case PTR_TO_FUNC: case PTR_TO_MAP_KEY: return true; @@ -3405,7 +3371,7 @@ */ *reg_type = info.reg_type; - if (*reg_type == PTR_TO_BTF_ID || *reg_type == PTR_TO_BTF_ID_OR_NULL) { + if (base_type(*reg_type) == PTR_TO_BTF_ID) { *btf = info.btf; *btf_id = info.btf_id; } else { @@ -3473,7 +3439,7 @@ } verbose(env, "R%d invalid %s access off=%d size=%d\n", - regno, reg_type_str[reg->type], off, size); + regno, reg_type_str(env, reg->type), off, size); return -EACCES; } @@ -4200,15 +4166,30 @@ mark_reg_unknown(env, regs, value_regno); } } - } else if (reg->type == PTR_TO_MEM) { + } else if (base_type(reg->type) == PTR_TO_MEM) { + bool rdonly_mem = type_is_rdonly_mem(reg->type); + + if (type_may_be_null(reg->type)) { + verbose(env, "R%d invalid mem access '%s'\n", regno, + reg_type_str(env, reg->type)); + return -EACCES; + } + + if (t == BPF_WRITE && rdonly_mem) { + verbose(env, "R%d cannot write into %s\n", + regno, reg_type_str(env, reg->type)); + return -EACCES; + } + if (t == BPF_WRITE && value_regno >= 0 && is_pointer_value(env, value_regno)) { verbose(env, "R%d leaks addr into mem\n", value_regno); return -EACCES; } + err = check_mem_region_access(env, regno, off, size, reg->mem_size, false); - if (!err && t == BPF_READ && value_regno >= 0) + if (!err && value_regno >= 0 && (t == BPF_READ || rdonly_mem)) mark_reg_unknown(env, regs, value_regno); } else if (reg->type == PTR_TO_CTX) { enum bpf_reg_type reg_type = SCALAR_VALUE; @@ -4238,7 +4219,7 @@ } else { mark_reg_known_zero(env, regs, value_regno); - if (reg_type_may_be_null(reg_type)) + if (type_may_be_null(reg_type)) regs[value_regno].id = ++env->id_gen; /* A load of ctx field could have different * actual load size with the one encoded in the @@ -4246,8 +4227,7 @@ * a sub-register. */ regs[value_regno].subreg_def = DEF_NOT_SUBREG; - if (reg_type == PTR_TO_BTF_ID || - reg_type == PTR_TO_BTF_ID_OR_NULL) { + if (base_type(reg_type) == PTR_TO_BTF_ID) { regs[value_regno].btf = btf; regs[value_regno].btf_id = btf_id; } @@ -4300,7 +4280,7 @@ } else if (type_is_sk_pointer(reg->type)) { if (t == BPF_WRITE) { verbose(env, "R%d cannot write into %s\n", - regno, reg_type_str[reg->type]); + regno, reg_type_str(env, reg->type)); return -EACCES; } err = check_sock_access(env, insn_idx, regno, off, size, t); @@ -4316,26 +4296,32 @@ } else if (reg->type == CONST_PTR_TO_MAP) { err = check_ptr_to_map_access(env, regs, regno, off, size, t, value_regno); - } else if (reg->type == PTR_TO_RDONLY_BUF) { - if (t == BPF_WRITE) { - verbose(env, "R%d cannot write into %s\n", - regno, reg_type_str[reg->type]); - return -EACCES; + } else if (base_type(reg->type) == PTR_TO_BUF) { + bool rdonly_mem = type_is_rdonly_mem(reg->type); + const char *buf_info; + u32 *max_access; + + if (rdonly_mem) { + if (t == BPF_WRITE) { + verbose(env, "R%d cannot write into %s\n", + regno, reg_type_str(env, reg->type)); + return -EACCES; + } + buf_info = "rdonly"; + max_access = &env->prog->aux->max_rdonly_access; + } else { + buf_info = "rdwr"; + max_access = &env->prog->aux->max_rdwr_access; } + err = check_buffer_access(env, reg, regno, off, size, false, - "rdonly", - &env->prog->aux->max_rdonly_access); - if (!err && value_regno >= 0) - mark_reg_unknown(env, regs, value_regno); - } else if (reg->type == PTR_TO_RDWR_BUF) { - err = check_buffer_access(env, reg, regno, off, size, false, - "rdwr", - &env->prog->aux->max_rdwr_access); - if (!err && t == BPF_READ && value_regno >= 0) + buf_info, max_access); + + if (!err && value_regno >= 0 && (rdonly_mem || t == BPF_READ)) mark_reg_unknown(env, regs, value_regno); } else { verbose(env, "R%d invalid mem access '%s'\n", regno, - reg_type_str[reg->type]); + reg_type_str(env, reg->type)); return -EACCES; } @@ -4409,7 +4395,7 @@ is_sk_reg(env, insn->dst_reg)) { verbose(env, "BPF_ATOMIC stores into R%d %s is not allowed\n", insn->dst_reg, - reg_type_str[reg_state(env, insn->dst_reg)->type]); + reg_type_str(env, reg_state(env, insn->dst_reg)->type)); return -EACCES; } @@ -4592,8 +4578,10 @@ struct bpf_call_arg_meta *meta) { struct bpf_reg_state *regs = cur_regs(env), *reg = ®s[regno]; + const char *buf_info; + u32 *max_access; - switch (reg->type) { + switch (base_type(reg->type)) { case PTR_TO_PACKET: case PTR_TO_PACKET_META: return check_packet_access(env, regno, reg->off, access_size, @@ -4612,18 +4600,20 @@ return check_mem_region_access(env, regno, reg->off, access_size, reg->mem_size, zero_size_allowed); - case PTR_TO_RDONLY_BUF: - if (meta && meta->raw_mode) - return -EACCES; - return check_buffer_access(env, reg, regno, reg->off, - access_size, zero_size_allowed, - "rdonly", - &env->prog->aux->max_rdonly_access); - case PTR_TO_RDWR_BUF: + case PTR_TO_BUF: + if (type_is_rdonly_mem(reg->type)) { + if (meta && meta->raw_mode) + return -EACCES; + + buf_info = "rdonly"; + max_access = &env->prog->aux->max_rdonly_access; + } else { + buf_info = "rdwr"; + max_access = &env->prog->aux->max_rdwr_access; + } return check_buffer_access(env, reg, regno, reg->off, access_size, zero_size_allowed, - "rdwr", - &env->prog->aux->max_rdwr_access); + buf_info, max_access); case PTR_TO_STACK: return check_stack_range_initialized( env, @@ -4635,9 +4625,9 @@ register_is_null(reg)) return 0; - verbose(env, "R%d type=%s expected=%s\n", regno, - reg_type_str[reg->type], - reg_type_str[PTR_TO_STACK]); + verbose(env, "R%d type=%s ", regno, + reg_type_str(env, reg->type)); + verbose(env, "expected=%s\n", reg_type_str(env, PTR_TO_STACK)); return -EACCES; } } @@ -4648,7 +4638,7 @@ if (register_is_null(reg)) return 0; - if (reg_type_may_be_null(reg->type)) { + if (type_may_be_null(reg->type)) { /* Assuming that the register contains a value check if the memory * access is safe. Temporarily save and restore the register's state as * the conversion shouldn't be visible to a caller. @@ -4796,9 +4786,8 @@ static bool arg_type_is_mem_ptr(enum bpf_arg_type type) { - return type == ARG_PTR_TO_MEM || - type == ARG_PTR_TO_MEM_OR_NULL || - type == ARG_PTR_TO_UNINIT_MEM; + return base_type(type) == ARG_PTR_TO_MEM || + base_type(type) == ARG_PTR_TO_UNINIT_MEM; } static bool arg_type_is_mem_size(enum bpf_arg_type type) @@ -4900,8 +4889,7 @@ PTR_TO_MAP_KEY, PTR_TO_MAP_VALUE, PTR_TO_MEM, - PTR_TO_RDONLY_BUF, - PTR_TO_RDWR_BUF, + PTR_TO_BUF, }, }; @@ -4932,31 +4920,26 @@ [ARG_PTR_TO_MAP_KEY] = &map_key_value_types, [ARG_PTR_TO_MAP_VALUE] = &map_key_value_types, [ARG_PTR_TO_UNINIT_MAP_VALUE] = &map_key_value_types, - [ARG_PTR_TO_MAP_VALUE_OR_NULL] = &map_key_value_types, [ARG_CONST_SIZE] = &scalar_types, [ARG_CONST_SIZE_OR_ZERO] = &scalar_types, [ARG_CONST_ALLOC_SIZE_OR_ZERO] = &scalar_types, [ARG_CONST_MAP_PTR] = &const_map_ptr_types, [ARG_PTR_TO_CTX] = &context_types, - [ARG_PTR_TO_CTX_OR_NULL] = &context_types, [ARG_PTR_TO_SOCK_COMMON] = &sock_types, #ifdef CONFIG_NET [ARG_PTR_TO_BTF_ID_SOCK_COMMON] = &btf_id_sock_common_types, #endif [ARG_PTR_TO_SOCKET] = &fullsock_types, - [ARG_PTR_TO_SOCKET_OR_NULL] = &fullsock_types, [ARG_PTR_TO_BTF_ID] = &btf_ptr_types, [ARG_PTR_TO_SPIN_LOCK] = &spin_lock_types, [ARG_PTR_TO_MEM] = &mem_types, - [ARG_PTR_TO_MEM_OR_NULL] = &mem_types, [ARG_PTR_TO_UNINIT_MEM] = &mem_types, [ARG_PTR_TO_ALLOC_MEM] = &alloc_mem_types, - [ARG_PTR_TO_ALLOC_MEM_OR_NULL] = &alloc_mem_types, [ARG_PTR_TO_INT] = &int_ptr_types, [ARG_PTR_TO_LONG] = &int_ptr_types, [ARG_PTR_TO_PERCPU_BTF_ID] = &percpu_btf_ptr_types, [ARG_PTR_TO_FUNC] = &func_ptr_types, - [ARG_PTR_TO_STACK_OR_NULL] = &stack_ptr_types, + [ARG_PTR_TO_STACK] = &stack_ptr_types, [ARG_PTR_TO_CONST_STR] = &const_str_ptr_types, [ARG_PTR_TO_TIMER] = &timer_types, }; @@ -4970,12 +4953,27 @@ const struct bpf_reg_types *compatible; int i, j; - compatible = compatible_reg_types[arg_type]; + compatible = compatible_reg_types[base_type(arg_type)]; if (!compatible) { verbose(env, "verifier internal error: unsupported arg type %d\n", arg_type); return -EFAULT; } + /* ARG_PTR_TO_MEM + RDONLY is compatible with PTR_TO_MEM and PTR_TO_MEM + RDONLY, + * but ARG_PTR_TO_MEM is compatible only with PTR_TO_MEM and NOT with PTR_TO_MEM + RDONLY + * + * Same for MAYBE_NULL: + * + * ARG_PTR_TO_MEM + MAYBE_NULL is compatible with PTR_TO_MEM and PTR_TO_MEM + MAYBE_NULL, + * but ARG_PTR_TO_MEM is compatible only with PTR_TO_MEM but NOT with PTR_TO_MEM + MAYBE_NULL + * + * Therefore we fold these flags depending on the arg_type before comparison. + */ + if (arg_type & MEM_RDONLY) + type &= ~MEM_RDONLY; + if (arg_type & PTR_MAYBE_NULL) + type &= ~PTR_MAYBE_NULL; + for (i = 0; i < ARRAY_SIZE(compatible->types); i++) { expected = compatible->types[i]; if (expected == NOT_INIT) @@ -4985,14 +4983,14 @@ goto found; } - verbose(env, "R%d type=%s expected=", regno, reg_type_str[type]); + verbose(env, "R%d type=%s expected=", regno, reg_type_str(env, reg->type)); for (j = 0; j + 1 < i; j++) - verbose(env, "%s, ", reg_type_str[compatible->types[j]]); - verbose(env, "%s\n", reg_type_str[compatible->types[j]]); + verbose(env, "%s, ", reg_type_str(env, compatible->types[j])); + verbose(env, "%s\n", reg_type_str(env, compatible->types[j])); return -EACCES; found: - if (type == PTR_TO_BTF_ID) { + if (reg->type == PTR_TO_BTF_ID) { if (!arg_btf_id) { if (!compatible->btf_id) { verbose(env, "verifier internal error: missing arg compatible BTF ID\n"); @@ -5051,15 +5049,14 @@ return -EACCES; } - if (arg_type == ARG_PTR_TO_MAP_VALUE || - arg_type == ARG_PTR_TO_UNINIT_MAP_VALUE || - arg_type == ARG_PTR_TO_MAP_VALUE_OR_NULL) { + if (base_type(arg_type) == ARG_PTR_TO_MAP_VALUE || + base_type(arg_type) == ARG_PTR_TO_UNINIT_MAP_VALUE) { err = resolve_map_arg_type(env, meta, &arg_type); if (err) return err; } - if (register_is_null(reg) && arg_type_may_be_null(arg_type)) + if (register_is_null(reg) && type_may_be_null(arg_type)) /* A NULL register has a SCALAR_VALUE type, so skip * type checking. */ @@ -5136,10 +5133,11 @@ err = check_helper_mem_access(env, regno, meta->map_ptr->key_size, false, NULL); - } else if (arg_type == ARG_PTR_TO_MAP_VALUE || - (arg_type == ARG_PTR_TO_MAP_VALUE_OR_NULL && - !register_is_null(reg)) || - arg_type == ARG_PTR_TO_UNINIT_MAP_VALUE) { + } else if (base_type(arg_type) == ARG_PTR_TO_MAP_VALUE || + base_type(arg_type) == ARG_PTR_TO_UNINIT_MAP_VALUE) { + if (type_may_be_null(arg_type) && register_is_null(reg)) + return 0; + /* bpf_map_xxx(..., map_ptr, ..., value) call: * check [value, value + map->value_size) validity */ @@ -6214,6 +6212,8 @@ int *insn_idx_p) { const struct bpf_func_proto *fn = NULL; + enum bpf_return_type ret_type; + enum bpf_type_flag ret_flag; struct bpf_reg_state *regs; struct bpf_call_arg_meta meta; int insn_idx = *insn_idx_p; @@ -6347,13 +6347,14 @@ regs[BPF_REG_0].subreg_def = DEF_NOT_SUBREG; /* update return register (already marked as written above) */ - if (fn->ret_type == RET_INTEGER) { + ret_type = fn->ret_type; + ret_flag = type_flag(fn->ret_type); + if (ret_type == RET_INTEGER) { /* sets type to SCALAR_VALUE */ mark_reg_unknown(env, regs, BPF_REG_0); - } else if (fn->ret_type == RET_VOID) { + } else if (ret_type == RET_VOID) { regs[BPF_REG_0].type = NOT_INIT; - } else if (fn->ret_type == RET_PTR_TO_MAP_VALUE_OR_NULL || - fn->ret_type == RET_PTR_TO_MAP_VALUE) { + } else if (base_type(ret_type) == RET_PTR_TO_MAP_VALUE) { /* There is no offset yet applied, variable or fixed */ mark_reg_known_zero(env, regs, BPF_REG_0); /* remember map_ptr, so that check_map_access() @@ -6367,28 +6368,25 @@ } regs[BPF_REG_0].map_ptr = meta.map_ptr; regs[BPF_REG_0].map_uid = meta.map_uid; - if (fn->ret_type == RET_PTR_TO_MAP_VALUE) { - regs[BPF_REG_0].type = PTR_TO_MAP_VALUE; - if (map_value_has_spin_lock(meta.map_ptr)) - regs[BPF_REG_0].id = ++env->id_gen; - } else { - regs[BPF_REG_0].type = PTR_TO_MAP_VALUE_OR_NULL; + regs[BPF_REG_0].type = PTR_TO_MAP_VALUE | ret_flag; + if (!type_may_be_null(ret_type) && + map_value_has_spin_lock(meta.map_ptr)) { + regs[BPF_REG_0].id = ++env->id_gen; } - } else if (fn->ret_type == RET_PTR_TO_SOCKET_OR_NULL) { + } else if (base_type(ret_type) == RET_PTR_TO_SOCKET) { mark_reg_known_zero(env, regs, BPF_REG_0); - regs[BPF_REG_0].type = PTR_TO_SOCKET_OR_NULL; - } else if (fn->ret_type == RET_PTR_TO_SOCK_COMMON_OR_NULL) { + regs[BPF_REG_0].type = PTR_TO_SOCKET | ret_flag; + } else if (base_type(ret_type) == RET_PTR_TO_SOCK_COMMON) { mark_reg_known_zero(env, regs, BPF_REG_0); - regs[BPF_REG_0].type = PTR_TO_SOCK_COMMON_OR_NULL; - } else if (fn->ret_type == RET_PTR_TO_TCP_SOCK_OR_NULL) { + regs[BPF_REG_0].type = PTR_TO_SOCK_COMMON | ret_flag; + } else if (base_type(ret_type) == RET_PTR_TO_TCP_SOCK) { mark_reg_known_zero(env, regs, BPF_REG_0); - regs[BPF_REG_0].type = PTR_TO_TCP_SOCK_OR_NULL; - } else if (fn->ret_type == RET_PTR_TO_ALLOC_MEM_OR_NULL) { + regs[BPF_REG_0].type = PTR_TO_TCP_SOCK | ret_flag; + } else if (base_type(ret_type) == RET_PTR_TO_ALLOC_MEM) { mark_reg_known_zero(env, regs, BPF_REG_0); - regs[BPF_REG_0].type = PTR_TO_MEM_OR_NULL; + regs[BPF_REG_0].type = PTR_TO_MEM | ret_flag; regs[BPF_REG_0].mem_size = meta.mem_size; - } else if (fn->ret_type == RET_PTR_TO_MEM_OR_BTF_ID_OR_NULL || - fn->ret_type == RET_PTR_TO_MEM_OR_BTF_ID) { + } else if (base_type(ret_type) == RET_PTR_TO_MEM_OR_BTF_ID) { const struct btf_type *t; mark_reg_known_zero(env, regs, BPF_REG_0); @@ -6406,29 +6404,30 @@ tname, PTR_ERR(ret)); return -EINVAL; } - regs[BPF_REG_0].type = - fn->ret_type == RET_PTR_TO_MEM_OR_BTF_ID ? - PTR_TO_MEM : PTR_TO_MEM_OR_NULL; + regs[BPF_REG_0].type = PTR_TO_MEM | ret_flag; regs[BPF_REG_0].mem_size = tsize; } else { - regs[BPF_REG_0].type = - fn->ret_type == RET_PTR_TO_MEM_OR_BTF_ID ? - PTR_TO_BTF_ID : PTR_TO_BTF_ID_OR_NULL; + /* MEM_RDONLY may be carried from ret_flag, but it + * doesn't apply on PTR_TO_BTF_ID. Fold it, otherwise + * it will confuse the check of PTR_TO_BTF_ID in + * check_mem_access(). + */ + ret_flag &= ~MEM_RDONLY; + + regs[BPF_REG_0].type = PTR_TO_BTF_ID | ret_flag; regs[BPF_REG_0].btf = meta.ret_btf; regs[BPF_REG_0].btf_id = meta.ret_btf_id; } - } else if (fn->ret_type == RET_PTR_TO_BTF_ID_OR_NULL || - fn->ret_type == RET_PTR_TO_BTF_ID) { + } else if (base_type(ret_type) == RET_PTR_TO_BTF_ID) { int ret_btf_id; mark_reg_known_zero(env, regs, BPF_REG_0); - regs[BPF_REG_0].type = fn->ret_type == RET_PTR_TO_BTF_ID ? - PTR_TO_BTF_ID : - PTR_TO_BTF_ID_OR_NULL; + regs[BPF_REG_0].type = PTR_TO_BTF_ID | ret_flag; ret_btf_id = *fn->ret_btf_id; if (ret_btf_id == 0) { - verbose(env, "invalid return type %d of func %s#%d\n", - fn->ret_type, func_id_name(func_id), func_id); + verbose(env, "invalid return type %u of func %s#%d\n", + base_type(ret_type), func_id_name(func_id), + func_id); return -EINVAL; } /* current BPF helper definitions are only coming from @@ -6437,12 +6436,12 @@ regs[BPF_REG_0].btf = btf_vmlinux; regs[BPF_REG_0].btf_id = ret_btf_id; } else { - verbose(env, "unknown return type %d of func %s#%d\n", - fn->ret_type, func_id_name(func_id), func_id); + verbose(env, "unknown return type %u of func %s#%d\n", + base_type(ret_type), func_id_name(func_id), func_id); return -EINVAL; } - if (reg_type_may_be_null(regs[BPF_REG_0].type)) + if (type_may_be_null(regs[BPF_REG_0].type)) regs[BPF_REG_0].id = ++env->id_gen; if (is_ptr_cast_function(func_id)) { @@ -6641,25 +6640,25 @@ if (known && (val >= BPF_MAX_VAR_OFF || val <= -BPF_MAX_VAR_OFF)) { verbose(env, "math between %s pointer and %lld is not allowed\n", - reg_type_str[type], val); + reg_type_str(env, type), val); return false; } if (reg->off >= BPF_MAX_VAR_OFF || reg->off <= -BPF_MAX_VAR_OFF) { verbose(env, "%s pointer offset %d is not allowed\n", - reg_type_str[type], reg->off); + reg_type_str(env, type), reg->off); return false; } if (smin == S64_MIN) { verbose(env, "math between %s pointer and register with unbounded min value is not allowed\n", - reg_type_str[type]); + reg_type_str(env, type)); return false; } if (smin >= BPF_MAX_VAR_OFF || smin <= -BPF_MAX_VAR_OFF) { verbose(env, "value %lld makes %s pointer be out of bounds\n", - smin, reg_type_str[type]); + smin, reg_type_str(env, type)); return false; } @@ -7036,11 +7035,13 @@ return -EACCES; } - switch (ptr_reg->type) { - case PTR_TO_MAP_VALUE_OR_NULL: + if (ptr_reg->type & PTR_MAYBE_NULL) { verbose(env, "R%d pointer arithmetic on %s prohibited, null-check it first\n", - dst, reg_type_str[ptr_reg->type]); + dst, reg_type_str(env, ptr_reg->type)); return -EACCES; + } + + switch (base_type(ptr_reg->type)) { case CONST_PTR_TO_MAP: /* smin_val represents the known value */ if (known && smin_val == 0 && opcode == BPF_ADD) @@ -7053,10 +7054,10 @@ case PTR_TO_XDP_SOCK: reject: verbose(env, "R%d pointer arithmetic on %s prohibited\n", - dst, reg_type_str[ptr_reg->type]); + dst, reg_type_str(env, ptr_reg->type)); return -EACCES; default: - if (reg_type_may_be_null(ptr_reg->type)) + if (type_may_be_null(ptr_reg->type)) goto reject; break; } @@ -8778,7 +8779,7 @@ struct bpf_reg_state *reg, u32 id, bool is_null) { - if (reg_type_may_be_null(reg->type) && reg->id == id && + if (type_may_be_null(reg->type) && reg->id == id && !WARN_ON_ONCE(!reg->id)) { if (WARN_ON_ONCE(reg->smin_value || reg->smax_value || !tnum_equals_const(reg->var_off, 0) || @@ -9156,7 +9157,7 @@ */ if (!is_jmp32 && BPF_SRC(insn->code) == BPF_K && insn->imm == 0 && (opcode == BPF_JEQ || opcode == BPF_JNE) && - reg_type_may_be_null(dst_reg->type)) { + type_may_be_null(dst_reg->type)) { /* Mark all identical registers in each branch as either * safe or unknown depending R == 0 or R != 0 conditional. */ @@ -9215,7 +9216,7 @@ if (insn->src_reg == BPF_PSEUDO_BTF_ID) { dst_reg->type = aux->btf_var.reg_type; - switch (dst_reg->type) { + switch (base_type(dst_reg->type)) { case PTR_TO_MEM: dst_reg->mem_size = aux->btf_var.mem_size; break; @@ -9412,7 +9413,7 @@ /* enforce return zero from async callbacks like timer */ if (reg->type != SCALAR_VALUE) { verbose(env, "In async callback the register R0 is not a known value (%s)\n", - reg_type_str[reg->type]); + reg_type_str(env, reg->type)); return -EINVAL; } @@ -9426,7 +9427,7 @@ if (is_subprog) { if (reg->type != SCALAR_VALUE) { verbose(env, "At subprogram exit the register R0 is not a scalar value (%s)\n", - reg_type_str[reg->type]); + reg_type_str(env, reg->type)); return -EINVAL; } return 0; @@ -9490,7 +9491,7 @@ if (reg->type != SCALAR_VALUE) { verbose(env, "At program exit the register R0 is not a known value (%s)\n", - reg_type_str[reg->type]); + reg_type_str(env, reg->type)); return -EINVAL; } @@ -10271,7 +10272,7 @@ return true; if (rcur->type == NOT_INIT) return false; - switch (rold->type) { + switch (base_type(rold->type)) { case SCALAR_VALUE: if (env->explore_alu_limits) return false; @@ -10293,6 +10294,22 @@ } case PTR_TO_MAP_KEY: case PTR_TO_MAP_VALUE: + /* a PTR_TO_MAP_VALUE could be safe to use as a + * PTR_TO_MAP_VALUE_OR_NULL into the same map. + * However, if the old PTR_TO_MAP_VALUE_OR_NULL then got NULL- + * checked, doing so could have affected others with the same + * id, and we can't check for that because we lost the id when + * we converted to a PTR_TO_MAP_VALUE. + */ + if (type_may_be_null(rold->type)) { + if (!type_may_be_null(rcur->type)) + return false; + if (memcmp(rold, rcur, offsetof(struct bpf_reg_state, id))) + return false; + /* Check our ids match any regs they're supposed to */ + return check_ids(rold->id, rcur->id, idmap); + } + /* If the new min/max/var_off satisfy the old ones and * everything else matches, we are OK. * 'id' is not compared, since it's only used for maps with @@ -10304,20 +10321,6 @@ return memcmp(rold, rcur, offsetof(struct bpf_reg_state, id)) == 0 && range_within(rold, rcur) && tnum_in(rold->var_off, rcur->var_off); - case PTR_TO_MAP_VALUE_OR_NULL: - /* a PTR_TO_MAP_VALUE could be safe to use as a - * PTR_TO_MAP_VALUE_OR_NULL into the same map. - * However, if the old PTR_TO_MAP_VALUE_OR_NULL then got NULL- - * checked, doing so could have affected others with the same - * id, and we can't check for that because we lost the id when - * we converted to a PTR_TO_MAP_VALUE. - */ - if (rcur->type != PTR_TO_MAP_VALUE_OR_NULL) - return false; - if (memcmp(rold, rcur, offsetof(struct bpf_reg_state, id))) - return false; - /* Check our ids match any regs they're supposed to */ - return check_ids(rold->id, rcur->id, idmap); case PTR_TO_PACKET_META: case PTR_TO_PACKET: if (rcur->type != rold->type) @@ -10346,11 +10349,8 @@ case PTR_TO_PACKET_END: case PTR_TO_FLOW_KEYS: case PTR_TO_SOCKET: - case PTR_TO_SOCKET_OR_NULL: case PTR_TO_SOCK_COMMON: - case PTR_TO_SOCK_COMMON_OR_NULL: case PTR_TO_TCP_SOCK: - case PTR_TO_TCP_SOCK_OR_NULL: case PTR_TO_XDP_SOCK: /* Only valid matches are exact, which memcmp() above * would have accepted @@ -10876,17 +10876,13 @@ /* Return true if it's OK to have the same insn return a different type. */ static bool reg_type_mismatch_ok(enum bpf_reg_type type) { - switch (type) { + switch (base_type(type)) { case PTR_TO_CTX: case PTR_TO_SOCKET: - case PTR_TO_SOCKET_OR_NULL: case PTR_TO_SOCK_COMMON: - case PTR_TO_SOCK_COMMON_OR_NULL: case PTR_TO_TCP_SOCK: - case PTR_TO_TCP_SOCK_OR_NULL: case PTR_TO_XDP_SOCK: case PTR_TO_BTF_ID: - case PTR_TO_BTF_ID_OR_NULL: return false; default: return true; @@ -11110,7 +11106,7 @@ if (is_ctx_reg(env, insn->dst_reg)) { verbose(env, "BPF_ST stores into R%d %s is not allowed\n", insn->dst_reg, - reg_type_str[reg_state(env, insn->dst_reg)->type]); + reg_type_str(env, reg_state(env, insn->dst_reg)->type)); return -EACCES; } @@ -11361,7 +11357,7 @@ err = -EINVAL; goto err_put; } - aux->btf_var.reg_type = PTR_TO_MEM; + aux->btf_var.reg_type = PTR_TO_MEM | MEM_RDONLY; aux->btf_var.mem_size = tsize; } else { aux->btf_var.reg_type = PTR_TO_BTF_ID; @@ -13183,7 +13179,7 @@ mark_reg_known_zero(env, regs, i); else if (regs[i].type == SCALAR_VALUE) mark_reg_unknown(env, regs, i); - else if (regs[i].type == PTR_TO_MEM_OR_NULL) { + else if (base_type(regs[i].type) == PTR_TO_MEM) { const u32 mem_size = regs[i].mem_size; mark_reg_known_zero(env, regs, i); diff -u linux-5.15.0/kernel/events/core.c linux-5.15.0/kernel/events/core.c --- linux-5.15.0/kernel/events/core.c +++ linux-5.15.0/kernel/events/core.c @@ -6353,7 +6353,7 @@ again: mutex_lock(&event->mmap_mutex); if (event->rb) { - if (event->rb->nr_pages != nr_pages) { + if (data_page_nr(event->rb) != nr_pages) { ret = -EINVAL; goto unlock; } diff -u linux-5.15.0/kernel/rcu/tree.c linux-5.15.0/kernel/rcu/tree.c --- linux-5.15.0/kernel/rcu/tree.c +++ linux-5.15.0/kernel/rcu/tree.c @@ -2476,7 +2476,7 @@ div = READ_ONCE(rcu_divisor); div = div < 0 ? 7 : div > sizeof(long) * 8 - 2 ? sizeof(long) * 8 - 2 : div; bl = max(rdp->blimit, pending >> div); - if (unlikely(bl > 100)) { + if (in_serving_softirq() && unlikely(bl > 100)) { long rrn = READ_ONCE(rcu_resched_ns); rrn = rrn < NSEC_PER_MSEC ? NSEC_PER_MSEC : rrn > NSEC_PER_SEC ? NSEC_PER_SEC : rrn; @@ -2513,18 +2513,23 @@ /* * Stop only if limit reached and CPU has something to do. */ - if (count >= bl && !offloaded && - (need_resched() || - (!is_idle_task(current) && !rcu_is_callbacks_kthread()))) - break; - if (unlikely(tlimit)) { - /* only call local_clock() every 32 callbacks */ - if (likely((count & 31) || local_clock() < tlimit)) - continue; - /* Exceeded the time limit, so leave. */ - break; - } - if (!in_serving_softirq()) { + if (in_serving_softirq()) { + if (count >= bl && (need_resched() || + (!is_idle_task(current) && !rcu_is_callbacks_kthread()))) + break; + + /* + * Make sure we don't spend too much time here and deprive other + * softirq vectors of CPU cycles. + */ + if (unlikely(tlimit)) { + /* only call local_clock() every 32 callbacks */ + if (likely((count & 31) || local_clock() < tlimit)) + continue; + /* Exceeded the time limit, so leave. */ + break; + } + } else { local_bh_enable(); lockdep_assert_irqs_enabled(); cond_resched_tasks_rcu_qs(); diff -u linux-5.15.0/kernel/sched/fair.c linux-5.15.0/kernel/sched/fair.c --- linux-5.15.0/kernel/sched/fair.c +++ linux-5.15.0/kernel/sched/fair.c @@ -3794,11 +3794,11 @@ se->avg.runnable_sum = se->avg.runnable_avg * divider; - se->avg.load_sum = divider; - if (se_weight(se)) { - se->avg.load_sum = - div_u64(se->avg.load_avg * se->avg.load_sum, se_weight(se)); - } + se->avg.load_sum = se->avg.load_avg * divider; + if (se_weight(se) < se->avg.load_sum) + se->avg.load_sum = div_u64(se->avg.load_sum, se_weight(se)); + else + se->avg.load_sum = 1; enqueue_load_avg(cfs_rq, se); cfs_rq->avg.util_avg += se->avg.util_avg; diff -u linux-5.15.0/kernel/time/timekeeping.c linux-5.15.0/kernel/time/timekeeping.c --- linux-5.15.0/kernel/time/timekeeping.c +++ linux-5.15.0/kernel/time/timekeeping.c @@ -482,7 +482,7 @@ * of the following timestamps. Callers need to be aware of that and * deal with it. */ -u64 ktime_get_mono_fast_ns(void) +u64 notrace ktime_get_mono_fast_ns(void) { return __ktime_get_fast_ns(&tk_fast_mono); } @@ -494,7 +494,7 @@ * Contrary to ktime_get_mono_fast_ns() this is always correct because the * conversion factor is not affected by NTP/PTP correction. */ -u64 ktime_get_raw_fast_ns(void) +u64 notrace ktime_get_raw_fast_ns(void) { return __ktime_get_fast_ns(&tk_fast_raw); } diff -u linux-5.15.0/kernel/trace/bpf_trace.c linux-5.15.0/kernel/trace/bpf_trace.c --- linux-5.15.0/kernel/trace/bpf_trace.c +++ linux-5.15.0/kernel/trace/bpf_trace.c @@ -345,7 +345,7 @@ .gpl_only = true, .ret_type = RET_INTEGER, .arg1_type = ARG_ANYTHING, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE, }; @@ -394,7 +394,7 @@ .func = bpf_trace_printk, .gpl_only = true, .ret_type = RET_INTEGER, - .arg1_type = ARG_PTR_TO_MEM, + .arg1_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg2_type = ARG_CONST_SIZE, }; @@ -446,9 +446,9 @@ .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_BTF_ID, .arg1_btf_id = &btf_seq_file_ids[0], - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE, - .arg4_type = ARG_PTR_TO_MEM_OR_NULL, + .arg4_type = ARG_PTR_TO_MEM | PTR_MAYBE_NULL | MEM_RDONLY, .arg5_type = ARG_CONST_SIZE_OR_ZERO, }; @@ -463,7 +463,7 @@ .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_BTF_ID, .arg1_btf_id = &btf_seq_file_ids[0], - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE_OR_ZERO, }; @@ -487,7 +487,7 @@ .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_BTF_ID, .arg1_btf_id = &btf_seq_file_ids[0], - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE_OR_ZERO, .arg4_type = ARG_ANYTHING, }; @@ -648,7 +648,7 @@ .arg1_type = ARG_PTR_TO_CTX, .arg2_type = ARG_CONST_MAP_PTR, .arg3_type = ARG_ANYTHING, - .arg4_type = ARG_PTR_TO_MEM, + .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg5_type = ARG_CONST_SIZE_OR_ZERO, }; @@ -958,7 +958,7 @@ .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_MEM, .arg2_type = ARG_CONST_SIZE, - .arg3_type = ARG_PTR_TO_MEM, + .arg3_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg4_type = ARG_CONST_SIZE, .arg5_type = ARG_ANYTHING, }; @@ -1207,7 +1207,7 @@ .arg1_type = ARG_PTR_TO_CTX, .arg2_type = ARG_CONST_MAP_PTR, .arg3_type = ARG_ANYTHING, - .arg4_type = ARG_PTR_TO_MEM, + .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg5_type = ARG_CONST_SIZE_OR_ZERO, }; @@ -1429,7 +1429,7 @@ .arg1_type = ARG_PTR_TO_CTX, .arg2_type = ARG_CONST_MAP_PTR, .arg3_type = ARG_ANYTHING, - .arg4_type = ARG_PTR_TO_MEM, + .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg5_type = ARG_CONST_SIZE_OR_ZERO, }; @@ -1483,7 +1483,7 @@ .gpl_only = true, .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE_OR_ZERO, .arg4_type = ARG_ANYTHING, }; diff -u linux-5.15.0/lib/iov_iter.c linux-5.15.0/lib/iov_iter.c --- linux-5.15.0/lib/iov_iter.c +++ linux-5.15.0/lib/iov_iter.c @@ -191,7 +191,7 @@ buf = iov->iov_base + skip; copy = min(bytes, iov->iov_len - skip); - if (IS_ENABLED(CONFIG_HIGHMEM) && !fault_in_pages_writeable(buf, copy)) { + if (IS_ENABLED(CONFIG_HIGHMEM) && !fault_in_writeable(buf, copy)) { kaddr = kmap_atomic(page); from = kaddr + offset; @@ -275,7 +275,7 @@ buf = iov->iov_base + skip; copy = min(bytes, iov->iov_len - skip); - if (IS_ENABLED(CONFIG_HIGHMEM) && !fault_in_pages_readable(buf, copy)) { + if (IS_ENABLED(CONFIG_HIGHMEM) && !fault_in_readable(buf, copy)) { kaddr = kmap_atomic(page); to = kaddr + offset; @@ -431,35 +431,81 @@ } /* + * fault_in_iov_iter_readable - fault in iov iterator for reading + * @i: iterator + * @size: maximum length + * * Fault in one or more iovecs of the given iov_iter, to a maximum length of - * bytes. For each iovec, fault in each page that constitutes the iovec. + * @size. For each iovec, fault in each page that constitutes the iovec. + * + * Returns the number of bytes not faulted in (like copy_to_user() and + * copy_from_user()). + * + * Always returns 0 for non-userspace iterators. + */ +size_t fault_in_iov_iter_readable(const struct iov_iter *i, size_t size) +{ + if (iter_is_iovec(i)) { + size_t count = min(size, iov_iter_count(i)); + const struct iovec *p; + size_t skip; + + size -= count; + for (p = i->iov, skip = i->iov_offset; count; p++, skip = 0) { + size_t len = min(count, p->iov_len - skip); + size_t ret; + + if (unlikely(!len)) + continue; + ret = fault_in_readable(p->iov_base + skip, len); + count -= len - ret; + if (ret) + break; + } + return count + size; + } + return 0; +} +EXPORT_SYMBOL(fault_in_iov_iter_readable); + +/* + * fault_in_iov_iter_writeable - fault in iov iterator for writing + * @i: iterator + * @size: maximum length + * + * Faults in the iterator using get_user_pages(), i.e., without triggering + * hardware page faults. This is primarily useful when we already know that + * some or all of the pages in @i aren't in memory. + * + * Returns the number of bytes not faulted in, like copy_to_user() and + * copy_from_user(). * - * Return 0 on success, or non-zero if the memory could not be accessed (i.e. - * because it is an invalid address). + * Always returns 0 for non-user-space iterators. */ -int iov_iter_fault_in_readable(const struct iov_iter *i, size_t bytes) +size_t fault_in_iov_iter_writeable(const struct iov_iter *i, size_t size) { if (iter_is_iovec(i)) { + size_t count = min(size, iov_iter_count(i)); const struct iovec *p; size_t skip; - if (bytes > i->count) - bytes = i->count; - for (p = i->iov, skip = i->iov_offset; bytes; p++, skip = 0) { - size_t len = min(bytes, p->iov_len - skip); - int err; + size -= count; + for (p = i->iov, skip = i->iov_offset; count; p++, skip = 0) { + size_t len = min(count, p->iov_len - skip); + size_t ret; if (unlikely(!len)) continue; - err = fault_in_pages_readable(p->iov_base + skip, len); - if (unlikely(err)) - return err; - bytes -= len; + ret = fault_in_safe_writeable(p->iov_base + skip, len); + count -= len - ret; + if (ret) + break; } + return count + size; } return 0; } -EXPORT_SYMBOL(iov_iter_fault_in_readable); +EXPORT_SYMBOL(fault_in_iov_iter_writeable); void iov_iter_init(struct iov_iter *i, unsigned int direction, const struct iovec *iov, unsigned long nr_segs, @@ -468,6 +514,7 @@ WARN_ON(direction & ~(READ | WRITE)); *i = (struct iov_iter) { .iter_type = ITER_IOVEC, + .nofault = false, .data_source = direction, .iov = iov, .nr_segs = nr_segs, @@ -1483,13 +1530,17 @@ return 0; if (likely(iter_is_iovec(i))) { + unsigned int gup_flags = 0; unsigned long addr; + if (iov_iter_rw(i) != WRITE) + gup_flags |= FOLL_WRITE; + if (i->nofault) + gup_flags |= FOLL_NOFAULT; + addr = first_iovec_segment(i, &len, start, maxsize, maxpages); n = DIV_ROUND_UP(len, PAGE_SIZE); - res = get_user_pages_fast(addr, n, - iov_iter_rw(i) != WRITE ? FOLL_WRITE : 0, - pages); + res = get_user_pages_fast(addr, n, gup_flags, pages); if (unlikely(res <= 0)) return res; return (res == n ? len : res * PAGE_SIZE) - *start; @@ -1605,15 +1656,20 @@ return 0; if (likely(iter_is_iovec(i))) { + unsigned int gup_flags = 0; unsigned long addr; + if (iov_iter_rw(i) != WRITE) + gup_flags |= FOLL_WRITE; + if (i->nofault) + gup_flags |= FOLL_NOFAULT; + addr = first_iovec_segment(i, &len, start, maxsize, ~0U); n = DIV_ROUND_UP(len, PAGE_SIZE); p = get_pages_array(n); if (!p) return -ENOMEM; - res = get_user_pages_fast(addr, n, - iov_iter_rw(i) != WRITE ? FOLL_WRITE : 0, p); + res = get_user_pages_fast(addr, n, gup_flags, p); if (unlikely(res <= 0)) { kvfree(p); *pages = NULL; diff -u linux-5.15.0/mm/filemap.c linux-5.15.0/mm/filemap.c --- linux-5.15.0/mm/filemap.c +++ linux-5.15.0/mm/filemap.c @@ -90,7 +90,7 @@ * ->lock_page (filemap_fault, access_process_vm) * * ->i_rwsem (generic_perform_write) - * ->mmap_lock (fault_in_pages_readable->do_page_fault) + * ->mmap_lock (fault_in_readable->do_page_fault) * * bdi->wb.list_lock * sb_lock (fs/fs-writeback.c) @@ -3760,7 +3760,7 @@ * same page as we're writing to, without it being marked * up-to-date. */ - if (unlikely(iov_iter_fault_in_readable(i, bytes))) { + if (unlikely(fault_in_iov_iter_readable(i, bytes))) { status = -EFAULT; break; } diff -u linux-5.15.0/mm/gup.c linux-5.15.0/mm/gup.c --- linux-5.15.0/mm/gup.c +++ linux-5.15.0/mm/gup.c @@ -943,6 +943,8 @@ /* mlock all present pages, but do not fault in new pages */ if ((*flags & (FOLL_POPULATE | FOLL_MLOCK)) == FOLL_MLOCK) return -ENOENT; + if (*flags & FOLL_NOFAULT) + return -EFAULT; if (*flags & FOLL_WRITE) fault_flags |= FAULT_FLAG_WRITE; if (*flags & FOLL_REMOTE) @@ -1682,6 +1684,122 @@ #endif /* !CONFIG_MMU */ /** + * fault_in_writeable - fault in userspace address range for writing + * @uaddr: start of address range + * @size: size of address range + * + * Returns the number of bytes not faulted in (like copy_to_user() and + * copy_from_user()). + */ +size_t fault_in_writeable(char __user *uaddr, size_t size) +{ + char __user *start = uaddr, *end; + + if (unlikely(size == 0)) + return 0; + if (!PAGE_ALIGNED(uaddr)) { + if (unlikely(__put_user(0, uaddr) != 0)) + return size; + uaddr = (char __user *)PAGE_ALIGN((unsigned long)uaddr); + } + end = (char __user *)PAGE_ALIGN((unsigned long)start + size); + if (unlikely(end < start)) + end = NULL; + while (uaddr != end) { + if (unlikely(__put_user(0, uaddr) != 0)) + goto out; + uaddr += PAGE_SIZE; + } + +out: + if (size > uaddr - start) + return size - (uaddr - start); + return 0; +} +EXPORT_SYMBOL(fault_in_writeable); + +/* + * fault_in_safe_writeable - fault in an address range for writing + * @uaddr: start of address range + * @size: length of address range + * + * Faults in an address range for writing. This is primarily useful when we + * already know that some or all of the pages in the address range aren't in + * memory. + * + * Unlike fault_in_writeable(), this function is non-destructive. + * + * Note that we don't pin or otherwise hold the pages referenced that we fault + * in. There's no guarantee that they'll stay in memory for any duration of + * time. + * + * Returns the number of bytes not faulted in, like copy_to_user() and + * copy_from_user(). + */ +size_t fault_in_safe_writeable(const char __user *uaddr, size_t size) +{ + unsigned long start = (unsigned long)uaddr, end; + struct mm_struct *mm = current->mm; + bool unlocked = false; + + if (unlikely(size == 0)) + return 0; + end = PAGE_ALIGN(start + size); + if (end < start) + end = 0; + + mmap_read_lock(mm); + do { + if (fixup_user_fault(mm, start, FAULT_FLAG_WRITE, &unlocked)) + break; + start = (start + PAGE_SIZE) & PAGE_MASK; + } while (start != end); + mmap_read_unlock(mm); + + if (size > (unsigned long)uaddr - start) + return size - ((unsigned long)uaddr - start); + return 0; +} +EXPORT_SYMBOL(fault_in_safe_writeable); + +/** + * fault_in_readable - fault in userspace address range for reading + * @uaddr: start of user address range + * @size: size of user address range + * + * Returns the number of bytes not faulted in (like copy_to_user() and + * copy_from_user()). + */ +size_t fault_in_readable(const char __user *uaddr, size_t size) +{ + const char __user *start = uaddr, *end; + volatile char c; + + if (unlikely(size == 0)) + return 0; + if (!PAGE_ALIGNED(uaddr)) { + if (unlikely(__get_user(c, uaddr) != 0)) + return size; + uaddr = (const char __user *)PAGE_ALIGN((unsigned long)uaddr); + } + end = (const char __user *)PAGE_ALIGN((unsigned long)start + size); + if (unlikely(end < start)) + end = NULL; + while (uaddr != end) { + if (unlikely(__get_user(c, uaddr) != 0)) + goto out; + uaddr += PAGE_SIZE; + } + +out: + (void)c; + if (size > uaddr - start) + return size - (uaddr - start); + return 0; +} +EXPORT_SYMBOL(fault_in_readable); + +/** * get_dump_page() - pin user page in memory while writing it to core dump * @addr: user address * @@ -2733,7 +2851,7 @@ if (WARN_ON_ONCE(gup_flags & ~(FOLL_WRITE | FOLL_LONGTERM | FOLL_FORCE | FOLL_PIN | FOLL_GET | - FOLL_FAST_ONLY))) + FOLL_FAST_ONLY | FOLL_NOFAULT))) return -EINVAL; if (gup_flags & FOLL_PIN) diff -u linux-5.15.0/mm/kasan/quarantine.c linux-5.15.0/mm/kasan/quarantine.c --- linux-5.15.0/mm/kasan/quarantine.c +++ linux-5.15.0/mm/kasan/quarantine.c @@ -315,6 +315,13 @@ struct qlist_head *q; q = this_cpu_ptr(&cpu_quarantine); + /* + * Ensure the ordering between the writing to q->offline and + * per_cpu_remove_cache. Prevent cpu_quarantine from being corrupted + * by interrupt. + */ + if (READ_ONCE(q->offline)) + return; qlist_move_cache(q, &to_free, cache); qlist_free_all(&to_free, cache); } diff -u linux-5.15.0/mm/kfence/core.c linux-5.15.0/mm/kfence/core.c --- linux-5.15.0/mm/kfence/core.c +++ linux-5.15.0/mm/kfence/core.c @@ -223,23 +223,2 @@ -static inline struct kfence_metadata *addr_to_metadata(unsigned long addr) -{ - long index; - - /* The checks do not affect performance; only called from slow-paths. */ - - if (!is_kfence_address((void *)addr)) - return NULL; - - /* - * May be an invalid index if called with an address at the edge of - * __kfence_pool, in which case we would report an "invalid access" - * error. - */ - index = (addr - (unsigned long)__kfence_pool) / (PAGE_SIZE * 2) - 1; - if (index < 0 || index >= CONFIG_KFENCE_NUM_OBJECTS) - return NULL; - - return &kfence_metadata[index]; -} - static inline unsigned long metadata_to_pageaddr(const struct kfence_metadata *meta) @@ -549,6 +528,8 @@ * enters __slab_free() slow-path. */ for (i = 0; i < KFENCE_POOL_SIZE / PAGE_SIZE; i++) { + struct page *page = &pages[i]; + if (!i || (i % 2)) continue; @@ -556,7 +537,11 @@ if (WARN_ON(compound_head(&pages[i]) != &pages[i])) goto err; - __SetPageSlab(&pages[i]); + __SetPageSlab(page); +#ifdef CONFIG_MEMCG + page->memcg_data = (unsigned long)&kfence_metadata[i / 2 - 1].objcg | + MEMCG_DATA_OBJCGS; +#endif } /* @@ -932,6 +917,9 @@ { struct kfence_metadata *meta = addr_to_metadata((unsigned long)addr); +#ifdef CONFIG_MEMCG + KFENCE_WARN_ON(meta->objcg); +#endif /* * If the objects of the cache are SLAB_TYPESAFE_BY_RCU, defer freeing * the object, as the object page may be recycled for other-typed diff -u linux-5.15.0/mm/kfence/kfence.h linux-5.15.0/mm/kfence/kfence.h --- linux-5.15.0/mm/kfence/kfence.h +++ linux-5.15.0/mm/kfence/kfence.h @@ -89,10 +89,34 @@ struct kfence_track free_track; /* For updating alloc_covered on frees. */ u32 alloc_stack_hash; +#ifdef CONFIG_MEMCG + struct obj_cgroup *objcg; +#endif }; extern struct kfence_metadata kfence_metadata[CONFIG_KFENCE_NUM_OBJECTS]; +static inline struct kfence_metadata *addr_to_metadata(unsigned long addr) +{ + long index; + + /* The checks do not affect performance; only called from slow-paths. */ + + if (!is_kfence_address((void *)addr)) + return NULL; + + /* + * May be an invalid index if called with an address at the edge of + * __kfence_pool, in which case we would report an "invalid access" + * error. + */ + index = (addr - (unsigned long)__kfence_pool) / (PAGE_SIZE * 2) - 1; + if (index < 0 || index >= CONFIG_KFENCE_NUM_OBJECTS) + return NULL; + + return &kfence_metadata[index]; +} + /* KFENCE error types for report generation. */ enum kfence_error_type { KFENCE_ERROR_OOB, /* Detected a out-of-bounds access. */ diff -u linux-5.15.0/mm/memcontrol.c linux-5.15.0/mm/memcontrol.c --- linux-5.15.0/mm/memcontrol.c +++ linux-5.15.0/mm/memcontrol.c @@ -650,6 +650,9 @@ static DEFINE_SPINLOCK(stats_flush_lock); static DEFINE_PER_CPU(unsigned int, stats_updates); static atomic_t stats_flush_threshold = ATOMIC_INIT(0); +static u64 flush_next_time; + +#define FLUSH_TIME (2UL*HZ) static inline void memcg_rstat_updated(struct mem_cgroup *memcg, int val) { @@ -671,6 +674,7 @@ if (!spin_trylock_irqsave(&stats_flush_lock, flag)) return; + flush_next_time = jiffies_64 + 2*FLUSH_TIME; cgroup_rstat_flush_irqsafe(root_mem_cgroup->css.cgroup); atomic_set(&stats_flush_threshold, 0); spin_unlock_irqrestore(&stats_flush_lock, flag); @@ -682,10 +686,16 @@ __mem_cgroup_flush_stats(); } +void mem_cgroup_flush_stats_delayed(void) +{ + if (time_after64(jiffies_64, flush_next_time)) + mem_cgroup_flush_stats(); +} + static void flush_memcg_stats_dwork(struct work_struct *w) { __mem_cgroup_flush_stats(); - queue_delayed_work(system_unbound_wq, &stats_flush_dwork, 2UL*HZ); + queue_delayed_work(system_unbound_wq, &stats_flush_dwork, FLUSH_TIME); } /** diff -u linux-5.15.0/mm/memory-failure.c linux-5.15.0/mm/memory-failure.c --- linux-5.15.0/mm/memory-failure.c +++ linux-5.15.0/mm/memory-failure.c @@ -1690,6 +1690,19 @@ if (PageTransHuge(hpage)) { /* + * Bail out before SetPageHasHWPoisoned() if hpage is + * huge_zero_page, although PG_has_hwpoisoned is not + * checked in set_huge_zero_page(). + * + * TODO: Handle memory failure of huge_zero_page thoroughly. + */ + if (is_huge_zero_page(hpage)) { + action_result(pfn, MF_MSG_UNSPLIT_THP, MF_IGNORED); + res = -EBUSY; + goto unlock_mutex; + } + + /* * The flag must be set after the refcount is bumped * otherwise it may race with THP split. * And the flag can't be set in get_hwpoison_page() since diff -u linux-5.15.0/mm/mmap.c linux-5.15.0/mm/mmap.c --- linux-5.15.0/mm/mmap.c +++ linux-5.15.0/mm/mmap.c @@ -2113,14 +2113,6 @@ return addr; } -#ifndef arch_get_mmap_end -#define arch_get_mmap_end(addr) (TASK_SIZE) -#endif - -#ifndef arch_get_mmap_base -#define arch_get_mmap_base(addr, base) (base) -#endif - /* Get an address range which is currently unmapped. * For shmat() with addr=0. * diff -u linux-5.15.0/mm/oom_kill.c linux-5.15.0/mm/oom_kill.c --- linux-5.15.0/mm/oom_kill.c +++ linux-5.15.0/mm/oom_kill.c @@ -635,7 +635,7 @@ */ set_bit(MMF_OOM_SKIP, &mm->flags); - /* Drop a reference taken by wake_oom_reaper */ + /* Drop a reference taken by queue_oom_reaper */ put_task_struct(tsk); } @@ -645,12 +645,12 @@ struct task_struct *tsk = NULL; wait_event_freezable(oom_reaper_wait, oom_reaper_list != NULL); - spin_lock(&oom_reaper_lock); + spin_lock_irq(&oom_reaper_lock); if (oom_reaper_list != NULL) { tsk = oom_reaper_list; oom_reaper_list = tsk->oom_reaper_list; } - spin_unlock(&oom_reaper_lock); + spin_unlock_irq(&oom_reaper_lock); if (tsk) oom_reap_task(tsk); @@ -659,22 +659,48 @@ return 0; } -static void wake_oom_reaper(struct task_struct *tsk) +static void wake_oom_reaper(struct timer_list *timer) { - /* mm is already queued? */ - if (test_and_set_bit(MMF_OOM_REAP_QUEUED, &tsk->signal->oom_mm->flags)) + struct task_struct *tsk = container_of(timer, struct task_struct, + oom_reaper_timer); + struct mm_struct *mm = tsk->signal->oom_mm; + unsigned long flags; + + /* The victim managed to terminate on its own - see exit_mmap */ + if (test_bit(MMF_OOM_SKIP, &mm->flags)) { + put_task_struct(tsk); return; + } - get_task_struct(tsk); - - spin_lock(&oom_reaper_lock); + spin_lock_irqsave(&oom_reaper_lock, flags); tsk->oom_reaper_list = oom_reaper_list; oom_reaper_list = tsk; - spin_unlock(&oom_reaper_lock); + spin_unlock_irqrestore(&oom_reaper_lock, flags); trace_wake_reaper(tsk->pid); wake_up(&oom_reaper_wait); } +/* + * Give the OOM victim time to exit naturally before invoking the oom_reaping. + * The timers timeout is arbitrary... the longer it is, the longer the worst + * case scenario for the OOM can take. If it is too small, the oom_reaper can + * get in the way and release resources needed by the process exit path. + * e.g. The futex robust list can sit in Anon|Private memory that gets reaped + * before the exit path is able to wake the futex waiters. + */ +#define OOM_REAPER_DELAY (2*HZ) +static void queue_oom_reaper(struct task_struct *tsk) +{ + /* mm is already queued? */ + if (test_and_set_bit(MMF_OOM_REAP_QUEUED, &tsk->signal->oom_mm->flags)) + return; + + get_task_struct(tsk); + timer_setup(&tsk->oom_reaper_timer, wake_oom_reaper, 0); + tsk->oom_reaper_timer.expires = jiffies + OOM_REAPER_DELAY; + add_timer(&tsk->oom_reaper_timer); +} + static int __init oom_init(void) { oom_reaper_th = kthread_run(oom_reaper, NULL, "oom_reaper"); @@ -682,7 +708,7 @@ } subsys_initcall(oom_init) #else -static inline void wake_oom_reaper(struct task_struct *tsk) +static inline void queue_oom_reaper(struct task_struct *tsk) { } #endif /* CONFIG_MMU */ @@ -933,7 +959,7 @@ rcu_read_unlock(); if (can_oom_reap) - wake_oom_reaper(victim); + queue_oom_reaper(victim); mmdrop(mm); put_task_struct(victim); @@ -969,7 +995,7 @@ task_lock(victim); if (task_will_free_mem(victim)) { mark_oom_victim(victim); - wake_oom_reaper(victim); + queue_oom_reaper(victim); task_unlock(victim); put_task_struct(victim); return; @@ -1067,7 +1093,7 @@ */ if (task_will_free_mem(current)) { mark_oom_victim(current); - wake_oom_reaper(current); + queue_oom_reaper(current); return true; } diff -u linux-5.15.0/mm/page_alloc.c linux-5.15.0/mm/page_alloc.c --- linux-5.15.0/mm/page_alloc.c +++ linux-5.15.0/mm/page_alloc.c @@ -8169,7 +8169,7 @@ */ #define adj_init_size(start, end, size, pos, adj) \ do { \ - if (start <= pos && pos < end && size > adj) \ + if (&start[0] <= &pos[0] && &pos[0] < &end[0] && size > adj) \ size -= adj; \ } while (0) diff -u linux-5.15.0/mm/slab.c linux-5.15.0/mm/slab.c --- linux-5.15.0/mm/slab.c +++ linux-5.15.0/mm/slab.c @@ -3658,7 +3658,7 @@ #endif /* CONFIG_NUMA */ #ifdef CONFIG_PRINTK -void kmem_obj_info(struct kmem_obj_info *kpp, void *object, struct page *page) +void __kmem_obj_info(struct kmem_obj_info *kpp, void *object, struct page *page) { struct kmem_cache *cachep; unsigned int objnr; diff -u linux-5.15.0/mm/slab.h linux-5.15.0/mm/slab.h --- linux-5.15.0/mm/slab.h +++ linux-5.15.0/mm/slab.h @@ -643,7 +643,7 @@ void *kp_stack[KS_ADDRS_COUNT]; void *kp_free_stack[KS_ADDRS_COUNT]; }; -void kmem_obj_info(struct kmem_obj_info *kpp, void *object, struct page *page); +void __kmem_obj_info(struct kmem_obj_info *kpp, void *object, struct page *page); #endif #endif /* MM_SLAB_H */ diff -u linux-5.15.0/mm/slub.c linux-5.15.0/mm/slub.c --- linux-5.15.0/mm/slub.c +++ linux-5.15.0/mm/slub.c @@ -4299,7 +4299,7 @@ } #ifdef CONFIG_PRINTK -void kmem_obj_info(struct kmem_obj_info *kpp, void *object, struct page *page) +void __kmem_obj_info(struct kmem_obj_info *kpp, void *object, struct page *page) { void *base; int __maybe_unused i; diff -u linux-5.15.0/net/can/isotp.c linux-5.15.0/net/can/isotp.c --- linux-5.15.0/net/can/isotp.c +++ linux-5.15.0/net/can/isotp.c @@ -866,6 +866,7 @@ struct canfd_frame *cf; int ae = (so->opt.flags & CAN_ISOTP_EXTEND_ADDR) ? 1 : 0; int wait_tx_done = (so->opt.flags & CAN_ISOTP_WAIT_TX_DONE) ? 1 : 0; + s64 hrtimer_sec = 0; int off; int err; @@ -964,7 +965,9 @@ isotp_create_fframe(cf, so, ae); /* start timeout for FC */ - hrtimer_start(&so->txtimer, ktime_set(1, 0), HRTIMER_MODE_REL_SOFT); + hrtimer_sec = 1; + hrtimer_start(&so->txtimer, ktime_set(hrtimer_sec, 0), + HRTIMER_MODE_REL_SOFT); } /* send the first or only CAN frame */ @@ -977,6 +980,11 @@ if (err) { pr_notice_once("can-isotp: %s: can_send_ret %pe\n", __func__, ERR_PTR(err)); + + /* no transmission -> no timeout monitoring */ + if (hrtimer_sec) + hrtimer_cancel(&so->txtimer); + goto err_out_drop; } @@ -1138,6 +1146,11 @@ lock_sock(sk); + if (so->bound) { + err = -EINVAL; + goto out; + } + /* do not register frame reception for functional addressing */ if (so->opt.flags & CAN_ISOTP_SF_BROADCAST) do_rx_reg = 0; @@ -1149,8 +1162,4 @@ } - if (so->bound && addr->can_ifindex == so->ifindex && - rx_id == so->rxid && tx_id == so->txid) - goto out; - dev = dev_get_by_index(net, addr->can_ifindex); if (!dev) { @@ -1178,19 +1187,6 @@ dev_put(dev); - if (so->bound && do_rx_reg) { - /* unregister old filter */ - if (so->ifindex) { - dev = dev_get_by_index(net, so->ifindex); - if (dev) { - can_rx_unregister(net, dev, so->rxid, - SINGLE_MASK(so->rxid), - isotp_rcv, sk); - dev_put(dev); - } - } - } - /* switch to new settings */ so->ifindex = ifindex; so->rxid = rx_id; diff -u linux-5.15.0/net/core/filter.c linux-5.15.0/net/core/filter.c --- linux-5.15.0/net/core/filter.c +++ linux-5.15.0/net/core/filter.c @@ -1713,7 +1713,7 @@ .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_CTX, .arg2_type = ARG_ANYTHING, - .arg3_type = ARG_PTR_TO_MEM, + .arg3_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg4_type = ARG_CONST_SIZE, .arg5_type = ARG_ANYTHING, }; @@ -2018,9 +2018,9 @@ .gpl_only = false, .pkt_access = true, .ret_type = RET_INTEGER, - .arg1_type = ARG_PTR_TO_MEM_OR_NULL, + .arg1_type = ARG_PTR_TO_MEM | PTR_MAYBE_NULL | MEM_RDONLY, .arg2_type = ARG_CONST_SIZE_OR_ZERO, - .arg3_type = ARG_PTR_TO_MEM_OR_NULL, + .arg3_type = ARG_PTR_TO_MEM | PTR_MAYBE_NULL | MEM_RDONLY, .arg4_type = ARG_CONST_SIZE_OR_ZERO, .arg5_type = ARG_ANYTHING, }; @@ -2541,7 +2541,7 @@ .gpl_only = false, .ret_type = RET_INTEGER, .arg1_type = ARG_ANYTHING, - .arg2_type = ARG_PTR_TO_MEM_OR_NULL, + .arg2_type = ARG_PTR_TO_MEM | PTR_MAYBE_NULL | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE_OR_ZERO, .arg4_type = ARG_ANYTHING, }; @@ -4177,7 +4177,7 @@ .arg1_type = ARG_PTR_TO_CTX, .arg2_type = ARG_CONST_MAP_PTR, .arg3_type = ARG_ANYTHING, - .arg4_type = ARG_PTR_TO_MEM, + .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg5_type = ARG_CONST_SIZE_OR_ZERO, }; @@ -4191,7 +4191,7 @@ .arg1_btf_id = &bpf_skb_output_btf_ids[0], .arg2_type = ARG_CONST_MAP_PTR, .arg3_type = ARG_ANYTHING, - .arg4_type = ARG_PTR_TO_MEM, + .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg5_type = ARG_CONST_SIZE_OR_ZERO, }; @@ -4374,7 +4374,7 @@ .gpl_only = false, .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE, .arg4_type = ARG_ANYTHING, }; @@ -4400,7 +4400,7 @@ .gpl_only = false, .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE, }; @@ -4570,7 +4570,7 @@ .arg1_type = ARG_PTR_TO_CTX, .arg2_type = ARG_CONST_MAP_PTR, .arg3_type = ARG_ANYTHING, - .arg4_type = ARG_PTR_TO_MEM, + .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg5_type = ARG_CONST_SIZE_OR_ZERO, }; @@ -4584,7 +4584,7 @@ .arg1_btf_id = &bpf_xdp_output_btf_ids[0], .arg2_type = ARG_CONST_MAP_PTR, .arg3_type = ARG_ANYTHING, - .arg4_type = ARG_PTR_TO_MEM, + .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg5_type = ARG_CONST_SIZE_OR_ZERO, }; @@ -5072,7 +5072,7 @@ .arg1_type = ARG_PTR_TO_BTF_ID_SOCK_COMMON, .arg2_type = ARG_ANYTHING, .arg3_type = ARG_ANYTHING, - .arg4_type = ARG_PTR_TO_MEM, + .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg5_type = ARG_CONST_SIZE, }; @@ -5106,7 +5106,7 @@ .arg1_type = ARG_PTR_TO_CTX, .arg2_type = ARG_ANYTHING, .arg3_type = ARG_ANYTHING, - .arg4_type = ARG_PTR_TO_MEM, + .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg5_type = ARG_CONST_SIZE, }; @@ -5140,7 +5140,7 @@ .arg1_type = ARG_PTR_TO_CTX, .arg2_type = ARG_ANYTHING, .arg3_type = ARG_ANYTHING, - .arg4_type = ARG_PTR_TO_MEM, + .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg5_type = ARG_CONST_SIZE, }; @@ -5315,7 +5315,7 @@ .gpl_only = false, .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE, }; @@ -5903,7 +5903,7 @@ .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_CTX, .arg2_type = ARG_ANYTHING, - .arg3_type = ARG_PTR_TO_MEM, + .arg3_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg4_type = ARG_CONST_SIZE }; @@ -5913,7 +5913,7 @@ .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_CTX, .arg2_type = ARG_ANYTHING, - .arg3_type = ARG_PTR_TO_MEM, + .arg3_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg4_type = ARG_CONST_SIZE }; @@ -5956,7 +5956,7 @@ .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_CTX, .arg2_type = ARG_ANYTHING, - .arg3_type = ARG_PTR_TO_MEM, + .arg3_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg4_type = ARG_CONST_SIZE }; @@ -6044,7 +6044,7 @@ .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_CTX, .arg2_type = ARG_ANYTHING, - .arg3_type = ARG_PTR_TO_MEM, + .arg3_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg4_type = ARG_CONST_SIZE }; @@ -6269,7 +6269,7 @@ .pkt_access = true, .ret_type = RET_PTR_TO_SOCK_COMMON_OR_NULL, .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE, .arg4_type = ARG_ANYTHING, .arg5_type = ARG_ANYTHING, @@ -6288,7 +6288,7 @@ .pkt_access = true, .ret_type = RET_PTR_TO_SOCKET_OR_NULL, .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE, .arg4_type = ARG_ANYTHING, .arg5_type = ARG_ANYTHING, @@ -6307,7 +6307,7 @@ .pkt_access = true, .ret_type = RET_PTR_TO_SOCKET_OR_NULL, .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE, .arg4_type = ARG_ANYTHING, .arg5_type = ARG_ANYTHING, @@ -6344,7 +6344,7 @@ .pkt_access = true, .ret_type = RET_PTR_TO_SOCKET_OR_NULL, .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE, .arg4_type = ARG_ANYTHING, .arg5_type = ARG_ANYTHING, @@ -6367,7 +6367,7 @@ .pkt_access = true, .ret_type = RET_PTR_TO_SOCK_COMMON_OR_NULL, .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE, .arg4_type = ARG_ANYTHING, .arg5_type = ARG_ANYTHING, @@ -6390,7 +6390,7 @@ .pkt_access = true, .ret_type = RET_PTR_TO_SOCKET_OR_NULL, .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE, .arg4_type = ARG_ANYTHING, .arg5_type = ARG_ANYTHING, @@ -6409,7 +6409,7 @@ .gpl_only = false, .ret_type = RET_PTR_TO_SOCK_COMMON_OR_NULL, .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE, .arg4_type = ARG_ANYTHING, .arg5_type = ARG_ANYTHING, @@ -6428,7 +6428,7 @@ .gpl_only = false, .ret_type = RET_PTR_TO_SOCKET_OR_NULL, .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE, .arg4_type = ARG_ANYTHING, .arg5_type = ARG_ANYTHING, @@ -6447,7 +6447,7 @@ .gpl_only = false, .ret_type = RET_PTR_TO_SOCKET_OR_NULL, .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE, .arg4_type = ARG_ANYTHING, .arg5_type = ARG_ANYTHING, @@ -6769,9 +6769,9 @@ .pkt_access = true, .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_BTF_ID_SOCK_COMMON, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE, - .arg4_type = ARG_PTR_TO_MEM, + .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg5_type = ARG_CONST_SIZE, }; @@ -6838,9 +6838,9 @@ .pkt_access = true, .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_BTF_ID_SOCK_COMMON, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE, - .arg4_type = ARG_PTR_TO_MEM, + .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg5_type = ARG_CONST_SIZE, }; @@ -7069,7 +7069,7 @@ .gpl_only = false, .ret_type = RET_INTEGER, .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, .arg3_type = ARG_CONST_SIZE, .arg4_type = ARG_ANYTHING, }; diff -u linux-5.15.0/net/core/sock_map.c linux-5.15.0/net/core/sock_map.c --- linux-5.15.0/net/core/sock_map.c +++ linux-5.15.0/net/core/sock_map.c @@ -1575,7 +1575,7 @@ .ctx_arg_info_size = 2, .ctx_arg_info = { { offsetof(struct bpf_iter__sockmap, key), - PTR_TO_RDONLY_BUF_OR_NULL }, + PTR_TO_BUF | PTR_MAYBE_NULL | MEM_RDONLY }, { offsetof(struct bpf_iter__sockmap, sk), PTR_TO_BTF_ID_OR_NULL }, }, diff -u linux-5.15.0/net/ipv4/esp4.c linux-5.15.0/net/ipv4/esp4.c --- linux-5.15.0/net/ipv4/esp4.c +++ linux-5.15.0/net/ipv4/esp4.c @@ -446,7 +446,6 @@ struct page *page; struct sk_buff *trailer; int tailen = esp->tailen; - unsigned int allocsz; /* this is non-NULL only with TCP/UDP Encapsulation */ if (x->encap) { @@ -456,8 +455,8 @@ return err; } - allocsz = ALIGN(skb->data_len + tailen, L1_CACHE_BYTES); - if (allocsz > ESP_SKB_FRAG_MAXSIZE) + if (ALIGN(tailen, L1_CACHE_BYTES) > PAGE_SIZE || + ALIGN(skb->data_len, L1_CACHE_BYTES) > PAGE_SIZE) goto cow; if (!skb_cloned(skb)) { diff -u linux-5.15.0/net/ipv4/ip_gre.c linux-5.15.0/net/ipv4/ip_gre.c --- linux-5.15.0/net/ipv4/ip_gre.c +++ linux-5.15.0/net/ipv4/ip_gre.c @@ -459,14 +459,12 @@ __be16 proto) { struct ip_tunnel *tunnel = netdev_priv(dev); - - if (tunnel->parms.o_flags & TUNNEL_SEQ) - tunnel->o_seqno++; + __be16 flags = tunnel->parms.o_flags; /* Push GRE header. */ gre_build_header(skb, tunnel->tun_hlen, - tunnel->parms.o_flags, proto, tunnel->parms.o_key, - htonl(tunnel->o_seqno)); + flags, proto, tunnel->parms.o_key, + (flags & TUNNEL_SEQ) ? htonl(atomic_fetch_inc(&tunnel->o_seqno)) : 0); ip_tunnel_xmit(skb, dev, tnl_params, tnl_params->protocol); } @@ -504,7 +502,7 @@ (TUNNEL_CSUM | TUNNEL_KEY | TUNNEL_SEQ); gre_build_header(skb, tunnel_hlen, flags, proto, tunnel_id_to_key32(tun_info->key.tun_id), - (flags & TUNNEL_SEQ) ? htonl(tunnel->o_seqno++) : 0); + (flags & TUNNEL_SEQ) ? htonl(atomic_fetch_inc(&tunnel->o_seqno)) : 0); ip_md_tunnel_xmit(skb, dev, IPPROTO_GRE, tunnel_hlen); @@ -581,7 +579,7 @@ } gre_build_header(skb, 8, TUNNEL_SEQ, - proto, 0, htonl(tunnel->o_seqno++)); + proto, 0, htonl(atomic_fetch_inc(&tunnel->o_seqno))); ip_md_tunnel_xmit(skb, dev, IPPROTO_GRE, tunnel_hlen); diff -u linux-5.15.0/net/ipv4/tcp_input.c linux-5.15.0/net/ipv4/tcp_input.c --- linux-5.15.0/net/ipv4/tcp_input.c +++ linux-5.15.0/net/ipv4/tcp_input.c @@ -3860,7 +3860,8 @@ tcp_process_tlp_ack(sk, ack, flag); if (tcp_ack_is_dubious(sk, flag)) { - if (!(flag & (FLAG_SND_UNA_ADVANCED | FLAG_NOT_DUP))) { + if (!(flag & (FLAG_SND_UNA_ADVANCED | + FLAG_NOT_DUP | FLAG_DSACKING_ACK))) { num_dupack = 1; /* Consider if pure acks were aggregated in tcp_add_backlog() */ if (!(flag & FLAG_DATA)) @@ -5420,7 +5421,17 @@ INDIRECT_CALL_1(sk->sk_write_space, sk_stream_write_space, sk); } -static void tcp_check_space(struct sock *sk) +/* Caller made space either from: + * 1) Freeing skbs in rtx queues (after tp->snd_una has advanced) + * 2) Sent skbs from output queue (and thus advancing tp->snd_nxt) + * + * We might be able to generate EPOLLOUT to the application if: + * 1) Space consumed in output/rtx queues is below sk->sk_sndbuf/2 + * 2) notsent amount (tp->write_seq - tp->snd_nxt) became + * small enough that tcp_stream_memory_free() decides it + * is time to generate EPOLLOUT. + */ +void tcp_check_space(struct sock *sk) { /* pairs with tcp_poll() */ smp_mb(); diff -u linux-5.15.0/net/ipv4/tcp_output.c linux-5.15.0/net/ipv4/tcp_output.c --- linux-5.15.0/net/ipv4/tcp_output.c +++ linux-5.15.0/net/ipv4/tcp_output.c @@ -82,6 +82,7 @@ NET_ADD_STATS(sock_net(sk), LINUX_MIB_TCPORIGDATASENT, tcp_skb_pcount(skb)); + tcp_check_space(sk); } /* SND.NXT, if window was not shrunk or the amount of shrunk was less than one diff -u linux-5.15.0/net/ipv6/esp6.c linux-5.15.0/net/ipv6/esp6.c --- linux-5.15.0/net/ipv6/esp6.c +++ linux-5.15.0/net/ipv6/esp6.c @@ -483,7 +483,6 @@ struct page *page; struct sk_buff *trailer; int tailen = esp->tailen; - unsigned int allocsz; if (x->encap) { int err = esp6_output_encap(x, skb, esp); @@ -492,8 +491,8 @@ return err; } - allocsz = ALIGN(skb->data_len + tailen, L1_CACHE_BYTES); - if (allocsz > ESP_SKB_FRAG_MAXSIZE) + if (ALIGN(tailen, L1_CACHE_BYTES) > PAGE_SIZE || + ALIGN(skb->data_len, L1_CACHE_BYTES) > PAGE_SIZE) goto cow; if (!skb_cloned(skb)) { diff -u linux-5.15.0/net/ipv6/ip6_gre.c linux-5.15.0/net/ipv6/ip6_gre.c --- linux-5.15.0/net/ipv6/ip6_gre.c +++ linux-5.15.0/net/ipv6/ip6_gre.c @@ -724,6 +724,7 @@ { struct ip6_tnl *tunnel = netdev_priv(dev); __be16 protocol; + __be16 flags; if (dev->type == ARPHRD_ETHER) IPCB(skb)->flags = 0; @@ -733,16 +734,13 @@ else fl6->daddr = tunnel->parms.raddr; - if (skb_cow_head(skb, dev->needed_headroom ?: tunnel->hlen)) - return -ENOMEM; - /* Push GRE header. */ protocol = (dev->type == ARPHRD_ETHER) ? htons(ETH_P_TEB) : proto; if (tunnel->parms.collect_md) { struct ip_tunnel_info *tun_info; const struct ip_tunnel_key *key; - __be16 flags; + int tun_hlen; tun_info = skb_tunnel_info_txcheck(skb); if (IS_ERR(tun_info) || @@ -760,21 +758,27 @@ dsfield = key->tos; flags = key->tun_flags & (TUNNEL_CSUM | TUNNEL_KEY | TUNNEL_SEQ); - tunnel->tun_hlen = gre_calc_hlen(flags); + tun_hlen = gre_calc_hlen(flags); + + if (skb_cow_head(skb, dev->needed_headroom ?: tun_hlen + tunnel->encap_hlen)) + return -ENOMEM; - gre_build_header(skb, tunnel->tun_hlen, + gre_build_header(skb, tun_hlen, flags, protocol, tunnel_id_to_key32(tun_info->key.tun_id), - (flags & TUNNEL_SEQ) ? htonl(tunnel->o_seqno++) + (flags & TUNNEL_SEQ) ? htonl(atomic_fetch_inc(&tunnel->o_seqno)) : 0); } else { - if (tunnel->parms.o_flags & TUNNEL_SEQ) - tunnel->o_seqno++; + if (skb_cow_head(skb, dev->needed_headroom ?: tunnel->hlen)) + return -ENOMEM; - gre_build_header(skb, tunnel->tun_hlen, tunnel->parms.o_flags, + flags = tunnel->parms.o_flags; + + gre_build_header(skb, tunnel->tun_hlen, flags, protocol, tunnel->parms.o_key, - htonl(tunnel->o_seqno)); + (flags & TUNNEL_SEQ) ? htonl(atomic_fetch_inc(&tunnel->o_seqno)) + : 0); } return ip6_tnl_xmit(skb, dev, dsfield, fl6, encap_limit, pmtu, @@ -1052,7 +1056,7 @@ /* Push GRE header. */ proto = (t->parms.erspan_ver == 1) ? htons(ETH_P_ERSPAN) : htons(ETH_P_ERSPAN2); - gre_build_header(skb, 8, TUNNEL_SEQ, proto, 0, htonl(t->o_seqno++)); + gre_build_header(skb, 8, TUNNEL_SEQ, proto, 0, htonl(atomic_fetch_inc(&t->o_seqno))); /* TooBig packet may have updated dst->dev's mtu */ if (!t->parms.collect_md && dst && dst_mtu(dst) > dst->dev->mtu) diff -u linux-5.15.0/net/ipv6/mcast.c linux-5.15.0/net/ipv6/mcast.c --- linux-5.15.0/net/ipv6/mcast.c +++ linux-5.15.0/net/ipv6/mcast.c @@ -460,10 +460,10 @@ newpsl->sl_addr[i] = psl->sl_addr[i]; atomic_sub(struct_size(psl, sl_addr, psl->sl_max), &sk->sk_omem_alloc); - kfree_rcu(psl, rcu); } + rcu_assign_pointer(pmc->sflist, newpsl); + kfree_rcu(psl, rcu); psl = newpsl; - rcu_assign_pointer(pmc->sflist, psl); } rv = 1; /* > 0 for insert logic below if sl_count is 0 */ for (i = 0; i < psl->sl_count; i++) { @@ -565,12 +565,12 @@ psl->sl_count, psl->sl_addr, 0); atomic_sub(struct_size(psl, sl_addr, psl->sl_max), &sk->sk_omem_alloc); - kfree_rcu(psl, rcu); } else { ip6_mc_del_src(idev, group, pmc->sfmode, 0, NULL, 0); } - mutex_unlock(&idev->mc_lock); rcu_assign_pointer(pmc->sflist, newpsl); + mutex_unlock(&idev->mc_lock); + kfree_rcu(psl, rcu); pmc->sfmode = gsf->gf_fmode; err = 0; done: diff -u linux-5.15.0/net/ipv6/route.c linux-5.15.0/net/ipv6/route.c --- linux-5.15.0/net/ipv6/route.c +++ linux-5.15.0/net/ipv6/route.c @@ -3303,6 +3303,7 @@ int rt_elasticity = net->ipv6.sysctl.ip6_rt_gc_elasticity; int rt_gc_timeout = net->ipv6.sysctl.ip6_rt_gc_timeout; unsigned long rt_last_gc = net->ipv6.ip6_rt_last_gc; + unsigned int val; int entries; entries = dst_entries_get_fast(ops); @@ -3313,13 +3314,13 @@ entries <= rt_max_size) goto out; - net->ipv6.ip6_rt_gc_expire++; - fib6_run_gc(net->ipv6.ip6_rt_gc_expire, net, true); + fib6_run_gc(atomic_inc_return(&net->ipv6.ip6_rt_gc_expire), net, true); entries = dst_entries_get_slow(ops); if (entries < ops->gc_thresh) - net->ipv6.ip6_rt_gc_expire = rt_gc_timeout>>1; + atomic_set(&net->ipv6.ip6_rt_gc_expire, rt_gc_timeout >> 1); out: - net->ipv6.ip6_rt_gc_expire -= net->ipv6.ip6_rt_gc_expire>>rt_elasticity; + val = atomic_read(&net->ipv6.ip6_rt_gc_expire); + atomic_set(&net->ipv6.ip6_rt_gc_expire, val - (val >> rt_elasticity)); return entries > rt_max_size; } @@ -6528,7 +6529,7 @@ net->ipv6.sysctl.ip6_rt_min_advmss = IPV6_MIN_MTU - 20 - 40; net->ipv6.sysctl.skip_notify_on_dev_down = 0; - net->ipv6.ip6_rt_gc_expire = 30*HZ; + atomic_set(&net->ipv6.ip6_rt_gc_expire, 30*HZ); ret = 0; out: diff -u linux-5.15.0/net/netfilter/nf_conntrack_core.c linux-5.15.0/net/netfilter/nf_conntrack_core.c --- linux-5.15.0/net/netfilter/nf_conntrack_core.c +++ linux-5.15.0/net/netfilter/nf_conntrack_core.c @@ -571,7 +571,7 @@ #define NFCT_ALIGN(len) (((len) + NFCT_INFOMASK) & ~NFCT_INFOMASK) -/* Released via destroy_conntrack() */ +/* Released via nf_ct_destroy() */ struct nf_conn *nf_ct_tmpl_alloc(struct net *net, const struct nf_conntrack_zone *zone, gfp_t flags) @@ -598,7 +598,7 @@ tmpl->status = IPS_TEMPLATE; write_pnet(&tmpl->ct_net, net); nf_ct_zone_add(tmpl, zone); - atomic_set(&tmpl->ct_general.use, 0); + refcount_set(&tmpl->ct_general.use, 1); return tmpl; } @@ -625,13 +625,12 @@ #endif } -static void -destroy_conntrack(struct nf_conntrack *nfct) +void nf_ct_destroy(struct nf_conntrack *nfct) { struct nf_conn *ct = (struct nf_conn *)nfct; - pr_debug("destroy_conntrack(%p)\n", ct); - WARN_ON(atomic_read(&nfct->use) != 0); + pr_debug("%s(%p)\n", __func__, ct); + WARN_ON(refcount_read(&nfct->use) != 0); if (unlikely(nf_ct_is_template(ct))) { nf_ct_tmpl_free(ct); @@ -656,9 +655,10 @@ if (ct->master) nf_ct_put(ct->master); - pr_debug("destroy_conntrack: returning ct=%p to slab\n", ct); + pr_debug("%s: returning ct=%p to slab\n", __func__, ct); nf_conntrack_free(ct); } +EXPORT_SYMBOL(nf_ct_destroy); static void nf_ct_delete_from_lists(struct nf_conn *ct) { @@ -755,7 +755,7 @@ /* caller must hold rcu readlock and none of the nf_conntrack_locks */ static void nf_ct_gc_expired(struct nf_conn *ct) { - if (!atomic_inc_not_zero(&ct->ct_general.use)) + if (!refcount_inc_not_zero(&ct->ct_general.use)) return; if (nf_ct_should_gc(ct)) @@ -823,7 +823,7 @@ * in, try to obtain a reference and re-check tuple */ ct = nf_ct_tuplehash_to_ctrack(h); - if (likely(atomic_inc_not_zero(&ct->ct_general.use))) { + if (likely(refcount_inc_not_zero(&ct->ct_general.use))) { if (likely(nf_ct_key_equal(h, tuple, zone, net))) goto found; @@ -920,7 +920,7 @@ smp_wmb(); /* The caller holds a reference to this object */ - atomic_set(&ct->ct_general.use, 2); + refcount_set(&ct->ct_general.use, 2); __nf_conntrack_hash_insert(ct, hash, reply_hash); nf_conntrack_double_unlock(hash, reply_hash); NF_CT_STAT_INC(net, insert); @@ -971,7 +971,7 @@ { struct nf_conn_tstamp *tstamp; - atomic_inc(&ct->ct_general.use); + refcount_inc(&ct->ct_general.use); ct->status |= IPS_CONFIRMED; /* set conntrack timestamp, if enabled. */ @@ -1364,7 +1364,7 @@ nf_ct_is_dying(tmp)) continue; - if (!atomic_inc_not_zero(&tmp->ct_general.use)) + if (!refcount_inc_not_zero(&tmp->ct_general.use)) continue; /* kill only if still in same netns -- might have moved due to @@ -1513,7 +1513,7 @@ continue; /* need to take reference to avoid possible races */ - if (!atomic_inc_not_zero(&tmp->ct_general.use)) + if (!refcount_inc_not_zero(&tmp->ct_general.use)) continue; if (gc_worker_skip_ct(tmp)) { @@ -1622,7 +1622,7 @@ /* Because we use RCU lookups, we set ct_general.use to zero before * this is inserted in any list. */ - atomic_set(&ct->ct_general.use, 0); + refcount_set(&ct->ct_general.use, 0); return ct; out: atomic_dec(&cnet->count); @@ -1647,7 +1647,7 @@ /* A freed object has refcnt == 0, that's * the golden rule for SLAB_TYPESAFE_BY_RCU */ - WARN_ON(atomic_read(&ct->ct_general.use) != 0); + WARN_ON(refcount_read(&ct->ct_general.use) != 0); nf_ct_ext_destroy(ct); kmem_cache_free(nf_conntrack_cachep, ct); @@ -1739,8 +1739,8 @@ if (!exp) __nf_ct_try_assign_helper(ct, tmpl, GFP_ATOMIC); - /* Now it is inserted into the unconfirmed list, bump refcount */ - nf_conntrack_get(&ct->ct_general); + /* Now it is inserted into the unconfirmed list, set refcount to 1. */ + refcount_set(&ct->ct_general.use, 1); nf_ct_add_to_unconfirmed_list(ct); local_bh_enable(); @@ -2352,7 +2352,7 @@ return NULL; found: - atomic_inc(&ct->ct_general.use); + refcount_inc(&ct->ct_general.use); spin_unlock(lockp); local_bh_enable(); return ct; @@ -2825,7 +2825,7 @@ static struct nf_ct_hook nf_conntrack_hook = { .update = nf_conntrack_update, - .destroy = destroy_conntrack, + .destroy = nf_ct_destroy, .get_tuple_skb = nf_conntrack_get_tuple_skb, }; diff -u linux-5.15.0/net/netfilter/nf_conntrack_netlink.c linux-5.15.0/net/netfilter/nf_conntrack_netlink.c --- linux-5.15.0/net/netfilter/nf_conntrack_netlink.c +++ linux-5.15.0/net/netfilter/nf_conntrack_netlink.c @@ -513,7 +513,7 @@ static int ctnetlink_dump_use(struct sk_buff *skb, const struct nf_conn *ct) { - if (nla_put_be32(skb, CTA_USE, htonl(atomic_read(&ct->ct_general.use)))) + if (nla_put_be32(skb, CTA_USE, htonl(refcount_read(&ct->ct_general.use)))) goto nla_put_failure; return 0; @@ -1210,7 +1210,7 @@ ct = nf_ct_tuplehash_to_ctrack(h); if (nf_ct_is_expired(ct)) { if (i < ARRAY_SIZE(nf_ct_evict) && - atomic_inc_not_zero(&ct->ct_general.use)) + refcount_inc_not_zero(&ct->ct_general.use)) nf_ct_evict[i++] = ct; continue; } @@ -1758,7 +1758,7 @@ NFNL_MSG_TYPE(cb->nlh->nlmsg_type), ct, dying ? true : false, 0); if (res < 0) { - if (!atomic_inc_not_zero(&ct->ct_general.use)) + if (!refcount_inc_not_zero(&ct->ct_general.use)) continue; cb->args[0] = cpu; cb->args[1] = (unsigned long)ct; diff -u linux-5.15.0/net/netfilter/nf_conntrack_standalone.c linux-5.15.0/net/netfilter/nf_conntrack_standalone.c --- linux-5.15.0/net/netfilter/nf_conntrack_standalone.c +++ linux-5.15.0/net/netfilter/nf_conntrack_standalone.c @@ -304,7 +304,7 @@ int ret = 0; WARN_ON(!ct); - if (unlikely(!atomic_inc_not_zero(&ct->ct_general.use))) + if (unlikely(!refcount_inc_not_zero(&ct->ct_general.use))) return 0; if (nf_ct_should_gc(ct)) { @@ -371,7 +371,7 @@ ct_show_zone(s, ct, NF_CT_DEFAULT_ZONE_DIR); ct_show_delta_time(s, ct); - seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use)); + seq_printf(s, "use=%u\n", refcount_read(&ct->ct_general.use)); if (seq_has_overflowed(s)) goto release; @@ -824,7 +824,7 @@ .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, -#if IS_ENABLED(CONFIG_NFT_FLOW_OFFLOAD) +#if IS_ENABLED(CONFIG_NF_FLOW_TABLE) [NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_OFFLOAD] = { .procname = "nf_flowtable_udp_timeout", .maxlen = sizeof(unsigned int), diff -u linux-5.15.0/net/netfilter/nf_flow_table_core.c linux-5.15.0/net/netfilter/nf_flow_table_core.c --- linux-5.15.0/net/netfilter/nf_flow_table_core.c +++ linux-5.15.0/net/netfilter/nf_flow_table_core.c @@ -48,7 +48,7 @@ struct flow_offload *flow; if (unlikely(nf_ct_is_dying(ct) || - !atomic_inc_not_zero(&ct->ct_general.use))) + !refcount_inc_not_zero(&ct->ct_general.use))) return NULL; flow = kzalloc(sizeof(*flow), GFP_ATOMIC); diff -u linux-5.15.0/net/netfilter/nft_ct.c linux-5.15.0/net/netfilter/nft_ct.c --- linux-5.15.0/net/netfilter/nft_ct.c +++ linux-5.15.0/net/netfilter/nft_ct.c @@ -259,10 +259,13 @@ ct = this_cpu_read(nft_ct_pcpu_template); - if (likely(atomic_read(&ct->ct_general.use) == 1)) { + if (likely(refcount_read(&ct->ct_general.use) == 1)) { + refcount_inc(&ct->ct_general.use); nf_ct_zone_add(ct, &zone); } else { - /* previous skb got queued to userspace */ + /* previous skb got queued to userspace, allocate temporary + * one until percpu template can be reused. + */ ct = nf_ct_tmpl_alloc(nft_net(pkt), &zone, GFP_ATOMIC); if (!ct) { regs->verdict.code = NF_DROP; @@ -270,7 +273,6 @@ } } - atomic_inc(&ct->ct_general.use); nf_ct_set(skb, ct, IP_CT_NEW); } #endif @@ -375,7 +377,6 @@ return false; } - atomic_set(&tmp->ct_general.use, 1); per_cpu(nft_ct_pcpu_template, cpu) = tmp; } diff -u linux-5.15.0/net/netfilter/nft_socket.c linux-5.15.0/net/netfilter/nft_socket.c --- linux-5.15.0/net/netfilter/nft_socket.c +++ linux-5.15.0/net/netfilter/nft_socket.c @@ -53,6 +53,32 @@ } #endif +static struct sock *nft_socket_do_lookup(const struct nft_pktinfo *pkt) +{ + const struct net_device *indev = nft_in(pkt); + const struct sk_buff *skb = pkt->skb; + struct sock *sk = NULL; + + if (!indev) + return NULL; + + switch (nft_pf(pkt)) { + case NFPROTO_IPV4: + sk = nf_sk_lookup_slow_v4(nft_net(pkt), skb, indev); + break; +#if IS_ENABLED(CONFIG_NF_TABLES_IPV6) + case NFPROTO_IPV6: + sk = nf_sk_lookup_slow_v6(nft_net(pkt), skb, indev); + break; +#endif + default: + WARN_ON_ONCE(1); + break; + } + + return sk; +} + static void nft_socket_eval(const struct nft_expr *expr, struct nft_regs *regs, const struct nft_pktinfo *pkt) @@ -66,20 +92,7 @@ sk = NULL; if (!sk) - switch(nft_pf(pkt)) { - case NFPROTO_IPV4: - sk = nf_sk_lookup_slow_v4(nft_net(pkt), skb, nft_in(pkt)); - break; -#if IS_ENABLED(CONFIG_NF_TABLES_IPV6) - case NFPROTO_IPV6: - sk = nf_sk_lookup_slow_v6(nft_net(pkt), skb, nft_in(pkt)); - break; -#endif - default: - WARN_ON_ONCE(1); - regs->verdict.code = NFT_BREAK; - return; - } + sk = nft_socket_do_lookup(pkt); if (!sk) { regs->verdict.code = NFT_BREAK; @@ -197,6 +210,16 @@ return 0; } +static int nft_socket_validate(const struct nft_ctx *ctx, + const struct nft_expr *expr, + const struct nft_data **data) +{ + return nft_chain_validate_hooks(ctx->chain, + (1 << NF_INET_PRE_ROUTING) | + (1 << NF_INET_LOCAL_IN) | + (1 << NF_INET_LOCAL_OUT)); +} + static struct nft_expr_type nft_socket_type; static const struct nft_expr_ops nft_socket_ops = { .type = &nft_socket_type, @@ -204,6 +227,7 @@ .eval = nft_socket_eval, .init = nft_socket_init, .dump = nft_socket_dump, + .validate = nft_socket_validate, }; static struct nft_expr_type nft_socket_type __read_mostly = { diff -u linux-5.15.0/net/netlink/af_netlink.c linux-5.15.0/net/netlink/af_netlink.c --- linux-5.15.0/net/netlink/af_netlink.c +++ linux-5.15.0/net/netlink/af_netlink.c @@ -2284,6 +2284,13 @@ * single netdev. The outcome is MSG_TRUNC error. */ skb_reserve(skb, skb_tailroom(skb) - alloc_size); + + /* Make sure malicious BPF programs can not read unitialized memory + * from skb->head -> skb->data + */ + skb_reset_network_header(skb); + skb_reset_mac_header(skb); + netlink_skb_set_owner_r(skb, sk); if (nlk->dump_done_errno > 0) { diff -u linux-5.15.0/net/nfc/core.c linux-5.15.0/net/nfc/core.c --- linux-5.15.0/net/nfc/core.c +++ linux-5.15.0/net/nfc/core.c @@ -38,7 +38,7 @@ device_lock(&dev->dev); - if (!device_is_registered(&dev->dev)) { + if (dev->shutting_down) { rc = -ENODEV; goto error; } @@ -94,7 +94,7 @@ device_lock(&dev->dev); - if (!device_is_registered(&dev->dev)) { + if (dev->shutting_down) { rc = -ENODEV; goto error; } @@ -142,7 +142,7 @@ device_lock(&dev->dev); - if (!device_is_registered(&dev->dev)) { + if (dev->shutting_down) { rc = -ENODEV; goto error; } @@ -207,7 +207,7 @@ device_lock(&dev->dev); - if (!device_is_registered(&dev->dev)) { + if (dev->shutting_down) { rc = -ENODEV; goto error; } @@ -246,7 +246,7 @@ device_lock(&dev->dev); - if (!device_is_registered(&dev->dev)) { + if (dev->shutting_down) { rc = -ENODEV; goto error; } @@ -291,7 +291,7 @@ device_lock(&dev->dev); - if (!device_is_registered(&dev->dev)) { + if (dev->shutting_down) { rc = -ENODEV; goto error; } @@ -335,7 +335,7 @@ device_lock(&dev->dev); - if (!device_is_registered(&dev->dev)) { + if (dev->shutting_down) { rc = -ENODEV; goto error; } @@ -401,7 +401,7 @@ device_lock(&dev->dev); - if (!device_is_registered(&dev->dev)) { + if (dev->shutting_down) { rc = -ENODEV; goto error; } @@ -448,7 +448,7 @@ device_lock(&dev->dev); - if (!device_is_registered(&dev->dev)) { + if (dev->shutting_down) { rc = -ENODEV; goto error; } @@ -495,7 +495,7 @@ device_lock(&dev->dev); - if (!device_is_registered(&dev->dev)) { + if (dev->shutting_down) { rc = -ENODEV; kfree_skb(skb); goto error; @@ -552,7 +552,7 @@ device_lock(&dev->dev); - if (!device_is_registered(&dev->dev)) { + if (dev->shutting_down) { rc = -ENODEV; goto error; } @@ -601,7 +601,7 @@ device_lock(&dev->dev); - if (!device_is_registered(&dev->dev)) { + if (dev->shutting_down) { rc = -ENODEV; goto error; } @@ -1134,6 +1134,7 @@ dev->rfkill = NULL; } } + dev->shutting_down = false; device_unlock(&dev->dev); rc = nfc_genl_device_added(dev); @@ -1166,12 +1167,10 @@ rfkill_unregister(dev->rfkill); rfkill_destroy(dev->rfkill); } + dev->shutting_down = true; device_unlock(&dev->dev); if (dev->ops->check_presence) { - device_lock(&dev->dev); - dev->shutting_down = true; - device_unlock(&dev->dev); del_timer_sync(&dev->check_pres_timer); cancel_work_sync(&dev->check_pres_work); } diff -u linux-5.15.0/net/nfc/netlink.c linux-5.15.0/net/nfc/netlink.c --- linux-5.15.0/net/nfc/netlink.c +++ linux-5.15.0/net/nfc/netlink.c @@ -1244,7 +1244,7 @@ struct sk_buff *msg; void *hdr; - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); if (!msg) return -ENOMEM; @@ -1260,7 +1260,7 @@ genlmsg_end(msg, hdr); - genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_KERNEL); + genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_ATOMIC); return 0; diff -u linux-5.15.0/net/openvswitch/conntrack.c linux-5.15.0/net/openvswitch/conntrack.c --- linux-5.15.0/net/openvswitch/conntrack.c +++ linux-5.15.0/net/openvswitch/conntrack.c @@ -1722,7 +1722,6 @@ goto err_free_ct; __set_bit(IPS_CONFIRMED_BIT, &ct_info.ct->status); - nf_conntrack_get(&ct_info.ct->ct_general); return 0; err_free_ct: __ovs_ct_free_action(&ct_info); diff -u linux-5.15.0/net/openvswitch/flow_netlink.c linux-5.15.0/net/openvswitch/flow_netlink.c --- linux-5.15.0/net/openvswitch/flow_netlink.c +++ linux-5.15.0/net/openvswitch/flow_netlink.c @@ -2436,7 +2436,7 @@ new_acts_size = max(next_offset + req_size, ksize(*sfa) * 2); if (new_acts_size > MAX_ACTIONS_BUFSIZE) { - if ((MAX_ACTIONS_BUFSIZE - next_offset) < req_size) { + if ((next_offset + req_size) > MAX_ACTIONS_BUFSIZE) { OVS_NLERR(log, "Flow action size exceeds max %u", MAX_ACTIONS_BUFSIZE); return ERR_PTR(-EMSGSIZE); diff -u linux-5.15.0/net/packet/af_packet.c linux-5.15.0/net/packet/af_packet.c --- linux-5.15.0/net/packet/af_packet.c +++ linux-5.15.0/net/packet/af_packet.c @@ -2820,8 +2820,9 @@ status = TP_STATUS_SEND_REQUEST; err = po->xmit(skb); - if (unlikely(err > 0)) { - err = net_xmit_errno(err); + if (unlikely(err != 0)) { + if (err > 0) + err = net_xmit_errno(err); if (err && __packet_get_status(po, ph) == TP_STATUS_AVAILABLE) { /* skb was destructed already */ @@ -3022,8 +3023,12 @@ skb->no_fcs = 1; err = po->xmit(skb); - if (err > 0 && (err = net_xmit_errno(err)) != 0) - goto out_unlock; + if (unlikely(err != 0)) { + if (err > 0) + err = net_xmit_errno(err); + if (err) + goto out_unlock; + } dev_put(dev); diff -u linux-5.15.0/net/rxrpc/net_ns.c linux-5.15.0/net/rxrpc/net_ns.c --- linux-5.15.0/net/rxrpc/net_ns.c +++ linux-5.15.0/net/rxrpc/net_ns.c @@ -113,7 +113,9 @@ struct rxrpc_net *rxnet = rxrpc_net(net); rxnet->live = false; + del_timer_sync(&rxnet->peer_keepalive_timer); cancel_work_sync(&rxnet->peer_keepalive_work); + /* Remove the timer again as the worker may have restarted it. */ del_timer_sync(&rxnet->peer_keepalive_timer); rxrpc_destroy_all_calls(rxnet); rxrpc_destroy_all_connections(rxnet); diff -u linux-5.15.0/net/sched/act_ct.c linux-5.15.0/net/sched/act_ct.c --- linux-5.15.0/net/sched/act_ct.c +++ linux-5.15.0/net/sched/act_ct.c @@ -1232,7 +1232,6 @@ return -ENOMEM; } __set_bit(IPS_CONFIRMED_BIT, &tmpl->status); - nf_conntrack_get(&tmpl->ct_general); p->tmpl = tmpl; return 0; diff -u linux-5.15.0/net/sched/cls_u32.c linux-5.15.0/net/sched/cls_u32.c --- linux-5.15.0/net/sched/cls_u32.c +++ linux-5.15.0/net/sched/cls_u32.c @@ -814,10 +814,6 @@ new->flags = n->flags; RCU_INIT_POINTER(new->ht_down, ht); - /* bump reference count as long as we hold pointer to structure */ - if (ht) - ht->refcnt++; - #ifdef CONFIG_CLS_U32_PERF /* Statistics may be incremented by readers during update * so we must keep them in tact. When the node is later destroyed @@ -839,6 +835,10 @@ return NULL; } + /* bump reference count as long as we hold pointer to structure */ + if (ht) + ht->refcnt++; + return new; } diff -u linux-5.15.0/net/smc/af_smc.c linux-5.15.0/net/smc/af_smc.c --- linux-5.15.0/net/smc/af_smc.c +++ linux-5.15.0/net/smc/af_smc.c @@ -1351,6 +1351,8 @@ smc->sk.sk_state = SMC_CLOSED; if (rc == -EPIPE || rc == -EAGAIN) smc->sk.sk_err = EPIPE; + else if (rc == -ECONNREFUSED) + smc->sk.sk_err = ECONNREFUSED; else if (signal_pending(current)) smc->sk.sk_err = -sock_intr_errno(timeo); sock_put(&smc->sk); /* passive closing */ @@ -2532,8 +2534,10 @@ if (smc->use_fallback) { rc = kernel_sock_shutdown(smc->clcsock, how); sk->sk_shutdown = smc->clcsock->sk->sk_shutdown; - if (sk->sk_shutdown == SHUTDOWN_MASK) + if (sk->sk_shutdown == SHUTDOWN_MASK) { sk->sk_state = SMC_CLOSED; + sock_put(sk); + } goto out; } switch (how) { diff -u linux-5.15.0/net/sunrpc/clnt.c linux-5.15.0/net/sunrpc/clnt.c --- linux-5.15.0/net/sunrpc/clnt.c +++ linux-5.15.0/net/sunrpc/clnt.c @@ -1065,10 +1065,13 @@ static void rpc_task_set_transport(struct rpc_task *task, struct rpc_clnt *clnt) { - if (task->tk_xprt && - !(test_bit(XPRT_OFFLINE, &task->tk_xprt->state) && - (task->tk_flags & RPC_TASK_MOVEABLE))) - return; + if (task->tk_xprt) { + if (!(test_bit(XPRT_OFFLINE, &task->tk_xprt->state) && + (task->tk_flags & RPC_TASK_MOVEABLE))) + return; + xprt_release(task); + xprt_put(task->tk_xprt); + } if (task->tk_flags & RPC_TASK_NO_ROUND_ROBIN) task->tk_xprt = rpc_task_get_first_xprt(clnt); else diff -u linux-5.15.0/net/sunrpc/xprtsock.c linux-5.15.0/net/sunrpc/xprtsock.c --- linux-5.15.0/net/sunrpc/xprtsock.c +++ linux-5.15.0/net/sunrpc/xprtsock.c @@ -2848,9 +2848,6 @@ } xprt_set_bound(xprt); xs_format_peer_addresses(xprt, "local", RPCBIND_NETID_LOCAL); - ret = ERR_PTR(xs_local_setup_socket(transport)); - if (ret) - goto out_err; break; default: ret = ERR_PTR(-EAFNOSUPPORT); diff -u linux-5.15.0/net/xdp/xsk.c linux-5.15.0/net/xdp/xsk.c --- linux-5.15.0/net/xdp/xsk.c +++ linux-5.15.0/net/xdp/xsk.c @@ -655,7 +655,7 @@ if (sk_can_busy_loop(sk)) sk_busy_loop(sk, 1); /* only support non-blocking sockets */ - if (xsk_no_wakeup(sk)) + if (xs->zc && xsk_no_wakeup(sk)) return 0; pool = xs->pool; diff -u linux-5.15.0/sound/pci/hda/patch_hdmi.c linux-5.15.0/sound/pci/hda/patch_hdmi.c --- linux-5.15.0/sound/pci/hda/patch_hdmi.c +++ linux-5.15.0/sound/pci/hda/patch_hdmi.c @@ -1387,7 +1387,7 @@ last_try: /* the last try; check the empty slots in pins */ - for (i = 0; i < spec->num_nids; i++) { + for (i = 0; i < spec->pcm_used; i++) { if (!test_bit(i, &spec->pcm_bitmap)) return i; } @@ -2263,7 +2263,9 @@ * dev_num is the device entry number in a pin */ - if (codec->mst_no_extra_pcms) + if (spec->dyn_pcm_no_legacy && codec->mst_no_extra_pcms) + pcm_num = spec->num_cvts; + else if (codec->mst_no_extra_pcms) pcm_num = spec->num_nids; else pcm_num = spec->num_nids + spec->dev_num - 1; diff -u linux-5.15.0/sound/pci/hda/patch_realtek.c linux-5.15.0/sound/pci/hda/patch_realtek.c --- linux-5.15.0/sound/pci/hda/patch_realtek.c +++ linux-5.15.0/sound/pci/hda/patch_realtek.c @@ -9176,6 +9176,7 @@ SND_PCI_QUIRK(0x1558, 0x8562, "Clevo NH[57][0-9]RZ[Q]", ALC269_FIXUP_DMIC), SND_PCI_QUIRK(0x1558, 0x8668, "Clevo NP50B[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x866d, "Clevo NP5[05]PN[HJK]", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x867c, "Clevo NP7[01]PNP", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x867d, "Clevo NP7[01]PN[HJK]", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x8680, "Clevo NJ50LU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x8686, "Clevo NH50[CZ]U", ALC256_FIXUP_MIC_NO_PRESENCE_AND_RESUME), @@ -9250,6 +9251,7 @@ SND_PCI_QUIRK(0x17aa, 0x3813, "Legion 7i 15IMHG05", ALC287_FIXUP_LEGION_15IMHG05_SPEAKERS), SND_PCI_QUIRK(0x17aa, 0x3818, "Lenovo C940", ALC298_FIXUP_LENOVO_SPK_VOLUME), SND_PCI_QUIRK(0x17aa, 0x3819, "Lenovo 13s Gen2 ITL", ALC287_FIXUP_13S_GEN2_SPEAKERS), + SND_PCI_QUIRK(0x17aa, 0x3820, "Yoga Duet 7 13ITL6", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS), SND_PCI_QUIRK(0x17aa, 0x3824, "Legion Y9000X 2020", ALC285_FIXUP_LEGION_Y9000X_SPEAKERS), SND_PCI_QUIRK(0x17aa, 0x3827, "Ideapad S740", ALC285_FIXUP_IDEAPAD_S740_COEF), SND_PCI_QUIRK(0x17aa, 0x3834, "Lenovo IdeaPad Slim 9i 14ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS), diff -u linux-5.15.0/sound/soc/atmel/sam9g20_wm8731.c linux-5.15.0/sound/soc/atmel/sam9g20_wm8731.c --- linux-5.15.0/sound/soc/atmel/sam9g20_wm8731.c +++ linux-5.15.0/sound/soc/atmel/sam9g20_wm8731.c @@ -46,35 +46,6 @@ */ #undef ENABLE_MIC_INPUT -static struct clk *mclk; - -static int at91sam9g20ek_set_bias_level(struct snd_soc_card *card, - struct snd_soc_dapm_context *dapm, - enum snd_soc_bias_level level) -{ - static int mclk_on; - int ret = 0; - - switch (level) { - case SND_SOC_BIAS_ON: - case SND_SOC_BIAS_PREPARE: - if (!mclk_on) - ret = clk_enable(mclk); - if (ret == 0) - mclk_on = 1; - break; - - case SND_SOC_BIAS_OFF: - case SND_SOC_BIAS_STANDBY: - if (mclk_on) - clk_disable(mclk); - mclk_on = 0; - break; - } - - return ret; -} - static const struct snd_soc_dapm_widget at91sam9g20ek_dapm_widgets[] = { SND_SOC_DAPM_MIC("Int Mic", NULL), SND_SOC_DAPM_SPK("Ext Spk", NULL), @@ -135,7 +106,6 @@ .owner = THIS_MODULE, .dai_link = &at91sam9g20ek_dai, .num_links = 1, - .set_bias_level = at91sam9g20ek_set_bias_level, .dapm_widgets = at91sam9g20ek_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(at91sam9g20ek_dapm_widgets), @@ -148,7 +118,6 @@ { struct device_node *np = pdev->dev.of_node; struct device_node *codec_np, *cpu_np; - struct clk *pllb; struct snd_soc_card *card = &snd_soc_at91sam9g20ek; int ret; @@ -162,31 +131,6 @@ return -EINVAL; } - /* - * Codec MCLK is supplied by PCK0 - set it up. - */ - mclk = clk_get(NULL, "pck0"); - if (IS_ERR(mclk)) { - dev_err(&pdev->dev, "Failed to get MCLK\n"); - ret = PTR_ERR(mclk); - goto err; - } - - pllb = clk_get(NULL, "pllb"); - if (IS_ERR(pllb)) { - dev_err(&pdev->dev, "Failed to get PLLB\n"); - ret = PTR_ERR(pllb); - goto err_mclk; - } - ret = clk_set_parent(mclk, pllb); - clk_put(pllb); - if (ret != 0) { - dev_err(&pdev->dev, "Failed to set MCLK parent\n"); - goto err_mclk; - } - - clk_set_rate(mclk, MCLK_RATE); - card->dev = &pdev->dev; /* Parse device node info */ @@ -230,9 +174,6 @@ return ret; -err_mclk: - clk_put(mclk); - mclk = NULL; err: atmel_ssc_put_audio(0); return ret; @@ -242,8 +183,6 @@ { struct snd_soc_card *card = platform_get_drvdata(pdev); - clk_disable(mclk); - mclk = NULL; snd_soc_unregister_card(card); atmel_ssc_put_audio(0); diff -u linux-5.15.0/sound/soc/codecs/msm8916-wcd-digital.c linux-5.15.0/sound/soc/codecs/msm8916-wcd-digital.c --- linux-5.15.0/sound/soc/codecs/msm8916-wcd-digital.c +++ linux-5.15.0/sound/soc/codecs/msm8916-wcd-digital.c @@ -1206,9 +1206,16 @@ dev_set_drvdata(dev, priv); - return devm_snd_soc_register_component(dev, &msm8916_wcd_digital, + ret = devm_snd_soc_register_component(dev, &msm8916_wcd_digital, msm8916_wcd_digital_dai, ARRAY_SIZE(msm8916_wcd_digital_dai)); + if (ret) + goto err_mclk; + + return 0; + +err_mclk: + clk_disable_unprepare(priv->mclk); err_clk: clk_disable_unprepare(priv->ahbclk); return ret; diff -u linux-5.15.0/sound/soc/codecs/rk817_codec.c linux-5.15.0/sound/soc/codecs/rk817_codec.c --- linux-5.15.0/sound/soc/codecs/rk817_codec.c +++ linux-5.15.0/sound/soc/codecs/rk817_codec.c @@ -489,7 +489,7 @@ rk817_codec_parse_dt_property(&pdev->dev, rk817_codec_data); - rk817_codec_data->mclk = clk_get(pdev->dev.parent, "mclk"); + rk817_codec_data->mclk = devm_clk_get(pdev->dev.parent, "mclk"); if (IS_ERR(rk817_codec_data->mclk)) { dev_dbg(&pdev->dev, "Unable to get mclk\n"); ret = -ENXIO; diff -u linux-5.15.0/sound/soc/codecs/wcd934x.c linux-5.15.0/sound/soc/codecs/wcd934x.c --- linux-5.15.0/sound/soc/codecs/wcd934x.c +++ linux-5.15.0/sound/soc/codecs/wcd934x.c @@ -1274,29 +1274,7 @@ if (sido_src == wcd->sido_input_src) return 0; - if (sido_src == SIDO_SOURCE_INTERNAL) { - regmap_update_bits(wcd->regmap, WCD934X_ANA_BUCK_CTL, - WCD934X_ANA_BUCK_HI_ACCU_EN_MASK, 0); - usleep_range(100, 110); - regmap_update_bits(wcd->regmap, WCD934X_ANA_BUCK_CTL, - WCD934X_ANA_BUCK_HI_ACCU_PRE_ENX_MASK, 0x0); - usleep_range(100, 110); - regmap_update_bits(wcd->regmap, WCD934X_ANA_RCO, - WCD934X_ANA_RCO_BG_EN_MASK, 0); - usleep_range(100, 110); - regmap_update_bits(wcd->regmap, WCD934X_ANA_BUCK_CTL, - WCD934X_ANA_BUCK_PRE_EN1_MASK, - WCD934X_ANA_BUCK_PRE_EN1_ENABLE); - usleep_range(100, 110); - regmap_update_bits(wcd->regmap, WCD934X_ANA_BUCK_CTL, - WCD934X_ANA_BUCK_PRE_EN2_MASK, - WCD934X_ANA_BUCK_PRE_EN2_ENABLE); - usleep_range(100, 110); - regmap_update_bits(wcd->regmap, WCD934X_ANA_BUCK_CTL, - WCD934X_ANA_BUCK_HI_ACCU_EN_MASK, - WCD934X_ANA_BUCK_HI_ACCU_ENABLE); - usleep_range(100, 110); - } else if (sido_src == SIDO_SOURCE_RCO_BG) { + if (sido_src == SIDO_SOURCE_RCO_BG) { regmap_update_bits(wcd->regmap, WCD934X_ANA_RCO, WCD934X_ANA_RCO_BG_EN_MASK, WCD934X_ANA_RCO_BG_ENABLE); @@ -1382,8 +1360,6 @@ regmap_update_bits(wcd->regmap, WCD934X_CLK_SYS_MCLK_PRG, WCD934X_EXT_CLK_BUF_EN_MASK | WCD934X_MCLK_EN_MASK, 0x0); - wcd934x_set_sido_input_src(wcd, SIDO_SOURCE_INTERNAL); - regmap_update_bits(wcd->regmap, WCD934X_ANA_BIAS, WCD934X_ANA_BIAS_EN_MASK, 0); regmap_update_bits(wcd->regmap, WCD934X_ANA_BIAS, diff -u linux-5.15.0/sound/soc/intel/common/soc-acpi-intel-tgl-match.c linux-5.15.0/sound/soc/intel/common/soc-acpi-intel-tgl-match.c --- linux-5.15.0/sound/soc/intel/common/soc-acpi-intel-tgl-match.c +++ linux-5.15.0/sound/soc/intel/common/soc-acpi-intel-tgl-match.c @@ -127,13 +127,13 @@ { .adr = 0x000123019F837300ull, .num_endpoints = 1, - .endpoints = &spk_l_endpoint, + .endpoints = &spk_r_endpoint, .name_prefix = "Right" }, { .adr = 0x000127019F837300ull, .num_endpoints = 1, - .endpoints = &spk_r_endpoint, + .endpoints = &spk_l_endpoint, .name_prefix = "Left" } }; diff -u linux-5.15.0/sound/soc/soc-dapm.c linux-5.15.0/sound/soc/soc-dapm.c --- linux-5.15.0/sound/soc/soc-dapm.c +++ linux-5.15.0/sound/soc/soc-dapm.c @@ -1685,8 +1685,7 @@ switch (w->id) { case snd_soc_dapm_pre: if (!w->event) - list_for_each_entry_safe_continue(w, n, list, - power_list); + continue; if (event == SND_SOC_DAPM_STREAM_START) ret = w->event(w, @@ -1698,8 +1697,7 @@ case snd_soc_dapm_post: if (!w->event) - list_for_each_entry_safe_continue(w, n, list, - power_list); + continue; if (event == SND_SOC_DAPM_STREAM_START) ret = w->event(w, reverted: --- linux-5.15.0/sound/soc/soc-generic-dmaengine-pcm.c +++ linux-5.15.0.orig/sound/soc/soc-generic-dmaengine-pcm.c @@ -82,10 +82,10 @@ memset(&slave_config, 0, sizeof(slave_config)); + if (!pcm->config) + prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config; + else - if (pcm->config && pcm->config->prepare_slave_config) prepare_slave_config = pcm->config->prepare_slave_config; - else - prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config; if (prepare_slave_config) { int ret = prepare_slave_config(substream, params, &slave_config); diff -u linux-5.15.0/sound/soc/soc-ops.c linux-5.15.0/sound/soc/soc-ops.c --- linux-5.15.0/sound/soc/soc-ops.c +++ linux-5.15.0/sound/soc/soc-ops.c @@ -461,7 +461,7 @@ ret = err; } } - return err; + return ret; } EXPORT_SYMBOL_GPL(snd_soc_put_volsw_sx); diff -u linux-5.15.0/sound/soc/soc-topology.c linux-5.15.0/sound/soc/soc-topology.c --- linux-5.15.0/sound/soc/soc-topology.c +++ linux-5.15.0/sound/soc/soc-topology.c @@ -1481,12 +1481,12 @@ template.num_kcontrols = le32_to_cpu(w->num_kcontrols); kc = devm_kcalloc(tplg->dev, le32_to_cpu(w->num_kcontrols), sizeof(*kc), GFP_KERNEL); if (!kc) - goto err; + goto hdr_err; kcontrol_type = devm_kcalloc(tplg->dev, le32_to_cpu(w->num_kcontrols), sizeof(unsigned int), GFP_KERNEL); if (!kcontrol_type) - goto err; + goto hdr_err; for (i = 0; i < w->num_kcontrols; i++) { control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos; diff -u linux-5.15.0/tools/objtool/check.c linux-5.15.0/tools/objtool/check.c --- linux-5.15.0/tools/objtool/check.c +++ linux-5.15.0/tools/objtool/check.c @@ -393,12 +393,12 @@ else if (reloc->addend == reloc->sym->sec->sh.sh_size) { insn = find_last_insn(file, reloc->sym->sec); if (!insn) { - WARN("can't find unreachable insn at %s+0x%x", + WARN("can't find unreachable insn at %s+0x%lx", reloc->sym->sec->name, reloc->addend); return -1; } } else { - WARN("can't find unreachable insn at %s+0x%x", + WARN("can't find unreachable insn at %s+0x%lx", reloc->sym->sec->name, reloc->addend); return -1; } @@ -428,12 +428,12 @@ else if (reloc->addend == reloc->sym->sec->sh.sh_size) { insn = find_last_insn(file, reloc->sym->sec); if (!insn) { - WARN("can't find reachable insn at %s+0x%x", + WARN("can't find reachable insn at %s+0x%lx", reloc->sym->sec->name, reloc->addend); return -1; } } else { - WARN("can't find reachable insn at %s+0x%x", + WARN("can't find reachable insn at %s+0x%lx", reloc->sym->sec->name, reloc->addend); return -1; } diff -u linux-5.15.0/tools/objtool/elf.c linux-5.15.0/tools/objtool/elf.c --- linux-5.15.0/tools/objtool/elf.c +++ linux-5.15.0/tools/objtool/elf.c @@ -485,7 +485,7 @@ int reltype); int elf_add_reloc(struct elf *elf, struct section *sec, unsigned long offset, - unsigned int type, struct symbol *sym, int addend) + unsigned int type, struct symbol *sym, long addend) { struct reloc *reloc; @@ -514,37 +514,180 @@ return 0; } -int elf_add_reloc_to_insn(struct elf *elf, struct section *sec, - unsigned long offset, unsigned int type, - struct section *insn_sec, unsigned long insn_off) +/* + * Ensure that any reloc section containing references to @sym is marked + * changed such that it will get re-generated in elf_rebuild_reloc_sections() + * with the new symbol index. + */ +static void elf_dirty_reloc_sym(struct elf *elf, struct symbol *sym) +{ + struct section *sec; + + list_for_each_entry(sec, &elf->sections, list) { + struct reloc *reloc; + + if (sec->changed) + continue; + + list_for_each_entry(reloc, &sec->reloc_list, list) { + if (reloc->sym == sym) { + sec->changed = true; + break; + } + } + } +} + +/* + * Move the first global symbol, as per sh_info, into a new, higher symbol + * index. This fees up the shndx for a new local symbol. + */ +static int elf_move_global_symbol(struct elf *elf, struct section *symtab, + struct section *symtab_shndx) { + Elf_Data *data, *shndx_data = NULL; + Elf32_Word first_non_local; struct symbol *sym; - int addend; + Elf_Scn *s; - if (insn_sec->sym) { - sym = insn_sec->sym; - addend = insn_off; + first_non_local = symtab->sh.sh_info; - } else { - /* - * The Clang assembler strips section symbols, so we have to - * reference the function symbol instead: - */ - sym = find_symbol_containing(insn_sec, insn_off); - if (!sym) { - /* - * Hack alert. This happens when we need to reference - * the NOP pad insn immediately after the function. - */ - sym = find_symbol_containing(insn_sec, insn_off - 1); + sym = find_symbol_by_index(elf, first_non_local); + if (!sym) { + WARN("no non-local symbols !?"); + return first_non_local; + } + + s = elf_getscn(elf->elf, symtab->idx); + if (!s) { + WARN_ELF("elf_getscn"); + return -1; + } + + data = elf_newdata(s); + if (!data) { + WARN_ELF("elf_newdata"); + return -1; + } + + data->d_buf = &sym->sym; + data->d_size = sizeof(sym->sym); + data->d_align = 1; + data->d_type = ELF_T_SYM; + + sym->idx = symtab->sh.sh_size / sizeof(sym->sym); + elf_dirty_reloc_sym(elf, sym); + + symtab->sh.sh_info += 1; + symtab->sh.sh_size += data->d_size; + symtab->changed = true; + + if (symtab_shndx) { + s = elf_getscn(elf->elf, symtab_shndx->idx); + if (!s) { + WARN_ELF("elf_getscn"); + return -1; } - if (!sym) { - WARN("can't find symbol containing %s+0x%lx", insn_sec->name, insn_off); + shndx_data = elf_newdata(s); + if (!shndx_data) { + WARN_ELF("elf_newshndx_data"); return -1; } - addend = insn_off - sym->offset; + shndx_data->d_buf = &sym->sec->idx; + shndx_data->d_size = sizeof(Elf32_Word); + shndx_data->d_align = 4; + shndx_data->d_type = ELF_T_WORD; + + symtab_shndx->sh.sh_size += 4; + symtab_shndx->changed = true; + } + + return first_non_local; +} + +static struct symbol * +elf_create_section_symbol(struct elf *elf, struct section *sec) +{ + struct section *symtab, *symtab_shndx; + Elf_Data *shndx_data = NULL; + struct symbol *sym; + Elf32_Word shndx; + + symtab = find_section_by_name(elf, ".symtab"); + if (symtab) { + symtab_shndx = find_section_by_name(elf, ".symtab_shndx"); + if (symtab_shndx) + shndx_data = symtab_shndx->data; + } else { + WARN("no .symtab"); + return NULL; + } + + sym = malloc(sizeof(*sym)); + if (!sym) { + perror("malloc"); + return NULL; + } + memset(sym, 0, sizeof(*sym)); + + sym->idx = elf_move_global_symbol(elf, symtab, symtab_shndx); + if (sym->idx < 0) { + WARN("elf_move_global_symbol"); + return NULL; + } + + sym->name = sec->name; + sym->sec = sec; + + // st_name 0 + sym->sym.st_info = GELF_ST_INFO(STB_LOCAL, STT_SECTION); + // st_other 0 + // st_value 0 + // st_size 0 + shndx = sec->idx; + if (shndx >= SHN_UNDEF && shndx < SHN_LORESERVE) { + sym->sym.st_shndx = shndx; + if (!shndx_data) + shndx = 0; + } else { + sym->sym.st_shndx = SHN_XINDEX; + if (!shndx_data) { + WARN("no .symtab_shndx"); + return NULL; + } + } + + if (!gelf_update_symshndx(symtab->data, shndx_data, sym->idx, &sym->sym, shndx)) { + WARN_ELF("gelf_update_symshndx"); + return NULL; + } + + elf_add_symbol(elf, sym); + + return sym; +} + +int elf_add_reloc_to_insn(struct elf *elf, struct section *sec, + unsigned long offset, unsigned int type, + struct section *insn_sec, unsigned long insn_off) +{ + struct symbol *sym = insn_sec->sym; + int addend = insn_off; + + if (!sym) { + /* + * Due to how weak functions work, we must use section based + * relocations. Symbol based relocations would result in the + * weak and non-weak function annotations being overlaid on the + * non-weak function after linking. + */ + sym = elf_create_section_symbol(elf, insn_sec); + if (!sym) + return -1; + + insn_sec->sym = sym; } return elf_add_reloc(elf, sec, offset, type, sym, addend); diff -u linux-5.15.0/tools/objtool/include/objtool/elf.h linux-5.15.0/tools/objtool/include/objtool/elf.h --- linux-5.15.0/tools/objtool/include/objtool/elf.h +++ linux-5.15.0/tools/objtool/include/objtool/elf.h @@ -72,7 +72,7 @@ struct symbol *sym; unsigned long offset; unsigned int type; - int addend; + long addend; int idx; bool jump_table_start; }; @@ -134,7 +134,7 @@ struct section *elf_create_section(struct elf *elf, const char *name, unsigned int sh_flags, size_t entsize, int nr); int elf_add_reloc(struct elf *elf, struct section *sec, unsigned long offset, - unsigned int type, struct symbol *sym, int addend); + unsigned int type, struct symbol *sym, long addend); int elf_add_reloc_to_insn(struct elf *elf, struct section *sec, unsigned long offset, unsigned int type, struct section *insn_sec, unsigned long insn_off); diff -u linux-5.15.0/tools/perf/builtin-report.c linux-5.15.0/tools/perf/builtin-report.c --- linux-5.15.0/tools/perf/builtin-report.c +++ linux-5.15.0/tools/perf/builtin-report.c @@ -349,6 +349,7 @@ struct perf_session *session = rep->session; u64 sample_type = evlist__combined_sample_type(session->evlist); bool is_pipe = perf_data__is_pipe(session->data); + struct evsel *evsel; if (session->itrace_synth_opts->callchain || session->itrace_synth_opts->add_callchain || @@ -403,6 +404,19 @@ } if (sort__mode == SORT_MODE__MEMORY) { + /* + * FIXUP: prior to kernel 5.18, Arm SPE missed to set + * PERF_SAMPLE_DATA_SRC bit in sample type. For backward + * compatibility, set the bit if it's an old perf data file. + */ + evlist__for_each_entry(session->evlist, evsel) { + if (strstr(evsel->name, "arm_spe") && + !(sample_type & PERF_SAMPLE_DATA_SRC)) { + evsel->core.attr.sample_type |= PERF_SAMPLE_DATA_SRC; + sample_type |= PERF_SAMPLE_DATA_SRC; + } + } + if (!is_pipe && !(sample_type & PERF_SAMPLE_DATA_SRC)) { ui__error("Selected --mem-mode but no mem data. " "Did you call perf record without -d?\n"); diff -u linux-5.15.0/tools/perf/builtin-script.c linux-5.15.0/tools/perf/builtin-script.c --- linux-5.15.0/tools/perf/builtin-script.c +++ linux-5.15.0/tools/perf/builtin-script.c @@ -455,7 +455,7 @@ return -EINVAL; if (PRINT_FIELD(DATA_SRC) && - evsel__check_stype(evsel, PERF_SAMPLE_DATA_SRC, "DATA_SRC", PERF_OUTPUT_DATA_SRC)) + evsel__do_check_stype(evsel, PERF_SAMPLE_DATA_SRC, "DATA_SRC", PERF_OUTPUT_DATA_SRC, allow_user_set)) return -EINVAL; if (PRINT_FIELD(WEIGHT) && diff -u linux-5.15.0/tools/perf/util/arm-spe.c linux-5.15.0/tools/perf/util/arm-spe.c --- linux-5.15.0/tools/perf/util/arm-spe.c +++ linux-5.15.0/tools/perf/util/arm-spe.c @@ -927,7 +927,8 @@ attr.type = PERF_TYPE_HARDWARE; attr.sample_type = evsel->core.attr.sample_type & PERF_SAMPLE_MASK; attr.sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID | - PERF_SAMPLE_PERIOD | PERF_SAMPLE_DATA_SRC; + PERF_SAMPLE_PERIOD | PERF_SAMPLE_DATA_SRC | + PERF_SAMPLE_ADDR; if (spe->timeless_decoding) attr.sample_type &= ~(u64)PERF_SAMPLE_TIME; else diff -u linux-5.15.0/tools/perf/util/symbol.c linux-5.15.0/tools/perf/util/symbol.c --- linux-5.15.0/tools/perf/util/symbol.c +++ linux-5.15.0/tools/perf/util/symbol.c @@ -101,11 +101,6 @@ return tail - str; } -void __weak arch__symbols__fixup_end(struct symbol *p, struct symbol *c) -{ - p->end = c->start; -} - const char * __weak arch__normalize_symbol_name(const char *name) { return name; @@ -217,7 +212,8 @@ } } -void symbols__fixup_end(struct rb_root_cached *symbols) +/* Update zero-sized symbols using the address of the next symbol */ +void symbols__fixup_end(struct rb_root_cached *symbols, bool is_kallsyms) { struct rb_node *nd, *prevnd = rb_first_cached(symbols); struct symbol *curr, *prev; @@ -231,8 +227,29 @@ prev = curr; curr = rb_entry(nd, struct symbol, rb_node); - if (prev->end == prev->start || prev->end != curr->start) - arch__symbols__fixup_end(prev, curr); + /* + * On some architecture kernel text segment start is located at + * some low memory address, while modules are located at high + * memory addresses (or vice versa). The gap between end of + * kernel text segment and beginning of first module's text + * segment is very big. Therefore do not fill this gap and do + * not assign it to the kernel dso map (kallsyms). + * + * In kallsyms, it determines module symbols using '[' character + * like in: + * ffffffffc1937000 T hdmi_driver_init [snd_hda_codec_hdmi] + */ + if (prev->end == prev->start) { + /* Last kernel/module symbol mapped to end of page */ + if (is_kallsyms && (!strchr(prev->name, '[') != + !strchr(curr->name, '['))) + prev->end = roundup(prev->end + 4096, 4096); + else + prev->end = curr->start; + + pr_debug4("%s sym:%s end:%#" PRIx64 "\n", + __func__, prev->name, prev->end); + } } /* Last entry */ @@ -1456,7 +1473,7 @@ if (kallsyms__delta(kmap, filename, &delta)) return -1; - symbols__fixup_end(&dso->symbols); + symbols__fixup_end(&dso->symbols, true); symbols__fixup_duplicate(&dso->symbols); if (dso->kernel == DSO_SPACE__KERNEL_GUEST) @@ -1648,7 +1665,7 @@ #undef bfd_asymbol_section #endif - symbols__fixup_end(&dso->symbols); + symbols__fixup_end(&dso->symbols, false); symbols__fixup_duplicate(&dso->symbols); dso->adjust_symbols = 1; diff -u linux-5.15.0/tools/testing/selftests/kvm/lib/x86_64/processor.c linux-5.15.0/tools/testing/selftests/kvm/lib/x86_64/processor.c --- linux-5.15.0/tools/testing/selftests/kvm/lib/x86_64/processor.c +++ linux-5.15.0/tools/testing/selftests/kvm/lib/x86_64/processor.c @@ -19,38 +19,6 @@ vm_vaddr_t exception_handlers; -/* Virtual translation table structure declarations */ -struct pageUpperEntry { - uint64_t present:1; - uint64_t writable:1; - uint64_t user:1; - uint64_t write_through:1; - uint64_t cache_disable:1; - uint64_t accessed:1; - uint64_t ignored_06:1; - uint64_t page_size:1; - uint64_t ignored_11_08:4; - uint64_t pfn:40; - uint64_t ignored_62_52:11; - uint64_t execute_disable:1; -}; - -struct pageTableEntry { - uint64_t present:1; - uint64_t writable:1; - uint64_t user:1; - uint64_t write_through:1; - uint64_t cache_disable:1; - uint64_t accessed:1; - uint64_t dirty:1; - uint64_t reserved_07:1; - uint64_t global:1; - uint64_t ignored_11_09:3; - uint64_t pfn:40; - uint64_t ignored_62_52:11; - uint64_t execute_disable:1; -}; - void regs_dump(FILE *stream, struct kvm_regs *regs, uint8_t indent) { @@ -195,23 +163,21 @@ return &page_table[index]; } -static struct pageUpperEntry *virt_create_upper_pte(struct kvm_vm *vm, - uint64_t pt_pfn, - uint64_t vaddr, - uint64_t paddr, - int level, - enum x86_page_size page_size) +static uint64_t *virt_create_upper_pte(struct kvm_vm *vm, + uint64_t pt_pfn, + uint64_t vaddr, + uint64_t paddr, + int level, + enum x86_page_size page_size) { - struct pageUpperEntry *pte = virt_get_pte(vm, pt_pfn, vaddr, level); + uint64_t *pte = virt_get_pte(vm, pt_pfn, vaddr, level); - if (!pte->present) { - pte->writable = true; - pte->present = true; - pte->page_size = (level == page_size); - if (pte->page_size) - pte->pfn = paddr >> vm->page_shift; + if (!(*pte & PTE_PRESENT_MASK)) { + *pte = PTE_PRESENT_MASK | PTE_WRITABLE_MASK; + if (level == page_size) + *pte |= PTE_LARGE_MASK | (paddr & PHYSICAL_PAGE_MASK); else - pte->pfn = vm_alloc_page_table(vm) >> vm->page_shift; + *pte |= vm_alloc_page_table(vm) & PHYSICAL_PAGE_MASK; } else { /* * Entry already present. Assert that the caller doesn't want @@ -221,7 +187,7 @@ TEST_ASSERT(level != page_size, "Cannot create hugepage at level: %u, vaddr: 0x%lx\n", page_size, vaddr); - TEST_ASSERT(!pte->page_size, + TEST_ASSERT(!(*pte & PTE_LARGE_MASK), "Cannot create page table at level: %u, vaddr: 0x%lx\n", level, vaddr); } @@ -232,8 +198,8 @@ enum x86_page_size page_size) { const uint64_t pg_size = 1ull << ((page_size * 9) + 12); - struct pageUpperEntry *pml4e, *pdpe, *pde; - struct pageTableEntry *pte; + uint64_t *pml4e, *pdpe, *pde; + uint64_t *pte; TEST_ASSERT(vm->mode == VM_MODE_PXXV48_4K, "Unknown or unsupported guest mode, mode: 0x%x", vm->mode); @@ -257,24 +223,22 @@ */ pml4e = virt_create_upper_pte(vm, vm->pgd >> vm->page_shift, vaddr, paddr, 3, page_size); - if (pml4e->page_size) + if (*pml4e & PTE_LARGE_MASK) return; - pdpe = virt_create_upper_pte(vm, pml4e->pfn, vaddr, paddr, 2, page_size); - if (pdpe->page_size) + pdpe = virt_create_upper_pte(vm, PTE_GET_PFN(*pml4e), vaddr, paddr, 2, page_size); + if (*pdpe & PTE_LARGE_MASK) return; - pde = virt_create_upper_pte(vm, pdpe->pfn, vaddr, paddr, 1, page_size); - if (pde->page_size) + pde = virt_create_upper_pte(vm, PTE_GET_PFN(*pdpe), vaddr, paddr, 1, page_size); + if (*pde & PTE_LARGE_MASK) return; /* Fill in page table entry. */ - pte = virt_get_pte(vm, pde->pfn, vaddr, 0); - TEST_ASSERT(!pte->present, + pte = virt_get_pte(vm, PTE_GET_PFN(*pde), vaddr, 0); + TEST_ASSERT(!(*pte & PTE_PRESENT_MASK), "PTE already present for 4k page at vaddr: 0x%lx\n", vaddr); - pte->pfn = paddr >> vm->page_shift; - pte->writable = true; - pte->present = 1; + *pte = PTE_PRESENT_MASK | PTE_WRITABLE_MASK | (paddr & PHYSICAL_PAGE_MASK); } void virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr) @@ -282,12 +246,12 @@ __virt_pg_map(vm, vaddr, paddr, X86_PAGE_SIZE_4K); } -static struct pageTableEntry *_vm_get_page_table_entry(struct kvm_vm *vm, int vcpuid, +static uint64_t *_vm_get_page_table_entry(struct kvm_vm *vm, int vcpuid, uint64_t vaddr) { uint16_t index[4]; - struct pageUpperEntry *pml4e, *pdpe, *pde; - struct pageTableEntry *pte; + uint64_t *pml4e, *pdpe, *pde; + uint64_t *pte; struct kvm_cpuid_entry2 *entry; struct kvm_sregs sregs; int max_phy_addr; @@ -329,30 +293,29 @@ index[3] = (vaddr >> 39) & 0x1ffu; pml4e = addr_gpa2hva(vm, vm->pgd); - TEST_ASSERT(pml4e[index[3]].present, + TEST_ASSERT(pml4e[index[3]] & PTE_PRESENT_MASK, "Expected pml4e to be present for gva: 0x%08lx", vaddr); - TEST_ASSERT((*(uint64_t*)(&pml4e[index[3]]) & - (rsvd_mask | (1ull << 7))) == 0, + TEST_ASSERT((pml4e[index[3]] & (rsvd_mask | PTE_LARGE_MASK)) == 0, "Unexpected reserved bits set."); - pdpe = addr_gpa2hva(vm, pml4e[index[3]].pfn * vm->page_size); - TEST_ASSERT(pdpe[index[2]].present, + pdpe = addr_gpa2hva(vm, PTE_GET_PFN(pml4e[index[3]]) * vm->page_size); + TEST_ASSERT(pdpe[index[2]] & PTE_PRESENT_MASK, "Expected pdpe to be present for gva: 0x%08lx", vaddr); - TEST_ASSERT(pdpe[index[2]].page_size == 0, + TEST_ASSERT(!(pdpe[index[2]] & PTE_LARGE_MASK), "Expected pdpe to map a pde not a 1-GByte page."); - TEST_ASSERT((*(uint64_t*)(&pdpe[index[2]]) & rsvd_mask) == 0, + TEST_ASSERT((pdpe[index[2]] & rsvd_mask) == 0, "Unexpected reserved bits set."); - pde = addr_gpa2hva(vm, pdpe[index[2]].pfn * vm->page_size); - TEST_ASSERT(pde[index[1]].present, + pde = addr_gpa2hva(vm, PTE_GET_PFN(pdpe[index[2]]) * vm->page_size); + TEST_ASSERT(pde[index[1]] & PTE_PRESENT_MASK, "Expected pde to be present for gva: 0x%08lx", vaddr); - TEST_ASSERT(pde[index[1]].page_size == 0, + TEST_ASSERT(!(pde[index[1]] & PTE_LARGE_MASK), "Expected pde to map a pte not a 2-MByte page."); - TEST_ASSERT((*(uint64_t*)(&pde[index[1]]) & rsvd_mask) == 0, + TEST_ASSERT((pde[index[1]] & rsvd_mask) == 0, "Unexpected reserved bits set."); - pte = addr_gpa2hva(vm, pde[index[1]].pfn * vm->page_size); - TEST_ASSERT(pte[index[0]].present, + pte = addr_gpa2hva(vm, PTE_GET_PFN(pde[index[1]]) * vm->page_size); + TEST_ASSERT(pte[index[0]] & PTE_PRESENT_MASK, "Expected pte to be present for gva: 0x%08lx", vaddr); return &pte[index[0]]; @@ -360,7 +323,7 @@ uint64_t vm_get_page_table_entry(struct kvm_vm *vm, int vcpuid, uint64_t vaddr) { - struct pageTableEntry *pte = _vm_get_page_table_entry(vm, vcpuid, vaddr); + uint64_t *pte = _vm_get_page_table_entry(vm, vcpuid, vaddr); return *(uint64_t *)pte; } @@ -368,18 +331,17 @@ void vm_set_page_table_entry(struct kvm_vm *vm, int vcpuid, uint64_t vaddr, uint64_t pte) { - struct pageTableEntry *new_pte = _vm_get_page_table_entry(vm, vcpuid, - vaddr); + uint64_t *new_pte = _vm_get_page_table_entry(vm, vcpuid, vaddr); *(uint64_t *)new_pte = pte; } void virt_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent) { - struct pageUpperEntry *pml4e, *pml4e_start; - struct pageUpperEntry *pdpe, *pdpe_start; - struct pageUpperEntry *pde, *pde_start; - struct pageTableEntry *pte, *pte_start; + uint64_t *pml4e, *pml4e_start; + uint64_t *pdpe, *pdpe_start; + uint64_t *pde, *pde_start; + uint64_t *pte, *pte_start; if (!vm->pgd_created) return; @@ -389,58 +351,58 @@ fprintf(stream, "%*s index hvaddr gpaddr " "addr w exec dirty\n", indent, ""); - pml4e_start = (struct pageUpperEntry *) addr_gpa2hva(vm, vm->pgd); + pml4e_start = (uint64_t *) addr_gpa2hva(vm, vm->pgd); for (uint16_t n1 = 0; n1 <= 0x1ffu; n1++) { pml4e = &pml4e_start[n1]; - if (!pml4e->present) + if (!(*pml4e & PTE_PRESENT_MASK)) continue; - fprintf(stream, "%*spml4e 0x%-3zx %p 0x%-12lx 0x%-10lx %u " + fprintf(stream, "%*spml4e 0x%-3zx %p 0x%-12lx 0x%-10llx %u " " %u\n", indent, "", pml4e - pml4e_start, pml4e, - addr_hva2gpa(vm, pml4e), (uint64_t) pml4e->pfn, - pml4e->writable, pml4e->execute_disable); + addr_hva2gpa(vm, pml4e), PTE_GET_PFN(*pml4e), + !!(*pml4e & PTE_WRITABLE_MASK), !!(*pml4e & PTE_NX_MASK)); - pdpe_start = addr_gpa2hva(vm, pml4e->pfn * vm->page_size); + pdpe_start = addr_gpa2hva(vm, *pml4e & PHYSICAL_PAGE_MASK); for (uint16_t n2 = 0; n2 <= 0x1ffu; n2++) { pdpe = &pdpe_start[n2]; - if (!pdpe->present) + if (!(*pdpe & PTE_PRESENT_MASK)) continue; - fprintf(stream, "%*spdpe 0x%-3zx %p 0x%-12lx 0x%-10lx " + fprintf(stream, "%*spdpe 0x%-3zx %p 0x%-12lx 0x%-10llx " "%u %u\n", indent, "", pdpe - pdpe_start, pdpe, addr_hva2gpa(vm, pdpe), - (uint64_t) pdpe->pfn, pdpe->writable, - pdpe->execute_disable); + PTE_GET_PFN(*pdpe), !!(*pdpe & PTE_WRITABLE_MASK), + !!(*pdpe & PTE_NX_MASK)); - pde_start = addr_gpa2hva(vm, pdpe->pfn * vm->page_size); + pde_start = addr_gpa2hva(vm, *pdpe & PHYSICAL_PAGE_MASK); for (uint16_t n3 = 0; n3 <= 0x1ffu; n3++) { pde = &pde_start[n3]; - if (!pde->present) + if (!(*pde & PTE_PRESENT_MASK)) continue; fprintf(stream, "%*spde 0x%-3zx %p " - "0x%-12lx 0x%-10lx %u %u\n", + "0x%-12lx 0x%-10llx %u %u\n", indent, "", pde - pde_start, pde, addr_hva2gpa(vm, pde), - (uint64_t) pde->pfn, pde->writable, - pde->execute_disable); + PTE_GET_PFN(*pde), !!(*pde & PTE_WRITABLE_MASK), + !!(*pde & PTE_NX_MASK)); - pte_start = addr_gpa2hva(vm, pde->pfn * vm->page_size); + pte_start = addr_gpa2hva(vm, *pde & PHYSICAL_PAGE_MASK); for (uint16_t n4 = 0; n4 <= 0x1ffu; n4++) { pte = &pte_start[n4]; - if (!pte->present) + if (!(*pte & PTE_PRESENT_MASK)) continue; fprintf(stream, "%*spte 0x%-3zx %p " - "0x%-12lx 0x%-10lx %u %u " + "0x%-12lx 0x%-10llx %u %u " " %u 0x%-10lx\n", indent, "", pte - pte_start, pte, addr_hva2gpa(vm, pte), - (uint64_t) pte->pfn, - pte->writable, - pte->execute_disable, - pte->dirty, + PTE_GET_PFN(*pte), + !!(*pte & PTE_WRITABLE_MASK), + !!(*pte & PTE_NX_MASK), + !!(*pte & PTE_DIRTY_MASK), ((uint64_t) n1 << 27) | ((uint64_t) n2 << 18) | ((uint64_t) n3 << 9) @@ -558,8 +520,8 @@ vm_paddr_t addr_gva2gpa(struct kvm_vm *vm, vm_vaddr_t gva) { uint16_t index[4]; - struct pageUpperEntry *pml4e, *pdpe, *pde; - struct pageTableEntry *pte; + uint64_t *pml4e, *pdpe, *pde; + uint64_t *pte; TEST_ASSERT(vm->mode == VM_MODE_PXXV48_4K, "Attempt to use " "unknown or unsupported guest mode, mode: 0x%x", vm->mode); @@ -572,22 +534,22 @@ if (!vm->pgd_created) goto unmapped_gva; pml4e = addr_gpa2hva(vm, vm->pgd); - if (!pml4e[index[3]].present) + if (!(pml4e[index[3]] & PTE_PRESENT_MASK)) goto unmapped_gva; - pdpe = addr_gpa2hva(vm, pml4e[index[3]].pfn * vm->page_size); - if (!pdpe[index[2]].present) + pdpe = addr_gpa2hva(vm, PTE_GET_PFN(pml4e[index[3]]) * vm->page_size); + if (!(pdpe[index[2]] & PTE_PRESENT_MASK)) goto unmapped_gva; - pde = addr_gpa2hva(vm, pdpe[index[2]].pfn * vm->page_size); - if (!pde[index[1]].present) + pde = addr_gpa2hva(vm, PTE_GET_PFN(pdpe[index[2]]) * vm->page_size); + if (!(pde[index[1]] & PTE_PRESENT_MASK)) goto unmapped_gva; - pte = addr_gpa2hva(vm, pde[index[1]].pfn * vm->page_size); - if (!pte[index[0]].present) + pte = addr_gpa2hva(vm, PTE_GET_PFN(pde[index[1]]) * vm->page_size); + if (!(pte[index[0]] & PTE_PRESENT_MASK)) goto unmapped_gva; - return (pte[index[0]].pfn * vm->page_size) + (gva & 0xfffu); + return (PTE_GET_PFN(pte[index[0]]) * vm->page_size) + (gva & 0xfffu); unmapped_gva: TEST_FAIL("No mapping for vm virtual address, gva: 0x%lx", gva); diff -u linux-5.15.0/tools/testing/selftests/net/test_vxlan_under_vrf.sh linux-5.15.0/tools/testing/selftests/net/test_vxlan_under_vrf.sh --- linux-5.15.0/tools/testing/selftests/net/test_vxlan_under_vrf.sh +++ linux-5.15.0/tools/testing/selftests/net/test_vxlan_under_vrf.sh @@ -130,5 +130,2 @@ -if ! ip netns exec vm-1 ping -c 1 -W 1 10.0.0.2 &> /dev/null; then - echo "[XFAIL]" -else - echo "[ OK ]" -fi +ip netns exec vm-1 ping -c 1 -W 1 10.0.0.2 &> /dev/null || (echo "[FAIL]"; false) +echo "[ OK ]" diff -u linux-5.15.0/tools/testing/selftests/seccomp/seccomp_bpf.c linux-5.15.0/tools/testing/selftests/seccomp/seccomp_bpf.c --- linux-5.15.0/tools/testing/selftests/seccomp/seccomp_bpf.c +++ linux-5.15.0/tools/testing/selftests/seccomp/seccomp_bpf.c @@ -955,7 +955,7 @@ ASSERT_EQ(0, ret); EXPECT_EQ(parent, syscall(__NR_getppid)); - EXPECT_EQ(-1, read(0, NULL, 0)); + EXPECT_EQ(-1, read(-1, NULL, 0)); EXPECT_EQ(E2BIG, errno); } @@ -974,7 +974,7 @@ EXPECT_EQ(parent, syscall(__NR_getppid)); /* "errno" of 0 is ok. */ - EXPECT_EQ(0, read(0, NULL, 0)); + EXPECT_EQ(0, read(-1, NULL, 0)); } /* @@ -995,7 +995,7 @@ ASSERT_EQ(0, ret); EXPECT_EQ(parent, syscall(__NR_getppid)); - EXPECT_EQ(-1, read(0, NULL, 0)); + EXPECT_EQ(-1, read(-1, NULL, 0)); EXPECT_EQ(4095, errno); } @@ -1026,7 +1026,7 @@ ASSERT_EQ(0, ret); EXPECT_EQ(parent, syscall(__NR_getppid)); - EXPECT_EQ(-1, read(0, NULL, 0)); + EXPECT_EQ(-1, read(-1, NULL, 0)); EXPECT_EQ(12, errno); } @@ -2579,7 +2579,7 @@ ret = prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0); if (!ret) return (void *)SIBLING_EXIT_NEWPRIVS; - read(0, NULL, 0); + read(-1, NULL, 0); return (void *)SIBLING_EXIT_UNKILLED; } only in patch2: unchanged: --- linux-5.15.0.orig/Documentation/filesystems/ext4/attributes.rst +++ linux-5.15.0/Documentation/filesystems/ext4/attributes.rst @@ -76,7 +76,7 @@ - Checksum of the extended attribute block. * - 0x14 - \_\_u32 - - h\_reserved[2] + - h\_reserved[3] - Zero. The checksum is calculated against the FS UUID, the 64-bit block number only in patch2: unchanged: --- linux-5.15.0.orig/arch/arc/kernel/entry.S +++ linux-5.15.0/arch/arc/kernel/entry.S @@ -196,6 +196,7 @@ st r0, [sp, PT_r0] ; sys call return value in pt_regs ;POST Sys Call Ptrace Hook + mov r0, sp ; pt_regs needed bl @syscall_trace_exit b ret_from_exception ; NOT ret_from_system_call at is saves r0 which ; we'd done before calling post hook above only in patch2: unchanged: --- linux-5.15.0.orig/arch/arm/boot/dts/am3517-evm.dts +++ linux-5.15.0/arch/arm/boot/dts/am3517-evm.dts @@ -161,6 +161,8 @@ /* HS USB Host PHY on PORT 1 */ hsusb1_phy: hsusb1_phy { + pinctrl-names = "default"; + pinctrl-0 = <&hsusb1_rst_pins>; compatible = "usb-nop-xceiv"; reset-gpios = <&gpio2 25 GPIO_ACTIVE_LOW>; /* gpio_57 */ #phy-cells = <0>; @@ -168,7 +170,9 @@ }; &davinci_emac { - status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <ðernet_pins>; + status = "okay"; }; &davinci_mdio { @@ -193,6 +197,8 @@ }; &i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins>; clock-frequency = <400000>; /* User DIP swithes [1:8] / User LEDS [1:2] */ tca6416: gpio@21 { @@ -205,6 +211,8 @@ }; &i2c3 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c3_pins>; clock-frequency = <400000>; }; @@ -223,6 +231,8 @@ }; &usbhshost { + pinctrl-names = "default"; + pinctrl-0 = <&hsusb1_pins>; port1-mode = "ehci-phy"; }; @@ -231,8 +241,35 @@ }; &omap3_pmx_core { - pinctrl-names = "default"; - pinctrl-0 = <&hsusb1_rst_pins>; + + ethernet_pins: pinmux_ethernet_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x21fe, PIN_INPUT | MUX_MODE0) /* rmii_mdio_data */ + OMAP3_CORE1_IOPAD(0x2200, MUX_MODE0) /* rmii_mdio_clk */ + OMAP3_CORE1_IOPAD(0x2202, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rmii_rxd0 */ + OMAP3_CORE1_IOPAD(0x2204, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rmii_rxd1 */ + OMAP3_CORE1_IOPAD(0x2206, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rmii_crs_dv */ + OMAP3_CORE1_IOPAD(0x2208, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* rmii_rxer */ + OMAP3_CORE1_IOPAD(0x220a, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* rmii_txd0 */ + OMAP3_CORE1_IOPAD(0x220c, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* rmii_txd1 */ + OMAP3_CORE1_IOPAD(0x220e, PIN_OUTPUT_PULLDOWN |MUX_MODE0) /* rmii_txen */ + OMAP3_CORE1_IOPAD(0x2210, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rmii_50mhz_clk */ + >; + }; + + i2c2_pins: pinmux_i2c2_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x21be, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c2_scl */ + OMAP3_CORE1_IOPAD(0x21c0, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c2_sda */ + >; + }; + + i2c3_pins: pinmux_i2c3_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x21c2, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c3_scl */ + OMAP3_CORE1_IOPAD(0x21c4, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c3_sda */ + >; + }; leds_pins: pinmux_leds_pins { pinctrl-single,pins = < @@ -300,8 +337,6 @@ }; &omap3_pmx_core2 { - pinctrl-names = "default"; - pinctrl-0 = <&hsusb1_pins>; hsusb1_pins: pinmux_hsusb1_pins { pinctrl-single,pins = < only in patch2: unchanged: --- linux-5.15.0.orig/arch/arm/boot/dts/am3517-som.dtsi +++ linux-5.15.0/arch/arm/boot/dts/am3517-som.dtsi @@ -69,6 +69,8 @@ }; &i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; clock-frequency = <400000>; s35390a: s35390a@30 { @@ -179,6 +181,13 @@ &omap3_pmx_core { + i2c1_pins: pinmux_i2c1_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x21ba, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c1_scl */ + OMAP3_CORE1_IOPAD(0x21bc, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c1_sda */ + >; + }; + wl12xx_buffer_pins: pinmux_wl12xx_buffer_pins { pinctrl-single,pins = < OMAP3_CORE1_IOPAD(0x2156, PIN_OUTPUT | MUX_MODE4) /* mmc1_dat7.gpio_129 */ only in patch2: unchanged: --- linux-5.15.0.orig/arch/arm/boot/dts/at91-sama5d3_xplained.dts +++ linux-5.15.0/arch/arm/boot/dts/at91-sama5d3_xplained.dts @@ -57,8 +57,8 @@ }; spi0: spi@f0004000 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_spi0_cs>; + pinctrl-names = "default", "cs"; + pinctrl-1 = <&pinctrl_spi0_cs>; cs-gpios = <&pioD 13 0>, <0>, <0>, <&pioD 16 0>; status = "okay"; }; @@ -171,8 +171,8 @@ }; spi1: spi@f8008000 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_spi1_cs>; + pinctrl-names = "default", "cs"; + pinctrl-1 = <&pinctrl_spi1_cs>; cs-gpios = <&pioC 25 0>; status = "okay"; }; only in patch2: unchanged: --- linux-5.15.0.orig/arch/arm/boot/dts/at91-sama5d4_xplained.dts +++ linux-5.15.0/arch/arm/boot/dts/at91-sama5d4_xplained.dts @@ -81,8 +81,8 @@ }; spi1: spi@fc018000 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_spi0_cs>; + pinctrl-names = "default", "cs"; + pinctrl-1 = <&pinctrl_spi1_cs>; cs-gpios = <&pioB 21 0>; status = "okay"; }; @@ -140,7 +140,7 @@ atmel,pins = ; }; - pinctrl_spi0_cs: spi0_cs_default { + pinctrl_spi1_cs: spi1_cs_default { atmel,pins = ; }; only in patch2: unchanged: --- linux-5.15.0.orig/arch/arm/boot/dts/at91-sama7g5ek.dts +++ linux-5.15.0/arch/arm/boot/dts/at91-sama7g5ek.dts @@ -403,7 +403,7 @@ pinctrl_flx3_default: flx3_default { pinmux = , ; - bias-disable; + bias-pull-up; }; pinctrl_flx4_default: flx4_default { only in patch2: unchanged: --- linux-5.15.0.orig/arch/arm/boot/dts/at91sam9g20ek_common.dtsi +++ linux-5.15.0/arch/arm/boot/dts/at91sam9g20ek_common.dtsi @@ -219,6 +219,12 @@ wm8731: wm8731@1b { compatible = "wm8731"; reg = <0x1b>; + + /* PCK0 at 12MHz */ + clocks = <&pmc PMC_TYPE_SYSTEM 8>; + clock-names = "mclk"; + assigned-clocks = <&pmc PMC_TYPE_SYSTEM 8>; + assigned-clock-rates = <12000000>; }; }; only in patch2: unchanged: --- linux-5.15.0.orig/arch/arm/boot/dts/imx6qdl-apalis.dtsi +++ linux-5.15.0/arch/arm/boot/dts/imx6qdl-apalis.dtsi @@ -286,6 +286,8 @@ codec: sgtl5000@a { compatible = "fsl,sgtl5000"; reg = <0x0a>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sgtl5000>; clocks = <&clks IMX6QDL_CLK_CKO>; VDDA-supply = <®_module_3v3_audio>; VDDIO-supply = <®_module_3v3>; @@ -516,8 +518,6 @@ MX6QDL_PAD_DISP0_DAT21__AUD4_TXD 0x130b0 MX6QDL_PAD_DISP0_DAT22__AUD4_TXFS 0x130b0 MX6QDL_PAD_DISP0_DAT23__AUD4_RXD 0x130b0 - /* SGTL5000 sys_mclk */ - MX6QDL_PAD_GPIO_5__CCM_CLKO1 0x130b0 >; }; @@ -810,6 +810,12 @@ >; }; + pinctrl_sgtl5000: sgtl5000grp { + fsl,pins = < + MX6QDL_PAD_GPIO_5__CCM_CLKO1 0x130b0 + >; + }; + pinctrl_spdif: spdifgrp { fsl,pins = < MX6QDL_PAD_GPIO_16__SPDIF_IN 0x1b0b0 only in patch2: unchanged: --- linux-5.15.0.orig/arch/arm/boot/dts/imx6ull-colibri.dtsi +++ linux-5.15.0/arch/arm/boot/dts/imx6ull-colibri.dtsi @@ -37,7 +37,7 @@ reg_sd1_vmmc: regulator-sd1-vmmc { compatible = "regulator-gpio"; - gpio = <&gpio5 9 GPIO_ACTIVE_HIGH>; + gpios = <&gpio5 9 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_snvs_reg_sd>; regulator-always-on; only in patch2: unchanged: --- linux-5.15.0.orig/arch/arm/boot/dts/logicpd-som-lv-35xx-devkit.dts +++ linux-5.15.0/arch/arm/boot/dts/logicpd-som-lv-35xx-devkit.dts @@ -11,3 +11,18 @@ model = "LogicPD Zoom OMAP35xx SOM-LV Development Kit"; compatible = "logicpd,dm3730-som-lv-devkit", "ti,omap3430", "ti,omap3"; }; + +&omap3_pmx_core2 { + pinctrl-names = "default"; + pinctrl-0 = <&hsusb2_2_pins>; + hsusb2_2_pins: pinmux_hsusb2_2_pins { + pinctrl-single,pins = < + OMAP3430_CORE2_IOPAD(0x25f0, PIN_OUTPUT | MUX_MODE3) /* etk_d10.hsusb2_clk */ + OMAP3430_CORE2_IOPAD(0x25f2, PIN_OUTPUT | MUX_MODE3) /* etk_d11.hsusb2_stp */ + OMAP3430_CORE2_IOPAD(0x25f4, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d12.hsusb2_dir */ + OMAP3430_CORE2_IOPAD(0x25f6, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d13.hsusb2_nxt */ + OMAP3430_CORE2_IOPAD(0x25f8, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d14.hsusb2_data0 */ + OMAP3430_CORE2_IOPAD(0x25fa, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d15.hsusb2_data1 */ + >; + }; +}; only in patch2: unchanged: --- linux-5.15.0.orig/arch/arm/boot/dts/logicpd-som-lv-37xx-devkit.dts +++ linux-5.15.0/arch/arm/boot/dts/logicpd-som-lv-37xx-devkit.dts @@ -11,3 +11,18 @@ model = "LogicPD Zoom DM3730 SOM-LV Development Kit"; compatible = "logicpd,dm3730-som-lv-devkit", "ti,omap3630", "ti,omap3"; }; + +&omap3_pmx_core2 { + pinctrl-names = "default"; + pinctrl-0 = <&hsusb2_2_pins>; + hsusb2_2_pins: pinmux_hsusb2_2_pins { + pinctrl-single,pins = < + OMAP3630_CORE2_IOPAD(0x25f0, PIN_OUTPUT | MUX_MODE3) /* etk_d10.hsusb2_clk */ + OMAP3630_CORE2_IOPAD(0x25f2, PIN_OUTPUT | MUX_MODE3) /* etk_d11.hsusb2_stp */ + OMAP3630_CORE2_IOPAD(0x25f4, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d12.hsusb2_dir */ + OMAP3630_CORE2_IOPAD(0x25f6, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d13.hsusb2_nxt */ + OMAP3630_CORE2_IOPAD(0x25f8, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d14.hsusb2_data0 */ + OMAP3630_CORE2_IOPAD(0x25fa, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d15.hsusb2_data1 */ + >; + }; +}; only in patch2: unchanged: --- linux-5.15.0.orig/arch/arm/boot/dts/logicpd-som-lv.dtsi +++ linux-5.15.0/arch/arm/boot/dts/logicpd-som-lv.dtsi @@ -265,21 +265,6 @@ }; }; -&omap3_pmx_core2 { - pinctrl-names = "default"; - pinctrl-0 = <&hsusb2_2_pins>; - hsusb2_2_pins: pinmux_hsusb2_2_pins { - pinctrl-single,pins = < - OMAP3630_CORE2_IOPAD(0x25f0, PIN_OUTPUT | MUX_MODE3) /* etk_d10.hsusb2_clk */ - OMAP3630_CORE2_IOPAD(0x25f2, PIN_OUTPUT | MUX_MODE3) /* etk_d11.hsusb2_stp */ - OMAP3630_CORE2_IOPAD(0x25f4, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d12.hsusb2_dir */ - OMAP3630_CORE2_IOPAD(0x25f6, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d13.hsusb2_nxt */ - OMAP3630_CORE2_IOPAD(0x25f8, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d14.hsusb2_data0 */ - OMAP3630_CORE2_IOPAD(0x25fa, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d15.hsusb2_data1 */ - >; - }; -}; - &uart2 { interrupts-extended = <&intc 73 &omap3_pmx_core OMAP3_UART2_RX>; pinctrl-names = "default"; only in patch2: unchanged: --- linux-5.15.0.orig/arch/arm/boot/dts/socfpga.dtsi +++ linux-5.15.0/arch/arm/boot/dts/socfpga.dtsi @@ -782,7 +782,7 @@ }; qspi: spi@ff705000 { - compatible = "cdns,qspi-nor"; + compatible = "intel,socfpga-qspi", "cdns,qspi-nor"; #address-cells = <1>; #size-cells = <0>; reg = <0xff705000 0x1000>, only in patch2: unchanged: --- linux-5.15.0.orig/arch/arm/boot/dts/socfpga_arria10.dtsi +++ linux-5.15.0/arch/arm/boot/dts/socfpga_arria10.dtsi @@ -756,7 +756,7 @@ }; qspi: spi@ff809000 { - compatible = "cdns,qspi-nor"; + compatible = "intel,socfpga-qspi", "cdns,qspi-nor"; #address-cells = <1>; #size-cells = <0>; reg = <0xff809000 0x100>, only in patch2: unchanged: --- linux-5.15.0.orig/arch/arm/mach-exynos/Kconfig +++ linux-5.15.0/arch/arm/mach-exynos/Kconfig @@ -18,7 +18,6 @@ select EXYNOS_PMU select EXYNOS_SROM select EXYNOS_PM_DOMAINS if PM_GENERIC_DOMAINS - select GPIOLIB select HAVE_ARM_ARCH_TIMER if ARCH_EXYNOS5 select HAVE_ARM_SCU if SMP select HAVE_S3C2410_I2C if I2C only in patch2: unchanged: --- linux-5.15.0.orig/arch/arm/mach-omap2/omap4-common.c +++ linux-5.15.0/arch/arm/mach-omap2/omap4-common.c @@ -314,10 +314,12 @@ np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-gic"); gic_dist_base_addr = of_iomap(np, 0); + of_node_put(np); WARN_ON(!gic_dist_base_addr); np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-twd-timer"); twd_base = of_iomap(np, 0); + of_node_put(np); WARN_ON(!twd_base); skip_errata_init: only in patch2: unchanged: --- linux-5.15.0.orig/arch/arm/mach-vexpress/spc.c +++ linux-5.15.0/arch/arm/mach-vexpress/spc.c @@ -580,7 +580,7 @@ } cluster = topology_physical_package_id(cpu_dev->id); - if (init_opp_table[cluster]) + if (cluster < 0 || init_opp_table[cluster]) continue; if (ve_init_opp_table(cpu_dev)) only in patch2: unchanged: --- linux-5.15.0.orig/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi +++ linux-5.15.0/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi @@ -594,7 +594,7 @@ }; qspi: spi@ff8d2000 { - compatible = "cdns,qspi-nor"; + compatible = "intel,socfpga-qspi", "cdns,qspi-nor"; #address-cells = <1>; #size-cells = <0>; reg = <0xff8d2000 0x100>, only in patch2: unchanged: --- linux-5.15.0.orig/arch/arm64/boot/dts/amlogic/meson-g12b-a311d.dtsi +++ linux-5.15.0/arch/arm64/boot/dts/amlogic/meson-g12b-a311d.dtsi @@ -11,26 +11,6 @@ compatible = "operating-points-v2"; opp-shared; - opp-100000000 { - opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <731000>; - }; - - opp-250000000 { - opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <731000>; - }; - - opp-500000000 { - opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <731000>; - }; - - opp-667000000 { - opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <731000>; - }; - opp-1000000000 { opp-hz = /bits/ 64 <1000000000>; opp-microvolt = <761000>; @@ -71,26 +51,6 @@ compatible = "operating-points-v2"; opp-shared; - opp-100000000 { - opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <731000>; - }; - - opp-250000000 { - opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <731000>; - }; - - opp-500000000 { - opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <731000>; - }; - - opp-667000000 { - opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <731000>; - }; - opp-1000000000 { opp-hz = /bits/ 64 <1000000000>; opp-microvolt = <731000>; only in patch2: unchanged: --- linux-5.15.0.orig/arch/arm64/boot/dts/amlogic/meson-g12b-s922x.dtsi +++ linux-5.15.0/arch/arm64/boot/dts/amlogic/meson-g12b-s922x.dtsi @@ -11,26 +11,6 @@ compatible = "operating-points-v2"; opp-shared; - opp-100000000 { - opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <731000>; - }; - - opp-250000000 { - opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <731000>; - }; - - opp-500000000 { - opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <731000>; - }; - - opp-667000000 { - opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <731000>; - }; - opp-1000000000 { opp-hz = /bits/ 64 <1000000000>; opp-microvolt = <731000>; @@ -76,26 +56,6 @@ compatible = "operating-points-v2"; opp-shared; - opp-100000000 { - opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <751000>; - }; - - opp-250000000 { - opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <751000>; - }; - - opp-500000000 { - opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <751000>; - }; - - opp-667000000 { - opp-hz = /bits/ 64 <667000000>; - opp-microvolt = <751000>; - }; - opp-1000000000 { opp-hz = /bits/ 64 <1000000000>; opp-microvolt = <771000>; only in patch2: unchanged: --- linux-5.15.0.orig/arch/arm64/boot/dts/amlogic/meson-sm1.dtsi +++ linux-5.15.0/arch/arm64/boot/dts/amlogic/meson-sm1.dtsi @@ -95,26 +95,6 @@ compatible = "operating-points-v2"; opp-shared; - opp-100000000 { - opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <730000>; - }; - - opp-250000000 { - opp-hz = /bits/ 64 <250000000>; - opp-microvolt = <730000>; - }; - - opp-500000000 { - opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <730000>; - }; - - opp-667000000 { - opp-hz = /bits/ 64 <666666666>; - opp-microvolt = <750000>; - }; - opp-1000000000 { opp-hz = /bits/ 64 <1000000000>; opp-microvolt = <770000>; only in patch2: unchanged: --- linux-5.15.0.orig/arch/arm64/boot/dts/freescale/imx8mm-var-som.dtsi +++ linux-5.15.0/arch/arm64/boot/dts/freescale/imx8mm-var-som.dtsi @@ -89,12 +89,12 @@ pendown-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>; ti,x-min = /bits/ 16 <125>; - touchscreen-size-x = /bits/ 16 <4008>; + touchscreen-size-x = <4008>; ti,y-min = /bits/ 16 <282>; - touchscreen-size-y = /bits/ 16 <3864>; + touchscreen-size-y = <3864>; ti,x-plate-ohms = /bits/ 16 <180>; - touchscreen-max-pressure = /bits/ 16 <255>; - touchscreen-average-samples = /bits/ 16 <10>; + touchscreen-max-pressure = <255>; + touchscreen-average-samples = <10>; ti,debounce-tol = /bits/ 16 <3>; ti,debounce-rep = /bits/ 16 <1>; ti,settle-delay-usec = /bits/ 16 <150>; only in patch2: unchanged: --- linux-5.15.0.orig/arch/arm64/boot/dts/freescale/imx8mm-venice-gw71xx.dtsi +++ linux-5.15.0/arch/arm64/boot/dts/freescale/imx8mm-venice-gw71xx.dtsi @@ -103,12 +103,14 @@ &usbotg1 { dr_mode = "otg"; + over-current-active-low; vbus-supply = <®_usb_otg1_vbus>; status = "okay"; }; &usbotg2 { dr_mode = "host"; + disable-over-current; status = "okay"; }; @@ -166,7 +168,7 @@ fsl,pins = < MX8MM_IOMUXC_ECSPI2_SCLK_ECSPI2_SCLK 0xd6 MX8MM_IOMUXC_ECSPI2_MOSI_ECSPI2_MOSI 0xd6 - MX8MM_IOMUXC_ECSPI2_SCLK_ECSPI2_SCLK 0xd6 + MX8MM_IOMUXC_ECSPI2_MISO_ECSPI2_MISO 0xd6 MX8MM_IOMUXC_ECSPI2_SS0_GPIO5_IO13 0xd6 >; }; only in patch2: unchanged: --- linux-5.15.0.orig/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx.dtsi +++ linux-5.15.0/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx.dtsi @@ -139,12 +139,14 @@ &usbotg1 { dr_mode = "otg"; + over-current-active-low; vbus-supply = <®_usb_otg1_vbus>; status = "okay"; }; &usbotg2 { dr_mode = "host"; + disable-over-current; vbus-supply = <®_usb_otg2_vbus>; status = "okay"; }; @@ -231,7 +233,7 @@ fsl,pins = < MX8MM_IOMUXC_ECSPI2_SCLK_ECSPI2_SCLK 0xd6 MX8MM_IOMUXC_ECSPI2_MOSI_ECSPI2_MOSI 0xd6 - MX8MM_IOMUXC_ECSPI2_SCLK_ECSPI2_SCLK 0xd6 + MX8MM_IOMUXC_ECSPI2_MISO_ECSPI2_MISO 0xd6 MX8MM_IOMUXC_ECSPI2_SS0_GPIO5_IO13 0xd6 >; }; only in patch2: unchanged: --- linux-5.15.0.orig/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx.dtsi +++ linux-5.15.0/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx.dtsi @@ -166,12 +166,14 @@ &usbotg1 { dr_mode = "otg"; + over-current-active-low; vbus-supply = <®_usb_otg1_vbus>; status = "okay"; }; &usbotg2 { dr_mode = "host"; + disable-over-current; vbus-supply = <®_usb_otg2_vbus>; status = "okay"; }; @@ -280,7 +282,7 @@ fsl,pins = < MX8MM_IOMUXC_ECSPI2_SCLK_ECSPI2_SCLK 0xd6 MX8MM_IOMUXC_ECSPI2_MOSI_ECSPI2_MOSI 0xd6 - MX8MM_IOMUXC_ECSPI2_SCLK_ECSPI2_SCLK 0xd6 + MX8MM_IOMUXC_ECSPI2_MISO_ECSPI2_MISO 0xd6 MX8MM_IOMUXC_ECSPI2_SS0_GPIO5_IO13 0xd6 >; }; only in patch2: unchanged: --- linux-5.15.0.orig/arch/arm64/boot/dts/freescale/imx8mn-ddr4-evk.dts +++ linux-5.15.0/arch/arm64/boot/dts/freescale/imx8mn-ddr4-evk.dts @@ -59,6 +59,10 @@ interrupts = <3 IRQ_TYPE_LEVEL_LOW>; rohm,reset-snvs-powered; + #clock-cells = <0>; + clocks = <&osc_32k 0>; + clock-output-names = "clk-32k-out"; + regulators { buck1_reg: BUCK1 { regulator-name = "buck1"; only in patch2: unchanged: --- linux-5.15.0.orig/arch/arm64/boot/dts/freescale/imx8mn-var-som.dtsi +++ linux-5.15.0/arch/arm64/boot/dts/freescale/imx8mn-var-som.dtsi @@ -70,12 +70,12 @@ pendown-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>; ti,x-min = /bits/ 16 <125>; - touchscreen-size-x = /bits/ 16 <4008>; + touchscreen-size-x = <4008>; ti,y-min = /bits/ 16 <282>; - touchscreen-size-y = /bits/ 16 <3864>; + touchscreen-size-y = <3864>; ti,x-plate-ohms = /bits/ 16 <180>; - touchscreen-max-pressure = /bits/ 16 <255>; - touchscreen-average-samples = /bits/ 16 <10>; + touchscreen-max-pressure = <255>; + touchscreen-average-samples = <10>; ti,debounce-tol = /bits/ 16 <3>; ti,debounce-rep = /bits/ 16 <1>; ti,settle-delay-usec = /bits/ 16 <150>; only in patch2: unchanged: --- linux-5.15.0.orig/arch/arm64/boot/dts/freescale/imx8mn.dtsi +++ linux-5.15.0/arch/arm64/boot/dts/freescale/imx8mn.dtsi @@ -263,7 +263,7 @@ ranges; sai2: sai@30020000 { - compatible = "fsl,imx8mm-sai", "fsl,imx8mq-sai"; + compatible = "fsl,imx8mn-sai", "fsl,imx8mq-sai"; reg = <0x30020000 0x10000>; interrupts = ; clocks = <&clk IMX8MN_CLK_SAI2_IPG>, @@ -277,7 +277,7 @@ }; sai3: sai@30030000 { - compatible = "fsl,imx8mm-sai", "fsl,imx8mq-sai"; + compatible = "fsl,imx8mn-sai", "fsl,imx8mq-sai"; reg = <0x30030000 0x10000>; interrupts = ; clocks = <&clk IMX8MN_CLK_SAI3_IPG>, @@ -291,7 +291,7 @@ }; sai5: sai@30050000 { - compatible = "fsl,imx8mm-sai", "fsl,imx8mq-sai"; + compatible = "fsl,imx8mn-sai", "fsl,imx8mq-sai"; reg = <0x30050000 0x10000>; interrupts = ; clocks = <&clk IMX8MN_CLK_SAI5_IPG>, @@ -307,7 +307,7 @@ }; sai6: sai@30060000 { - compatible = "fsl,imx8mm-sai", "fsl,imx8mq-sai"; + compatible = "fsl,imx8mn-sai", "fsl,imx8mq-sai"; reg = <0x30060000 0x10000>; interrupts = ; clocks = <&clk IMX8MN_CLK_SAI6_IPG>, @@ -364,7 +364,7 @@ }; sai7: sai@300b0000 { - compatible = "fsl,imx8mm-sai", "fsl,imx8mq-sai"; + compatible = "fsl,imx8mn-sai", "fsl,imx8mq-sai"; reg = <0x300b0000 0x10000>; interrupts = ; clocks = <&clk IMX8MN_CLK_SAI7_IPG>, only in patch2: unchanged: --- linux-5.15.0.orig/arch/arm64/boot/dts/freescale/imx8qm.dtsi +++ linux-5.15.0/arch/arm64/boot/dts/freescale/imx8qm.dtsi @@ -155,7 +155,7 @@ }; clk: clock-controller { - compatible = "fsl,imx8qxp-clk", "fsl,scu-clk"; + compatible = "fsl,imx8qm-clk", "fsl,scu-clk"; #clock-cells = <2>; }; only in patch2: unchanged: --- linux-5.15.0.orig/arch/arm64/include/asm/page.h +++ linux-5.15.0/arch/arm64/include/asm/page.h @@ -41,7 +41,6 @@ typedef struct page *pgtable_t; -int pfn_valid(unsigned long pfn); int pfn_is_map_memory(unsigned long pfn); #include only in patch2: unchanged: --- linux-5.15.0.orig/arch/mips/include/asm/timex.h +++ linux-5.15.0/arch/mips/include/asm/timex.h @@ -40,9 +40,9 @@ typedef unsigned int cycles_t; /* - * On R4000/R4400 before version 5.0 an erratum exists such that if the - * cycle counter is read in the exact moment that it is matching the - * compare register, no interrupt will be generated. + * On R4000/R4400 an erratum exists such that if the cycle counter is + * read in the exact moment that it is matching the compare register, + * no interrupt will be generated. * * There is a suggested workaround and also the erratum can't strike if * the compare interrupt isn't being used as the clock source device. @@ -63,7 +63,7 @@ if (!__builtin_constant_p(cpu_has_counter)) asm volatile("" : "=m" (cpu_data[0].options)); if (likely(cpu_has_counter && - prid >= (PRID_IMP_R4000 | PRID_REV_ENCODE_44(5, 0)))) + prid > (PRID_IMP_R4000 | PRID_REV_ENCODE_44(15, 15)))) return 1; else return 0; only in patch2: unchanged: --- linux-5.15.0.orig/arch/mips/kernel/time.c +++ linux-5.15.0/arch/mips/kernel/time.c @@ -141,15 +141,10 @@ case CPU_R4400MC: /* * The published errata for the R4400 up to 3.0 say the CPU - * has the mfc0 from count bug. + * has the mfc0 from count bug. This seems the last version + * produced. */ - if ((current_cpu_data.processor_id & 0xff) <= 0x30) - return 1; - - /* - * we assume newer revisions are ok - */ - return 0; + return 1; } return 0; only in patch2: unchanged: --- linux-5.15.0.orig/arch/parisc/kernel/processor.c +++ linux-5.15.0/arch/parisc/kernel/processor.c @@ -418,8 +418,7 @@ } seq_printf(m, " (0x%02lx)\n", boot_cpu_data.pdc.capabilities); - seq_printf(m, "model\t\t: %s\n" - "model name\t: %s\n", + seq_printf(m, "model\t\t: %s - %s\n", boot_cpu_data.pdc.sys_model_name, cpuinfo->dev ? cpuinfo->dev->name : "Unknown"); only in patch2: unchanged: --- linux-5.15.0.orig/arch/parisc/kernel/setup.c +++ linux-5.15.0/arch/parisc/kernel/setup.c @@ -150,6 +150,8 @@ #ifdef CONFIG_PA11 dma_ops_init(); #endif + + clear_sched_clock_stable(); } /* only in patch2: unchanged: --- linux-5.15.0.orig/arch/powerpc/kernel/cputable.c +++ linux-5.15.0/arch/powerpc/kernel/cputable.c @@ -2119,7 +2119,7 @@ struct static_key_true mmu_feature_keys[NUM_MMU_FTR_KEYS] = { [0 ... NUM_MMU_FTR_KEYS - 1] = STATIC_KEY_TRUE_INIT }; -EXPORT_SYMBOL_GPL(mmu_feature_keys); +EXPORT_SYMBOL(mmu_feature_keys); void __init mmu_feature_keys_init(void) { only in patch2: unchanged: --- linux-5.15.0.orig/arch/powerpc/kernel/reloc_64.S +++ linux-5.15.0/arch/powerpc/kernel/reloc_64.S @@ -8,8 +8,10 @@ #include RELA = 7 -RELACOUNT = 0x6ffffff9 +RELASZ = 8 +RELAENT = 9 R_PPC64_RELATIVE = 22 +R_PPC64_UADDR64 = 43 /* * r3 = desired final address of kernel @@ -25,29 +27,38 @@ add r9,r9,r12 /* r9 has runtime addr of .rela.dyn section */ ld r10,(p_st - 0b)(r12) add r10,r10,r12 /* r10 has runtime addr of _stext */ + ld r13,(p_sym - 0b)(r12) + add r13,r13,r12 /* r13 has runtime addr of .dynsym */ /* - * Scan the dynamic section for the RELA and RELACOUNT entries. + * Scan the dynamic section for the RELA, RELASZ and RELAENT entries. */ li r7,0 li r8,0 -1: ld r6,0(r11) /* get tag */ +.Ltags: + ld r6,0(r11) /* get tag */ cmpdi r6,0 - beq 4f /* end of list */ + beq .Lend_of_list /* end of list */ cmpdi r6,RELA bne 2f ld r7,8(r11) /* get RELA pointer in r7 */ - b 3f -2: addis r6,r6,(-RELACOUNT)@ha - cmpdi r6,RELACOUNT@l + b 4f +2: cmpdi r6,RELASZ bne 3f - ld r8,8(r11) /* get RELACOUNT value in r8 */ -3: addi r11,r11,16 - b 1b -4: cmpdi r7,0 /* check we have both RELA and RELACOUNT */ + ld r8,8(r11) /* get RELASZ value in r8 */ + b 4f +3: cmpdi r6,RELAENT + bne 4f + ld r12,8(r11) /* get RELAENT value in r12 */ +4: addi r11,r11,16 + b .Ltags +.Lend_of_list: + cmpdi r7,0 /* check we have RELA, RELASZ, RELAENT */ cmpdi cr1,r8,0 - beq 6f - beq cr1,6f + beq .Lout + beq cr1,.Lout + cmpdi r12,0 + beq .Lout /* * Work out linktime address of _stext and hence the @@ -62,23 +73,39 @@ /* * Run through the list of relocations and process the - * R_PPC64_RELATIVE ones. + * R_PPC64_RELATIVE and R_PPC64_UADDR64 ones. */ + divd r8,r8,r12 /* RELASZ / RELAENT */ mtctr r8 -5: ld r0,8(9) /* ELF64_R_TYPE(reloc->r_info) */ +.Lrels: ld r0,8(r9) /* ELF64_R_TYPE(reloc->r_info) */ cmpdi r0,R_PPC64_RELATIVE - bne 6f + bne .Luaddr64 ld r6,0(r9) /* reloc->r_offset */ ld r0,16(r9) /* reloc->r_addend */ + b .Lstore +.Luaddr64: + srdi r14,r0,32 /* ELF64_R_SYM(reloc->r_info) */ + clrldi r0,r0,32 + cmpdi r0,R_PPC64_UADDR64 + bne .Lnext + ld r6,0(r9) + ld r0,16(r9) + mulli r14,r14,24 /* 24 == sizeof(elf64_sym) */ + add r14,r14,r13 /* elf64_sym[ELF64_R_SYM] */ + ld r14,8(r14) + add r0,r0,r14 +.Lstore: add r0,r0,r3 stdx r0,r7,r6 - addi r9,r9,24 - bdnz 5b - -6: blr +.Lnext: + add r9,r9,r12 + bdnz .Lrels +.Lout: + blr .balign 8 p_dyn: .8byte __dynamic_start - 0b p_rela: .8byte __rela_dyn_start - 0b +p_sym: .8byte __dynamic_symtab - 0b p_st: .8byte _stext - 0b only in patch2: unchanged: --- linux-5.15.0.orig/arch/powerpc/kernel/vmlinux.lds.S +++ linux-5.15.0/arch/powerpc/kernel/vmlinux.lds.S @@ -275,9 +275,7 @@ . = ALIGN(8); .dynsym : AT(ADDR(.dynsym) - LOAD_OFFSET) { -#ifdef CONFIG_PPC32 __dynamic_symtab = .; -#endif *(.dynsym) } .dynstr : AT(ADDR(.dynstr) - LOAD_OFFSET) { *(.dynstr) } only in patch2: unchanged: --- linux-5.15.0.orig/arch/powerpc/kvm/book3s_64_vio.c +++ linux-5.15.0/arch/powerpc/kvm/book3s_64_vio.c @@ -421,13 +421,19 @@ tbl[idx % TCES_PER_PAGE] = tce; } -static void kvmppc_clear_tce(struct mm_struct *mm, struct iommu_table *tbl, - unsigned long entry) +static void kvmppc_clear_tce(struct mm_struct *mm, struct kvmppc_spapr_tce_table *stt, + struct iommu_table *tbl, unsigned long entry) { - unsigned long hpa = 0; - enum dma_data_direction dir = DMA_NONE; + unsigned long i; + unsigned long subpages = 1ULL << (stt->page_shift - tbl->it_page_shift); + unsigned long io_entry = entry << (stt->page_shift - tbl->it_page_shift); + + for (i = 0; i < subpages; ++i) { + unsigned long hpa = 0; + enum dma_data_direction dir = DMA_NONE; - iommu_tce_xchg_no_kill(mm, tbl, entry, &hpa, &dir); + iommu_tce_xchg_no_kill(mm, tbl, io_entry + i, &hpa, &dir); + } } static long kvmppc_tce_iommu_mapped_dec(struct kvm *kvm, @@ -486,6 +492,8 @@ break; } + iommu_tce_kill(tbl, io_entry, subpages); + return ret; } @@ -545,6 +553,8 @@ break; } + iommu_tce_kill(tbl, io_entry, subpages); + return ret; } @@ -591,10 +601,9 @@ ret = kvmppc_tce_iommu_map(vcpu->kvm, stt, stit->tbl, entry, ua, dir); - iommu_tce_kill(stit->tbl, entry, 1); if (ret != H_SUCCESS) { - kvmppc_clear_tce(vcpu->kvm->mm, stit->tbl, entry); + kvmppc_clear_tce(vcpu->kvm->mm, stt, stit->tbl, entry); goto unlock_exit; } } @@ -670,13 +679,13 @@ */ if (get_user(tce, tces + i)) { ret = H_TOO_HARD; - goto invalidate_exit; + goto unlock_exit; } tce = be64_to_cpu(tce); if (kvmppc_tce_to_ua(vcpu->kvm, tce, &ua)) { ret = H_PARAMETER; - goto invalidate_exit; + goto unlock_exit; } list_for_each_entry_lockless(stit, &stt->iommu_tables, next) { @@ -685,19 +694,15 @@ iommu_tce_direction(tce)); if (ret != H_SUCCESS) { - kvmppc_clear_tce(vcpu->kvm->mm, stit->tbl, - entry); - goto invalidate_exit; + kvmppc_clear_tce(vcpu->kvm->mm, stt, stit->tbl, + entry + i); + goto unlock_exit; } } kvmppc_tce_put(stt, entry + i, tce); } -invalidate_exit: - list_for_each_entry_lockless(stit, &stt->iommu_tables, next) - iommu_tce_kill(stit->tbl, entry, npages); - unlock_exit: srcu_read_unlock(&vcpu->kvm->srcu, idx); @@ -736,20 +741,16 @@ continue; if (ret == H_TOO_HARD) - goto invalidate_exit; + return ret; WARN_ON_ONCE(1); - kvmppc_clear_tce(vcpu->kvm->mm, stit->tbl, entry); + kvmppc_clear_tce(vcpu->kvm->mm, stt, stit->tbl, entry + i); } } for (i = 0; i < npages; ++i, ioba += (1ULL << stt->page_shift)) kvmppc_tce_put(stt, ioba >> stt->page_shift, tce_value); -invalidate_exit: - list_for_each_entry_lockless(stit, &stt->iommu_tables, next) - iommu_tce_kill(stit->tbl, ioba >> stt->page_shift, npages); - return ret; } EXPORT_SYMBOL_GPL(kvmppc_h_stuff_tce); only in patch2: unchanged: --- linux-5.15.0.orig/arch/powerpc/kvm/book3s_64_vio_hv.c +++ linux-5.15.0/arch/powerpc/kvm/book3s_64_vio_hv.c @@ -247,13 +247,19 @@ tbl->it_ops->tce_kill(tbl, entry, pages, true); } -static void kvmppc_rm_clear_tce(struct kvm *kvm, struct iommu_table *tbl, - unsigned long entry) +static void kvmppc_rm_clear_tce(struct kvm *kvm, struct kvmppc_spapr_tce_table *stt, + struct iommu_table *tbl, unsigned long entry) { - unsigned long hpa = 0; - enum dma_data_direction dir = DMA_NONE; + unsigned long i; + unsigned long subpages = 1ULL << (stt->page_shift - tbl->it_page_shift); + unsigned long io_entry = entry << (stt->page_shift - tbl->it_page_shift); + + for (i = 0; i < subpages; ++i) { + unsigned long hpa = 0; + enum dma_data_direction dir = DMA_NONE; - iommu_tce_xchg_no_kill_rm(kvm->mm, tbl, entry, &hpa, &dir); + iommu_tce_xchg_no_kill_rm(kvm->mm, tbl, io_entry + i, &hpa, &dir); + } } static long kvmppc_rm_tce_iommu_mapped_dec(struct kvm *kvm, @@ -316,6 +322,8 @@ break; } + iommu_tce_kill_rm(tbl, io_entry, subpages); + return ret; } @@ -379,6 +387,8 @@ break; } + iommu_tce_kill_rm(tbl, io_entry, subpages); + return ret; } @@ -420,10 +430,8 @@ ret = kvmppc_rm_tce_iommu_map(vcpu->kvm, stt, stit->tbl, entry, ua, dir); - iommu_tce_kill_rm(stit->tbl, entry, 1); - if (ret != H_SUCCESS) { - kvmppc_rm_clear_tce(vcpu->kvm, stit->tbl, entry); + kvmppc_rm_clear_tce(vcpu->kvm, stt, stit->tbl, entry); return ret; } } @@ -561,7 +569,7 @@ ua = 0; if (kvmppc_rm_tce_to_ua(vcpu->kvm, tce, &ua)) { ret = H_PARAMETER; - goto invalidate_exit; + goto unlock_exit; } list_for_each_entry_lockless(stit, &stt->iommu_tables, next) { @@ -570,19 +578,15 @@ iommu_tce_direction(tce)); if (ret != H_SUCCESS) { - kvmppc_rm_clear_tce(vcpu->kvm, stit->tbl, - entry); - goto invalidate_exit; + kvmppc_rm_clear_tce(vcpu->kvm, stt, stit->tbl, + entry + i); + goto unlock_exit; } } kvmppc_rm_tce_put(stt, entry + i, tce); } -invalidate_exit: - list_for_each_entry_lockless(stit, &stt->iommu_tables, next) - iommu_tce_kill_rm(stit->tbl, entry, npages); - unlock_exit: if (!prereg) arch_spin_unlock(&kvm->mmu_lock.rlock.raw_lock); @@ -620,20 +624,16 @@ continue; if (ret == H_TOO_HARD) - goto invalidate_exit; + return ret; WARN_ON_ONCE_RM(1); - kvmppc_rm_clear_tce(vcpu->kvm, stit->tbl, entry); + kvmppc_rm_clear_tce(vcpu->kvm, stt, stit->tbl, entry + i); } } for (i = 0; i < npages; ++i, ioba += (1ULL << stt->page_shift)) kvmppc_rm_tce_put(stt, ioba >> stt->page_shift, tce_value); -invalidate_exit: - list_for_each_entry_lockless(stit, &stt->iommu_tables, next) - iommu_tce_kill_rm(stit->tbl, ioba >> stt->page_shift, npages); - return ret; } only in patch2: unchanged: --- linux-5.15.0.orig/arch/powerpc/perf/Makefile +++ linux-5.15.0/arch/powerpc/perf/Makefile @@ -3,11 +3,11 @@ obj-y += callchain.o callchain_$(BITS).o perf_regs.o obj-$(CONFIG_COMPAT) += callchain_32.o -obj-$(CONFIG_PPC_PERF_CTRS) += core-book3s.o bhrb.o +obj-$(CONFIG_PPC_PERF_CTRS) += core-book3s.o obj64-$(CONFIG_PPC_PERF_CTRS) += ppc970-pmu.o power5-pmu.o \ power5+-pmu.o power6-pmu.o power7-pmu.o \ isa207-common.o power8-pmu.o power9-pmu.o \ - generic-compat-pmu.o power10-pmu.o + generic-compat-pmu.o power10-pmu.o bhrb.o obj32-$(CONFIG_PPC_PERF_CTRS) += mpc7450-pmu.o obj-$(CONFIG_PPC_POWERNV) += imc-pmu.o only in patch2: unchanged: --- linux-5.15.0.orig/arch/powerpc/perf/power9-pmu.c +++ linux-5.15.0/arch/powerpc/perf/power9-pmu.c @@ -133,11 +133,11 @@ /* Table of alternatives, sorted by column 0 */ static const unsigned int power9_event_alternatives[][MAX_ALT] = { - { PM_INST_DISP, PM_INST_DISP_ALT }, - { PM_RUN_CYC_ALT, PM_RUN_CYC }, - { PM_RUN_INST_CMPL_ALT, PM_RUN_INST_CMPL }, - { PM_LD_MISS_L1, PM_LD_MISS_L1_ALT }, { PM_BR_2PATH, PM_BR_2PATH_ALT }, + { PM_INST_DISP, PM_INST_DISP_ALT }, + { PM_RUN_CYC_ALT, PM_RUN_CYC }, + { PM_LD_MISS_L1, PM_LD_MISS_L1_ALT }, + { PM_RUN_INST_CMPL_ALT, PM_RUN_INST_CMPL }, }; static int power9_get_alternatives(u64 event, unsigned int flags, u64 alt[]) only in patch2: unchanged: --- linux-5.15.0.orig/arch/powerpc/tools/relocs_check.sh +++ linux-5.15.0/arch/powerpc/tools/relocs_check.sh @@ -39,6 +39,7 @@ # R_PPC_NONE grep -F -w -v 'R_PPC64_RELATIVE R_PPC64_NONE +R_PPC64_UADDR64 R_PPC_ADDR16_LO R_PPC_ADDR16_HI R_PPC_ADDR16_HA @@ -54,9 +55,3 @@ num_bad=$(echo "$bad_relocs" | wc -l) echo "WARNING: $num_bad bad relocations" echo "$bad_relocs" - -# If we see this type of relocation it's an idication that -# we /may/ be using an old version of binutils. -if echo "$bad_relocs" | grep -q -F -w R_PPC64_UADDR64; then - echo "WARNING: You need at least binutils >= 2.19 to build a CONFIG_RELOCATABLE kernel" -fi only in patch2: unchanged: --- linux-5.15.0.orig/arch/riscv/kernel/patch.c +++ linux-5.15.0/arch/riscv/kernel/patch.c @@ -104,7 +104,7 @@ struct patch_insn *patch = data; int ret = 0; - if (atomic_inc_return(&patch->cpu_count) == 1) { + if (atomic_inc_return(&patch->cpu_count) == num_online_cpus()) { ret = patch_text_nosync(patch->addr, &patch->insn, GET_INSN_LENGTH(patch->insn)); only in patch2: unchanged: --- linux-5.15.0.orig/arch/x86/include/asm/compat.h +++ linux-5.15.0/arch/x86/include/asm/compat.h @@ -28,15 +28,13 @@ typedef __kernel_fsid_t compat_fsid_t; struct compat_stat { - compat_dev_t st_dev; - u16 __pad1; + u32 st_dev; compat_ino_t st_ino; compat_mode_t st_mode; compat_nlink_t st_nlink; __compat_uid_t st_uid; __compat_gid_t st_gid; - compat_dev_t st_rdev; - u16 __pad2; + u32 st_rdev; u32 st_size; u32 st_blksize; u32 st_blocks; only in patch2: unchanged: --- linux-5.15.0.orig/arch/x86/include/asm/microcode.h +++ linux-5.15.0/arch/x86/include/asm/microcode.h @@ -132,10 +132,12 @@ void reload_early_microcode(void); extern bool get_builtin_firmware(struct cpio_data *cd, const char *name); extern bool initrd_gone; +void microcode_bsp_resume(void); #else static inline void __init load_ucode_bsp(void) { } static inline void load_ucode_ap(void) { } static inline void reload_early_microcode(void) { } +static inline void microcode_bsp_resume(void) { } static inline bool get_builtin_firmware(struct cpio_data *cd, const char *name) { return false; } #endif only in patch2: unchanged: --- linux-5.15.0.orig/arch/x86/kernel/cpu/microcode/core.c +++ linux-5.15.0/arch/x86/kernel/cpu/microcode/core.c @@ -775,9 +775,9 @@ }; /** - * mc_bp_resume - Update boot CPU microcode during resume. + * microcode_bsp_resume - Update boot CPU microcode during resume. */ -static void mc_bp_resume(void) +void microcode_bsp_resume(void) { int cpu = smp_processor_id(); struct ucode_cpu_info *uci = ucode_cpu_info + cpu; @@ -789,7 +789,7 @@ } static struct syscore_ops mc_syscore_ops = { - .resume = mc_bp_resume, + .resume = microcode_bsp_resume, }; static int mc_cpu_starting(unsigned int cpu) only in patch2: unchanged: --- linux-5.15.0.orig/arch/x86/lib/usercopy_64.c +++ linux-5.15.0/arch/x86/lib/usercopy_64.c @@ -121,7 +121,7 @@ /* cache copy and flush to align dest */ if (!IS_ALIGNED(dest, 8)) { - unsigned len = min_t(unsigned, size, ALIGN(dest, 8) - dest); + size_t len = min_t(size_t, size, ALIGN(dest, 8) - dest); memcpy((void *) dest, (void *) source, len); clean_cache_range((void *) dest, len); only in patch2: unchanged: --- linux-5.15.0.orig/arch/x86/pci/xen.c +++ linux-5.15.0/arch/x86/pci/xen.c @@ -472,7 +472,6 @@ xen_msi_ops.setup_msi_irqs = xen_setup_msi_irqs; } xen_msi_ops.teardown_msi_irqs = xen_pv_teardown_msi_irqs; - pci_msi_ignore_mask = 1; } else if (xen_hvm_domain()) { xen_msi_ops.setup_msi_irqs = xen_hvm_setup_msi_irqs; xen_msi_ops.teardown_msi_irqs = xen_teardown_msi_irqs; @@ -486,6 +485,11 @@ * in allocating the native domain and never use it. */ x86_init.irqs.create_pci_msi_domain = xen_create_pci_msi_domain; + /* + * With XEN PIRQ/Eventchannels in use PCI/MSI[-X] masking is solely + * controlled by the hypervisor. + */ + pci_msi_ignore_mask = 1; } #else /* CONFIG_PCI_MSI */ only in patch2: unchanged: --- linux-5.15.0.orig/arch/xtensa/kernel/coprocessor.S +++ linux-5.15.0/arch/xtensa/kernel/coprocessor.S @@ -29,7 +29,7 @@ .if XTENSA_HAVE_COPROCESSOR(x); \ .align 4; \ .Lsave_cp_regs_cp##x: \ - xchal_cp##x##_store a2 a4 a5 a6 a7; \ + xchal_cp##x##_store a2 a3 a4 a5 a6; \ jx a0; \ .endif @@ -46,7 +46,7 @@ .if XTENSA_HAVE_COPROCESSOR(x); \ .align 4; \ .Lload_cp_regs_cp##x: \ - xchal_cp##x##_load a2 a4 a5 a6 a7; \ + xchal_cp##x##_load a2 a3 a4 a5 a6; \ jx a0; \ .endif only in patch2: unchanged: --- linux-5.15.0.orig/arch/xtensa/platforms/iss/console.c +++ linux-5.15.0/arch/xtensa/platforms/iss/console.c @@ -36,24 +36,19 @@ static struct tty_driver *serial_driver; static struct tty_port serial_port; static DEFINE_TIMER(serial_timer, rs_poll); -static DEFINE_SPINLOCK(timer_lock); static int rs_open(struct tty_struct *tty, struct file * filp) { - spin_lock_bh(&timer_lock); if (tty->count == 1) mod_timer(&serial_timer, jiffies + SERIAL_TIMER_VALUE); - spin_unlock_bh(&timer_lock); return 0; } static void rs_close(struct tty_struct *tty, struct file * filp) { - spin_lock_bh(&timer_lock); if (tty->count == 1) del_timer_sync(&serial_timer); - spin_unlock_bh(&timer_lock); } @@ -73,8 +68,6 @@ int rd = 1; unsigned char c; - spin_lock(&timer_lock); - while (simc_poll(0)) { rd = simc_read(0, &c, 1); if (rd <= 0) @@ -87,7 +80,6 @@ tty_flip_buffer_push(port); if (rd) mod_timer(&serial_timer, jiffies + SERIAL_TIMER_VALUE); - spin_unlock(&timer_lock); } only in patch2: unchanged: --- linux-5.15.0.orig/block/bdev.c +++ linux-5.15.0/block/bdev.c @@ -1016,7 +1016,7 @@ } EXPORT_SYMBOL(__invalidate_device); -void iterate_bdevs(void (*func)(struct block_device *, void *), void *arg) +void sync_bdevs(bool wait) { struct inode *inode, *old_inode = NULL; @@ -1047,8 +1047,19 @@ bdev = I_BDEV(inode); mutex_lock(&bdev->bd_disk->open_mutex); - if (bdev->bd_openers) - func(bdev, arg); + if (!bdev->bd_openers) { + ; /* skip */ + } else if (wait) { + /* + * We keep the error status of individual mapping so + * that applications can catch the writeback error using + * fsync(2). See filemap_fdatawait_keep_errors() for + * details. + */ + filemap_fdatawait_keep_errors(inode->i_mapping); + } else { + filemap_fdatawrite(inode->i_mapping); + } mutex_unlock(&bdev->bd_disk->open_mutex); spin_lock(&blockdev_superblock->s_inode_list_lock); only in patch2: unchanged: --- linux-5.15.0.orig/drivers/ata/pata_marvell.c +++ linux-5.15.0/drivers/ata/pata_marvell.c @@ -83,6 +83,8 @@ switch(ap->port_no) { case 0: + if (!ap->ioaddr.bmdma_addr) + return ATA_CBL_PATA_UNK; if (ioread8(ap->ioaddr.bmdma_addr + 1) & 1) return ATA_CBL_PATA40; return ATA_CBL_PATA80; only in patch2: unchanged: --- linux-5.15.0.orig/drivers/base/arch_topology.c +++ linux-5.15.0/drivers/base/arch_topology.c @@ -609,7 +609,7 @@ for_each_online_cpu(cpu) { cpu_topo = &cpu_topology[cpu]; - if (cpuid_topo->llc_id == cpu_topo->llc_id) { + if (cpu_topo->llc_id != -1 && cpuid_topo->llc_id == cpu_topo->llc_id) { cpumask_set_cpu(cpu, &cpuid_topo->llc_sibling); cpumask_set_cpu(cpuid, &cpu_topo->llc_sibling); } only in patch2: unchanged: --- linux-5.15.0.orig/drivers/block/Kconfig +++ linux-5.15.0/drivers/block/Kconfig @@ -33,6 +33,22 @@ To compile this driver as a module, choose M here: the module will be called floppy. +config BLK_DEV_FD_RAWCMD + bool "Support for raw floppy disk commands (DEPRECATED)" + depends on BLK_DEV_FD + help + If you want to use actual physical floppies and expect to do + special low-level hardware accesses to them (access and use + non-standard formats, for example), then enable this. + + Note that the code enabled by this option is rarely used and + might be unstable or insecure, and distros should not enable it. + + Note: FDRAWCMD is deprecated and will be removed from the kernel + in the near future. + + If unsure, say N. + config AMIGA_FLOPPY tristate "Amiga floppy support" depends on AMIGA only in patch2: unchanged: --- linux-5.15.0.orig/drivers/clk/sunxi/clk-sun9i-mmc.c +++ linux-5.15.0/drivers/clk/sunxi/clk-sun9i-mmc.c @@ -109,6 +109,8 @@ spin_lock_init(&data->lock); r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) + return -EINVAL; /* one clock/reset pair per word */ count = DIV_ROUND_UP((resource_size(r)), SUN9I_MMC_WIDTH); data->membase = devm_ioremap_resource(&pdev->dev, r); only in patch2: unchanged: --- linux-5.15.0.orig/drivers/cpufreq/sun50i-cpufreq-nvmem.c +++ linux-5.15.0/drivers/cpufreq/sun50i-cpufreq-nvmem.c @@ -98,8 +98,10 @@ return -ENOMEM; ret = sun50i_cpufreq_get_efuse(&speed); - if (ret) + if (ret) { + kfree(opp_tables); return ret; + } snprintf(name, MAX_NAME_LEN, "speed%d", speed); only in patch2: unchanged: --- linux-5.15.0.orig/drivers/dma/dw-edma/dw-edma-v0-core.c +++ linux-5.15.0/drivers/dma/dw-edma/dw-edma-v0-core.c @@ -415,8 +415,11 @@ (DW_EDMA_V0_CCS | DW_EDMA_V0_LLE)); /* Linked list */ #ifdef CONFIG_64BIT - SET_CH_64(dw, chan->dir, chan->id, llp.reg, - chunk->ll_region.paddr); + /* llp is not aligned on 64bit -> keep 32bit accesses */ + SET_CH_32(dw, chan->dir, chan->id, llp.lsb, + lower_32_bits(chunk->ll_region.paddr)); + SET_CH_32(dw, chan->dir, chan->id, llp.msb, + upper_32_bits(chunk->ll_region.paddr)); #else /* CONFIG_64BIT */ SET_CH_32(dw, chan->dir, chan->id, llp.lsb, lower_32_bits(chunk->ll_region.paddr)); only in patch2: unchanged: --- linux-5.15.0.orig/drivers/dma/imx-sdma.c +++ linux-5.15.0/drivers/dma/imx-sdma.c @@ -198,12 +198,12 @@ s32 per_2_firi_addr; s32 mcu_2_firi_addr; s32 uart_2_per_addr; - s32 uart_2_mcu_ram_addr; + s32 uart_2_mcu_addr; s32 per_2_app_addr; s32 mcu_2_app_addr; s32 per_2_per_addr; s32 uartsh_2_per_addr; - s32 uartsh_2_mcu_ram_addr; + s32 uartsh_2_mcu_addr; s32 per_2_shp_addr; s32 mcu_2_shp_addr; s32 ata_2_mcu_addr; @@ -232,8 +232,8 @@ s32 mcu_2_ecspi_addr; s32 mcu_2_sai_addr; s32 sai_2_mcu_addr; - s32 uart_2_mcu_addr; - s32 uartsh_2_mcu_addr; + s32 uart_2_mcu_rom_addr; + s32 uartsh_2_mcu_rom_addr; /* End of v3 array */ s32 mcu_2_zqspi_addr; /* End of v4 array */ @@ -1780,17 +1780,17 @@ saddr_arr[i] = addr_arr[i]; /* - * get uart_2_mcu_addr/uartsh_2_mcu_addr rom script specially because - * they are now replaced by uart_2_mcu_ram_addr/uartsh_2_mcu_ram_addr - * to be compatible with legacy freescale/nxp sdma firmware, and they - * are located in the bottom part of sdma_script_start_addrs which are - * beyond the SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1. + * For compatibility with NXP internal legacy kernel before 4.19 which + * is based on uart ram script and mainline kernel based on uart rom + * script, both uart ram/rom scripts are present in newer sdma + * firmware. Use the rom versions if they are present (V3 or newer). */ - if (addr->uart_2_mcu_addr) - sdma->script_addrs->uart_2_mcu_addr = addr->uart_2_mcu_addr; - if (addr->uartsh_2_mcu_addr) - sdma->script_addrs->uartsh_2_mcu_addr = addr->uartsh_2_mcu_addr; - + if (sdma->script_number >= SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V3) { + if (addr->uart_2_mcu_rom_addr) + sdma->script_addrs->uart_2_mcu_addr = addr->uart_2_mcu_rom_addr; + if (addr->uartsh_2_mcu_rom_addr) + sdma->script_addrs->uartsh_2_mcu_addr = addr->uartsh_2_mcu_rom_addr; + } } static void sdma_load_firmware(const struct firmware *fw, void *context) @@ -1869,7 +1869,7 @@ u32 reg, val, shift, num_map, i; int ret = 0; - if (IS_ERR(np) || IS_ERR(gpr_np)) + if (IS_ERR(np) || !gpr_np) goto out; event_remap = of_find_property(np, propname, NULL); @@ -1917,7 +1917,7 @@ } out: - if (!IS_ERR(gpr_np)) + if (gpr_np) of_node_put(gpr_np); return ret; only in patch2: unchanged: --- linux-5.15.0.orig/drivers/dma/mediatek/mtk-uart-apdma.c +++ linux-5.15.0/drivers/dma/mediatek/mtk-uart-apdma.c @@ -274,7 +274,7 @@ unsigned int status; int ret; - ret = pm_runtime_get_sync(mtkd->ddev.dev); + ret = pm_runtime_resume_and_get(mtkd->ddev.dev); if (ret < 0) { pm_runtime_put_noidle(chan->device->dev); return ret; @@ -288,18 +288,21 @@ ret = readx_poll_timeout(readl, c->base + VFF_EN, status, !status, 10, 100); if (ret) - return ret; + goto err_pm; ret = request_irq(c->irq, mtk_uart_apdma_irq_handler, IRQF_TRIGGER_NONE, KBUILD_MODNAME, chan); if (ret < 0) { dev_err(chan->device->dev, "Can't request dma IRQ\n"); - return -EINVAL; + ret = -EINVAL; + goto err_pm; } if (mtkd->support_33bits) mtk_uart_apdma_write(c, VFF_4G_SUPPORT, VFF_4G_SUPPORT_CLR_B); +err_pm: + pm_runtime_put_noidle(mtkd->ddev.dev); return ret; } only in patch2: unchanged: --- linux-5.15.0.orig/drivers/firewire/core-card.c +++ linux-5.15.0/drivers/firewire/core-card.c @@ -668,6 +668,7 @@ void fw_core_remove_card(struct fw_card *card) { struct fw_card_driver dummy_driver = dummy_driver_template; + unsigned long flags; card->driver->update_phy_reg(card, 4, PHY_LINK_ACTIVE | PHY_CONTENDER, 0); @@ -682,7 +683,9 @@ dummy_driver.stop_iso = card->driver->stop_iso; card->driver = &dummy_driver; + spin_lock_irqsave(&card->lock, flags); fw_destroy_nodes(card); + spin_unlock_irqrestore(&card->lock, flags); /* Wait for all users, especially device workqueue jobs, to finish. */ fw_card_put(card); only in patch2: unchanged: --- linux-5.15.0.orig/drivers/firewire/core-cdev.c +++ linux-5.15.0/drivers/firewire/core-cdev.c @@ -1480,6 +1480,7 @@ { struct outbound_phy_packet_event *e = container_of(packet, struct outbound_phy_packet_event, p); + struct client *e_client; switch (status) { /* expected: */ @@ -1496,9 +1497,10 @@ } e->phy_packet.data[0] = packet->timestamp; + e_client = e->client; queue_event(e->client, &e->event, &e->phy_packet, sizeof(e->phy_packet) + e->phy_packet.length, NULL, 0); - client_put(e->client); + client_put(e_client); } static int ioctl_send_phy_packet(struct client *client, union ioctl_arg *arg) only in patch2: unchanged: --- linux-5.15.0.orig/drivers/firewire/core-topology.c +++ linux-5.15.0/drivers/firewire/core-topology.c @@ -375,16 +375,13 @@ card->bm_retries = 0; } +/* Must be called with card->lock held */ void fw_destroy_nodes(struct fw_card *card) { - unsigned long flags; - - spin_lock_irqsave(&card->lock, flags); card->color++; if (card->local_node != NULL) for_each_fw_node(card, card->local_node, report_lost_node); card->local_node = NULL; - spin_unlock_irqrestore(&card->lock, flags); } static void move_tree(struct fw_node *node0, struct fw_node *node1, int port) @@ -510,6 +507,8 @@ struct fw_node *local_node; unsigned long flags; + spin_lock_irqsave(&card->lock, flags); + /* * If the selfID buffer is not the immediate successor of the * previously processed one, we cannot reliably compare the @@ -521,8 +520,6 @@ card->bm_retries = 0; } - spin_lock_irqsave(&card->lock, flags); - card->broadcast_channel_allocated = card->broadcast_channel_auto_allocated; card->node_id = node_id; /* only in patch2: unchanged: --- linux-5.15.0.orig/drivers/firewire/core-transaction.c +++ linux-5.15.0/drivers/firewire/core-transaction.c @@ -73,24 +73,25 @@ static int close_transaction(struct fw_transaction *transaction, struct fw_card *card, int rcode) { - struct fw_transaction *t; + struct fw_transaction *t = NULL, *iter; unsigned long flags; spin_lock_irqsave(&card->lock, flags); - list_for_each_entry(t, &card->transaction_list, link) { - if (t == transaction) { - if (!try_cancel_split_timeout(t)) { + list_for_each_entry(iter, &card->transaction_list, link) { + if (iter == transaction) { + if (!try_cancel_split_timeout(iter)) { spin_unlock_irqrestore(&card->lock, flags); goto timed_out; } - list_del_init(&t->link); - card->tlabel_mask &= ~(1ULL << t->tlabel); + list_del_init(&iter->link); + card->tlabel_mask &= ~(1ULL << iter->tlabel); + t = iter; break; } } spin_unlock_irqrestore(&card->lock, flags); - if (&t->link != &card->transaction_list) { + if (t) { t->callback(card, rcode, NULL, 0, t->callback_data); return 0; } @@ -935,7 +936,7 @@ void fw_core_handle_response(struct fw_card *card, struct fw_packet *p) { - struct fw_transaction *t; + struct fw_transaction *t = NULL, *iter; unsigned long flags; u32 *data; size_t data_length; @@ -947,20 +948,21 @@ rcode = HEADER_GET_RCODE(p->header[1]); spin_lock_irqsave(&card->lock, flags); - list_for_each_entry(t, &card->transaction_list, link) { - if (t->node_id == source && t->tlabel == tlabel) { - if (!try_cancel_split_timeout(t)) { + list_for_each_entry(iter, &card->transaction_list, link) { + if (iter->node_id == source && iter->tlabel == tlabel) { + if (!try_cancel_split_timeout(iter)) { spin_unlock_irqrestore(&card->lock, flags); goto timed_out; } - list_del_init(&t->link); - card->tlabel_mask &= ~(1ULL << t->tlabel); + list_del_init(&iter->link); + card->tlabel_mask &= ~(1ULL << iter->tlabel); + t = iter; break; } } spin_unlock_irqrestore(&card->lock, flags); - if (&t->link == &card->transaction_list) { + if (!t) { timed_out: fw_notice(card, "unsolicited response (source %x, tlabel %x)\n", source, tlabel); only in patch2: unchanged: --- linux-5.15.0.orig/drivers/firewire/sbp2.c +++ linux-5.15.0/drivers/firewire/sbp2.c @@ -408,7 +408,7 @@ void *payload, size_t length, void *callback_data) { struct sbp2_logical_unit *lu = callback_data; - struct sbp2_orb *orb; + struct sbp2_orb *orb = NULL, *iter; struct sbp2_status status; unsigned long flags; @@ -433,17 +433,18 @@ /* Lookup the orb corresponding to this status write. */ spin_lock_irqsave(&lu->tgt->lock, flags); - list_for_each_entry(orb, &lu->orb_list, link) { + list_for_each_entry(iter, &lu->orb_list, link) { if (STATUS_GET_ORB_HIGH(status) == 0 && - STATUS_GET_ORB_LOW(status) == orb->request_bus) { - orb->rcode = RCODE_COMPLETE; - list_del(&orb->link); + STATUS_GET_ORB_LOW(status) == iter->request_bus) { + iter->rcode = RCODE_COMPLETE; + list_del(&iter->link); + orb = iter; break; } } spin_unlock_irqrestore(&lu->tgt->lock, flags); - if (&orb->link != &lu->orb_list) { + if (orb) { orb->callback(orb, &status); kref_put(&orb->kref, free_orb); /* orb callback reference */ } else { only in patch2: unchanged: --- linux-5.15.0.orig/drivers/gpio/gpio-mvebu.c +++ linux-5.15.0/drivers/gpio/gpio-mvebu.c @@ -871,13 +871,6 @@ mvpwm->chip.dev = dev; mvpwm->chip.ops = &mvebu_pwm_ops; mvpwm->chip.npwm = mvchip->chip.ngpio; - /* - * There may already be some PWM allocated, so we can't force - * mvpwm->chip.base to a fixed point like mvchip->chip.base. - * So, we let pwmchip_add() do the numbering and take the next free - * region. - */ - mvpwm->chip.base = -1; spin_lock_init(&mvpwm->lock); only in patch2: unchanged: --- linux-5.15.0.orig/drivers/gpio/gpio-pca953x.c +++ linux-5.15.0/drivers/gpio/gpio-pca953x.c @@ -762,11 +762,11 @@ bitmap_xor(cur_stat, new_stat, old_stat, gc->ngpio); bitmap_and(trigger, cur_stat, chip->irq_mask, gc->ngpio); + bitmap_copy(chip->irq_stat, new_stat, gc->ngpio); + if (bitmap_empty(trigger, gc->ngpio)) return false; - bitmap_copy(chip->irq_stat, new_stat, gc->ngpio); - bitmap_and(cur_stat, chip->irq_trig_fall, old_stat, gc->ngpio); bitmap_and(old_stat, chip->irq_trig_raise, new_stat, gc->ngpio); bitmap_or(new_stat, old_stat, cur_stat, gc->ngpio); only in patch2: unchanged: --- linux-5.15.0.orig/drivers/gpio/gpio-visconti.c +++ linux-5.15.0/drivers/gpio/gpio-visconti.c @@ -130,7 +130,6 @@ struct gpio_irq_chip *girq; struct irq_domain *parent; struct device_node *irq_parent; - struct fwnode_handle *fwnode; int ret; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); @@ -150,14 +149,12 @@ } parent = irq_find_host(irq_parent); + of_node_put(irq_parent); if (!parent) { dev_err(dev, "No IRQ parent domain\n"); return -ENODEV; } - fwnode = of_node_to_fwnode(irq_parent); - of_node_put(irq_parent); - ret = bgpio_init(&priv->gpio_chip, dev, 4, priv->base + GPIO_IDATA, priv->base + GPIO_OSET, @@ -180,7 +177,7 @@ girq = &priv->gpio_chip.irq; girq->chip = irq_chip; - girq->fwnode = fwnode; + girq->fwnode = of_node_to_fwnode(dev->of_node); girq->parent_domain = parent; girq->child_to_parent_hwirq = visconti_gpio_child_to_parent_hwirq; girq->populate_parent_alloc_arg = visconti_gpio_populate_parent_fwspec; only in patch2: unchanged: --- linux-5.15.0.orig/drivers/gpio/gpiolib-of.c +++ linux-5.15.0/drivers/gpio/gpiolib-of.c @@ -912,7 +912,7 @@ i, &start); of_property_read_u32_index(np, "gpio-reserved-ranges", i + 1, &count); - if (start >= chip->ngpio || start + count >= chip->ngpio) + if (start >= chip->ngpio || start + count > chip->ngpio) continue; bitmap_clear(chip->valid_mask, start, count); only in patch2: unchanged: --- linux-5.15.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ linux-5.15.0/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c @@ -24,6 +24,7 @@ #include #include +#include #include "amdgpu.h" #include "amdgpu_ras.h" @@ -694,7 +695,8 @@ adev->virt.caps |= AMDGPU_SRIOV_CAPS_ENABLE_IOV; if (!reg) { - if (is_virtual_machine()) /* passthrough mode exclus sriov mod */ + /* passthrough mode exclus sriov mod */ + if (is_virtual_machine() && !xen_initial_domain()) adev->virt.caps |= AMDGPU_PASSTHROUGH_MODE; } only in patch2: unchanged: --- linux-5.15.0.orig/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c +++ linux-5.15.0/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c @@ -1428,6 +1428,7 @@ return &clk_src->base; } + kfree(clk_src); BREAK_TO_DEBUGGER(); return NULL; } only in patch2: unchanged: --- linux-5.15.0.orig/drivers/gpu/drm/armada/armada_gem.c +++ linux-5.15.0/drivers/gpu/drm/armada/armada_gem.c @@ -336,7 +336,7 @@ struct drm_armada_gem_pwrite *args = data; struct armada_gem_object *dobj; char __user *ptr; - int ret; + int ret = 0; DRM_DEBUG_DRIVER("handle %u off %u size %u ptr 0x%llx\n", args->handle, args->offset, args->size, args->ptr); @@ -349,9 +349,8 @@ if (!access_ok(ptr, args->size)) return -EFAULT; - ret = fault_in_pages_readable(ptr, args->size); - if (ret) - return ret; + if (fault_in_readable(ptr, args->size)) + return -EFAULT; dobj = armada_gem_object_lookup(file, args->handle); if (dobj == NULL) only in patch2: unchanged: --- linux-5.15.0.orig/drivers/gpu/drm/i915/display/intel_psr.c +++ linux-5.15.0/drivers/gpu/drm/i915/display/intel_psr.c @@ -936,6 +936,20 @@ return false; } + /* Wa_16011303918:adl-p */ + if (crtc_state->vrr.enable && + IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0)) { + drm_dbg_kms(&dev_priv->drm, + "PSR2 not enabled, not compatible with HW stepping + VRR\n"); + return false; + } + + if (!_compute_psr2_sdp_prior_scanline_indication(intel_dp, crtc_state)) { + drm_dbg_kms(&dev_priv->drm, + "PSR2 not enabled, PSR2 SDP indication do not fit in hblank\n"); + return false; + } + if (HAS_PSR2_SEL_FETCH(dev_priv)) { if (!intel_psr2_sel_fetch_config_valid(intel_dp, crtc_state) && !HAS_PSR_HW_TRACKING(dev_priv)) { @@ -949,12 +963,12 @@ if (!crtc_state->enable_psr2_sel_fetch && IS_TGL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_C0)) { drm_dbg_kms(&dev_priv->drm, "PSR2 HW tracking is not supported this Display stepping\n"); - return false; + goto unsupported; } if (!psr2_granularity_check(intel_dp, crtc_state)) { drm_dbg_kms(&dev_priv->drm, "PSR2 not enabled, SU granularity not compatible\n"); - return false; + goto unsupported; } if (!crtc_state->enable_psr2_sel_fetch && @@ -963,25 +977,15 @@ "PSR2 not enabled, resolution %dx%d > max supported %dx%d\n", crtc_hdisplay, crtc_vdisplay, psr_max_h, psr_max_v); - return false; - } - - if (!_compute_psr2_sdp_prior_scanline_indication(intel_dp, crtc_state)) { - drm_dbg_kms(&dev_priv->drm, - "PSR2 not enabled, PSR2 SDP indication do not fit in hblank\n"); - return false; - } - - /* Wa_16011303918:adl-p */ - if (crtc_state->vrr.enable && - IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0)) { - drm_dbg_kms(&dev_priv->drm, - "PSR2 not enabled, not compatible with HW stepping + VRR\n"); - return false; + goto unsupported; } tgl_dc3co_exitline_compute_config(intel_dp, crtc_state); return true; + +unsupported: + crtc_state->enable_psr2_sel_fetch = false; + return false; } void intel_psr_compute_config(struct intel_dp *intel_dp, only in patch2: unchanged: --- linux-5.15.0.orig/drivers/gpu/drm/i915/display/intel_vbt_defs.h +++ linux-5.15.0/drivers/gpu/drm/i915/display/intel_vbt_defs.h @@ -307,6 +307,9 @@ #define HDMI_MAX_DATA_RATE_PLATFORM 0 /* 204 */ #define HDMI_MAX_DATA_RATE_297 1 /* 204 */ #define HDMI_MAX_DATA_RATE_165 2 /* 204 */ +#define HDMI_MAX_DATA_RATE_594 3 /* 249 */ +#define HDMI_MAX_DATA_RATE_340 4 /* 249 */ +#define HDMI_MAX_DATA_RATE_300 5 /* 249 */ #define LEGACY_CHILD_DEVICE_CONFIG_SIZE 33 only in patch2: unchanged: --- linux-5.15.0.orig/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c +++ linux-5.15.0/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c @@ -90,7 +90,10 @@ __drm_atomic_helper_plane_destroy_state(plane->state); kfree(to_mdp5_plane_state(plane->state)); + plane->state = NULL; mdp5_state = kzalloc(sizeof(*mdp5_state), GFP_KERNEL); + if (!mdp5_state) + return; if (plane->type == DRM_PLANE_TYPE_PRIMARY) mdp5_state->base.zpos = STAGE_BASE; only in patch2: unchanged: --- linux-5.15.0.orig/drivers/gpu/drm/msm/disp/msm_disp_snapshot_util.c +++ linux-5.15.0/drivers/gpu/drm/msm/disp/msm_disp_snapshot_util.c @@ -169,6 +169,8 @@ va_list va; new_blk = kzalloc(sizeof(struct msm_disp_state_block), GFP_KERNEL); + if (!new_blk) + return; va_start(va, fmt); only in patch2: unchanged: --- linux-5.15.0.orig/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c +++ linux-5.15.0/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c @@ -229,7 +229,7 @@ ret = i2c_smbus_write_byte_data(ts->i2c, reg, val); if (ret) - dev_err(&ts->dsi->dev, "I2C write failed: %d\n", ret); + dev_err(&ts->i2c->dev, "I2C write failed: %d\n", ret); } static int rpi_touchscreen_write(struct rpi_touchscreen *ts, u16 reg, u32 val) @@ -265,7 +265,7 @@ return 0; } -static int rpi_touchscreen_enable(struct drm_panel *panel) +static int rpi_touchscreen_prepare(struct drm_panel *panel) { struct rpi_touchscreen *ts = panel_to_ts(panel); int i; @@ -295,6 +295,13 @@ rpi_touchscreen_write(ts, DSI_STARTDSI, 0x01); msleep(100); + return 0; +} + +static int rpi_touchscreen_enable(struct drm_panel *panel) +{ + struct rpi_touchscreen *ts = panel_to_ts(panel); + /* Turn on the backlight. */ rpi_touchscreen_i2c_write(ts, REG_PWM, 255); @@ -349,7 +356,7 @@ static const struct drm_panel_funcs rpi_touchscreen_funcs = { .disable = rpi_touchscreen_disable, .unprepare = rpi_touchscreen_noop, - .prepare = rpi_touchscreen_noop, + .prepare = rpi_touchscreen_prepare, .enable = rpi_touchscreen_enable, .get_modes = rpi_touchscreen_get_modes, }; only in patch2: unchanged: --- linux-5.15.0.orig/drivers/gpu/drm/sun4i/sun4i_frontend.c +++ linux-5.15.0/drivers/gpu/drm/sun4i/sun4i_frontend.c @@ -222,13 +222,11 @@ /* Set the physical address of the buffer in memory */ paddr = drm_fb_cma_get_gem_addr(fb, state, 0); - paddr -= PHYS_OFFSET; DRM_DEBUG_DRIVER("Setting buffer #0 address to %pad\n", &paddr); regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR0_REG, paddr); if (fb->format->num_planes > 1) { paddr = drm_fb_cma_get_gem_addr(fb, state, swap ? 2 : 1); - paddr -= PHYS_OFFSET; DRM_DEBUG_DRIVER("Setting buffer #1 address to %pad\n", &paddr); regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR1_REG, paddr); @@ -236,7 +234,6 @@ if (fb->format->num_planes > 2) { paddr = drm_fb_cma_get_gem_addr(fb, state, swap ? 1 : 2); - paddr -= PHYS_OFFSET; DRM_DEBUG_DRIVER("Setting buffer #2 address to %pad\n", &paddr); regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR2_REG, paddr); only in patch2: unchanged: --- linux-5.15.0.orig/drivers/iio/dac/ad5592r-base.c +++ linux-5.15.0/drivers/iio/dac/ad5592r-base.c @@ -523,7 +523,7 @@ if (!ret) st->channel_modes[reg] = tmp; - fwnode_property_read_u32(child, "adi,off-state", &tmp); + ret = fwnode_property_read_u32(child, "adi,off-state", &tmp); if (!ret) st->channel_offstate[reg] = tmp; } only in patch2: unchanged: --- linux-5.15.0.orig/drivers/iio/imu/bmi160/bmi160_core.c +++ linux-5.15.0/drivers/iio/imu/bmi160/bmi160_core.c @@ -730,7 +730,7 @@ ret = regmap_write(data->regmap, BMI160_REG_CMD, BMI160_CMD_SOFTRESET); if (ret) - return ret; + goto disable_regulator; usleep_range(BMI160_SOFTRESET_USLEEP, BMI160_SOFTRESET_USLEEP + 1); @@ -741,29 +741,37 @@ if (use_spi) { ret = regmap_read(data->regmap, BMI160_REG_DUMMY, &val); if (ret) - return ret; + goto disable_regulator; } ret = regmap_read(data->regmap, BMI160_REG_CHIP_ID, &val); if (ret) { dev_err(dev, "Error reading chip id\n"); - return ret; + goto disable_regulator; } if (val != BMI160_CHIP_ID_VAL) { dev_err(dev, "Wrong chip id, got %x expected %x\n", val, BMI160_CHIP_ID_VAL); - return -ENODEV; + ret = -ENODEV; + goto disable_regulator; } ret = bmi160_set_mode(data, BMI160_ACCEL, true); if (ret) - return ret; + goto disable_regulator; ret = bmi160_set_mode(data, BMI160_GYRO, true); if (ret) - return ret; + goto disable_accel; return 0; + +disable_accel: + bmi160_set_mode(data, BMI160_ACCEL, false); + +disable_regulator: + regulator_bulk_disable(ARRAY_SIZE(data->supplies), data->supplies); + return ret; } static int bmi160_data_rdy_trigger_set_state(struct iio_trigger *trig, only in patch2: unchanged: --- linux-5.15.0.orig/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c +++ linux-5.15.0/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c @@ -18,12 +18,15 @@ unsigned int mask, val; int ret; - /* setup interface registers */ - ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG6, - INV_ICM42600_INTF_CONFIG6_MASK, - INV_ICM42600_INTF_CONFIG6_I3C_EN); - if (ret) - return ret; + /* + * setup interface registers + * This register write to REG_INTF_CONFIG6 enables a spike filter that + * is impacting the line and can prevent the I2C ACK to be seen by the + * controller. So we don't test the return value. + */ + regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG6, + INV_ICM42600_INTF_CONFIG6_MASK, + INV_ICM42600_INTF_CONFIG6_I3C_EN); ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG4, INV_ICM42600_INTF_CONFIG4_I3C_BUS_ONLY, 0); only in patch2: unchanged: --- linux-5.15.0.orig/drivers/iio/magnetometer/ak8975.c +++ linux-5.15.0/drivers/iio/magnetometer/ak8975.c @@ -389,6 +389,7 @@ if (ret) { dev_warn(&data->client->dev, "Failed to enable specified Vid supply\n"); + regulator_disable(data->vdd); return ret; } only in patch2: unchanged: --- linux-5.15.0.orig/drivers/infiniband/hw/irdma/cm.c +++ linux-5.15.0/drivers/infiniband/hw/irdma/cm.c @@ -2305,10 +2305,8 @@ return NULL; } -static void irdma_cm_node_free_cb(struct rcu_head *rcu_head) +static void irdma_destroy_connection(struct irdma_cm_node *cm_node) { - struct irdma_cm_node *cm_node = - container_of(rcu_head, struct irdma_cm_node, rcu_head); struct irdma_cm_core *cm_core = cm_node->cm_core; struct irdma_qp *iwqp; struct irdma_cm_info nfo; @@ -2356,7 +2354,6 @@ } cm_core->cm_free_ah(cm_node); - kfree(cm_node); } /** @@ -2384,8 +2381,9 @@ spin_unlock_irqrestore(&cm_core->ht_lock, flags); - /* wait for all list walkers to exit their grace period */ - call_rcu(&cm_node->rcu_head, irdma_cm_node_free_cb); + irdma_destroy_connection(cm_node); + + kfree_rcu(cm_node, rcu_head); } /** @@ -3465,12 +3463,6 @@ } cm_id = iwqp->cm_id; - /* make sure we havent already closed this connection */ - if (!cm_id) { - spin_unlock_irqrestore(&iwqp->lock, flags); - return; - } - original_hw_tcp_state = iwqp->hw_tcp_state; original_ibqp_state = iwqp->ibqp_state; last_ae = iwqp->last_aeq; @@ -3492,11 +3484,11 @@ disconn_status = -ECONNRESET; } - if ((original_hw_tcp_state == IRDMA_TCP_STATE_CLOSED || - original_hw_tcp_state == IRDMA_TCP_STATE_TIME_WAIT || - last_ae == IRDMA_AE_RDMAP_ROE_BAD_LLP_CLOSE || - last_ae == IRDMA_AE_BAD_CLOSE || - last_ae == IRDMA_AE_LLP_CONNECTION_RESET || iwdev->rf->reset)) { + if (original_hw_tcp_state == IRDMA_TCP_STATE_CLOSED || + original_hw_tcp_state == IRDMA_TCP_STATE_TIME_WAIT || + last_ae == IRDMA_AE_RDMAP_ROE_BAD_LLP_CLOSE || + last_ae == IRDMA_AE_BAD_CLOSE || + last_ae == IRDMA_AE_LLP_CONNECTION_RESET || iwdev->rf->reset || !cm_id) { issue_close = 1; iwqp->cm_id = NULL; qp->term_flags = 0; only in patch2: unchanged: --- linux-5.15.0.orig/drivers/infiniband/sw/siw/siw_cm.c +++ linux-5.15.0/drivers/infiniband/sw/siw/siw_cm.c @@ -968,14 +968,15 @@ siw_cep_set_inuse(new_cep); rv = siw_proc_mpareq(new_cep); - siw_cep_set_free(new_cep); - if (rv != -EAGAIN) { siw_cep_put(cep); new_cep->listen_cep = NULL; - if (rv) + if (rv) { + siw_cep_set_free(new_cep); goto error; + } } + siw_cep_set_free(new_cep); } return; only in patch2: unchanged: --- linux-5.15.0.orig/drivers/input/keyboard/omap4-keypad.c +++ linux-5.15.0/drivers/input/keyboard/omap4-keypad.c @@ -393,7 +393,7 @@ * revision register. */ error = pm_runtime_get_sync(dev); - if (error) { + if (error < 0) { dev_err(dev, "pm_runtime_get_sync() failed\n"); pm_runtime_put_noidle(dev); return error; only in patch2: unchanged: --- linux-5.15.0.orig/drivers/interconnect/qcom/sdx55.c +++ linux-5.15.0/drivers/interconnect/qcom/sdx55.c @@ -18,7 +18,6 @@ #include "icc-rpmh.h" #include "sdx55.h" -DEFINE_QNODE(ipa_core_master, SDX55_MASTER_IPA_CORE, 1, 8, SDX55_SLAVE_IPA_CORE); DEFINE_QNODE(llcc_mc, SDX55_MASTER_LLCC, 4, 4, SDX55_SLAVE_EBI_CH0); DEFINE_QNODE(acm_tcu, SDX55_MASTER_TCU_0, 1, 8, SDX55_SLAVE_LLCC, SDX55_SLAVE_MEM_NOC_SNOC, SDX55_SLAVE_MEM_NOC_PCIE_SNOC); DEFINE_QNODE(qnm_snoc_gc, SDX55_MASTER_SNOC_GC_MEM_NOC, 1, 8, SDX55_SLAVE_LLCC); @@ -40,7 +39,6 @@ DEFINE_QNODE(xm_qdss_etr, SDX55_MASTER_QDSS_ETR, 1, 8, SDX55_SLAVE_SNOC_CFG, SDX55_SLAVE_EMAC_CFG, SDX55_SLAVE_USB3, SDX55_SLAVE_AOSS, SDX55_SLAVE_SPMI_FETCHER, SDX55_SLAVE_QDSS_CFG, SDX55_SLAVE_PDM, SDX55_SLAVE_SNOC_MEM_NOC_GC, SDX55_SLAVE_TCSR, SDX55_SLAVE_CNOC_DDRSS, SDX55_SLAVE_SPMI_VGI_COEX, SDX55_SLAVE_QPIC, SDX55_SLAVE_OCIMEM, SDX55_SLAVE_IPA_CFG, SDX55_SLAVE_USB3_PHY_CFG, SDX55_SLAVE_AOP, SDX55_SLAVE_BLSP_1, SDX55_SLAVE_SDCC_1, SDX55_SLAVE_CNOC_MSS, SDX55_SLAVE_PCIE_PARF, SDX55_SLAVE_ECC_CFG, SDX55_SLAVE_AUDIO, SDX55_SLAVE_AOSS, SDX55_SLAVE_PRNG, SDX55_SLAVE_CRYPTO_0_CFG, SDX55_SLAVE_TCU, SDX55_SLAVE_CLK_CTL, SDX55_SLAVE_IMEM_CFG); DEFINE_QNODE(xm_sdc1, SDX55_MASTER_SDCC_1, 1, 8, SDX55_SLAVE_AOSS, SDX55_SLAVE_IPA_CFG, SDX55_SLAVE_ANOC_SNOC, SDX55_SLAVE_AOP, SDX55_SLAVE_AUDIO); DEFINE_QNODE(xm_usb3, SDX55_MASTER_USB3, 1, 8, SDX55_SLAVE_ANOC_SNOC); -DEFINE_QNODE(ipa_core_slave, SDX55_SLAVE_IPA_CORE, 1, 8); DEFINE_QNODE(ebi, SDX55_SLAVE_EBI_CH0, 1, 4); DEFINE_QNODE(qns_llcc, SDX55_SLAVE_LLCC, 1, 16, SDX55_SLAVE_EBI_CH0); DEFINE_QNODE(qns_memnoc_snoc, SDX55_SLAVE_MEM_NOC_SNOC, 1, 8, SDX55_MASTER_MEM_NOC_SNOC); @@ -82,7 +80,6 @@ DEFINE_QBCM(bcm_mc0, "MC0", true, &ebi); DEFINE_QBCM(bcm_sh0, "SH0", true, &qns_llcc); DEFINE_QBCM(bcm_ce0, "CE0", false, &qxm_crypto); -DEFINE_QBCM(bcm_ip0, "IP0", false, &ipa_core_slave); DEFINE_QBCM(bcm_pn0, "PN0", false, &qhm_snoc_cfg); DEFINE_QBCM(bcm_sh3, "SH3", false, &xm_apps_rdwr); DEFINE_QBCM(bcm_sh4, "SH4", false, &qns_memnoc_snoc, &qns_sys_pcie); @@ -219,22 +216,6 @@ .num_bcms = ARRAY_SIZE(system_noc_bcms), }; -static struct qcom_icc_bcm *ipa_virt_bcms[] = { - &bcm_ip0, -}; - -static struct qcom_icc_node *ipa_virt_nodes[] = { - [MASTER_IPA_CORE] = &ipa_core_master, - [SLAVE_IPA_CORE] = &ipa_core_slave, -}; - -static const struct qcom_icc_desc sdx55_ipa_virt = { - .nodes = ipa_virt_nodes, - .num_nodes = ARRAY_SIZE(ipa_virt_nodes), - .bcms = ipa_virt_bcms, - .num_bcms = ARRAY_SIZE(ipa_virt_bcms), -}; - static const struct of_device_id qnoc_of_match[] = { { .compatible = "qcom,sdx55-mc-virt", .data = &sdx55_mc_virt}, @@ -242,8 +223,6 @@ .data = &sdx55_mem_noc}, { .compatible = "qcom,sdx55-system-noc", .data = &sdx55_system_noc}, - { .compatible = "qcom,sdx55-ipa-virt", - .data = &sdx55_ipa_virt}, { } }; MODULE_DEVICE_TABLE(of, qnoc_of_match); only in patch2: unchanged: --- linux-5.15.0.orig/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c +++ linux-5.15.0/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c @@ -183,7 +183,14 @@ { struct arm_smmu_mmu_notifier *smmu_mn = mn_to_smmu(mn); struct arm_smmu_domain *smmu_domain = smmu_mn->domain; - size_t size = end - start + 1; + size_t size; + + /* + * The mm_types defines vm_end as the first byte after the end address, + * different from IOMMU subsystem using the last address of an address + * range. So do a simple translation here by calculating size correctly. + */ + size = end - start; if (!(smmu_domain->smmu->features & ARM_SMMU_FEAT_BTM)) arm_smmu_tlb_inv_range_asid(start, size, smmu_mn->cd->asid, only in patch2: unchanged: --- linux-5.15.0.orig/drivers/iommu/intel/svm.c +++ linux-5.15.0/drivers/iommu/intel/svm.c @@ -978,6 +978,10 @@ goto bad_req; } + /* Drop Stop Marker message. No need for a response. */ + if (unlikely(req->lpig && !req->rd_req && !req->wr_req)) + goto prq_advance; + if (!svm || svm->pasid != req->pasid) { /* * It can't go away, because the driver is not permitted only in patch2: unchanged: --- linux-5.15.0.orig/drivers/misc/vmw_vmci/Kconfig +++ linux-5.15.0/drivers/misc/vmw_vmci/Kconfig @@ -5,7 +5,7 @@ config VMWARE_VMCI tristate "VMware VMCI Driver" - depends on X86 && PCI + depends on (X86 || ARM64) && !CPU_BIG_ENDIAN && PCI help This is VMware's Virtual Machine Communication Interface. It enables high-speed communication between host and guest in a virtual only in patch2: unchanged: --- linux-5.15.0.orig/drivers/misc/vmw_vmci/vmci_guest.c +++ linux-5.15.0/drivers/misc/vmw_vmci/vmci_guest.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -31,6 +32,12 @@ #define VMCI_UTIL_NUM_RESOURCES 1 +/* + * Datagram buffers for DMA send/receive must accommodate at least + * a maximum sized datagram and the header. + */ +#define VMCI_DMA_DG_BUFFER_SIZE (VMCI_MAX_DG_SIZE + PAGE_SIZE) + static bool vmci_disable_msi; module_param_named(disable_msi, vmci_disable_msi, bool, 0); MODULE_PARM_DESC(disable_msi, "Disable MSI use in driver - (default=0)"); @@ -45,13 +52,18 @@ struct vmci_guest_device { struct device *dev; /* PCI device we are attached to */ void __iomem *iobase; + void __iomem *mmio_base; bool exclusive_vectors; struct tasklet_struct datagram_tasklet; struct tasklet_struct bm_tasklet; + struct wait_queue_head inout_wq; void *data_buffer; + dma_addr_t data_buffer_base; + void *tx_buffer; + dma_addr_t tx_buffer_base; void *notification_bitmap; dma_addr_t notification_base; }; @@ -89,6 +101,92 @@ return vm_context_id; } +static unsigned int vmci_read_reg(struct vmci_guest_device *dev, u32 reg) +{ + if (dev->mmio_base != NULL) + return readl(dev->mmio_base + reg); + return ioread32(dev->iobase + reg); +} + +static void vmci_write_reg(struct vmci_guest_device *dev, u32 val, u32 reg) +{ + if (dev->mmio_base != NULL) + writel(val, dev->mmio_base + reg); + else + iowrite32(val, dev->iobase + reg); +} + +static void vmci_read_data(struct vmci_guest_device *vmci_dev, + void *dest, size_t size) +{ + if (vmci_dev->mmio_base == NULL) + ioread8_rep(vmci_dev->iobase + VMCI_DATA_IN_ADDR, + dest, size); + else { + /* + * For DMA datagrams, the data_buffer will contain the header on the + * first page, followed by the incoming datagram(s) on the following + * pages. The header uses an S/G element immediately following the + * header on the first page to point to the data area. + */ + struct vmci_data_in_out_header *buffer_header = vmci_dev->data_buffer; + struct vmci_sg_elem *sg_array = (struct vmci_sg_elem *)(buffer_header + 1); + size_t buffer_offset = dest - vmci_dev->data_buffer; + + buffer_header->opcode = 1; + buffer_header->size = 1; + buffer_header->busy = 0; + sg_array[0].addr = vmci_dev->data_buffer_base + buffer_offset; + sg_array[0].size = size; + + vmci_write_reg(vmci_dev, lower_32_bits(vmci_dev->data_buffer_base), + VMCI_DATA_IN_LOW_ADDR); + + wait_event(vmci_dev->inout_wq, buffer_header->busy == 1); + } +} + +static int vmci_write_data(struct vmci_guest_device *dev, + struct vmci_datagram *dg) +{ + int result; + + if (dev->mmio_base != NULL) { + struct vmci_data_in_out_header *buffer_header = dev->tx_buffer; + u8 *dg_out_buffer = (u8 *)(buffer_header + 1); + + if (VMCI_DG_SIZE(dg) > VMCI_MAX_DG_SIZE) + return VMCI_ERROR_INVALID_ARGS; + + /* + * Initialize send buffer with outgoing datagram + * and set up header for inline data. Device will + * not access buffer asynchronously - only after + * the write to VMCI_DATA_OUT_LOW_ADDR. + */ + memcpy(dg_out_buffer, dg, VMCI_DG_SIZE(dg)); + buffer_header->opcode = 0; + buffer_header->size = VMCI_DG_SIZE(dg); + buffer_header->busy = 1; + + vmci_write_reg(dev, lower_32_bits(dev->tx_buffer_base), + VMCI_DATA_OUT_LOW_ADDR); + + /* Caller holds a spinlock, so cannot block. */ + spin_until_cond(buffer_header->busy == 0); + + result = vmci_read_reg(vmci_dev_g, VMCI_RESULT_LOW_ADDR); + if (result == VMCI_SUCCESS) + result = (int)buffer_header->result; + } else { + iowrite8_rep(dev->iobase + VMCI_DATA_OUT_ADDR, + dg, VMCI_DG_SIZE(dg)); + result = vmci_read_reg(vmci_dev_g, VMCI_RESULT_LOW_ADDR); + } + + return result; +} + /* * VM to hypervisor call mechanism. We use the standard VMware naming * convention since shared code is calling this function as well. @@ -114,9 +212,8 @@ spin_lock_irqsave(&vmci_dev_spinlock, flags); if (vmci_dev_g) { - iowrite8_rep(vmci_dev_g->iobase + VMCI_DATA_OUT_ADDR, - dg, VMCI_DG_SIZE(dg)); - result = ioread32(vmci_dev_g->iobase + VMCI_RESULT_LOW_ADDR); + vmci_write_data(vmci_dev_g, dg); + result = vmci_read_reg(vmci_dev_g, VMCI_RESULT_LOW_ADDR); } else { result = VMCI_ERROR_UNAVAILABLE; } @@ -195,15 +292,17 @@ } /* - * Reads datagrams from the data in port and dispatches them. We - * always start reading datagrams into only the first page of the - * datagram buffer. If the datagrams don't fit into one page, we - * use the maximum datagram buffer size for the remainder of the - * invocation. This is a simple heuristic for not penalizing - * small datagrams. + * Reads datagrams from the device and dispatches them. For IO port + * based access to the device, we always start reading datagrams into + * only the first page of the datagram buffer. If the datagrams don't + * fit into one page, we use the maximum datagram buffer size for the + * remainder of the invocation. This is a simple heuristic for not + * penalizing small datagrams. For DMA-based datagrams, we always + * use the maximum datagram buffer size, since there is no performance + * penalty for doing so. * * This function assumes that it has exclusive access to the data - * in port for the duration of the call. + * in register(s) for the duration of the call. */ static void vmci_dispatch_dgs(unsigned long data) { @@ -211,23 +310,41 @@ u8 *dg_in_buffer = vmci_dev->data_buffer; struct vmci_datagram *dg; size_t dg_in_buffer_size = VMCI_MAX_DG_SIZE; - size_t current_dg_in_buffer_size = PAGE_SIZE; + size_t current_dg_in_buffer_size; size_t remaining_bytes; + bool is_io_port = vmci_dev->mmio_base == NULL; BUILD_BUG_ON(VMCI_MAX_DG_SIZE < PAGE_SIZE); - ioread8_rep(vmci_dev->iobase + VMCI_DATA_IN_ADDR, - vmci_dev->data_buffer, current_dg_in_buffer_size); + if (!is_io_port) { + /* For mmio, the first page is used for the header. */ + dg_in_buffer += PAGE_SIZE; + + /* + * For DMA-based datagram operations, there is no performance + * penalty for reading the maximum buffer size. + */ + current_dg_in_buffer_size = VMCI_MAX_DG_SIZE; + } else { + current_dg_in_buffer_size = PAGE_SIZE; + } + vmci_read_data(vmci_dev, dg_in_buffer, current_dg_in_buffer_size); dg = (struct vmci_datagram *)dg_in_buffer; remaining_bytes = current_dg_in_buffer_size; + /* + * Read through the buffer until an invalid datagram header is + * encountered. The exit condition for datagrams read through + * VMCI_DATA_IN_ADDR is a bit more complicated, since a datagram + * can start on any page boundary in the buffer. + */ while (dg->dst.resource != VMCI_INVALID_ID || - remaining_bytes > PAGE_SIZE) { + (is_io_port && remaining_bytes > PAGE_SIZE)) { unsigned dg_in_size; /* - * When the input buffer spans multiple pages, a datagram can - * start on any page boundary in the buffer. + * If using VMCI_DATA_IN_ADDR, skip to the next page + * as a datagram can start on any page boundary. */ if (dg->dst.resource == VMCI_INVALID_ID) { dg = (struct vmci_datagram *)roundup( @@ -277,11 +394,10 @@ current_dg_in_buffer_size = dg_in_buffer_size; - ioread8_rep(vmci_dev->iobase + - VMCI_DATA_IN_ADDR, - vmci_dev->data_buffer + + vmci_read_data(vmci_dev, + dg_in_buffer + remaining_bytes, - current_dg_in_buffer_size - + current_dg_in_buffer_size - remaining_bytes); } @@ -319,10 +435,8 @@ current_dg_in_buffer_size = dg_in_buffer_size; for (;;) { - ioread8_rep(vmci_dev->iobase + - VMCI_DATA_IN_ADDR, - vmci_dev->data_buffer, - current_dg_in_buffer_size); + vmci_read_data(vmci_dev, dg_in_buffer, + current_dg_in_buffer_size); if (bytes_to_skip <= current_dg_in_buffer_size) break; @@ -339,8 +453,7 @@ if (remaining_bytes < VMCI_DG_HEADERSIZE) { /* Get the next batch of datagrams. */ - ioread8_rep(vmci_dev->iobase + VMCI_DATA_IN_ADDR, - vmci_dev->data_buffer, + vmci_read_data(vmci_dev, dg_in_buffer, current_dg_in_buffer_size); dg = (struct vmci_datagram *)dg_in_buffer; remaining_bytes = current_dg_in_buffer_size; @@ -384,7 +497,7 @@ unsigned int icr; /* Acknowledge interrupt and determine what needs doing. */ - icr = ioread32(dev->iobase + VMCI_ICR_ADDR); + icr = vmci_read_reg(dev, VMCI_ICR_ADDR); if (icr == 0 || icr == ~0) return IRQ_NONE; @@ -398,6 +511,12 @@ icr &= ~VMCI_ICR_NOTIFICATION; } + + if (icr & VMCI_ICR_DMA_DATAGRAM) { + wake_up_all(&dev->inout_wq); + icr &= ~VMCI_ICR_DMA_DATAGRAM; + } + if (icr != 0) dev_warn(dev->dev, "Ignoring unknown interrupt cause (%d)\n", @@ -423,13 +542,47 @@ } /* + * Interrupt handler for MSI-X interrupt vector VMCI_INTR_DMA_DATAGRAM, + * which is for the completion of a DMA datagram send or receive operation. + * Will only get called if we are using MSI-X with exclusive vectors. + */ +static irqreturn_t vmci_interrupt_dma_datagram(int irq, void *_dev) +{ + struct vmci_guest_device *dev = _dev; + + wake_up_all(&dev->inout_wq); + + return IRQ_HANDLED; +} + +static void vmci_free_dg_buffers(struct vmci_guest_device *vmci_dev) +{ + if (vmci_dev->mmio_base != NULL) { + if (vmci_dev->tx_buffer != NULL) + dma_free_coherent(vmci_dev->dev, + VMCI_DMA_DG_BUFFER_SIZE, + vmci_dev->tx_buffer, + vmci_dev->tx_buffer_base); + if (vmci_dev->data_buffer != NULL) + dma_free_coherent(vmci_dev->dev, + VMCI_DMA_DG_BUFFER_SIZE, + vmci_dev->data_buffer, + vmci_dev->data_buffer_base); + } else { + vfree(vmci_dev->data_buffer); + } +} + +/* * Most of the initialization at module load time is done here. */ static int vmci_guest_probe_device(struct pci_dev *pdev, const struct pci_device_id *id) { struct vmci_guest_device *vmci_dev; - void __iomem *iobase; + void __iomem *iobase = NULL; + void __iomem *mmio_base = NULL; + unsigned int num_irq_vectors; unsigned int capabilities; unsigned int caps_in_use; unsigned long cmd; @@ -445,17 +598,34 @@ return error; } - error = pcim_iomap_regions(pdev, 1 << 0, KBUILD_MODNAME); - if (error) { - dev_err(&pdev->dev, "Failed to reserve/map IO regions\n"); - return error; + /* + * The VMCI device with mmio access to registers requests 256KB + * for BAR1. If present, driver will use new VMCI device + * functionality for register access and datagram send/recv. + */ + + if (pci_resource_len(pdev, 1) == VMCI_WITH_MMIO_ACCESS_BAR_SIZE) { + dev_info(&pdev->dev, "MMIO register access is available\n"); + mmio_base = pci_iomap_range(pdev, 1, VMCI_MMIO_ACCESS_OFFSET, + VMCI_MMIO_ACCESS_SIZE); + /* If the map fails, we fall back to IOIO access. */ + if (!mmio_base) + dev_warn(&pdev->dev, "Failed to map MMIO register access\n"); + } + + if (!mmio_base) { + if (IS_ENABLED(CONFIG_ARM64)) { + dev_err(&pdev->dev, "MMIO base is invalid\n"); + return -ENXIO; + } + error = pcim_iomap_regions(pdev, BIT(0), KBUILD_MODNAME); + if (error) { + dev_err(&pdev->dev, "Failed to reserve/map IO regions\n"); + return error; + } + iobase = pcim_iomap_table(pdev)[0]; } - iobase = pcim_iomap_table(pdev)[0]; - - dev_info(&pdev->dev, "Found VMCI PCI device at %#lx, irq %u\n", - (unsigned long)iobase, pdev->irq); - vmci_dev = devm_kzalloc(&pdev->dev, sizeof(*vmci_dev), GFP_KERNEL); if (!vmci_dev) { dev_err(&pdev->dev, @@ -466,17 +636,35 @@ vmci_dev->dev = &pdev->dev; vmci_dev->exclusive_vectors = false; vmci_dev->iobase = iobase; + vmci_dev->mmio_base = mmio_base; tasklet_init(&vmci_dev->datagram_tasklet, vmci_dispatch_dgs, (unsigned long)vmci_dev); tasklet_init(&vmci_dev->bm_tasklet, vmci_process_bitmap, (unsigned long)vmci_dev); + init_waitqueue_head(&vmci_dev->inout_wq); + + if (mmio_base != NULL) { + vmci_dev->tx_buffer = dma_alloc_coherent(&pdev->dev, VMCI_DMA_DG_BUFFER_SIZE, + &vmci_dev->tx_buffer_base, + GFP_KERNEL); + if (!vmci_dev->tx_buffer) { + dev_err(&pdev->dev, + "Can't allocate memory for datagram tx buffer\n"); + return -ENOMEM; + } - vmci_dev->data_buffer = vmalloc(VMCI_MAX_DG_SIZE); + vmci_dev->data_buffer = dma_alloc_coherent(&pdev->dev, VMCI_DMA_DG_BUFFER_SIZE, + &vmci_dev->data_buffer_base, + GFP_KERNEL); + } else { + vmci_dev->data_buffer = vmalloc(VMCI_MAX_DG_SIZE); + } if (!vmci_dev->data_buffer) { dev_err(&pdev->dev, "Can't allocate memory for datagram buffer\n"); - return -ENOMEM; + error = -ENOMEM; + goto err_free_data_buffers; } pci_set_master(pdev); /* To enable queue_pair functionality. */ @@ -490,11 +678,11 @@ * * Right now, we need datagrams. There are no fallbacks. */ - capabilities = ioread32(vmci_dev->iobase + VMCI_CAPS_ADDR); + capabilities = vmci_read_reg(vmci_dev, VMCI_CAPS_ADDR); if (!(capabilities & VMCI_CAPS_DATAGRAM)) { dev_err(&pdev->dev, "Device does not support datagrams\n"); error = -ENXIO; - goto err_free_data_buffer; + goto err_free_data_buffers; } caps_in_use = VMCI_CAPS_DATAGRAM; @@ -531,10 +719,32 @@ } } + if (mmio_base != NULL) { + if (capabilities & VMCI_CAPS_DMA_DATAGRAM) { + caps_in_use |= VMCI_CAPS_DMA_DATAGRAM; + } else { + dev_err(&pdev->dev, + "Missing capability: VMCI_CAPS_DMA_DATAGRAM\n"); + error = -ENXIO; + goto err_free_notification_bitmap; + } + } + dev_info(&pdev->dev, "Using capabilities 0x%x\n", caps_in_use); /* Let the host know which capabilities we intend to use. */ - iowrite32(caps_in_use, vmci_dev->iobase + VMCI_CAPS_ADDR); + vmci_write_reg(vmci_dev, caps_in_use, VMCI_CAPS_ADDR); + + if (caps_in_use & VMCI_CAPS_DMA_DATAGRAM) { + /* Let the device know the size for pages passed down. */ + vmci_write_reg(vmci_dev, PAGE_SHIFT, VMCI_GUEST_PAGE_SHIFT); + + /* Configure the high order parts of the data in/out buffers. */ + vmci_write_reg(vmci_dev, upper_32_bits(vmci_dev->data_buffer_base), + VMCI_DATA_IN_HIGH_ADDR); + vmci_write_reg(vmci_dev, upper_32_bits(vmci_dev->tx_buffer_base), + VMCI_DATA_OUT_HIGH_ADDR); + } /* Set up global device so that we can start sending datagrams */ spin_lock_irq(&vmci_dev_spinlock); @@ -561,7 +771,7 @@ /* Check host capabilities. */ error = vmci_check_host_caps(pdev); if (error) - goto err_remove_bitmap; + goto err_remove_vmci_dev_g; /* Enable device. */ @@ -581,13 +791,17 @@ * Enable interrupts. Try MSI-X first, then MSI, and then fallback on * legacy interrupts. */ - error = pci_alloc_irq_vectors(pdev, VMCI_MAX_INTRS, VMCI_MAX_INTRS, - PCI_IRQ_MSIX); + if (vmci_dev->mmio_base != NULL) + num_irq_vectors = VMCI_MAX_INTRS; + else + num_irq_vectors = VMCI_MAX_INTRS_NOTIFICATION; + error = pci_alloc_irq_vectors(pdev, num_irq_vectors, num_irq_vectors, + PCI_IRQ_MSIX); if (error < 0) { error = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSIX | PCI_IRQ_MSI | PCI_IRQ_LEGACY); if (error < 0) - goto err_remove_bitmap; + goto err_unsubscribe_event; } else { vmci_dev->exclusive_vectors = true; } @@ -620,6 +834,17 @@ pci_irq_vector(pdev, 1), error); goto err_free_irq; } + if (caps_in_use & VMCI_CAPS_DMA_DATAGRAM) { + error = request_irq(pci_irq_vector(pdev, 2), + vmci_interrupt_dma_datagram, + 0, KBUILD_MODNAME, vmci_dev); + if (error) { + dev_err(&pdev->dev, + "Failed to allocate irq %u: %d\n", + pci_irq_vector(pdev, 2), error); + goto err_free_bm_irq; + } + } } dev_dbg(&pdev->dev, "Registered device\n"); @@ -630,17 +855,22 @@ cmd = VMCI_IMR_DATAGRAM; if (caps_in_use & VMCI_CAPS_NOTIFICATIONS) cmd |= VMCI_IMR_NOTIFICATION; - iowrite32(cmd, vmci_dev->iobase + VMCI_IMR_ADDR); + if (caps_in_use & VMCI_CAPS_DMA_DATAGRAM) + cmd |= VMCI_IMR_DMA_DATAGRAM; + vmci_write_reg(vmci_dev, cmd, VMCI_IMR_ADDR); /* Enable interrupts. */ - iowrite32(VMCI_CONTROL_INT_ENABLE, - vmci_dev->iobase + VMCI_CONTROL_ADDR); + vmci_write_reg(vmci_dev, VMCI_CONTROL_INT_ENABLE, VMCI_CONTROL_ADDR); pci_set_drvdata(pdev, vmci_dev); vmci_call_vsock_callback(false); return 0; +err_free_bm_irq: + if (vmci_dev->exclusive_vectors) + free_irq(pci_irq_vector(pdev, 1), vmci_dev); + err_free_irq: free_irq(pci_irq_vector(pdev, 0), vmci_dev); tasklet_kill(&vmci_dev->datagram_tasklet); @@ -649,29 +879,29 @@ err_disable_msi: pci_free_irq_vectors(pdev); +err_unsubscribe_event: vmci_err = vmci_event_unsubscribe(ctx_update_sub_id); if (vmci_err < VMCI_SUCCESS) dev_warn(&pdev->dev, "Failed to unsubscribe from event (type=%d) with subscriber (ID=0x%x): %d\n", VMCI_EVENT_CTX_ID_UPDATE, ctx_update_sub_id, vmci_err); -err_remove_bitmap: - if (vmci_dev->notification_bitmap) { - iowrite32(VMCI_CONTROL_RESET, - vmci_dev->iobase + VMCI_CONTROL_ADDR); - dma_free_coherent(&pdev->dev, PAGE_SIZE, - vmci_dev->notification_bitmap, - vmci_dev->notification_base); - } - err_remove_vmci_dev_g: spin_lock_irq(&vmci_dev_spinlock); vmci_pdev = NULL; vmci_dev_g = NULL; spin_unlock_irq(&vmci_dev_spinlock); -err_free_data_buffer: - vfree(vmci_dev->data_buffer); +err_free_notification_bitmap: + if (vmci_dev->notification_bitmap) { + vmci_write_reg(vmci_dev, VMCI_CONTROL_RESET, VMCI_CONTROL_ADDR); + dma_free_coherent(&pdev->dev, PAGE_SIZE, + vmci_dev->notification_bitmap, + vmci_dev->notification_base); + } + +err_free_data_buffers: + vmci_free_dg_buffers(vmci_dev); /* The rest are managed resources and will be freed by PCI core */ return error; @@ -700,15 +930,18 @@ spin_unlock_irq(&vmci_dev_spinlock); dev_dbg(&pdev->dev, "Resetting vmci device\n"); - iowrite32(VMCI_CONTROL_RESET, vmci_dev->iobase + VMCI_CONTROL_ADDR); + vmci_write_reg(vmci_dev, VMCI_CONTROL_RESET, VMCI_CONTROL_ADDR); /* * Free IRQ and then disable MSI/MSI-X as appropriate. For * MSI-X, we might have multiple vectors, each with their own * IRQ, which we must free too. */ - if (vmci_dev->exclusive_vectors) + if (vmci_dev->exclusive_vectors) { free_irq(pci_irq_vector(pdev, 1), vmci_dev); + if (vmci_dev->mmio_base != NULL) + free_irq(pci_irq_vector(pdev, 2), vmci_dev); + } free_irq(pci_irq_vector(pdev, 0), vmci_dev); pci_free_irq_vectors(pdev); @@ -726,7 +959,10 @@ vmci_dev->notification_base); } - vfree(vmci_dev->data_buffer); + vmci_free_dg_buffers(vmci_dev); + + if (vmci_dev->mmio_base != NULL) + pci_iounmap(pdev, vmci_dev->mmio_base); /* The rest are managed resources and will be freed by PCI core */ } only in patch2: unchanged: --- linux-5.15.0.orig/drivers/misc/vmw_vmci/vmci_queue_pair.c +++ linux-5.15.0/drivers/misc/vmw_vmci/vmci_queue_pair.c @@ -2577,6 +2577,12 @@ if (result < VMCI_SUCCESS) return result; + /* + * This virt_wmb() ensures that data written to the queue + * is observable before the new producer_tail is. + */ + virt_wmb(); + vmci_q_header_add_producer_tail(produce_q->q_header, written, produce_q_size); return written; @@ -2620,6 +2626,12 @@ if (buf_ready < VMCI_SUCCESS) return (ssize_t) buf_ready; + /* + * This virt_rmb() ensures that data from the queue will be read + * after we have determined how much is ready to be consumed. + */ + virt_rmb(); + read = (size_t) (buf_ready > buf_size ? buf_size : buf_ready); head = vmci_q_header_consumer_head(produce_q->q_header); if (likely(head + read < consume_q_size)) { only in patch2: unchanged: --- linux-5.15.0.orig/drivers/mmc/core/mmc.c +++ linux-5.15.0/drivers/mmc/core/mmc.c @@ -1381,13 +1381,17 @@ goto out_err; } + /* + * Bump to HS timing and frequency. Some cards don't handle + * SEND_STATUS reliably at the initial frequency. + */ mmc_set_timing(host, MMC_TIMING_MMC_HS); + mmc_set_bus_speed(card); + err = mmc_switch_status(card, true); if (err) goto out_err; - mmc_set_clock(host, card->ext_csd.hs_max_dtr); - /* Switch card to DDR with strobe bit */ val = EXT_CSD_DDR_BUS_WIDTH_8 | EXT_CSD_BUS_WIDTH_STROBE; err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, @@ -1445,7 +1449,7 @@ static int mmc_select_hs200(struct mmc_card *card) { struct mmc_host *host = card->host; - unsigned int old_timing, old_signal_voltage; + unsigned int old_timing, old_signal_voltage, old_clock; int err = -EINVAL; u8 val; @@ -1476,8 +1480,17 @@ false, true, MMC_CMD_RETRIES); if (err) goto err; + + /* + * Bump to HS timing and frequency. Some cards don't handle + * SEND_STATUS reliably at the initial frequency. + * NB: We can't move to full (HS200) speeds until after we've + * successfully switched over. + */ old_timing = host->ios.timing; + old_clock = host->ios.clock; mmc_set_timing(host, MMC_TIMING_MMC_HS200); + mmc_set_clock(card->host, card->ext_csd.hs_max_dtr); /* * For HS200, CRC errors are not a reliable way to know the @@ -1490,8 +1503,10 @@ * mmc_select_timing() assumes timing has not changed if * it is a switch error. */ - if (err == -EBADMSG) + if (err == -EBADMSG) { + mmc_set_clock(host, old_clock); mmc_set_timing(host, old_timing); + } } err: if (err) { only in patch2: unchanged: --- linux-5.15.0.orig/drivers/mmc/host/sdhci-msm.c +++ linux-5.15.0/drivers/mmc/host/sdhci-msm.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "sdhci-pltfm.h" #include "cqhci.h" @@ -2482,6 +2483,43 @@ of_property_read_u32(node, "qcom,dll-config", &msm_host->dll_config); } +static int sdhci_msm_gcc_reset(struct device *dev, struct sdhci_host *host) +{ + struct reset_control *reset; + int ret = 0; + + reset = reset_control_get_optional_exclusive(dev, NULL); + if (IS_ERR(reset)) + return dev_err_probe(dev, PTR_ERR(reset), + "unable to acquire core_reset\n"); + + if (!reset) + return ret; + + ret = reset_control_assert(reset); + if (ret) { + reset_control_put(reset); + return dev_err_probe(dev, ret, "core_reset assert failed\n"); + } + + /* + * The hardware requirement for delay between assert/deassert + * is at least 3-4 sleep clock (32.7KHz) cycles, which comes to + * ~125us (4/32768). To be on the safe side add 200us delay. + */ + usleep_range(200, 210); + + ret = reset_control_deassert(reset); + if (ret) { + reset_control_put(reset); + return dev_err_probe(dev, ret, "core_reset deassert failed\n"); + } + + usleep_range(200, 210); + reset_control_put(reset); + + return ret; +} static int sdhci_msm_probe(struct platform_device *pdev) { @@ -2529,6 +2567,10 @@ msm_host->saved_tuning_phase = INVALID_TUNING_PHASE; + ret = sdhci_msm_gcc_reset(&pdev->dev, host); + if (ret) + goto pltfm_free; + /* Setup SDCC bus voter clock. */ msm_host->bus_clk = devm_clk_get(&pdev->dev, "bus"); if (!IS_ERR(msm_host->bus_clk)) { only in patch2: unchanged: --- linux-5.15.0.orig/drivers/mmc/host/sunxi-mmc.c +++ linux-5.15.0/drivers/mmc/host/sunxi-mmc.c @@ -377,8 +377,9 @@ pdes[i].buf_addr_ptr1 = cpu_to_le32(sg_dma_address(&data->sg[i]) >> host->cfg->idma_des_shift); - pdes[i].buf_addr_ptr2 = cpu_to_le32((u32)next_desc >> - host->cfg->idma_des_shift); + pdes[i].buf_addr_ptr2 = + cpu_to_le32(next_desc >> + host->cfg->idma_des_shift); } pdes[0].config |= cpu_to_le32(SDXC_IDMAC_DES0_FD); only in patch2: unchanged: --- linux-5.15.0.orig/drivers/mtd/nand/raw/mtk_ecc.c +++ linux-5.15.0/drivers/mtd/nand/raw/mtk_ecc.c @@ -43,6 +43,7 @@ struct mtk_ecc_caps { u32 err_mask; + u32 err_shift; const u8 *ecc_strength; const u32 *ecc_regs; u8 num_ecc_strength; @@ -76,7 +77,7 @@ }; static const u8 ecc_strength_mt7622[] = { - 4, 6, 8, 10, 12, 14, 16 + 4, 6, 8, 10, 12 }; enum mtk_ecc_regs { @@ -221,7 +222,7 @@ for (i = 0; i < sectors; i++) { offset = (i >> 2) << 2; err = readl(ecc->regs + ECC_DECENUM0 + offset); - err = err >> ((i % 4) * 8); + err = err >> ((i % 4) * ecc->caps->err_shift); err &= ecc->caps->err_mask; if (err == ecc->caps->err_mask) { /* uncorrectable errors */ @@ -449,6 +450,7 @@ static const struct mtk_ecc_caps mtk_ecc_caps_mt2701 = { .err_mask = 0x3f, + .err_shift = 8, .ecc_strength = ecc_strength_mt2701, .ecc_regs = mt2701_ecc_regs, .num_ecc_strength = 20, @@ -459,6 +461,7 @@ static const struct mtk_ecc_caps mtk_ecc_caps_mt2712 = { .err_mask = 0x7f, + .err_shift = 8, .ecc_strength = ecc_strength_mt2712, .ecc_regs = mt2712_ecc_regs, .num_ecc_strength = 23, @@ -468,10 +471,11 @@ }; static const struct mtk_ecc_caps mtk_ecc_caps_mt7622 = { - .err_mask = 0x3f, + .err_mask = 0x1f, + .err_shift = 5, .ecc_strength = ecc_strength_mt7622, .ecc_regs = mt7622_ecc_regs, - .num_ecc_strength = 7, + .num_ecc_strength = 5, .ecc_mode_shift = 4, .parity_bits = 13, .pg_irq_sel = 0, only in patch2: unchanged: --- linux-5.15.0.orig/drivers/mtd/nand/raw/sh_flctl.c +++ linux-5.15.0/drivers/mtd/nand/raw/sh_flctl.c @@ -384,7 +384,8 @@ dma_addr_t dma_addr; dma_cookie_t cookie; uint32_t reg; - int ret; + int ret = 0; + unsigned long time_left; if (dir == DMA_FROM_DEVICE) { chan = flctl->chan_fifo0_rx; @@ -425,13 +426,14 @@ goto out; } - ret = + time_left = wait_for_completion_timeout(&flctl->dma_complete, msecs_to_jiffies(3000)); - if (ret <= 0) { + if (time_left == 0) { dmaengine_terminate_all(chan); dev_err(&flctl->pdev->dev, "wait_for_completion_timeout\n"); + ret = -ETIMEDOUT; } out: @@ -441,7 +443,7 @@ dma_unmap_single(chan->device->dev, dma_addr, len, dir); - /* ret > 0 is success */ + /* ret == 0 is success */ return ret; } @@ -465,7 +467,7 @@ /* initiate DMA transfer */ if (flctl->chan_fifo0_rx && rlen >= 32 && - flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_FROM_DEVICE) > 0) + !flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_FROM_DEVICE)) goto convert; /* DMA success */ /* do polling transfer */ @@ -524,7 +526,7 @@ /* initiate DMA transfer */ if (flctl->chan_fifo0_tx && rlen >= 32 && - flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_TO_DEVICE) > 0) + !flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_TO_DEVICE)) return; /* DMA success */ /* do polling transfer */ only in patch2: unchanged: --- linux-5.15.0.orig/drivers/net/can/grcan.c +++ linux-5.15.0/drivers/net/can/grcan.c @@ -241,13 +241,14 @@ .rxsize = GRCAN_DEFAULT_BUFFER_SIZE, \ } -#define GRCAN_TXBUG_SAFE_GRLIB_VERSION 0x4100 +#define GRCAN_TXBUG_SAFE_GRLIB_VERSION 4100 #define GRLIB_VERSION_MASK 0xffff /* GRCAN private data structure */ struct grcan_priv { struct can_priv can; /* must be the first member */ struct net_device *dev; + struct device *ofdev_dev; struct napi_struct napi; struct grcan_registers __iomem *regs; /* ioremap'ed registers */ @@ -924,7 +925,7 @@ struct grcan_priv *priv = netdev_priv(dev); struct grcan_dma *dma = &priv->dma; - dma_free_coherent(&dev->dev, dma->base_size, dma->base_buf, + dma_free_coherent(priv->ofdev_dev, dma->base_size, dma->base_buf, dma->base_handle); memset(dma, 0, sizeof(*dma)); } @@ -949,7 +950,7 @@ /* Extra GRCAN_BUFFER_ALIGNMENT to allow for alignment */ dma->base_size = lsize + ssize + GRCAN_BUFFER_ALIGNMENT; - dma->base_buf = dma_alloc_coherent(&dev->dev, + dma->base_buf = dma_alloc_coherent(priv->ofdev_dev, dma->base_size, &dma->base_handle, GFP_KERNEL); @@ -1113,8 +1114,10 @@ priv->closing = true; if (priv->need_txbug_workaround) { + spin_unlock_irqrestore(&priv->lock, flags); del_timer_sync(&priv->hang_timer); del_timer_sync(&priv->rr_timer); + spin_lock_irqsave(&priv->lock, flags); } netif_stop_queue(dev); grcan_stop_hardware(dev); @@ -1134,7 +1137,7 @@ return 0; } -static int grcan_transmit_catch_up(struct net_device *dev, int budget) +static void grcan_transmit_catch_up(struct net_device *dev) { struct grcan_priv *priv = netdev_priv(dev); unsigned long flags; @@ -1142,7 +1145,7 @@ spin_lock_irqsave(&priv->lock, flags); - work_done = catch_up_echo_skb(dev, budget, true); + work_done = catch_up_echo_skb(dev, -1, true); if (work_done) { if (!priv->resetting && !priv->closing && !(priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)) @@ -1156,8 +1159,6 @@ } spin_unlock_irqrestore(&priv->lock, flags); - - return work_done; } static int grcan_receive(struct net_device *dev, int budget) @@ -1239,19 +1240,13 @@ struct net_device *dev = priv->dev; struct grcan_registers __iomem *regs = priv->regs; unsigned long flags; - int tx_work_done, rx_work_done; - int rx_budget = budget / 2; - int tx_budget = budget - rx_budget; + int work_done; - /* Half of the budget for receiving messages */ - rx_work_done = grcan_receive(dev, rx_budget); + work_done = grcan_receive(dev, budget); - /* Half of the budget for transmitting messages as that can trigger echo - * frames being received - */ - tx_work_done = grcan_transmit_catch_up(dev, tx_budget); + grcan_transmit_catch_up(dev); - if (rx_work_done < rx_budget && tx_work_done < tx_budget) { + if (work_done < budget) { napi_complete(napi); /* Guarantee no interference with a running reset that otherwise @@ -1268,7 +1263,7 @@ spin_unlock_irqrestore(&priv->lock, flags); } - return rx_work_done + tx_work_done; + return work_done; } /* Work tx bug by waiting while for the risky situation to clear. If that fails, @@ -1600,6 +1595,7 @@ memcpy(&priv->config, &grcan_module_config, sizeof(struct grcan_device_config)); priv->dev = dev; + priv->ofdev_dev = &ofdev->dev; priv->regs = base; priv->can.bittiming_const = &grcan_bittiming_const; priv->can.do_set_bittiming = grcan_set_bittiming; @@ -1652,6 +1648,7 @@ static int grcan_probe(struct platform_device *ofdev) { struct device_node *np = ofdev->dev.of_node; + struct device_node *sysid_parent; u32 sysid, ambafreq; int irq, err; void __iomem *base; @@ -1660,10 +1657,15 @@ /* Compare GRLIB version number with the first that does not * have the tx bug (see start_xmit) */ - err = of_property_read_u32(np, "systemid", &sysid); - if (!err && ((sysid & GRLIB_VERSION_MASK) - >= GRCAN_TXBUG_SAFE_GRLIB_VERSION)) - txbug = false; + sysid_parent = of_find_node_by_path("/ambapp0"); + if (sysid_parent) { + of_node_get(sysid_parent); + err = of_property_read_u32(sysid_parent, "systemid", &sysid); + if (!err && ((sysid & GRLIB_VERSION_MASK) >= + GRCAN_TXBUG_SAFE_GRLIB_VERSION)) + txbug = false; + of_node_put(sysid_parent); + } err = of_property_read_u32(np, "freq", &ambafreq); if (err) { only in patch2: unchanged: --- linux-5.15.0.orig/drivers/net/dsa/mv88e6xxx/port_hidden.c +++ linux-5.15.0/drivers/net/dsa/mv88e6xxx/port_hidden.c @@ -40,8 +40,9 @@ { int bit = __bf_shf(MV88E6XXX_PORT_RESERVED_1A_BUSY); - return mv88e6xxx_wait_bit(chip, MV88E6XXX_PORT_RESERVED_1A_CTRL_PORT, - MV88E6XXX_PORT_RESERVED_1A, bit, 0); + return mv88e6xxx_port_wait_bit(chip, + MV88E6XXX_PORT_RESERVED_1A_CTRL_PORT, + MV88E6XXX_PORT_RESERVED_1A, bit, 0); } int mv88e6xxx_port_hidden_read(struct mv88e6xxx_chip *chip, int block, int port, only in patch2: unchanged: --- linux-5.15.0.orig/drivers/net/ethernet/Kconfig +++ linux-5.15.0/drivers/net/ethernet/Kconfig @@ -34,15 +34,6 @@ source "drivers/net/ethernet/aquantia/Kconfig" source "drivers/net/ethernet/arc/Kconfig" source "drivers/net/ethernet/atheros/Kconfig" -source "drivers/net/ethernet/broadcom/Kconfig" -source "drivers/net/ethernet/brocade/Kconfig" -source "drivers/net/ethernet/cadence/Kconfig" -source "drivers/net/ethernet/calxeda/Kconfig" -source "drivers/net/ethernet/cavium/Kconfig" -source "drivers/net/ethernet/chelsio/Kconfig" -source "drivers/net/ethernet/cirrus/Kconfig" -source "drivers/net/ethernet/cisco/Kconfig" -source "drivers/net/ethernet/cortina/Kconfig" config CX_ECAT tristate "Beckhoff CX5020 EtherCAT master support" @@ -56,6 +47,14 @@ To compile this driver as a module, choose M here. The module will be called ec_bhf. +source "drivers/net/ethernet/broadcom/Kconfig" +source "drivers/net/ethernet/cadence/Kconfig" +source "drivers/net/ethernet/calxeda/Kconfig" +source "drivers/net/ethernet/cavium/Kconfig" +source "drivers/net/ethernet/chelsio/Kconfig" +source "drivers/net/ethernet/cirrus/Kconfig" +source "drivers/net/ethernet/cisco/Kconfig" +source "drivers/net/ethernet/cortina/Kconfig" source "drivers/net/ethernet/davicom/Kconfig" config DNET @@ -82,7 +81,6 @@ source "drivers/net/ethernet/i825xx/Kconfig" source "drivers/net/ethernet/ibm/Kconfig" source "drivers/net/ethernet/intel/Kconfig" -source "drivers/net/ethernet/microsoft/Kconfig" source "drivers/net/ethernet/xscale/Kconfig" config JME @@ -125,8 +123,9 @@ source "drivers/net/ethernet/mellanox/Kconfig" source "drivers/net/ethernet/micrel/Kconfig" source "drivers/net/ethernet/microchip/Kconfig" -source "drivers/net/ethernet/moxa/Kconfig" source "drivers/net/ethernet/mscc/Kconfig" +source "drivers/net/ethernet/microsoft/Kconfig" +source "drivers/net/ethernet/moxa/Kconfig" source "drivers/net/ethernet/myricom/Kconfig" config FEALNX @@ -138,10 +137,10 @@ Say Y here to support the Myson MTD-800 family of PCI-based Ethernet cards. +source "drivers/net/ethernet/ni/Kconfig" source "drivers/net/ethernet/natsemi/Kconfig" source "drivers/net/ethernet/neterion/Kconfig" source "drivers/net/ethernet/netronome/Kconfig" -source "drivers/net/ethernet/ni/Kconfig" source "drivers/net/ethernet/8390/Kconfig" source "drivers/net/ethernet/nvidia/Kconfig" source "drivers/net/ethernet/nxp/Kconfig" @@ -161,6 +160,7 @@ source "drivers/net/ethernet/pasemi/Kconfig" source "drivers/net/ethernet/pensando/Kconfig" source "drivers/net/ethernet/qlogic/Kconfig" +source "drivers/net/ethernet/brocade/Kconfig" source "drivers/net/ethernet/qualcomm/Kconfig" source "drivers/net/ethernet/rdc/Kconfig" source "drivers/net/ethernet/realtek/Kconfig" @@ -168,10 +168,10 @@ source "drivers/net/ethernet/rocker/Kconfig" source "drivers/net/ethernet/samsung/Kconfig" source "drivers/net/ethernet/seeq/Kconfig" -source "drivers/net/ethernet/sfc/Kconfig" source "drivers/net/ethernet/sgi/Kconfig" source "drivers/net/ethernet/silan/Kconfig" source "drivers/net/ethernet/sis/Kconfig" +source "drivers/net/ethernet/sfc/Kconfig" source "drivers/net/ethernet/smsc/Kconfig" source "drivers/net/ethernet/socionext/Kconfig" source "drivers/net/ethernet/stmicro/Kconfig" only in patch2: unchanged: --- linux-5.15.0.orig/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c +++ linux-5.15.0/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c @@ -489,11 +489,15 @@ info->phc_index = -1; fman_node = of_get_parent(mac_node); - if (fman_node) + if (fman_node) { ptp_node = of_parse_phandle(fman_node, "ptimer-handle", 0); + of_node_put(fman_node); + } - if (ptp_node) + if (ptp_node) { ptp_dev = of_find_device_by_node(ptp_node); + of_node_put(ptp_node); + } if (ptp_dev) ptp = platform_get_drvdata(ptp_dev); only in patch2: unchanged: --- linux-5.15.0.orig/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +++ linux-5.15.0/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c @@ -93,6 +93,13 @@ enum hclge_cmd_status status; struct hclge_desc desc; + if (msg_len > HCLGE_MBX_MAX_MSG_SIZE) { + dev_err(&hdev->pdev->dev, + "msg data length(=%u) exceeds maximum(=%u)\n", + msg_len, HCLGE_MBX_MAX_MSG_SIZE); + return -EMSGSIZE; + } + resp_pf_to_vf = (struct hclge_mbx_pf_to_vf_cmd *)desc.data; hclge_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_MBX_PF_TO_VF, false); @@ -175,7 +182,7 @@ ring_num = req->msg.ring_num; if (ring_num > HCLGE_MBX_MAX_RING_CHAIN_PARAM_NUM) - return -ENOMEM; + return -EINVAL; for (i = 0; i < ring_num; i++) { if (req->msg.param[i].tqp_index >= vport->nic.kinfo.rss_size) { @@ -586,9 +593,9 @@ return hclge_set_vport_mtu(vport, mtu); } -static void hclge_get_queue_id_in_pf(struct hclge_vport *vport, - struct hclge_mbx_vf_to_pf_cmd *mbx_req, - struct hclge_respond_to_vf_msg *resp_msg) +static int hclge_get_queue_id_in_pf(struct hclge_vport *vport, + struct hclge_mbx_vf_to_pf_cmd *mbx_req, + struct hclge_respond_to_vf_msg *resp_msg) { struct hnae3_handle *handle = &vport->nic; struct hclge_dev *hdev = vport->back; @@ -598,17 +605,18 @@ if (queue_id >= handle->kinfo.num_tqps) { dev_err(&hdev->pdev->dev, "Invalid queue id(%u) from VF %u\n", queue_id, mbx_req->mbx_src_vfid); - return; + return -EINVAL; } qid_in_pf = hclge_covert_handle_qid_global(&vport->nic, queue_id); memcpy(resp_msg->data, &qid_in_pf, sizeof(qid_in_pf)); resp_msg->len = sizeof(qid_in_pf); + return 0; } -static void hclge_get_rss_key(struct hclge_vport *vport, - struct hclge_mbx_vf_to_pf_cmd *mbx_req, - struct hclge_respond_to_vf_msg *resp_msg) +static int hclge_get_rss_key(struct hclge_vport *vport, + struct hclge_mbx_vf_to_pf_cmd *mbx_req, + struct hclge_respond_to_vf_msg *resp_msg) { #define HCLGE_RSS_MBX_RESP_LEN 8 struct hclge_dev *hdev = vport->back; @@ -624,13 +632,14 @@ dev_warn(&hdev->pdev->dev, "failed to get the rss hash key, the index(%u) invalid !\n", index); - return; + return -EINVAL; } memcpy(resp_msg->data, &hdev->vport[0].rss_hash_key[index * HCLGE_RSS_MBX_RESP_LEN], HCLGE_RSS_MBX_RESP_LEN); resp_msg->len = HCLGE_RSS_MBX_RESP_LEN; + return 0; } static void hclge_link_fail_parse(struct hclge_dev *hdev, u8 link_fail_code) @@ -805,10 +814,10 @@ "VF fail(%d) to set mtu\n", ret); break; case HCLGE_MBX_GET_QID_IN_PF: - hclge_get_queue_id_in_pf(vport, req, &resp_msg); + ret = hclge_get_queue_id_in_pf(vport, req, &resp_msg); break; case HCLGE_MBX_GET_RSS_KEY: - hclge_get_rss_key(vport, req, &resp_msg); + ret = hclge_get_rss_key(vport, req, &resp_msg); break; case HCLGE_MBX_GET_LINK_MODE: hclge_get_link_mode(vport, req); only in patch2: unchanged: --- linux-5.15.0.orig/drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c +++ linux-5.15.0/drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c @@ -772,7 +772,7 @@ /* If we only have one page, still need to get shadown wqe when * wqe rolling-over page */ - if (curr_pg != end_pg || MASKED_WQE_IDX(wq, end_prod_idx) < *prod_idx) { + if (curr_pg != end_pg || end_prod_idx < *prod_idx) { void *shadow_addr = &wq->shadow_wqe[curr_pg * wq->max_wqe_size]; copy_wqe_to_shadow(wq, shadow_addr, num_wqebbs, *prod_idx); @@ -842,7 +842,10 @@ *cons_idx = curr_cons_idx; - if (curr_pg != end_pg) { + /* If we only have one page, still need to get shadown wqe when + * wqe rolling-over page + */ + if (curr_pg != end_pg || end_cons_idx < curr_cons_idx) { void *shadow_addr = &wq->shadow_wqe[curr_pg * wq->max_wqe_size]; copy_wqe_to_shadow(wq, shadow_addr, num_wqebbs, *cons_idx); only in patch2: unchanged: --- linux-5.15.0.orig/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c +++ linux-5.15.0/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c @@ -903,7 +903,8 @@ /* Tx IPsec offload doesn't seem to work on this * device, so block these requests for now. */ - if (!(sam->flags & XFRM_OFFLOAD_INBOUND)) { + sam->flags = sam->flags & ~XFRM_OFFLOAD_IPV6; + if (sam->flags != XFRM_OFFLOAD_INBOUND) { err = -EOPNOTSUPP; goto err_out; } only in patch2: unchanged: --- linux-5.15.0.orig/drivers/net/ethernet/mediatek/mtk_sgmii.c +++ linux-5.15.0/drivers/net/ethernet/mediatek/mtk_sgmii.c @@ -26,6 +26,7 @@ break; ss->regmap[i] = syscon_node_to_regmap(np); + of_node_put(np); if (IS_ERR(ss->regmap[i])) return PTR_ERR(ss->regmap[i]); } only in patch2: unchanged: --- linux-5.15.0.orig/drivers/net/ethernet/mellanox/mlx5/core/diag/rsc_dump.c +++ linux-5.15.0/drivers/net/ethernet/mellanox/mlx5/core/diag/rsc_dump.c @@ -31,6 +31,7 @@ struct mlx5_rsc_dump { u32 pdn; struct mlx5_core_mkey mkey; + u32 number_of_menu_items; u16 fw_segment_type[MLX5_SGMT_TYPE_NUM]; }; @@ -50,21 +51,37 @@ return -EINVAL; } -static void mlx5_rsc_dump_read_menu_sgmt(struct mlx5_rsc_dump *rsc_dump, struct page *page) +#define MLX5_RSC_DUMP_MENU_HEADER_SIZE (MLX5_ST_SZ_BYTES(resource_dump_info_segment) + \ + MLX5_ST_SZ_BYTES(resource_dump_command_segment) + \ + MLX5_ST_SZ_BYTES(resource_dump_menu_segment)) + +static int mlx5_rsc_dump_read_menu_sgmt(struct mlx5_rsc_dump *rsc_dump, struct page *page, + int read_size, int start_idx) { void *data = page_address(page); enum mlx5_sgmt_type sgmt_idx; int num_of_items; char *sgmt_name; void *member; + int size = 0; void *menu; int i; - menu = MLX5_ADDR_OF(menu_resource_dump_response, data, menu); - num_of_items = MLX5_GET(resource_dump_menu_segment, menu, num_of_records); + if (!start_idx) { + menu = MLX5_ADDR_OF(menu_resource_dump_response, data, menu); + rsc_dump->number_of_menu_items = MLX5_GET(resource_dump_menu_segment, menu, + num_of_records); + size = MLX5_RSC_DUMP_MENU_HEADER_SIZE; + data += size; + } + num_of_items = rsc_dump->number_of_menu_items; + + for (i = 0; start_idx + i < num_of_items; i++) { + size += MLX5_ST_SZ_BYTES(resource_dump_menu_record); + if (size >= read_size) + return start_idx + i; - for (i = 0; i < num_of_items; i++) { - member = MLX5_ADDR_OF(resource_dump_menu_segment, menu, record[i]); + member = data + MLX5_ST_SZ_BYTES(resource_dump_menu_record) * i; sgmt_name = MLX5_ADDR_OF(resource_dump_menu_record, member, segment_name); sgmt_idx = mlx5_rsc_dump_sgmt_get_by_name(sgmt_name); if (sgmt_idx == -EINVAL) @@ -72,6 +89,7 @@ rsc_dump->fw_segment_type[sgmt_idx] = MLX5_GET(resource_dump_menu_record, member, segment_type); } + return 0; } static int mlx5_rsc_dump_trigger(struct mlx5_core_dev *dev, struct mlx5_rsc_dump_cmd *cmd, @@ -168,6 +186,7 @@ struct mlx5_rsc_dump_cmd *cmd = NULL; struct mlx5_rsc_key key = {}; struct page *page; + int start_idx = 0; int size; int err; @@ -189,7 +208,7 @@ if (err < 0) goto destroy_cmd; - mlx5_rsc_dump_read_menu_sgmt(dev->rsc_dump, page); + start_idx = mlx5_rsc_dump_read_menu_sgmt(dev->rsc_dump, page, size, start_idx); } while (err > 0); only in patch2: unchanged: --- linux-5.15.0.orig/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c +++ linux-5.15.0/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c @@ -309,8 +309,8 @@ if (err) return err; - err = update_buffer_lossy(max_mtu, curr_pfc_en, prio2buffer, port_buff_cell_sz, - xoff, &port_buffer, &update_buffer); + err = update_buffer_lossy(max_mtu, curr_pfc_en, prio2buffer, xoff, + port_buff_cell_sz, &port_buffer, &update_buffer); if (err) return err; } only in patch2: unchanged: --- linux-5.15.0.orig/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +++ linux-5.15.0/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c @@ -1198,6 +1198,16 @@ if (err) return err; + if (priv->dcbx_dp.trust_state == MLX5_QPTS_TRUST_PCP && priv->dcbx.dscp_app_cnt) { + /* + * Align the driver state with the register state. + * Temporary state change is required to enable the app list reset. + */ + priv->dcbx_dp.trust_state = MLX5_QPTS_TRUST_DSCP; + mlx5e_dcbnl_delete_app(priv); + priv->dcbx_dp.trust_state = MLX5_QPTS_TRUST_PCP; + } + mlx5e_params_calc_trust_tx_min_inline_mode(priv->mdev, &priv->channels.params, priv->dcbx_dp.trust_state); only in patch2: unchanged: --- linux-5.15.0.orig/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.h +++ linux-5.15.0/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.h @@ -15,7 +15,12 @@ struct lag_mp { struct notifier_block fib_nb; - struct fib_info *mfi; /* used in tracking fib events */ + struct { + const void *mfi; /* used in tracking fib events */ + u32 priority; + u32 dst; + int dst_len; + } fib; struct workqueue_struct *wq; }; only in patch2: unchanged: --- linux-5.15.0.orig/drivers/net/ethernet/smsc/smsc911x.c +++ linux-5.15.0/drivers/net/ethernet/smsc/smsc911x.c @@ -2429,7 +2429,7 @@ if (irq == -EPROBE_DEFER) { retval = -EPROBE_DEFER; goto out_0; - } else if (irq <= 0) { + } else if (irq < 0) { pr_warn("Could not allocate irq resource\n"); retval = -ENODEV; goto out_0; only in patch2: unchanged: --- linux-5.15.0.orig/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c +++ linux-5.15.0/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c @@ -454,6 +454,7 @@ plat->has_gmac4 = 1; plat->force_sf_dma_mode = 0; plat->tso_en = 1; + plat->sph_disable = 1; /* Multiplying factor to the clk_eee_i clock time * period to make it closer to 100 ns. This value only in patch2: unchanged: --- linux-5.15.0.orig/drivers/net/hippi/rrunner.c +++ linux-5.15.0/drivers/net/hippi/rrunner.c @@ -1353,7 +1353,9 @@ rrpriv->fw_running = 0; + spin_unlock_irqrestore(&rrpriv->lock, flags); del_timer_sync(&rrpriv->timer); + spin_lock_irqsave(&rrpriv->lock, flags); writel(0, ®s->TxPi); writel(0, ®s->IpRxPi); only in patch2: unchanged: --- linux-5.15.0.orig/drivers/net/mdio/mdio-mux-bcm6368.c +++ linux-5.15.0/drivers/net/mdio/mdio-mux-bcm6368.c @@ -115,7 +115,7 @@ md->mii_bus = devm_mdiobus_alloc(&pdev->dev); if (!md->mii_bus) { dev_err(&pdev->dev, "mdiomux bus alloc failed\n"); - return ENOMEM; + return -ENOMEM; } bus = md->mii_bus; only in patch2: unchanged: --- linux-5.15.0.orig/drivers/net/phy/marvell10g.c +++ linux-5.15.0/drivers/net/phy/marvell10g.c @@ -789,7 +789,7 @@ cssr1 = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_CSSR1); if (cssr1 < 0) - return val; + return cssr1; /* If the link settings are not resolved, mark the link down */ if (!(cssr1 & MV_PCS_CSSR1_RESOLVED)) { only in patch2: unchanged: --- linux-5.15.0.orig/drivers/net/virtio_net.c +++ linux-5.15.0/drivers/net/virtio_net.c @@ -965,6 +965,24 @@ * xdp.data_meta were adjusted */ len = xdp.data_end - xdp.data + vi->hdr_len + metasize; + + /* recalculate headroom if xdp.data or xdp_data_meta + * were adjusted, note that offset should always point + * to the start of the reserved bytes for virtio_net + * header which are followed by xdp.data, that means + * that offset is equal to the headroom (when buf is + * starting at the beginning of the page, otherwise + * there is a base offset inside the page) but it's used + * with a different starting point (buf start) than + * xdp.data (buf start + vnet hdr size). If xdp.data or + * data_meta were adjusted by the xdp prog then the + * headroom size has changed and so has the offset, we + * can use data_hard_start, which points at buf start + + * vnet hdr size, to calculate the new headroom and use + * it later to compute buf start in page_to_skb() + */ + headroom = xdp.data - xdp.data_hard_start - metasize; + /* We can only create skb based on xdp_page. */ if (unlikely(xdp_page != page)) { rcu_read_unlock(); @@ -972,7 +990,7 @@ head_skb = page_to_skb(vi, rq, xdp_page, offset, len, PAGE_SIZE, false, metasize, - VIRTIO_XDP_HEADROOM); + headroom); return head_skb; } break; only in patch2: unchanged: --- linux-5.15.0.orig/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c +++ linux-5.15.0/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c @@ -80,7 +80,7 @@ mt76_rmw_field(dev, 0x15a10, 0x1f << 16, 0x9); /* RG_SSUSB_G1_CDR_BIC_LTR = 0xf */ - mt76_rmw_field(dev, 0x15a0c, 0xf << 28, 0xf); + mt76_rmw_field(dev, 0x15a0c, 0xfU << 28, 0xf); /* RG_SSUSB_CDR_BR_PE1D = 0x3 */ mt76_rmw_field(dev, 0x15c58, 0x3 << 6, 0x3); only in patch2: unchanged: --- linux-5.15.0.orig/drivers/nfc/nfcmrvl/main.c +++ linux-5.15.0/drivers/nfc/nfcmrvl/main.c @@ -183,6 +183,7 @@ { struct nci_dev *ndev = priv->ndev; + nci_unregister_device(ndev); if (priv->ndev->nfc_dev->fw_download_in_progress) nfcmrvl_fw_dnld_abort(priv); @@ -191,7 +192,6 @@ if (gpio_is_valid(priv->config.reset_n_io)) gpio_free(priv->config.reset_n_io); - nci_unregister_device(ndev); nci_free_device(ndev); kfree(priv); } only in patch2: unchanged: --- linux-5.15.0.orig/drivers/perf/arm_pmu.c +++ linux-5.15.0/drivers/perf/arm_pmu.c @@ -398,6 +398,9 @@ if (!validate_event(event->pmu, &fake_pmu, leader)) return -EINVAL; + if (event == leader) + return 0; + for_each_sibling_event(sibling, leader) { if (!validate_event(event->pmu, &fake_pmu, sibling)) return -EINVAL; @@ -487,12 +490,7 @@ local64_set(&hwc->period_left, hwc->sample_period); } - if (event->group_leader != event) { - if (validate_group(event) != 0) - return -EINVAL; - } - - return 0; + return validate_group(event); } static int armpmu_event_init(struct perf_event *event) only in patch2: unchanged: --- linux-5.15.0.orig/drivers/phy/amlogic/phy-meson-g12a-usb3-pcie.c +++ linux-5.15.0/drivers/phy/amlogic/phy-meson-g12a-usb3-pcie.c @@ -414,19 +414,19 @@ ret = clk_prepare_enable(priv->clk_ref); if (ret) - goto err_disable_clk_ref; + return ret; priv->reset = devm_reset_control_array_get_exclusive(dev); - if (IS_ERR(priv->reset)) - return PTR_ERR(priv->reset); + if (IS_ERR(priv->reset)) { + ret = PTR_ERR(priv->reset); + goto err_disable_clk_ref; + } priv->phy = devm_phy_create(dev, np, &phy_g12a_usb3_pcie_ops); if (IS_ERR(priv->phy)) { ret = PTR_ERR(priv->phy); - if (ret != -EPROBE_DEFER) - dev_err(dev, "failed to create PHY\n"); - - return ret; + dev_err_probe(dev, ret, "failed to create PHY\n"); + goto err_disable_clk_ref; } phy_set_drvdata(priv->phy, priv); @@ -434,8 +434,12 @@ phy_provider = devm_of_phy_provider_register(dev, phy_g12a_usb3_pcie_xlate); + if (IS_ERR(phy_provider)) { + ret = PTR_ERR(phy_provider); + goto err_disable_clk_ref; + } - return PTR_ERR_OR_ZERO(phy_provider); + return 0; err_disable_clk_ref: clk_disable_unprepare(priv->clk_ref); only in patch2: unchanged: --- linux-5.15.0.orig/drivers/phy/motorola/phy-mapphone-mdm6600.c +++ linux-5.15.0/drivers/phy/motorola/phy-mapphone-mdm6600.c @@ -629,7 +629,8 @@ cleanup: if (error < 0) phy_mdm6600_device_power_off(ddata); - + pm_runtime_disable(ddata->dev); + pm_runtime_dont_use_autosuspend(ddata->dev); return error; } only in patch2: unchanged: --- linux-5.15.0.orig/drivers/phy/samsung/phy-exynos5250-sata.c +++ linux-5.15.0/drivers/phy/samsung/phy-exynos5250-sata.c @@ -187,6 +187,7 @@ return -EINVAL; sata_phy->client = of_find_i2c_device_by_node(node); + of_node_put(node); if (!sata_phy->client) return -EPROBE_DEFER; @@ -195,20 +196,21 @@ sata_phy->phyclk = devm_clk_get(dev, "sata_phyctrl"); if (IS_ERR(sata_phy->phyclk)) { dev_err(dev, "failed to get clk for PHY\n"); - return PTR_ERR(sata_phy->phyclk); + ret = PTR_ERR(sata_phy->phyclk); + goto put_dev; } ret = clk_prepare_enable(sata_phy->phyclk); if (ret < 0) { dev_err(dev, "failed to enable source clk\n"); - return ret; + goto put_dev; } sata_phy->phy = devm_phy_create(dev, NULL, &exynos_sata_phy_ops); if (IS_ERR(sata_phy->phy)) { - clk_disable_unprepare(sata_phy->phyclk); dev_err(dev, "failed to create PHY\n"); - return PTR_ERR(sata_phy->phy); + ret = PTR_ERR(sata_phy->phy); + goto clk_disable; } phy_set_drvdata(sata_phy->phy, sata_phy); @@ -216,11 +218,18 @@ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); if (IS_ERR(phy_provider)) { - clk_disable_unprepare(sata_phy->phyclk); - return PTR_ERR(phy_provider); + ret = PTR_ERR(phy_provider); + goto clk_disable; } return 0; + +clk_disable: + clk_disable_unprepare(sata_phy->phyclk); +put_dev: + put_device(&sata_phy->client->dev); + + return ret; } static const struct of_device_id exynos_sata_phy_of_match[] = { only in patch2: unchanged: --- linux-5.15.0.orig/drivers/phy/ti/phy-am654-serdes.c +++ linux-5.15.0/drivers/phy/ti/phy-am654-serdes.c @@ -838,7 +838,7 @@ clk_err: of_clk_del_provider(node); - + pm_runtime_disable(dev); return ret; } only in patch2: unchanged: --- linux-5.15.0.orig/drivers/phy/ti/phy-omap-usb2.c +++ linux-5.15.0/drivers/phy/ti/phy-omap-usb2.c @@ -215,7 +215,7 @@ return 0; err1: - clk_disable(phy->wkupclk); + clk_disable_unprepare(phy->wkupclk); err0: return ret; only in patch2: unchanged: --- linux-5.15.0.orig/drivers/pinctrl/mediatek/Kconfig +++ linux-5.15.0/drivers/pinctrl/mediatek/Kconfig @@ -30,6 +30,7 @@ select GENERIC_PINMUX_FUNCTIONS select GPIOLIB select OF_GPIO + select EINT_MTK select PINCTRL_MTK_V2 config PINCTRL_MTK_PARIS only in patch2: unchanged: --- linux-5.15.0.orig/drivers/pinctrl/pinctrl-pistachio.c +++ linux-5.15.0/drivers/pinctrl/pinctrl-pistachio.c @@ -1374,10 +1374,10 @@ } irq = irq_of_parse_and_map(child, 0); - if (irq < 0) { - dev_err(pctl->dev, "No IRQ for bank %u: %d\n", i, irq); + if (!irq) { + dev_err(pctl->dev, "No IRQ for bank %u\n", i); of_node_put(child); - ret = irq; + ret = -EINVAL; goto err; } only in patch2: unchanged: --- linux-5.15.0.orig/drivers/pinctrl/samsung/Kconfig +++ linux-5.15.0/drivers/pinctrl/samsung/Kconfig @@ -4,14 +4,13 @@ # config PINCTRL_SAMSUNG bool - depends on OF_GPIO + select GPIOLIB select PINMUX select PINCONF config PINCTRL_EXYNOS bool "Pinctrl common driver part for Samsung Exynos SoCs" - depends on OF_GPIO - depends on ARCH_EXYNOS || ARCH_S5PV210 || COMPILE_TEST + depends on ARCH_EXYNOS || ARCH_S5PV210 || (COMPILE_TEST && OF) select PINCTRL_SAMSUNG select PINCTRL_EXYNOS_ARM if ARM && (ARCH_EXYNOS || ARCH_S5PV210) select PINCTRL_EXYNOS_ARM64 if ARM64 && ARCH_EXYNOS @@ -26,12 +25,10 @@ config PINCTRL_S3C24XX bool "Samsung S3C24XX SoC pinctrl driver" - depends on OF_GPIO - depends on ARCH_S3C24XX || COMPILE_TEST + depends on ARCH_S3C24XX || (COMPILE_TEST && OF) select PINCTRL_SAMSUNG config PINCTRL_S3C64XX bool "Samsung S3C64XX SoC pinctrl driver" - depends on OF_GPIO - depends on ARCH_S3C64XX || COMPILE_TEST + depends on ARCH_S3C64XX || (COMPILE_TEST && OF) select PINCTRL_SAMSUNG only in patch2: unchanged: --- linux-5.15.0.orig/drivers/platform/x86/hp-wmi.c +++ linux-5.15.0/drivers/platform/x86/hp-wmi.c @@ -284,7 +284,7 @@ int val = 0, ret; ret = hp_wmi_perform_query(query, HPWMI_READ, &val, - sizeof(val), sizeof(val)); + 0, sizeof(val)); if (ret) return ret < 0 ? ret : -EINVAL; only in patch2: unchanged: --- linux-5.15.0.orig/drivers/platform/x86/samsung-laptop.c +++ linux-5.15.0/drivers/platform/x86/samsung-laptop.c @@ -1121,8 +1121,6 @@ if (value > samsung->kbd_led.max_brightness) value = samsung->kbd_led.max_brightness; - else if (value < 0) - value = 0; samsung->kbd_led_wk = value; queue_work(samsung->led_workqueue, &samsung->kbd_led_work); only in patch2: unchanged: --- linux-5.15.0.orig/drivers/s390/block/dasd.c +++ linux-5.15.0/drivers/s390/block/dasd.c @@ -1422,6 +1422,13 @@ if (!cqr->lpm) cqr->lpm = dasd_path_get_opm(device); } + /* + * remember the amount of formatted tracks to prevent double format on + * ESE devices + */ + if (cqr->block) + cqr->trkcount = atomic_read(&cqr->block->trkcount); + if (cqr->cpmode == 1) { rc = ccw_device_tm_start(device->cdev, cqr->cpaddr, (long) cqr, cqr->lpm); @@ -1639,6 +1646,7 @@ unsigned long now; int nrf_suppressed = 0; int fp_suppressed = 0; + struct request *req; u8 *sense = NULL; int expires; @@ -1739,7 +1747,12 @@ } if (dasd_ese_needs_format(cqr->block, irb)) { - if (rq_data_dir((struct request *)cqr->callback_data) == READ) { + req = dasd_get_callback_data(cqr); + if (!req) { + cqr->status = DASD_CQR_ERROR; + return; + } + if (rq_data_dir(req) == READ) { device->discipline->ese_read(cqr, irb); cqr->status = DASD_CQR_SUCCESS; cqr->stopclk = now; @@ -2762,8 +2775,7 @@ * complete a request partially. */ if (proc_bytes) { - blk_update_request(req, BLK_STS_OK, - blk_rq_bytes(req) - proc_bytes); + blk_update_request(req, BLK_STS_OK, proc_bytes); blk_mq_requeue_request(req, true); } else if (likely(!blk_should_fake_timeout(req->q))) { blk_mq_complete_request(req); only in patch2: unchanged: --- linux-5.15.0.orig/drivers/s390/block/dasd_eckd.c +++ linux-5.15.0/drivers/s390/block/dasd_eckd.c @@ -3095,13 +3095,24 @@ } static bool test_and_set_format_track(struct dasd_format_entry *to_format, - struct dasd_block *block) + struct dasd_ccw_req *cqr) { + struct dasd_block *block = cqr->block; struct dasd_format_entry *format; unsigned long flags; bool rc = false; spin_lock_irqsave(&block->format_lock, flags); + if (cqr->trkcount != atomic_read(&block->trkcount)) { + /* + * The number of formatted tracks has changed after request + * start and we can not tell if the current track was involved. + * To avoid data corruption treat it as if the current track is + * involved + */ + rc = true; + goto out; + } list_for_each_entry(format, &block->format_list, list) { if (format->track == to_format->track) { rc = true; @@ -3121,6 +3132,7 @@ unsigned long flags; spin_lock_irqsave(&block->format_lock, flags); + atomic_inc(&block->trkcount); list_del_init(&format->list); spin_unlock_irqrestore(&block->format_lock, flags); } @@ -3157,7 +3169,7 @@ sector_t curr_trk; int rc; - req = cqr->callback_data; + req = dasd_get_callback_data(cqr); block = cqr->block; base = block->base; private = base->private; @@ -3182,8 +3194,11 @@ } format->track = curr_trk; /* test if track is already in formatting by another thread */ - if (test_and_set_format_track(format, block)) + if (test_and_set_format_track(format, cqr)) { + /* this is no real error so do not count down retries */ + cqr->retries++; return ERR_PTR(-EEXIST); + } fdata.start_unit = curr_trk; fdata.stop_unit = curr_trk; @@ -3282,12 +3297,11 @@ cqr->proc_bytes = blk_count * blksize; return 0; } - if (dst && !skip_block) { - dst += off; + if (dst && !skip_block) memset(dst, 0, blksize); - } else { + else skip_block--; - } + dst += blksize; blk_count++; } } only in patch2: unchanged: --- linux-5.15.0.orig/drivers/s390/block/dasd_int.h +++ linux-5.15.0/drivers/s390/block/dasd_int.h @@ -188,6 +188,7 @@ void (*callback)(struct dasd_ccw_req *, void *data); void *callback_data; unsigned int proc_bytes; /* bytes for partial completion */ + unsigned int trkcount; /* count formatted tracks */ }; /* @@ -611,6 +612,7 @@ struct list_head format_list; spinlock_t format_lock; + atomic_t trkcount; }; struct dasd_attention_data { @@ -757,6 +759,18 @@ return 0; } +/* + * return the callback data of the original request in case there are + * ERP requests build on top of it + */ +static inline void *dasd_get_callback_data(struct dasd_ccw_req *cqr) +{ + while (cqr->refers) + cqr = cqr->refers; + + return cqr->callback_data; +} + /* externals in dasd.c */ #define DASD_PROFILE_OFF 0 #define DASD_PROFILE_ON 1 only in patch2: unchanged: --- linux-5.15.0.orig/drivers/scsi/bnx2i/bnx2i_hwi.c +++ linux-5.15.0/drivers/scsi/bnx2i/bnx2i_hwi.c @@ -1977,7 +1977,7 @@ if (nopin->cq_req_sn != qp->cqe_exp_seq_sn) break; - if (unlikely(test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx))) { + if (unlikely(test_bit(ISCSI_CONN_FLAG_SUSPEND_RX, &conn->flags))) { if (nopin->op_code == ISCSI_OP_NOOP_IN && nopin->itt == (u16) RESERVED_ITT) { printk(KERN_ALERT "bnx2i: Unsolicited " only in patch2: unchanged: --- linux-5.15.0.orig/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ linux-5.15.0/drivers/scsi/bnx2i/bnx2i_iscsi.c @@ -1721,7 +1721,7 @@ struct iscsi_conn *conn = ep->conn->cls_conn->dd_data; /* Must suspend all rx queue activity for this ep */ - set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx); + set_bit(ISCSI_CONN_FLAG_SUSPEND_RX, &conn->flags); } /* CONN_DISCONNECT timeout may or may not be an issue depending * on what transcribed in TCP layer, different targets behave only in patch2: unchanged: --- linux-5.15.0.orig/drivers/scsi/cxgbi/libcxgbi.c +++ linux-5.15.0/drivers/scsi/cxgbi/libcxgbi.c @@ -1634,11 +1634,11 @@ log_debug(1 << CXGBI_DBG_PDU_RX, "csk 0x%p, conn 0x%p.\n", csk, conn); - if (unlikely(!conn || conn->suspend_rx)) { + if (unlikely(!conn || test_bit(ISCSI_CONN_FLAG_SUSPEND_RX, &conn->flags))) { log_debug(1 << CXGBI_DBG_PDU_RX, - "csk 0x%p, conn 0x%p, id %d, suspend_rx %lu!\n", + "csk 0x%p, conn 0x%p, id %d, conn flags 0x%lx!\n", csk, conn, conn ? conn->id : 0xFF, - conn ? conn->suspend_rx : 0xFF); + conn ? conn->flags : 0xFF); return; } only in patch2: unchanged: --- linux-5.15.0.orig/drivers/scsi/libiscsi_tcp.c +++ linux-5.15.0/drivers/scsi/libiscsi_tcp.c @@ -927,7 +927,7 @@ */ conn->last_recv = jiffies; - if (unlikely(conn->suspend_rx)) { + if (unlikely(test_bit(ISCSI_CONN_FLAG_SUSPEND_RX, &conn->flags))) { ISCSI_DBG_TCP(conn, "Rx suspended!\n"); *status = ISCSI_TCP_SUSPENDED; return 0; only in patch2: unchanged: --- linux-5.15.0.orig/drivers/scsi/qedi/qedi_iscsi.c +++ linux-5.15.0/drivers/scsi/qedi/qedi_iscsi.c @@ -859,6 +859,37 @@ return qedi_iscsi_send_ioreq(task); } +static void qedi_offload_work(struct work_struct *work) +{ + struct qedi_endpoint *qedi_ep = + container_of(work, struct qedi_endpoint, offload_work); + struct qedi_ctx *qedi; + int wait_delay = 5 * HZ; + int ret; + + qedi = qedi_ep->qedi; + + ret = qedi_iscsi_offload_conn(qedi_ep); + if (ret) { + QEDI_ERR(&qedi->dbg_ctx, + "offload error: iscsi_cid=%u, qedi_ep=%p, ret=%d\n", + qedi_ep->iscsi_cid, qedi_ep, ret); + qedi_ep->state = EP_STATE_OFLDCONN_FAILED; + return; + } + + ret = wait_event_interruptible_timeout(qedi_ep->tcp_ofld_wait, + (qedi_ep->state == + EP_STATE_OFLDCONN_COMPL), + wait_delay); + if (ret <= 0 || qedi_ep->state != EP_STATE_OFLDCONN_COMPL) { + qedi_ep->state = EP_STATE_OFLDCONN_FAILED; + QEDI_ERR(&qedi->dbg_ctx, + "Offload conn TIMEOUT iscsi_cid=%u, qedi_ep=%p\n", + qedi_ep->iscsi_cid, qedi_ep); + } +} + static struct iscsi_endpoint * qedi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr, int non_blocking) @@ -907,6 +938,7 @@ } qedi_ep = ep->dd_data; memset(qedi_ep, 0, sizeof(struct qedi_endpoint)); + INIT_WORK(&qedi_ep->offload_work, qedi_offload_work); qedi_ep->state = EP_STATE_IDLE; qedi_ep->iscsi_cid = (u32)-1; qedi_ep->qedi = qedi; @@ -1055,12 +1087,11 @@ qedi_ep = ep->dd_data; qedi = qedi_ep->qedi; + flush_work(&qedi_ep->offload_work); + if (qedi_ep->state == EP_STATE_OFLDCONN_START) goto ep_exit_recover; - if (qedi_ep->state != EP_STATE_OFLDCONN_NONE) - flush_work(&qedi_ep->offload_work); - if (qedi_ep->conn) { qedi_conn = qedi_ep->conn; abrt_conn = qedi_conn->abrt_conn; @@ -1234,37 +1265,6 @@ return rc; } -static void qedi_offload_work(struct work_struct *work) -{ - struct qedi_endpoint *qedi_ep = - container_of(work, struct qedi_endpoint, offload_work); - struct qedi_ctx *qedi; - int wait_delay = 5 * HZ; - int ret; - - qedi = qedi_ep->qedi; - - ret = qedi_iscsi_offload_conn(qedi_ep); - if (ret) { - QEDI_ERR(&qedi->dbg_ctx, - "offload error: iscsi_cid=%u, qedi_ep=%p, ret=%d\n", - qedi_ep->iscsi_cid, qedi_ep, ret); - qedi_ep->state = EP_STATE_OFLDCONN_FAILED; - return; - } - - ret = wait_event_interruptible_timeout(qedi_ep->tcp_ofld_wait, - (qedi_ep->state == - EP_STATE_OFLDCONN_COMPL), - wait_delay); - if ((ret <= 0) || (qedi_ep->state != EP_STATE_OFLDCONN_COMPL)) { - qedi_ep->state = EP_STATE_OFLDCONN_FAILED; - QEDI_ERR(&qedi->dbg_ctx, - "Offload conn TIMEOUT iscsi_cid=%u, qedi_ep=%p\n", - qedi_ep->iscsi_cid, qedi_ep); - } -} - static int qedi_set_path(struct Scsi_Host *shost, struct iscsi_path *path_data) { struct qedi_ctx *qedi; @@ -1380,7 +1380,6 @@ qedi_ep->dst_addr, qedi_ep->dst_port); } - INIT_WORK(&qedi_ep->offload_work, qedi_offload_work); queue_work(qedi->offload_thread, &qedi_ep->offload_work); ret = 0; only in patch2: unchanged: --- linux-5.15.0.orig/drivers/scsi/sr_ioctl.c +++ linux-5.15.0/drivers/scsi/sr_ioctl.c @@ -41,7 +41,7 @@ int result; unsigned char *buffer; - buffer = kmalloc(32, GFP_KERNEL); + buffer = kzalloc(32, GFP_KERNEL); if (!buffer) return -ENOMEM; @@ -55,10 +55,13 @@ cgc.data_direction = DMA_FROM_DEVICE; result = sr_do_ioctl(cd, &cgc); + if (result) + goto err; tochdr->cdth_trk0 = buffer[2]; tochdr->cdth_trk1 = buffer[3]; +err: kfree(buffer); return result; } @@ -71,7 +74,7 @@ int result; unsigned char *buffer; - buffer = kmalloc(32, GFP_KERNEL); + buffer = kzalloc(32, GFP_KERNEL); if (!buffer) return -ENOMEM; @@ -86,6 +89,8 @@ cgc.data_direction = DMA_FROM_DEVICE; result = sr_do_ioctl(cd, &cgc); + if (result) + goto err; tocentry->cdte_ctrl = buffer[5] & 0xf; tocentry->cdte_adr = buffer[5] >> 4; @@ -98,6 +103,7 @@ tocentry->cdte_addr.lba = (((((buffer[8] << 8) + buffer[9]) << 8) + buffer[10]) << 8) + buffer[11]; +err: kfree(buffer); return result; } @@ -384,7 +390,7 @@ { Scsi_CD *cd = cdi->handle; struct packet_command cgc; - char *buffer = kmalloc(32, GFP_KERNEL); + char *buffer = kzalloc(32, GFP_KERNEL); int result; if (!buffer) @@ -400,10 +406,13 @@ cgc.data_direction = DMA_FROM_DEVICE; cgc.timeout = IOCTL_TIMEOUT; result = sr_do_ioctl(cd, &cgc); + if (result) + goto err; memcpy(mcn->medium_catalog_number, buffer + 9, 13); mcn->medium_catalog_number[13] = 0; +err: kfree(buffer); return result; } only in patch2: unchanged: --- linux-5.15.0.orig/drivers/usb/dwc3/drd.c +++ linux-5.15.0/drivers/usb/dwc3/drd.c @@ -571,16 +571,15 @@ { int ret, irq; + if (ROLE_SWITCH && + device_property_read_bool(dwc->dev, "usb-role-switch")) + return dwc3_setup_role_switch(dwc); + dwc->edev = dwc3_get_extcon(dwc); if (IS_ERR(dwc->edev)) return PTR_ERR(dwc->edev); - if (ROLE_SWITCH && - device_property_read_bool(dwc->dev, "usb-role-switch")) { - ret = dwc3_setup_role_switch(dwc); - if (ret < 0) - return ret; - } else if (dwc->edev) { + if (dwc->edev) { dwc->edev_nb.notifier_call = dwc3_drd_notifier; ret = extcon_register_notifier(dwc->edev, EXTCON_USB_HOST, &dwc->edev_nb); only in patch2: unchanged: --- linux-5.15.0.orig/drivers/usb/gadget/configfs.c +++ linux-5.15.0/drivers/usb/gadget/configfs.c @@ -1447,6 +1447,8 @@ usb_ep_autoconfig_reset(cdev->gadget); spin_lock_irqsave(&gi->spinlock, flags); cdev->gadget = NULL; + cdev->deactivations = 0; + gadget->deactivated = false; set_gadget_data(gadget, NULL); spin_unlock_irqrestore(&gi->spinlock, flags); } only in patch2: unchanged: --- linux-5.15.0.orig/drivers/usb/gadget/function/uvc_queue.c +++ linux-5.15.0/drivers/usb/gadget/function/uvc_queue.c @@ -264,6 +264,8 @@ buf->state = UVC_BUF_STATE_ERROR; vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_ERROR); } + queue->buf_used = 0; + /* This must be protected by the irqlock spinlock to avoid race * conditions between uvc_queue_buffer and the disconnection event that * could result in an interruptible wait in uvc_dequeue_buffer. Do not only in patch2: unchanged: --- linux-5.15.0.orig/drivers/usb/misc/uss720.c +++ linux-5.15.0/drivers/usb/misc/uss720.c @@ -71,6 +71,7 @@ dev_dbg(&priv->usbdev->dev, "destroying priv datastructure\n"); usb_put_dev(priv->usbdev); + priv->usbdev = NULL; kfree(priv); } @@ -736,7 +737,6 @@ parport_announce_port(pp); usb_set_intfdata(intf, pp); - usb_put_dev(usbdev); return 0; probe_abort: @@ -754,7 +754,6 @@ usb_set_intfdata(intf, NULL); if (pp) { priv = pp->private_data; - priv->usbdev = NULL; priv->pp = NULL; dev_dbg(&intf->dev, "parport_remove_port\n"); parport_remove_port(pp); only in patch2: unchanged: --- linux-5.15.0.orig/drivers/usb/mtu3/mtu3_dr.c +++ linux-5.15.0/drivers/usb/mtu3/mtu3_dr.c @@ -21,10 +21,8 @@ static void toggle_opstate(struct ssusb_mtk *ssusb) { - if (!ssusb->otg_switch.is_u3_drd) { - mtu3_setbits(ssusb->mac_base, U3D_DEVICE_CONTROL, DC_SESSION); - mtu3_setbits(ssusb->mac_base, U3D_POWER_MANAGEMENT, SOFT_CONN); - } + mtu3_setbits(ssusb->mac_base, U3D_DEVICE_CONTROL, DC_SESSION); + mtu3_setbits(ssusb->mac_base, U3D_POWER_MANAGEMENT, SOFT_CONN); } /* only port0 supports dual-role mode */ only in patch2: unchanged: --- linux-5.15.0.orig/drivers/usb/phy/phy-generic.c +++ linux-5.15.0/drivers/usb/phy/phy-generic.c @@ -268,6 +268,13 @@ return -EPROBE_DEFER; } + nop->vbus_draw = devm_regulator_get_exclusive(dev, "vbus"); + if (PTR_ERR(nop->vbus_draw) == -ENODEV) + nop->vbus_draw = NULL; + if (IS_ERR(nop->vbus_draw)) + return dev_err_probe(dev, PTR_ERR(nop->vbus_draw), + "could not get vbus regulator\n"); + nop->dev = dev; nop->phy.dev = nop->dev; nop->phy.label = "nop-xceiv"; only in patch2: unchanged: --- linux-5.15.0.orig/drivers/usb/serial/whiteheat.c +++ linux-5.15.0/drivers/usb/serial/whiteheat.c @@ -584,9 +584,8 @@ switch (command) { case WHITEHEAT_GET_DTR_RTS: info = usb_get_serial_port_data(port); - memcpy(&info->mcr, command_info->result_buffer, - sizeof(struct whiteheat_dr_info)); - break; + info->mcr = command_info->result_buffer[0]; + break; } } exit: only in patch2: unchanged: --- linux-5.15.0.orig/fs/btrfs/xattr.c +++ linux-5.15.0/fs/btrfs/xattr.c @@ -264,7 +264,8 @@ inode_inc_iversion(inode); inode->i_ctime = current_time(inode); ret = btrfs_update_inode(trans, root, BTRFS_I(inode)); - BUG_ON(ret); + if (ret) + btrfs_abort_transaction(trans, ret); out: if (start_trans) btrfs_end_transaction(trans); @@ -418,7 +419,8 @@ inode_inc_iversion(inode); inode->i_ctime = current_time(inode); ret = btrfs_update_inode(trans, root, BTRFS_I(inode)); - BUG_ON(ret); + if (ret) + btrfs_abort_transaction(trans, ret); } btrfs_end_transaction(trans); only in patch2: unchanged: --- linux-5.15.0.orig/fs/erofs/data.c +++ linux-5.15.0/fs/erofs/data.c @@ -287,7 +287,7 @@ if (!err) return iomap_dio_rw(iocb, to, &erofs_iomap_ops, - NULL, 0); + NULL, 0, 0); if (err < 0) return err; } only in patch2: unchanged: --- linux-5.15.0.orig/fs/ext4/file.c +++ linux-5.15.0/fs/ext4/file.c @@ -74,7 +74,7 @@ return generic_file_read_iter(iocb, to); } - ret = iomap_dio_rw(iocb, to, &ext4_iomap_ops, NULL, 0); + ret = iomap_dio_rw(iocb, to, &ext4_iomap_ops, NULL, 0, 0); inode_unlock_shared(inode); file_accessed(iocb->ki_filp); @@ -566,7 +566,8 @@ if (ilock_shared) iomap_ops = &ext4_iomap_overwrite_ops; ret = iomap_dio_rw(iocb, from, iomap_ops, &ext4_dio_write_ops, - (unaligned_io || extend) ? IOMAP_DIO_FORCE_WAIT : 0); + (unaligned_io || extend) ? IOMAP_DIO_FORCE_WAIT : 0, + 0); if (ret == -ENOTBLK) ret = 0; only in patch2: unchanged: --- linux-5.15.0.orig/fs/ext4/page-io.c +++ linux-5.15.0/fs/ext4/page-io.c @@ -134,8 +134,10 @@ continue; } clear_buffer_async_write(bh); - if (bio->bi_status) + if (bio->bi_status) { + set_buffer_write_io_error(bh); buffer_io_error(bh); + } } while ((bh = bh->b_this_page) != head); spin_unlock_irqrestore(&head->b_uptodate_lock, flags); if (!under_io) { only in patch2: unchanged: --- linux-5.15.0.orig/fs/gfs2/glock.h +++ linux-5.15.0/fs/gfs2/glock.h @@ -150,6 +150,8 @@ list_for_each_entry(gh, &gl->gl_holders, gh_list) { if (!test_bit(HIF_HOLDER, &gh->gh_iflags)) break; + if (test_bit(HIF_MAY_DEMOTE, &gh->gh_iflags)) + continue; if (gh->gh_owner_pid == pid) goto out; } @@ -325,6 +327,24 @@ spin_unlock(&gl->gl_lockref.lock); } +static inline void gfs2_holder_allow_demote(struct gfs2_holder *gh) +{ + struct gfs2_glock *gl = gh->gh_gl; + + spin_lock(&gl->gl_lockref.lock); + set_bit(HIF_MAY_DEMOTE, &gh->gh_iflags); + spin_unlock(&gl->gl_lockref.lock); +} + +static inline void gfs2_holder_disallow_demote(struct gfs2_holder *gh) +{ + struct gfs2_glock *gl = gh->gh_gl; + + spin_lock(&gl->gl_lockref.lock); + clear_bit(HIF_MAY_DEMOTE, &gh->gh_iflags); + spin_unlock(&gl->gl_lockref.lock); +} + extern void gfs2_inode_remember_delete(struct gfs2_glock *gl, u64 generation); extern bool gfs2_inode_already_deleted(struct gfs2_glock *gl, u64 generation); only in patch2: unchanged: --- linux-5.15.0.orig/fs/gfs2/incore.h +++ linux-5.15.0/fs/gfs2/incore.h @@ -252,6 +252,7 @@ enum { /* States */ + HIF_MAY_DEMOTE = 1, HIF_HOLDER = 6, /* Set for gh that "holds" the glock */ HIF_WAIT = 10, }; @@ -386,9 +387,8 @@ u64 i_generation; u64 i_eattr; unsigned long i_flags; /* GIF_... */ - struct gfs2_glock *i_gl; /* Move into i_gh? */ + struct gfs2_glock *i_gl; struct gfs2_holder i_iopen_gh; - struct gfs2_holder i_gh; /* for prepare/commit_write only */ struct gfs2_qadata *i_qadata; /* quota allocation data */ struct gfs2_holder i_rgd_gh; struct gfs2_blkreserv i_res; /* rgrp multi-block reservation */ only in patch2: unchanged: --- linux-5.15.0.orig/fs/internal.h +++ linux-5.15.0/fs/internal.h @@ -24,7 +24,6 @@ extern void __init bdev_cache_init(void); extern int __sync_blockdev(struct block_device *bdev, int wait); -void iterate_bdevs(void (*)(struct block_device *, void *), void *); void emergency_thaw_bdev(struct super_block *sb); #else static inline void bdev_cache_init(void) @@ -35,10 +34,6 @@ { return 0; } -static inline void iterate_bdevs(void (*f)(struct block_device *, void *), - void *arg) -{ -} static inline int emergency_thaw_bdev(struct super_block *sb) { return 0; only in patch2: unchanged: --- linux-5.15.0.orig/fs/iomap/direct-io.c +++ linux-5.15.0/fs/iomap/direct-io.c @@ -31,6 +31,7 @@ atomic_t ref; unsigned flags; int error; + size_t done_before; bool wait_for_completion; union { @@ -124,6 +125,9 @@ if (ret > 0 && (dio->flags & IOMAP_DIO_NEED_SYNC)) ret = generic_write_sync(iocb, ret); + if (ret > 0) + ret += dio->done_before; + kfree(dio); return ret; @@ -371,6 +375,8 @@ loff_t length = iov_iter_zero(iomap_length(iter), dio->submit.iter); dio->size += length; + if (!length) + return -EFAULT; return length; } @@ -402,6 +408,8 @@ copied = copy_to_iter(inline_data, length, iter); } dio->size += copied; + if (!copied) + return -EFAULT; return copied; } @@ -446,13 +454,21 @@ * may be pure data writes. In that case, we still need to do a full data sync * completion. * + * When page faults are disabled and @dio_flags includes IOMAP_DIO_PARTIAL, + * __iomap_dio_rw can return a partial result if it encounters a non-resident + * page in @iter after preparing a transfer. In that case, the non-resident + * pages can be faulted in and the request resumed with @done_before set to the + * number of bytes previously transferred. The request will then complete with + * the correct total number of bytes transferred; this is essential for + * completing partial requests asynchronously. + * * Returns -ENOTBLK In case of a page invalidation invalidation failure for * writes. The callers needs to fall back to buffered I/O in this case. */ struct iomap_dio * __iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter, const struct iomap_ops *ops, const struct iomap_dio_ops *dops, - unsigned int dio_flags) + unsigned int dio_flags, size_t done_before) { struct address_space *mapping = iocb->ki_filp->f_mapping; struct inode *inode = file_inode(iocb->ki_filp); @@ -482,6 +498,7 @@ dio->dops = dops; dio->error = 0; dio->flags = 0; + dio->done_before = done_before; dio->submit.iter = iter; dio->submit.waiter = current; @@ -577,6 +594,12 @@ if (iov_iter_rw(iter) == READ && iomi.pos >= dio->i_size) iov_iter_revert(iter, iomi.pos - dio->i_size); + if (ret == -EFAULT && dio->size && (dio_flags & IOMAP_DIO_PARTIAL)) { + if (!(iocb->ki_flags & IOCB_NOWAIT)) + wait_for_completion = true; + ret = 0; + } + /* magic error code to fall back to buffered I/O */ if (ret == -ENOTBLK) { wait_for_completion = true; @@ -642,11 +665,11 @@ ssize_t iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter, const struct iomap_ops *ops, const struct iomap_dio_ops *dops, - unsigned int dio_flags) + unsigned int dio_flags, size_t done_before) { struct iomap_dio *dio; - dio = __iomap_dio_rw(iocb, iter, ops, dops, dio_flags); + dio = __iomap_dio_rw(iocb, iter, ops, dops, dio_flags, done_before); if (IS_ERR_OR_NULL(dio)) return PTR_ERR_OR_ZERO(dio); return iomap_dio_complete(dio); only in patch2: unchanged: --- linux-5.15.0.orig/fs/ksmbd/vfs_cache.c +++ linux-5.15.0/fs/ksmbd/vfs_cache.c @@ -497,6 +497,7 @@ list_for_each_entry(lfp, &ci->m_fp_list, node) { if (inode == file_inode(lfp->filp)) { atomic_dec(&ci->m_count); + lfp = ksmbd_fp_get(lfp); read_unlock(&ci->m_lock); return lfp; } only in patch2: unchanged: --- linux-5.15.0.orig/fs/ntfs/file.c +++ linux-5.15.0/fs/ntfs/file.c @@ -1829,7 +1829,7 @@ * pages being swapped out between us bringing them into memory * and doing the actual copying. */ - if (unlikely(iov_iter_fault_in_readable(i, bytes))) { + if (unlikely(fault_in_iov_iter_readable(i, bytes))) { status = -EFAULT; break; } only in patch2: unchanged: --- linux-5.15.0.orig/fs/ntfs3/file.c +++ linux-5.15.0/fs/ntfs3/file.c @@ -989,7 +989,7 @@ frame_vbo = pos & ~(frame_size - 1); index = frame_vbo >> PAGE_SHIFT; - if (unlikely(iov_iter_fault_in_readable(from, bytes))) { + if (unlikely(fault_in_iov_iter_readable(from, bytes))) { err = -EFAULT; goto out; } only in patch2: unchanged: --- linux-5.15.0.orig/fs/stat.c +++ linux-5.15.0/fs/stat.c @@ -334,9 +334,6 @@ # define choose_32_64(a,b) b #endif -#define valid_dev(x) choose_32_64(old_valid_dev(x),true) -#define encode_dev(x) choose_32_64(old_encode_dev,new_encode_dev)(x) - #ifndef INIT_STRUCT_STAT_PADDING # define INIT_STRUCT_STAT_PADDING(st) memset(&st, 0, sizeof(st)) #endif @@ -345,7 +342,9 @@ { struct stat tmp; - if (!valid_dev(stat->dev) || !valid_dev(stat->rdev)) + if (sizeof(tmp.st_dev) < 4 && !old_valid_dev(stat->dev)) + return -EOVERFLOW; + if (sizeof(tmp.st_rdev) < 4 && !old_valid_dev(stat->rdev)) return -EOVERFLOW; #if BITS_PER_LONG == 32 if (stat->size > MAX_NON_LFS) @@ -353,7 +352,7 @@ #endif INIT_STRUCT_STAT_PADDING(tmp); - tmp.st_dev = encode_dev(stat->dev); + tmp.st_dev = new_encode_dev(stat->dev); tmp.st_ino = stat->ino; if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino) return -EOVERFLOW; @@ -363,7 +362,7 @@ return -EOVERFLOW; SET_UID(tmp.st_uid, from_kuid_munged(current_user_ns(), stat->uid)); SET_GID(tmp.st_gid, from_kgid_munged(current_user_ns(), stat->gid)); - tmp.st_rdev = encode_dev(stat->rdev); + tmp.st_rdev = new_encode_dev(stat->rdev); tmp.st_size = stat->size; tmp.st_atime = stat->atime.tv_sec; tmp.st_mtime = stat->mtime.tv_sec; @@ -644,11 +643,13 @@ { struct compat_stat tmp; - if (!old_valid_dev(stat->dev) || !old_valid_dev(stat->rdev)) + if (sizeof(tmp.st_dev) < 4 && !old_valid_dev(stat->dev)) + return -EOVERFLOW; + if (sizeof(tmp.st_rdev) < 4 && !old_valid_dev(stat->rdev)) return -EOVERFLOW; memset(&tmp, 0, sizeof(tmp)); - tmp.st_dev = old_encode_dev(stat->dev); + tmp.st_dev = new_encode_dev(stat->dev); tmp.st_ino = stat->ino; if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino) return -EOVERFLOW; @@ -658,7 +659,7 @@ return -EOVERFLOW; SET_UID(tmp.st_uid, from_kuid_munged(current_user_ns(), stat->uid)); SET_GID(tmp.st_gid, from_kgid_munged(current_user_ns(), stat->gid)); - tmp.st_rdev = old_encode_dev(stat->rdev); + tmp.st_rdev = new_encode_dev(stat->rdev); if ((u64) stat->size > MAX_NON_LFS) return -EOVERFLOW; tmp.st_size = stat->size; only in patch2: unchanged: --- linux-5.15.0.orig/fs/xfs/xfs_file.c +++ linux-5.15.0/fs/xfs/xfs_file.c @@ -259,7 +259,7 @@ ret = xfs_ilock_iocb(iocb, XFS_IOLOCK_SHARED); if (ret) return ret; - ret = iomap_dio_rw(iocb, to, &xfs_read_iomap_ops, NULL, 0); + ret = iomap_dio_rw(iocb, to, &xfs_read_iomap_ops, NULL, 0, 0); xfs_iunlock(ip, XFS_IOLOCK_SHARED); return ret; @@ -569,7 +569,7 @@ } trace_xfs_file_direct_write(iocb, from); ret = iomap_dio_rw(iocb, from, &xfs_direct_write_iomap_ops, - &xfs_dio_write_ops, 0); + &xfs_dio_write_ops, 0, 0); out_unlock: if (iolock) xfs_iunlock(ip, iolock); @@ -647,7 +647,7 @@ trace_xfs_file_direct_write(iocb, from); ret = iomap_dio_rw(iocb, from, &xfs_direct_write_iomap_ops, - &xfs_dio_write_ops, flags); + &xfs_dio_write_ops, flags, 0); /* * Retry unaligned I/O with exclusive blocking semantics if the DIO only in patch2: unchanged: --- linux-5.15.0.orig/fs/xfs/xfs_super.c +++ linux-5.15.0/fs/xfs/xfs_super.c @@ -729,6 +729,7 @@ int wait) { struct xfs_mount *mp = XFS_M(sb); + int error; trace_xfs_fs_sync_fs(mp, __return_address); @@ -738,7 +739,10 @@ if (!wait) return 0; - xfs_log_force(mp, XFS_LOG_SYNC); + error = xfs_log_force(mp, XFS_LOG_SYNC); + if (error) + return error; + if (laptop_mode) { /* * The disk must be active because we're syncing. only in patch2: unchanged: --- linux-5.15.0.orig/include/linux/etherdevice.h +++ linux-5.15.0/include/linux/etherdevice.h @@ -127,7 +127,7 @@ #endif } -static inline bool is_multicast_ether_addr_64bits(const u8 addr[6+2]) +static inline bool is_multicast_ether_addr_64bits(const u8 *addr) { #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64 #ifdef __BIG_ENDIAN @@ -364,8 +364,7 @@ * Please note that alignment of addr1 & addr2 are only guaranteed to be 16 bits. */ -static inline bool ether_addr_equal_64bits(const u8 addr1[6+2], - const u8 addr2[6+2]) +static inline bool ether_addr_equal_64bits(const u8 *addr1, const u8 *addr2) { #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64 u64 fold = (*(const u64 *)addr1) ^ (*(const u64 *)addr2); only in patch2: unchanged: --- linux-5.15.0.orig/include/linux/iomap.h +++ linux-5.15.0/include/linux/iomap.h @@ -330,12 +330,19 @@ */ #define IOMAP_DIO_OVERWRITE_ONLY (1 << 1) +/* + * When a page fault occurs, return a partial synchronous result and allow + * the caller to retry the rest of the operation after dealing with the page + * fault. + */ +#define IOMAP_DIO_PARTIAL (1 << 2) + ssize_t iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter, const struct iomap_ops *ops, const struct iomap_dio_ops *dops, - unsigned int dio_flags); + unsigned int dio_flags, size_t done_before); struct iomap_dio *__iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter, const struct iomap_ops *ops, const struct iomap_dio_ops *dops, - unsigned int dio_flags); + unsigned int dio_flags, size_t done_before); ssize_t iomap_dio_complete(struct iomap_dio *dio); int iomap_dio_iopoll(struct kiocb *kiocb, bool spin); only in patch2: unchanged: --- linux-5.15.0.orig/include/linux/kernel.h +++ linux-5.15.0/include/linux/kernel.h @@ -277,7 +277,7 @@ return buf; } -extern int hex_to_bin(char ch); +extern int hex_to_bin(unsigned char ch); extern int __must_check hex2bin(u8 *dst, const char *src, size_t count); extern char *bin2hex(char *dst, const void *src, size_t count); only in patch2: unchanged: --- linux-5.15.0.orig/include/linux/mtd/mtd.h +++ linux-5.15.0/include/linux/mtd/mtd.h @@ -394,10 +394,8 @@ /* List of partitions attached to this MTD device */ struct list_head partitions; - union { - struct mtd_part part; - struct mtd_master master; - }; + struct mtd_part part; + struct mtd_master master; }; static inline struct mtd_info *mtd_get_master(struct mtd_info *mtd) only in patch2: unchanged: --- linux-5.15.0.orig/include/linux/netfilter/nf_conntrack_common.h +++ linux-5.15.0/include/linux/netfilter/nf_conntrack_common.h @@ -2,7 +2,7 @@ #ifndef _NF_CONNTRACK_COMMON_H #define _NF_CONNTRACK_COMMON_H -#include +#include #include struct ip_conntrack_stat { @@ -25,19 +25,21 @@ #define NFCT_PTRMASK ~(NFCT_INFOMASK) struct nf_conntrack { - atomic_t use; + refcount_t use; }; void nf_conntrack_destroy(struct nf_conntrack *nfct); + +/* like nf_ct_put, but without module dependency on nf_conntrack */ static inline void nf_conntrack_put(struct nf_conntrack *nfct) { - if (nfct && atomic_dec_and_test(&nfct->use)) + if (nfct && refcount_dec_and_test(&nfct->use)) nf_conntrack_destroy(nfct); } static inline void nf_conntrack_get(struct nf_conntrack *nfct) { if (nfct) - atomic_inc(&nfct->use); + refcount_inc(&nfct->use); } #endif /* _NF_CONNTRACK_COMMON_H */ only in patch2: unchanged: --- linux-5.15.0.orig/include/linux/pagemap.h +++ linux-5.15.0/include/linux/pagemap.h @@ -733,61 +733,11 @@ extern void add_page_wait_queue(struct page *page, wait_queue_entry_t *waiter); /* - * Fault everything in given userspace address range in. + * Fault in userspace address range. */ -static inline int fault_in_pages_writeable(char __user *uaddr, size_t size) -{ - char __user *end = uaddr + size - 1; - - if (unlikely(size == 0)) - return 0; - - if (unlikely(uaddr > end)) - return -EFAULT; - /* - * Writing zeroes into userspace here is OK, because we know that if - * the zero gets there, we'll be overwriting it. - */ - do { - if (unlikely(__put_user(0, uaddr) != 0)) - return -EFAULT; - uaddr += PAGE_SIZE; - } while (uaddr <= end); - - /* Check whether the range spilled into the next page. */ - if (((unsigned long)uaddr & PAGE_MASK) == - ((unsigned long)end & PAGE_MASK)) - return __put_user(0, end); - - return 0; -} - -static inline int fault_in_pages_readable(const char __user *uaddr, size_t size) -{ - volatile char c; - const char __user *end = uaddr + size - 1; - - if (unlikely(size == 0)) - return 0; - - if (unlikely(uaddr > end)) - return -EFAULT; - - do { - if (unlikely(__get_user(c, uaddr) != 0)) - return -EFAULT; - uaddr += PAGE_SIZE; - } while (uaddr <= end); - - /* Check whether the range spilled into the next page. */ - if (((unsigned long)uaddr & PAGE_MASK) == - ((unsigned long)end & PAGE_MASK)) { - return __get_user(c, end); - } - - (void)c; - return 0; -} +size_t fault_in_writeable(char __user *uaddr, size_t size); +size_t fault_in_safe_writeable(const char __user *uaddr, size_t size); +size_t fault_in_readable(const char __user *uaddr, size_t size); int add_to_page_cache_locked(struct page *page, struct address_space *mapping, pgoff_t index, gfp_t gfp_mask); only in patch2: unchanged: --- linux-5.15.0.orig/include/linux/sched/mm.h +++ linux-5.15.0/include/linux/sched/mm.h @@ -106,6 +106,14 @@ #endif /* CONFIG_MEMCG */ #ifdef CONFIG_MMU +#ifndef arch_get_mmap_end +#define arch_get_mmap_end(addr) (TASK_SIZE) +#endif + +#ifndef arch_get_mmap_base +#define arch_get_mmap_base(addr, base) (base) +#endif + extern void arch_pick_mmap_layout(struct mm_struct *mm, struct rlimit *rlim_stack); extern unsigned long only in patch2: unchanged: --- linux-5.15.0.orig/include/linux/uio.h +++ linux-5.15.0/include/linux/uio.h @@ -35,6 +35,7 @@ struct iov_iter { u8 iter_type; + bool nofault; bool data_source; size_t iov_offset; size_t count; @@ -133,7 +134,8 @@ size_t bytes, struct iov_iter *i); void iov_iter_advance(struct iov_iter *i, size_t bytes); void iov_iter_revert(struct iov_iter *i, size_t bytes); -int iov_iter_fault_in_readable(const struct iov_iter *i, size_t bytes); +size_t fault_in_iov_iter_readable(const struct iov_iter *i, size_t bytes); +size_t fault_in_iov_iter_writeable(const struct iov_iter *i, size_t bytes); size_t iov_iter_single_seg_count(const struct iov_iter *i); size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes, struct iov_iter *i); only in patch2: unchanged: --- linux-5.15.0.orig/include/linux/vmw_vmci_defs.h +++ linux-5.15.0/include/linux/vmw_vmci_defs.h @@ -12,15 +12,20 @@ #include /* Register offsets. */ -#define VMCI_STATUS_ADDR 0x00 -#define VMCI_CONTROL_ADDR 0x04 -#define VMCI_ICR_ADDR 0x08 -#define VMCI_IMR_ADDR 0x0c -#define VMCI_DATA_OUT_ADDR 0x10 -#define VMCI_DATA_IN_ADDR 0x14 -#define VMCI_CAPS_ADDR 0x18 -#define VMCI_RESULT_LOW_ADDR 0x1c -#define VMCI_RESULT_HIGH_ADDR 0x20 +#define VMCI_STATUS_ADDR 0x00 +#define VMCI_CONTROL_ADDR 0x04 +#define VMCI_ICR_ADDR 0x08 +#define VMCI_IMR_ADDR 0x0c +#define VMCI_DATA_OUT_ADDR 0x10 +#define VMCI_DATA_IN_ADDR 0x14 +#define VMCI_CAPS_ADDR 0x18 +#define VMCI_RESULT_LOW_ADDR 0x1c +#define VMCI_RESULT_HIGH_ADDR 0x20 +#define VMCI_DATA_OUT_LOW_ADDR 0x24 +#define VMCI_DATA_OUT_HIGH_ADDR 0x28 +#define VMCI_DATA_IN_LOW_ADDR 0x2c +#define VMCI_DATA_IN_HIGH_ADDR 0x30 +#define VMCI_GUEST_PAGE_SHIFT 0x34 /* Max number of devices. */ #define VMCI_MAX_DEVICES 1 @@ -39,17 +44,27 @@ #define VMCI_CAPS_DATAGRAM BIT(2) #define VMCI_CAPS_NOTIFICATIONS BIT(3) #define VMCI_CAPS_PPN64 BIT(4) +#define VMCI_CAPS_DMA_DATAGRAM BIT(5) /* Interrupt Cause register bits. */ #define VMCI_ICR_DATAGRAM BIT(0) #define VMCI_ICR_NOTIFICATION BIT(1) +#define VMCI_ICR_DMA_DATAGRAM BIT(2) /* Interrupt Mask register bits. */ #define VMCI_IMR_DATAGRAM BIT(0) #define VMCI_IMR_NOTIFICATION BIT(1) +#define VMCI_IMR_DMA_DATAGRAM BIT(2) -/* Maximum MSI/MSI-X interrupt vectors in the device. */ -#define VMCI_MAX_INTRS 2 +/* + * Maximum MSI/MSI-X interrupt vectors in the device. + * If VMCI_CAPS_DMA_DATAGRAM is supported by the device, + * VMCI_MAX_INTRS_DMA_DATAGRAM vectors are available, + * otherwise only VMCI_MAX_INTRS_NOTIFICATION. + */ +#define VMCI_MAX_INTRS_NOTIFICATION 2 +#define VMCI_MAX_INTRS_DMA_DATAGRAM 3 +#define VMCI_MAX_INTRS VMCI_MAX_INTRS_DMA_DATAGRAM /* * Supported interrupt vectors. There is one for each ICR value above, @@ -58,6 +73,7 @@ enum { VMCI_INTR_DATAGRAM = 0, VMCI_INTR_NOTIFICATION = 1, + VMCI_INTR_DMA_DATAGRAM = 2, }; /* @@ -83,6 +99,52 @@ #define VMCI_MAX_PINNED_QP_MEMORY ((size_t)(32 * 1024)) /* + * The version of the VMCI device that supports MMIO access to registers + * requests 256KB for BAR1 whereas the version of VMCI that supports + * MSI/MSI-X only requests 8KB. The layout of the larger 256KB region is: + * - the first 128KB are used for MSI/MSI-X. + * - the following 64KB are used for MMIO register access. + * - the remaining 64KB are unused. + */ +#define VMCI_WITH_MMIO_ACCESS_BAR_SIZE ((size_t)(256 * 1024)) +#define VMCI_MMIO_ACCESS_OFFSET ((size_t)(128 * 1024)) +#define VMCI_MMIO_ACCESS_SIZE ((size_t)(64 * 1024)) + +/* + * For VMCI devices supporting the VMCI_CAPS_DMA_DATAGRAM capability, the + * sending and receiving of datagrams can be performed using DMA to/from + * a driver allocated buffer. + * Sending and receiving will be handled as follows: + * - when sending datagrams, the driver initializes the buffer where the + * data part will refer to the outgoing VMCI datagram, sets the busy flag + * to 1 and writes the address of the buffer to VMCI_DATA_OUT_HIGH_ADDR + * and VMCI_DATA_OUT_LOW_ADDR. Writing to VMCI_DATA_OUT_LOW_ADDR triggers + * the device processing of the buffer. When the device has processed the + * buffer, it will write the result value to the buffer and then clear the + * busy flag. + * - when receiving datagrams, the driver initializes the buffer where the + * data part will describe the receive buffer, clears the busy flag and + * writes the address of the buffer to VMCI_DATA_IN_HIGH_ADDR and + * VMCI_DATA_IN_LOW_ADDR. Writing to VMCI_DATA_IN_LOW_ADDR triggers the + * device processing of the buffer. The device will copy as many available + * datagrams into the buffer as possible, and then sets the busy flag. + * When the busy flag is set, the driver will process the datagrams in the + * buffer. + */ +struct vmci_data_in_out_header { + uint32_t busy; + uint32_t opcode; + uint32_t size; + uint32_t rsvd; + uint64_t result; +}; + +struct vmci_sg_elem { + uint64_t addr; + uint64_t size; +}; + +/* * We have a fixed set of resource IDs available in the VMX. * This allows us to have a very simple implementation since we statically * know how many will create datagram handles. If a new caller arrives and only in patch2: unchanged: --- linux-5.15.0.orig/include/net/ip6_tunnel.h +++ linux-5.15.0/include/net/ip6_tunnel.h @@ -57,7 +57,7 @@ /* These fields used only by GRE */ __u32 i_seqno; /* The last seen seqno */ - __u32 o_seqno; /* The last output seqno */ + atomic_t o_seqno; /* The last output seqno */ int hlen; /* tun_hlen + encap_hlen */ int tun_hlen; /* Precalculated header length */ int encap_hlen; /* Encap header length (FOU,GUE) */ only in patch2: unchanged: --- linux-5.15.0.orig/include/net/mac80211.h +++ linux-5.15.0/include/net/mac80211.h @@ -7,7 +7,7 @@ * Copyright 2007-2010 Johannes Berg * Copyright 2013-2014 Intel Mobile Communications GmbH * Copyright (C) 2015 - 2017 Intel Deutschland GmbH - * Copyright (C) 2018 - 2021 Intel Corporation + * Copyright (C) 2018 - 2022 Intel Corporation */ #ifndef MAC80211_H @@ -875,6 +875,17 @@ IEEE80211_TX_CTRL_DONT_REORDER = BIT(8), }; +/** + * enum mac80211_tx_status_flags - flags to describe transmit status + * + * @IEEE80211_TX_STATUS_ACK_SIGNAL_VALID: ACK signal is valid + * + * These flags are used in tx_info->status.flags. + */ +enum mac80211_tx_status_flags { + IEEE80211_TX_STATUS_ACK_SIGNAL_VALID = BIT(0), +}; + /* * This definition is used as a mask to clear all temporary flags, which are * set by the tx handlers for each transmission attempt by the mac80211 stack. @@ -1038,7 +1049,7 @@ * @status.antenna: (legacy, kept only for iwlegacy) * @status.tx_time: airtime consumed for transmission; note this is only * used for WMM AC, not for airtime fairness - * @status.is_valid_ack_signal: ACK signal is valid + * @status.flags: status flags, see &enum mac80211_tx_status_flags * @status.status_driver_data: driver use area * @ack: union part for pure ACK data * @ack.cookie: cookie for the ACK @@ -1091,8 +1102,8 @@ u8 ampdu_len; u8 antenna; u16 tx_time; - bool is_valid_ack_signal; - void *status_driver_data[19 / sizeof(void *)]; + u8 flags; + void *status_driver_data[18 / sizeof(void *)]; } status; struct { struct ieee80211_tx_rate driver_rates[ only in patch2: unchanged: --- linux-5.15.0.orig/include/scsi/libiscsi.h +++ linux-5.15.0/include/scsi/libiscsi.h @@ -52,8 +52,10 @@ #define ISID_SIZE 6 -/* Connection suspend "bit" */ -#define ISCSI_SUSPEND_BIT 1 +/* Connection flags */ +#define ISCSI_CONN_FLAG_SUSPEND_TX BIT(0) +#define ISCSI_CONN_FLAG_SUSPEND_RX BIT(1) +#define ISCSI_CONN_FLAG_BOUND BIT(2) #define ISCSI_ITT_MASK 0x1fff #define ISCSI_TOTAL_CMDS_MAX 4096 @@ -199,8 +201,7 @@ struct list_head cmdqueue; /* data-path cmd queue */ struct list_head requeue; /* tasks needing another run */ struct work_struct xmitwork; /* per-conn. xmit workqueue */ - unsigned long suspend_tx; /* suspend Tx */ - unsigned long suspend_rx; /* suspend Rx */ + unsigned long flags; /* ISCSI_CONN_FLAGs */ /* negotiated params */ unsigned max_recv_dlength; /* initiator_max_recv_dsl*/ only in patch2: unchanged: --- linux-5.15.0.orig/kernel/bpf/map_iter.c +++ linux-5.15.0/kernel/bpf/map_iter.c @@ -174,9 +174,9 @@ .ctx_arg_info_size = 2, .ctx_arg_info = { { offsetof(struct bpf_iter__bpf_map_elem, key), - PTR_TO_RDONLY_BUF_OR_NULL }, + PTR_TO_BUF | PTR_MAYBE_NULL | MEM_RDONLY }, { offsetof(struct bpf_iter__bpf_map_elem, value), - PTR_TO_RDWR_BUF_OR_NULL }, + PTR_TO_BUF | PTR_MAYBE_NULL }, }, }; only in patch2: unchanged: --- linux-5.15.0.orig/kernel/dma/mapping.c +++ linux-5.15.0/kernel/dma/mapping.c @@ -296,10 +296,6 @@ if (WARN_ON_ONCE(!dev->dma_mask)) return DMA_MAPPING_ERROR; - /* Don't allow RAM to be mapped */ - if (WARN_ON_ONCE(pfn_valid(PHYS_PFN(phys_addr)))) - return DMA_MAPPING_ERROR; - if (dma_map_direct(dev, ops)) addr = dma_direct_map_resource(dev, phys_addr, size, dir, attrs); else if (ops->map_resource) only in patch2: unchanged: --- linux-5.15.0.orig/kernel/events/internal.h +++ linux-5.15.0/kernel/events/internal.h @@ -116,6 +116,11 @@ } #endif +static inline int data_page_nr(struct perf_buffer *rb) +{ + return rb->nr_pages << page_order(rb); +} + static inline unsigned long perf_data_size(struct perf_buffer *rb) { return rb->nr_pages << (PAGE_SHIFT + page_order(rb)); only in patch2: unchanged: --- linux-5.15.0.orig/kernel/events/ring_buffer.c +++ linux-5.15.0/kernel/events/ring_buffer.c @@ -859,11 +859,6 @@ } #else -static int data_page_nr(struct perf_buffer *rb) -{ - return rb->nr_pages << page_order(rb); -} - static struct page * __perf_mmap_to_page(struct perf_buffer *rb, unsigned long pgoff) { only in patch2: unchanged: --- linux-5.15.0.orig/kernel/irq/internals.h +++ linux-5.15.0/kernel/irq/internals.h @@ -29,12 +29,14 @@ * IRQTF_WARNED - warning "IRQ_WAKE_THREAD w/o thread_fn" has been printed * IRQTF_AFFINITY - irq thread is requested to adjust affinity * IRQTF_FORCED_THREAD - irq action is force threaded + * IRQTF_READY - signals that irq thread is ready */ enum { IRQTF_RUNTHREAD, IRQTF_WARNED, IRQTF_AFFINITY, IRQTF_FORCED_THREAD, + IRQTF_READY, }; /* only in patch2: unchanged: --- linux-5.15.0.orig/kernel/irq/irqdesc.c +++ linux-5.15.0/kernel/irq/irqdesc.c @@ -407,6 +407,7 @@ lockdep_set_class(&desc->lock, &irq_desc_lock_class); mutex_init(&desc->request_mutex); init_rcu_head(&desc->rcu); + init_waitqueue_head(&desc->wait_for_threads); desc_set_defaults(irq, desc, node, affinity, owner); irqd_set(&desc->irq_data, flags); @@ -575,6 +576,7 @@ raw_spin_lock_init(&desc[i].lock); lockdep_set_class(&desc[i].lock, &irq_desc_lock_class); mutex_init(&desc[i].request_mutex); + init_waitqueue_head(&desc[i].wait_for_threads); desc_set_defaults(i, &desc[i], node, NULL, NULL); } return arch_early_irq_init(); only in patch2: unchanged: --- linux-5.15.0.orig/kernel/irq/manage.c +++ linux-5.15.0/kernel/irq/manage.c @@ -1249,6 +1249,31 @@ } /* + * Internal function to notify that a interrupt thread is ready. + */ +static void irq_thread_set_ready(struct irq_desc *desc, + struct irqaction *action) +{ + set_bit(IRQTF_READY, &action->thread_flags); + wake_up(&desc->wait_for_threads); +} + +/* + * Internal function to wake up a interrupt thread and wait until it is + * ready. + */ +static void wake_up_and_wait_for_irq_thread_ready(struct irq_desc *desc, + struct irqaction *action) +{ + if (!action || !action->thread) + return; + + wake_up_process(action->thread); + wait_event(desc->wait_for_threads, + test_bit(IRQTF_READY, &action->thread_flags)); +} + +/* * Interrupt handler thread */ static int irq_thread(void *data) @@ -1259,6 +1284,8 @@ irqreturn_t (*handler_fn)(struct irq_desc *desc, struct irqaction *action); + irq_thread_set_ready(desc, action); + if (force_irqthreads() && test_bit(IRQTF_FORCED_THREAD, &action->thread_flags)) handler_fn = irq_forced_thread_fn; @@ -1683,8 +1710,6 @@ } if (!shared) { - init_waitqueue_head(&desc->wait_for_threads); - /* Setup the type (level, edge polarity) if configured: */ if (new->flags & IRQF_TRIGGER_MASK) { ret = __irq_set_trigger(desc, @@ -1780,14 +1805,8 @@ irq_setup_timings(desc, new); - /* - * Strictly no need to wake it up, but hung_task complains - * when no hard interrupt wakes the thread up. - */ - if (new->thread) - wake_up_process(new->thread); - if (new->secondary) - wake_up_process(new->secondary->thread); + wake_up_and_wait_for_irq_thread_ready(desc, new); + wake_up_and_wait_for_irq_thread_ready(desc, new->secondary); register_irq_proc(irq, desc); new->dir = NULL; only in patch2: unchanged: --- linux-5.15.0.orig/lib/hexdump.c +++ linux-5.15.0/lib/hexdump.c @@ -22,15 +22,33 @@ * * hex_to_bin() converts one hex digit to its actual value or -1 in case of bad * input. + * + * This function is used to load cryptographic keys, so it is coded in such a + * way that there are no conditions or memory accesses that depend on data. + * + * Explanation of the logic: + * (ch - '9' - 1) is negative if ch <= '9' + * ('0' - 1 - ch) is negative if ch >= '0' + * we "and" these two values, so the result is negative if ch is in the range + * '0' ... '9' + * we are only interested in the sign, so we do a shift ">> 8"; note that right + * shift of a negative value is implementation-defined, so we cast the + * value to (unsigned) before the shift --- we have 0xffffff if ch is in + * the range '0' ... '9', 0 otherwise + * we "and" this value with (ch - '0' + 1) --- we have a value 1 ... 10 if ch is + * in the range '0' ... '9', 0 otherwise + * we add this value to -1 --- we have a value 0 ... 9 if ch is in the range '0' + * ... '9', -1 otherwise + * the next line is similar to the previous one, but we need to decode both + * uppercase and lowercase letters, so we use (ch & 0xdf), which converts + * lowercase to uppercase */ -int hex_to_bin(char ch) +int hex_to_bin(unsigned char ch) { - if ((ch >= '0') && (ch <= '9')) - return ch - '0'; - ch = tolower(ch); - if ((ch >= 'a') && (ch <= 'f')) - return ch - 'a' + 10; - return -1; + unsigned char cu = ch & 0xdf; + return -1 + + ((ch - '0' + 1) & (unsigned)((ch - '9' - 1) & ('0' - 1 - ch)) >> 8) + + ((cu - 'A' + 11) & (unsigned)((cu - 'F' - 1) & ('A' - 1 - cu)) >> 8); } EXPORT_SYMBOL(hex_to_bin); @@ -45,10 +63,13 @@ int hex2bin(u8 *dst, const char *src, size_t count) { while (count--) { - int hi = hex_to_bin(*src++); - int lo = hex_to_bin(*src++); + int hi, lo; - if ((hi < 0) || (lo < 0)) + hi = hex_to_bin(*src++); + if (unlikely(hi < 0)) + return -EINVAL; + lo = hex_to_bin(*src++); + if (unlikely(lo < 0)) return -EINVAL; *dst++ = (hi << 4) | lo; only in patch2: unchanged: --- linux-5.15.0.orig/mm/kfence/report.c +++ linux-5.15.0/mm/kfence/report.c @@ -273,3 +273,50 @@ /* We encountered a memory safety error, taint the kernel! */ add_taint(TAINT_BAD_PAGE, LOCKDEP_STILL_OK); } + +#ifdef CONFIG_PRINTK +static void kfence_to_kp_stack(const struct kfence_track *track, void **kp_stack) +{ + int i, j; + + i = get_stack_skipnr(track->stack_entries, track->num_stack_entries, NULL); + for (j = 0; i < track->num_stack_entries && j < KS_ADDRS_COUNT; ++i, ++j) + kp_stack[j] = (void *)track->stack_entries[i]; + if (j < KS_ADDRS_COUNT) + kp_stack[j] = NULL; +} + +bool __kfence_obj_info(struct kmem_obj_info *kpp, void *object, struct page *page) +{ + struct kfence_metadata *meta = addr_to_metadata((unsigned long)object); + unsigned long flags; + + if (!meta) + return false; + + /* + * If state is UNUSED at least show the pointer requested; the rest + * would be garbage data. + */ + kpp->kp_ptr = object; + + /* Requesting info an a never-used object is almost certainly a bug. */ + if (WARN_ON(meta->state == KFENCE_OBJECT_UNUSED)) + return true; + + raw_spin_lock_irqsave(&meta->lock, flags); + + kpp->kp_page = page; + kpp->kp_slab_cache = meta->cache; + kpp->kp_objp = (void *)meta->addr; + kfence_to_kp_stack(&meta->alloc_track, kpp->kp_stack); + if (meta->state == KFENCE_OBJECT_FREED) + kfence_to_kp_stack(&meta->free_track, kpp->kp_free_stack); + /* get_stack_skipnr() ensures the first entry is outside allocator. */ + kpp->kp_ret = kpp->kp_stack[0]; + + raw_spin_unlock_irqrestore(&meta->lock, flags); + + return true; +} +#endif only in patch2: unchanged: --- linux-5.15.0.orig/mm/mmu_notifier.c +++ linux-5.15.0/mm/mmu_notifier.c @@ -1036,6 +1036,18 @@ } EXPORT_SYMBOL_GPL(mmu_interval_notifier_insert_locked); +static bool +mmu_interval_seq_released(struct mmu_notifier_subscriptions *subscriptions, + unsigned long seq) +{ + bool ret; + + spin_lock(&subscriptions->lock); + ret = subscriptions->invalidate_seq != seq; + spin_unlock(&subscriptions->lock); + return ret; +} + /** * mmu_interval_notifier_remove - Remove a interval notifier * @interval_sub: Interval subscription to unregister @@ -1083,7 +1095,7 @@ lock_map_release(&__mmu_notifier_invalidate_range_start_map); if (seq) wait_event(subscriptions->wq, - READ_ONCE(subscriptions->invalidate_seq) != seq); + mmu_interval_seq_released(subscriptions, seq)); /* pairs with mmgrab in mmu_interval_notifier_insert() */ mmdrop(mm); only in patch2: unchanged: --- linux-5.15.0.orig/mm/slab_common.c +++ linux-5.15.0/mm/slab_common.c @@ -568,6 +568,13 @@ } EXPORT_SYMBOL_GPL(kmem_valid_obj); +static void kmem_obj_info(struct kmem_obj_info *kpp, void *object, struct page *page) +{ + if (__kfence_obj_info(kpp, object, page)) + return; + __kmem_obj_info(kpp, object, page); +} + /** * kmem_dump_obj - Print available slab provenance information * @object: slab object for which to find provenance information. @@ -603,6 +610,8 @@ pr_cont(" slab%s %s", cp, kp.kp_slab_cache->name); else pr_cont(" slab%s", cp); + if (is_kfence_address(object)) + pr_cont(" (kfence)"); if (kp.kp_objp) pr_cont(" start %px", kp.kp_objp); if (kp.kp_data_offset) only in patch2: unchanged: --- linux-5.15.0.orig/mm/slob.c +++ linux-5.15.0/mm/slob.c @@ -462,7 +462,7 @@ } #ifdef CONFIG_PRINTK -void kmem_obj_info(struct kmem_obj_info *kpp, void *object, struct page *page) +void __kmem_obj_info(struct kmem_obj_info *kpp, void *object, struct page *page) { kpp->kp_ptr = object; kpp->kp_page = page; only in patch2: unchanged: --- linux-5.15.0.orig/mm/workingset.c +++ linux-5.15.0/mm/workingset.c @@ -352,7 +352,7 @@ inc_lruvec_state(lruvec, WORKINGSET_REFAULT_BASE + file); - mem_cgroup_flush_stats(); + mem_cgroup_flush_stats_delayed(); /* * Compare the distance to the existing workingset size. We * don't activate pages that couldn't stay resident even if only in patch2: unchanged: --- linux-5.15.0.orig/net/core/bpf_sk_storage.c +++ linux-5.15.0/net/core/bpf_sk_storage.c @@ -929,7 +929,7 @@ { offsetof(struct bpf_iter__bpf_sk_storage_map, sk), PTR_TO_BTF_ID_OR_NULL }, { offsetof(struct bpf_iter__bpf_sk_storage_map, value), - PTR_TO_RDWR_BUF_OR_NULL }, + PTR_TO_BUF | PTR_MAYBE_NULL }, }, .seq_info = &iter_seq_info, }; only in patch2: unchanged: --- linux-5.15.0.orig/net/core/lwt_bpf.c +++ linux-5.15.0/net/core/lwt_bpf.c @@ -158,10 +158,8 @@ return dst->lwtstate->orig_output(net, sk, skb); } -static int xmit_check_hhlen(struct sk_buff *skb) +static int xmit_check_hhlen(struct sk_buff *skb, int hh_len) { - int hh_len = skb_dst(skb)->dev->hard_header_len; - if (skb_headroom(skb) < hh_len) { int nhead = HH_DATA_ALIGN(hh_len - skb_headroom(skb)); @@ -273,6 +271,7 @@ bpf = bpf_lwt_lwtunnel(dst->lwtstate); if (bpf->xmit.prog) { + int hh_len = dst->dev->hard_header_len; __be16 proto = skb->protocol; int ret; @@ -290,7 +289,7 @@ /* If the header was expanded, headroom might be too * small for L2 header to come, expand as needed. */ - ret = xmit_check_hhlen(skb); + ret = xmit_check_hhlen(skb, hh_len); if (unlikely(ret)) return ret; only in patch2: unchanged: --- linux-5.15.0.orig/net/dsa/port.c +++ linux-5.15.0/net/dsa/port.c @@ -1201,8 +1201,10 @@ if (ds->ops->phylink_mac_link_down) ds->ops->phylink_mac_link_down(ds, port, MLO_AN_FIXED, PHY_INTERFACE_MODE_NA); + of_node_put(phy_np); return dsa_port_phylink_register(dp); } + of_node_put(phy_np); return 0; } only in patch2: unchanged: --- linux-5.15.0.orig/net/dsa/tag_hellcreek.c +++ linux-5.15.0/net/dsa/tag_hellcreek.c @@ -21,6 +21,14 @@ struct dsa_port *dp = dsa_slave_to_port(dev); u8 *tag; + /* Calculate checksums (if required) before adding the trailer tag to + * avoid including it in calculations. That would lead to wrong + * checksums after the switch strips the tag. + */ + if (skb->ip_summed == CHECKSUM_PARTIAL && + skb_checksum_help(skb)) + return NULL; + /* Tag encoding */ tag = skb_put(skb, HELLCREEK_TAG_LEN); *tag = BIT(dp->index); only in patch2: unchanged: --- linux-5.15.0.orig/net/ipv4/igmp.c +++ linux-5.15.0/net/ipv4/igmp.c @@ -2403,9 +2403,10 @@ /* decrease mem now to avoid the memleak warning */ atomic_sub(struct_size(psl, sl_addr, psl->sl_max), &sk->sk_omem_alloc); - kfree_rcu(psl, rcu); } rcu_assign_pointer(pmc->sflist, newpsl); + if (psl) + kfree_rcu(psl, rcu); psl = newpsl; } rv = 1; /* > 0 for insert logic below if sl_count is 0 */ @@ -2507,11 +2508,13 @@ /* decrease mem now to avoid the memleak warning */ atomic_sub(struct_size(psl, sl_addr, psl->sl_max), &sk->sk_omem_alloc); - kfree_rcu(psl, rcu); - } else + } else { (void) ip_mc_del_src(in_dev, &msf->imsf_multiaddr, pmc->sfmode, 0, NULL, 0); + } rcu_assign_pointer(pmc->sflist, newpsl); + if (psl) + kfree_rcu(psl, rcu); pmc->sfmode = msf->imsf_fmode; err = 0; done: only in patch2: unchanged: --- linux-5.15.0.orig/net/ipv4/syncookies.c +++ linux-5.15.0/net/ipv4/syncookies.c @@ -283,6 +283,7 @@ EXPORT_SYMBOL(cookie_ecn_ok); struct request_sock *cookie_tcp_reqsk_alloc(const struct request_sock_ops *ops, + const struct tcp_request_sock_ops *af_ops, struct sock *sk, struct sk_buff *skb) { @@ -299,6 +300,10 @@ return NULL; treq = tcp_rsk(req); + + /* treq->af_specific might be used to perform TCP_MD5 lookup */ + treq->af_specific = af_ops; + treq->syn_tos = TCP_SKB_CB(skb)->ip_dsfield; #if IS_ENABLED(CONFIG_MPTCP) treq->is_mptcp = sk_is_mptcp(sk); @@ -366,7 +371,8 @@ goto out; ret = NULL; - req = cookie_tcp_reqsk_alloc(&tcp_request_sock_ops, sk, skb); + req = cookie_tcp_reqsk_alloc(&tcp_request_sock_ops, + &tcp_request_sock_ipv4_ops, sk, skb); if (!req) goto out; only in patch2: unchanged: --- linux-5.15.0.orig/net/ipv4/tcp_minisocks.c +++ linux-5.15.0/net/ipv4/tcp_minisocks.c @@ -538,7 +538,7 @@ newtp->tsoffset = treq->ts_off; #ifdef CONFIG_TCP_MD5SIG newtp->md5sig_info = NULL; /*XXX*/ - if (newtp->af_specific->md5_lookup(sk, newsk)) + if (treq->af_specific->req_md5_lookup(sk, req_to_sk(req))) newtp->tcp_header_len += TCPOLEN_MD5SIG_ALIGNED; #endif if (skb->len >= TCP_MSS_DEFAULT + newtp->tcp_header_len) only in patch2: unchanged: --- linux-5.15.0.orig/net/ipv4/tcp_rate.c +++ linux-5.15.0/net/ipv4/tcp_rate.c @@ -73,26 +73,31 @@ * * If an ACK (s)acks multiple skbs (e.g., stretched-acks), this function is * called multiple times. We favor the information from the most recently - * sent skb, i.e., the skb with the highest prior_delivered count. + * sent skb, i.e., the skb with the most recently sent time and the highest + * sequence. */ void tcp_rate_skb_delivered(struct sock *sk, struct sk_buff *skb, struct rate_sample *rs) { struct tcp_sock *tp = tcp_sk(sk); struct tcp_skb_cb *scb = TCP_SKB_CB(skb); + u64 tx_tstamp; if (!scb->tx.delivered_mstamp) return; + tx_tstamp = tcp_skb_timestamp_us(skb); if (!rs->prior_delivered || - after(scb->tx.delivered, rs->prior_delivered)) { + tcp_skb_sent_after(tx_tstamp, tp->first_tx_mstamp, + scb->end_seq, rs->last_end_seq)) { rs->prior_delivered = scb->tx.delivered; rs->prior_mstamp = scb->tx.delivered_mstamp; rs->is_app_limited = scb->tx.is_app_limited; rs->is_retrans = scb->sacked & TCPCB_RETRANS; + rs->last_end_seq = scb->end_seq; /* Record send time of most recently ACKed packet: */ - tp->first_tx_mstamp = tcp_skb_timestamp_us(skb); + tp->first_tx_mstamp = tx_tstamp; /* Find the duration of the "send phase" of this window: */ rs->interval_us = tcp_stamp_us_delta(tp->first_tx_mstamp, scb->tx.first_tx_mstamp); only in patch2: unchanged: --- linux-5.15.0.orig/net/ipv6/netfilter.c +++ linux-5.15.0/net/ipv6/netfilter.c @@ -24,14 +24,13 @@ { const struct ipv6hdr *iph = ipv6_hdr(skb); struct sock *sk = sk_to_full_sk(sk_partial); + struct net_device *dev = skb_dst(skb)->dev; struct flow_keys flkeys; unsigned int hh_len; struct dst_entry *dst; int strict = (ipv6_addr_type(&iph->daddr) & (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL)); struct flowi6 fl6 = { - .flowi6_oif = sk && sk->sk_bound_dev_if ? sk->sk_bound_dev_if : - strict ? skb_dst(skb)->dev->ifindex : 0, .flowi6_mark = skb->mark, .flowi6_uid = sock_net_uid(net, sk), .daddr = iph->daddr, @@ -39,6 +38,13 @@ }; int err; + if (sk && sk->sk_bound_dev_if) + fl6.flowi6_oif = sk->sk_bound_dev_if; + else if (strict) + fl6.flowi6_oif = dev->ifindex; + else + fl6.flowi6_oif = l3mdev_master_ifindex(dev); + fib6_rules_early_flow_dissect(net, skb, &fl6, &flkeys); dst = ip6_route_output(net, sk, &fl6); err = dst->error; only in patch2: unchanged: --- linux-5.15.0.orig/net/ipv6/syncookies.c +++ linux-5.15.0/net/ipv6/syncookies.c @@ -170,7 +170,8 @@ goto out; ret = NULL; - req = cookie_tcp_reqsk_alloc(&tcp6_request_sock_ops, sk, skb); + req = cookie_tcp_reqsk_alloc(&tcp6_request_sock_ops, + &tcp_request_sock_ipv6_ops, sk, skb); if (!req) goto out; only in patch2: unchanged: --- linux-5.15.0.orig/net/l3mdev/l3mdev.c +++ linux-5.15.0/net/l3mdev/l3mdev.c @@ -147,7 +147,7 @@ dev = dev_get_by_index_rcu(net, ifindex); while (dev && !netif_is_l3_master(dev)) - dev = netdev_master_upper_dev_get(dev); + dev = netdev_master_upper_dev_get_rcu(dev); return dev ? dev->ifindex : 0; } only in patch2: unchanged: --- linux-5.15.0.orig/net/mac80211/status.c +++ linux-5.15.0/net/mac80211/status.c @@ -5,6 +5,7 @@ * Copyright 2006-2007 Jiri Benc * Copyright 2008-2010 Johannes Berg * Copyright 2013-2014 Intel Mobile Communications GmbH + * Copyright 2021-2022 Intel Corporation */ #include @@ -628,6 +629,8 @@ u64 cookie = IEEE80211_SKB_CB(skb)->ack.cookie; struct ieee80211_sub_if_data *sdata; struct ieee80211_hdr *hdr = (void *)skb->data; + bool is_valid_ack_signal = + !!(info->status.flags & IEEE80211_TX_STATUS_ACK_SIGNAL_VALID); rcu_read_lock(); sdata = ieee80211_sdata_from_skb(local, skb); @@ -644,7 +647,7 @@ cfg80211_probe_status(sdata->dev, hdr->addr1, cookie, acked, info->status.ack_signal, - info->status.is_valid_ack_signal, + is_valid_ack_signal, GFP_ATOMIC); else if (ieee80211_is_mgmt(hdr->frame_control)) cfg80211_mgmt_tx_status(&sdata->wdev, cookie, @@ -1102,7 +1105,7 @@ struct ieee80211_supported_band *sband; struct sta_info *sta = NULL; int rates_idx, retry_count; - bool acked, noack_success; + bool acked, noack_success, ack_signal_valid; u16 tx_time_est; if (pubsta) { @@ -1133,6 +1136,8 @@ acked = !!(info->flags & IEEE80211_TX_STAT_ACK); noack_success = !!(info->flags & IEEE80211_TX_STAT_NOACK_TRANSMITTED); + ack_signal_valid = + !!(info->status.flags & IEEE80211_TX_STATUS_ACK_SIGNAL_VALID); if (pubsta) { struct ieee80211_sub_if_data *sdata = sta->sdata; @@ -1161,7 +1166,7 @@ unlikely(sdata->u.mgd.probe_send_count > 0)) sdata->u.mgd.probe_send_count = 0; - if (info->status.is_valid_ack_signal) { + if (ack_signal_valid) { sta->status_stats.last_ack_signal = (s8)info->status.ack_signal; sta->status_stats.ack_signal_filled = true; only in patch2: unchanged: --- linux-5.15.0.orig/net/netfilter/ipvs/ip_vs_conn.c +++ linux-5.15.0/net/netfilter/ipvs/ip_vs_conn.c @@ -1495,7 +1495,7 @@ pr_info("Connection hash table configured " "(size=%d, memory=%ldKbytes)\n", ip_vs_conn_tab_size, - (long)(ip_vs_conn_tab_size*sizeof(struct list_head))/1024); + (long)(ip_vs_conn_tab_size*sizeof(*ip_vs_conn_tab))/1024); IP_VS_DBG(0, "Each connection entry needs %zd bytes at least\n", sizeof(struct ip_vs_conn)); only in patch2: unchanged: --- linux-5.15.0.orig/net/netfilter/nf_conntrack_expect.c +++ linux-5.15.0/net/netfilter/nf_conntrack_expect.c @@ -203,12 +203,12 @@ * about to invoke ->destroy(), or nf_ct_delete() via timeout * or early_drop(). * - * The atomic_inc_not_zero() check tells: If that fails, we + * The refcount_inc_not_zero() check tells: If that fails, we * know that the ct is being destroyed. If it succeeds, we * can be sure the ct cannot disappear underneath. */ if (unlikely(nf_ct_is_dying(exp->master) || - !atomic_inc_not_zero(&exp->master->ct_general.use))) + !refcount_inc_not_zero(&exp->master->ct_general.use))) return NULL; if (exp->flags & NF_CT_EXPECT_PERMANENT) { only in patch2: unchanged: --- linux-5.15.0.orig/net/netfilter/nf_synproxy_core.c +++ linux-5.15.0/net/netfilter/nf_synproxy_core.c @@ -349,7 +349,6 @@ goto err2; __set_bit(IPS_CONFIRMED_BIT, &ct->status); - nf_conntrack_get(&ct->ct_general); snet->tmpl = ct; snet->stats = alloc_percpu(struct synproxy_stats); only in patch2: unchanged: --- linux-5.15.0.orig/net/netfilter/nft_set_rbtree.c +++ linux-5.15.0/net/netfilter/nft_set_rbtree.c @@ -349,7 +349,11 @@ *ext = &rbe->ext; return -EEXIST; } else { - p = &parent->rb_left; + overlap = false; + if (nft_rbtree_interval_end(rbe)) + p = &parent->rb_left; + else + p = &parent->rb_right; } } only in patch2: unchanged: --- linux-5.15.0.orig/net/netfilter/xt_CT.c +++ linux-5.15.0/net/netfilter/xt_CT.c @@ -24,7 +24,7 @@ return XT_CONTINUE; if (ct) { - atomic_inc(&ct->ct_general.use); + refcount_inc(&ct->ct_general.use); nf_ct_set(skb, ct, IP_CT_NEW); } else { nf_ct_set(skb, ct, IP_CT_UNTRACKED); @@ -201,7 +201,6 @@ goto err4; } __set_bit(IPS_CONFIRMED_BIT, &ct->status); - nf_conntrack_get(&ct->ct_general); out: info->ct = ct; return 0; only in patch2: unchanged: --- linux-5.15.0.orig/net/rxrpc/local_object.c +++ linux-5.15.0/net/rxrpc/local_object.c @@ -117,6 +117,7 @@ local, srx->transport_type, srx->transport.family); udp_conf.family = srx->transport.family; + udp_conf.use_udp_checksums = true; if (udp_conf.family == AF_INET) { udp_conf.local_ip = srx->transport.sin.sin_addr; udp_conf.local_udp_port = srx->transport.sin.sin_port; @@ -124,6 +125,8 @@ } else { udp_conf.local_ip6 = srx->transport.sin6.sin6_addr; udp_conf.local_udp_port = srx->transport.sin6.sin6_port; + udp_conf.use_udp6_tx_checksums = true; + udp_conf.use_udp6_rx_checksums = true; #endif } ret = udp_sock_create(net, &udp_conf, &local->socket); only in patch2: unchanged: --- linux-5.15.0.orig/net/sctp/sm_sideeffect.c +++ linux-5.15.0/net/sctp/sm_sideeffect.c @@ -458,6 +458,10 @@ goto out_unlock; } + /* This happens when the response arrives after the timer is triggered. */ + if (!asoc->strreset_chunk) + goto out_unlock; + error = sctp_do_sm(net, SCTP_EVENT_T_TIMEOUT, SCTP_ST_TIMEOUT(SCTP_EVENT_TIMEOUT_RECONF), asoc->state, asoc->ep, asoc, only in patch2: unchanged: --- linux-5.15.0.orig/net/tls/tls_device.c +++ linux-5.15.0/net/tls/tls_device.c @@ -483,11 +483,13 @@ copy = min_t(size_t, size, (pfrag->size - pfrag->offset)); copy = min_t(size_t, copy, (max_open_record_len - record->len)); - rc = tls_device_copy_data(page_address(pfrag->page) + - pfrag->offset, copy, msg_iter); - if (rc) - goto handle_error; - tls_append_frag(record, pfrag, copy); + if (copy) { + rc = tls_device_copy_data(page_address(pfrag->page) + + pfrag->offset, copy, msg_iter); + if (rc) + goto handle_error; + tls_append_frag(record, pfrag, copy); + } size -= copy; if (!size) { only in patch2: unchanged: --- linux-5.15.0.orig/sound/firewire/fireworks/fireworks_hwdep.c +++ linux-5.15.0/sound/firewire/fireworks/fireworks_hwdep.c @@ -34,6 +34,7 @@ type = SNDRV_FIREWIRE_EVENT_EFW_RESPONSE; if (copy_to_user(buf, &type, sizeof(type))) return -EFAULT; + count += sizeof(type); remained -= sizeof(type); buf += sizeof(type); only in patch2: unchanged: --- linux-5.15.0.orig/sound/soc/codecs/da7219.c +++ linux-5.15.0/sound/soc/codecs/da7219.c @@ -446,7 +446,7 @@ struct soc_mixer_control *mixer_ctrl = (struct soc_mixer_control *) kcontrol->private_value; unsigned int reg = mixer_ctrl->reg; - __le16 val; + __le16 val_new, val_old; int ret; /* @@ -454,13 +454,19 @@ * Therefore we need to convert to little endian here to align with * HW registers. */ - val = cpu_to_le16(ucontrol->value.integer.value[0]); + val_new = cpu_to_le16(ucontrol->value.integer.value[0]); mutex_lock(&da7219->ctrl_lock); - ret = regmap_raw_write(da7219->regmap, reg, &val, sizeof(val)); + ret = regmap_raw_read(da7219->regmap, reg, &val_old, sizeof(val_old)); + if (ret == 0 && (val_old != val_new)) + ret = regmap_raw_write(da7219->regmap, reg, + &val_new, sizeof(val_new)); mutex_unlock(&da7219->ctrl_lock); - return ret; + if (ret < 0) + return ret; + + return val_old != val_new; } only in patch2: unchanged: --- linux-5.15.0.orig/sound/soc/codecs/wm8731.c +++ linux-5.15.0/sound/soc/codecs/wm8731.c @@ -602,7 +602,7 @@ ret = wm8731_reset(wm8731->regmap); if (ret < 0) { dev_err(dev, "Failed to issue reset: %d\n", ret); - goto err_regulator_enable; + goto err; } /* Clear POWEROFF, keep everything else disabled */ @@ -619,10 +619,7 @@ regcache_mark_dirty(wm8731->regmap); -err_regulator_enable: - /* Regulators will be enabled by bias management */ - regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); - +err: return ret; } @@ -766,21 +763,27 @@ ret = PTR_ERR(wm8731->regmap); dev_err(&i2c->dev, "Failed to allocate register map: %d\n", ret); - return ret; + goto err_regulator_enable; } ret = wm8731_hw_init(&i2c->dev, wm8731); if (ret != 0) - return ret; + goto err_regulator_enable; ret = devm_snd_soc_register_component(&i2c->dev, &soc_component_dev_wm8731, &wm8731_dai, 1); if (ret != 0) { dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret); - return ret; + goto err_regulator_enable; } return 0; + +err_regulator_enable: + /* Regulators will be enabled by bias management */ + regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); + + return ret; } static int wm8731_i2c_remove(struct i2c_client *client) only in patch2: unchanged: --- linux-5.15.0.orig/sound/soc/codecs/wm8958-dsp2.c +++ linux-5.15.0/sound/soc/codecs/wm8958-dsp2.c @@ -530,7 +530,7 @@ wm8958_dsp_apply(component, mbc, wm8994->mbc_ena[mbc]); - return 0; + return 1; } #define WM8958_MBC_SWITCH(xname, xval) {\ @@ -656,7 +656,7 @@ wm8958_dsp_apply(component, vss, wm8994->vss_ena[vss]); - return 0; + return 1; } @@ -730,7 +730,7 @@ wm8958_dsp_apply(component, hpf % 3, ucontrol->value.integer.value[0]); - return 0; + return 1; } #define WM8958_HPF_SWITCH(xname, xval) {\ @@ -824,7 +824,7 @@ wm8958_dsp_apply(component, eq, ucontrol->value.integer.value[0]); - return 0; + return 1; } #define WM8958_ENH_EQ_SWITCH(xname, xval) {\ only in patch2: unchanged: --- linux-5.15.0.orig/sound/soc/meson/aiu-acodec-ctrl.c +++ linux-5.15.0/sound/soc/meson/aiu-acodec-ctrl.c @@ -58,7 +58,7 @@ snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL); - return 0; + return 1; } static SOC_ENUM_SINGLE_DECL(aiu_acodec_ctrl_mux_enum, AIU_ACODEC_CTRL, only in patch2: unchanged: --- linux-5.15.0.orig/sound/soc/meson/aiu-codec-ctrl.c +++ linux-5.15.0/sound/soc/meson/aiu-codec-ctrl.c @@ -57,7 +57,7 @@ snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL); - return 0; + return 1; } static SOC_ENUM_SINGLE_DECL(aiu_hdmi_ctrl_mux_enum, AIU_HDMI_CLK_DATA_CTRL, only in patch2: unchanged: --- linux-5.15.0.orig/sound/soc/meson/g12a-tohdmitx.c +++ linux-5.15.0/sound/soc/meson/g12a-tohdmitx.c @@ -67,7 +67,7 @@ snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL); - return 0; + return 1; } static SOC_ENUM_SINGLE_DECL(g12a_tohdmitx_i2s_mux_enum, TOHDMITX_CTRL0, only in patch2: unchanged: --- linux-5.15.0.orig/sound/usb/midi.c +++ linux-5.15.0/sound/usb/midi.c @@ -1194,6 +1194,7 @@ } while (drain_urbs && timeout); finish_wait(&ep->drain_wait, &wait); } + port->active = 0; spin_unlock_irq(&ep->buffer_lock); } only in patch2: unchanged: --- linux-5.15.0.orig/sound/usb/usbaudio.h +++ linux-5.15.0/sound/usb/usbaudio.h @@ -8,7 +8,7 @@ */ /* handling of USB vendor/product ID pairs as 32-bit numbers */ -#define USB_ID(vendor, product) (((vendor) << 16) | (product)) +#define USB_ID(vendor, product) (((unsigned int)(vendor) << 16) | (product)) #define USB_ID_VENDOR(id) ((id) >> 16) #define USB_ID_PRODUCT(id) ((u16)(id)) only in patch2: unchanged: --- linux-5.15.0.orig/tools/lib/perf/evlist.c +++ linux-5.15.0/tools/lib/perf/evlist.c @@ -577,7 +577,6 @@ { struct perf_evsel *evsel; const struct perf_cpu_map *cpus = evlist->cpus; - const struct perf_thread_map *threads = evlist->threads; if (!ops || !ops->get || !ops->mmap) return -EINVAL; @@ -589,7 +588,7 @@ perf_evlist__for_each_entry(evlist, evsel) { if ((evsel->attr.read_format & PERF_FORMAT_ID) && evsel->sample_id == NULL && - perf_evsel__alloc_id(evsel, perf_cpu_map__nr(cpus), threads->nr) < 0) + perf_evsel__alloc_id(evsel, evsel->fd->max_x, evsel->fd->max_y) < 0) return -ENOMEM; } only in patch2: unchanged: --- linux-5.15.0.orig/tools/perf/arch/arm64/util/Build +++ linux-5.15.0/tools/perf/arch/arm64/util/Build @@ -1,5 +1,4 @@ perf-y += header.o -perf-y += machine.o perf-y += perf_regs.o perf-y += tsc.o perf-y += pmu.o only in patch2: unchanged: --- linux-5.15.0.orig/tools/perf/arch/powerpc/util/Build +++ linux-5.15.0/tools/perf/arch/powerpc/util/Build @@ -1,5 +1,4 @@ perf-y += header.o -perf-y += machine.o perf-y += kvm-stat.o perf-y += perf_regs.o perf-y += mem-events.o only in patch2: unchanged: --- linux-5.15.0.orig/tools/perf/arch/s390/util/machine.c +++ linux-5.15.0/tools/perf/arch/s390/util/machine.c @@ -35,19 +35,3 @@ return 0; } - -/* On s390 kernel text segment start is located at very low memory addresses, - * for example 0x10000. Modules are located at very high memory addresses, - * for example 0x3ff xxxx xxxx. The gap between end of kernel text segment - * and beginning of first module's text segment is very big. - * Therefore do not fill this gap and do not assign it to the kernel dso map. - */ -void arch__symbols__fixup_end(struct symbol *p, struct symbol *c) -{ - if (strchr(p->name, '[') == NULL && strchr(c->name, '[')) - /* Last kernel symbol mapped to end of page */ - p->end = roundup(p->end, page_size); - else - p->end = c->start; - pr_debug4("%s sym:%s end:%#" PRIx64 "\n", __func__, p->name, p->end); -} only in patch2: unchanged: --- linux-5.15.0.orig/tools/perf/util/symbol-elf.c +++ linux-5.15.0/tools/perf/util/symbol-elf.c @@ -1290,7 +1290,7 @@ * For misannotated, zeroed, ASM function sizes. */ if (nr > 0) { - symbols__fixup_end(&dso->symbols); + symbols__fixup_end(&dso->symbols, false); symbols__fixup_duplicate(&dso->symbols); if (kmap) { /* only in patch2: unchanged: --- linux-5.15.0.orig/tools/perf/util/symbol.h +++ linux-5.15.0/tools/perf/util/symbol.h @@ -192,7 +192,7 @@ bool kernel); void symbols__insert(struct rb_root_cached *symbols, struct symbol *sym); void symbols__fixup_duplicate(struct rb_root_cached *symbols); -void symbols__fixup_end(struct rb_root_cached *symbols); +void symbols__fixup_end(struct rb_root_cached *symbols, bool is_kallsyms); void maps__fixup_end(struct maps *maps); typedef int (*mapfn_t)(u64 start, u64 len, u64 pgoff, void *data); @@ -230,7 +230,6 @@ #define SYMBOL_A 0 #define SYMBOL_B 1 -void arch__symbols__fixup_end(struct symbol *p, struct symbol *c); int arch__compare_symbol_names(const char *namea, const char *nameb); int arch__compare_symbol_names_n(const char *namea, const char *nameb, unsigned int n); only in patch2: unchanged: --- linux-5.15.0.orig/tools/testing/selftests/bpf/prog_tests/ksyms_btf.c +++ linux-5.15.0/tools/testing/selftests/bpf/prog_tests/ksyms_btf.c @@ -7,6 +7,7 @@ #include "test_ksyms_btf.skel.h" #include "test_ksyms_btf_null_check.skel.h" #include "test_ksyms_weak.skel.h" +#include "test_ksyms_btf_write_check.skel.h" static int duration; @@ -109,6 +110,16 @@ test_ksyms_weak__destroy(skel); } +static void test_write_check(void) +{ + struct test_ksyms_btf_write_check *skel; + + skel = test_ksyms_btf_write_check__open_and_load(); + ASSERT_ERR_PTR(skel, "unexpected load of a prog writing to ksym memory\n"); + + test_ksyms_btf_write_check__destroy(skel); +} + void test_ksyms_btf(void) { int percpu_datasec; @@ -136,4 +147,7 @@ if (test__start_subtest("weak_ksyms")) test_weak_syms(); + + if (test__start_subtest("write_check")) + test_write_check(); } only in patch2: unchanged: --- linux-5.15.0.orig/tools/testing/selftests/bpf/progs/test_ksyms_btf_write_check.c +++ linux-5.15.0/tools/testing/selftests/bpf/progs/test_ksyms_btf_write_check.c @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2021 Google */ + +#include "vmlinux.h" + +#include + +extern const int bpf_prog_active __ksym; /* int type global var. */ + +SEC("raw_tp/sys_enter") +int handler(const void *ctx) +{ + int *active; + __u32 cpu; + + cpu = bpf_get_smp_processor_id(); + active = (int *)bpf_per_cpu_ptr(&bpf_prog_active, cpu); + if (active) { + /* Kernel memory obtained from bpf_{per,this}_cpu_ptr + * is read-only, should _not_ pass verification. + */ + /* WRITE_ONCE */ + *(volatile int *)active = -1; + } + + return 0; +} + +char _license[] SEC("license") = "GPL"; only in patch2: unchanged: --- linux-5.15.0.orig/tools/testing/selftests/bpf/verifier/calls.c +++ linux-5.15.0/tools/testing/selftests/bpf/verifier/calls.c @@ -108,6 +108,25 @@ .errstr = "R0 min value is outside of the allowed memory range", }, { + "calls: trigger reg2btf_ids[reg->type] for reg->type > __BPF_REG_TYPE_MAX", + .insns = { + BPF_MOV64_REG(BPF_REG_1, BPF_REG_10), + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8), + BPF_ST_MEM(BPF_DW, BPF_REG_1, 0, 0), + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_KFUNC_CALL, 0, 0), + BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_KFUNC_CALL, 0, 0), + BPF_EXIT_INSN(), + }, + .prog_type = BPF_PROG_TYPE_SCHED_CLS, + .result = REJECT, + .errstr = "arg#0 pointer type STRUCT prog_test_ref_kfunc must point", + .fixup_kfunc_btf_id = { + { "bpf_kfunc_call_test_acquire", 3 }, + { "bpf_kfunc_call_test_release", 5 }, + }, +}, +{ "calls: overlapping caller/callee", .insns = { BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 0), only in patch2: unchanged: --- linux-5.15.0.orig/tools/testing/selftests/drivers/net/mlxsw/vxlan_flooding.sh +++ linux-5.15.0/tools/testing/selftests/drivers/net/mlxsw/vxlan_flooding.sh @@ -172,6 +172,17 @@ local lsb local i + # Prevent unwanted packets from entering the bridge and interfering + # with the test. + tc qdisc add dev br0 clsact + tc filter add dev br0 egress protocol all pref 1 handle 1 \ + matchall skip_hw action drop + tc qdisc add dev $h1 clsact + tc filter add dev $h1 egress protocol all pref 1 handle 1 \ + flower skip_hw dst_mac de:ad:be:ef:13:37 action pass + tc filter add dev $h1 egress protocol all pref 2 handle 2 \ + matchall skip_hw action drop + tc qdisc add dev $rp2 clsact for i in $(eval echo {1..$num_remotes}); do @@ -194,6 +205,12 @@ done tc qdisc del dev $rp2 clsact + + tc filter del dev $h1 egress protocol all pref 2 handle 2 matchall + tc filter del dev $h1 egress protocol all pref 1 handle 1 flower + tc qdisc del dev $h1 clsact + tc filter del dev br0 egress protocol all pref 1 handle 1 matchall + tc qdisc del dev br0 clsact } flooding_check_packets() only in patch2: unchanged: --- linux-5.15.0.orig/tools/testing/selftests/drivers/net/ocelot/tc_flower_chains.sh +++ linux-5.15.0/tools/testing/selftests/drivers/net/ocelot/tc_flower_chains.sh @@ -185,7 +185,7 @@ tc filter add dev $eth0 ingress chain $(IS2 0 0) pref 1 \ protocol ipv4 flower skip_sw ip_proto udp dst_port 5201 \ - action police rate 50mbit burst 64k \ + action police rate 50mbit burst 64k conform-exceed drop/pipe \ action goto chain $(IS2 1 0) } only in patch2: unchanged: --- linux-5.15.0.orig/tools/testing/selftests/kvm/include/x86_64/processor.h +++ linux-5.15.0/tools/testing/selftests/kvm/include/x86_64/processor.h @@ -58,6 +58,21 @@ /* CPUID.0x8000_0001.EDX */ #define CPUID_GBPAGES (1ul << 26) +/* Page table bitfield declarations */ +#define PTE_PRESENT_MASK BIT_ULL(0) +#define PTE_WRITABLE_MASK BIT_ULL(1) +#define PTE_USER_MASK BIT_ULL(2) +#define PTE_ACCESSED_MASK BIT_ULL(5) +#define PTE_DIRTY_MASK BIT_ULL(6) +#define PTE_LARGE_MASK BIT_ULL(7) +#define PTE_GLOBAL_MASK BIT_ULL(8) +#define PTE_NX_MASK BIT_ULL(63) + +#define PAGE_SHIFT 12 + +#define PHYSICAL_PAGE_MASK GENMASK_ULL(51, 12) +#define PTE_GET_PFN(pte) (((pte) & PHYSICAL_PAGE_MASK) >> PAGE_SHIFT) + /* General Registers in 64-Bit Mode */ struct gpr64_regs { u64 rax; only in patch2: unchanged: --- linux-5.15.0.orig/tools/testing/selftests/kvm/kvm_page_table_test.c +++ linux-5.15.0/tools/testing/selftests/kvm/kvm_page_table_test.c @@ -278,7 +278,7 @@ else guest_test_phys_mem = p->phys_offset; #ifdef __s390x__ - alignment = max(0x100000, alignment); + alignment = max(0x100000UL, alignment); #endif guest_test_phys_mem &= ~(alignment - 1); only in patch2: unchanged: --- linux-5.15.0.orig/tools/testing/selftests/net/forwarding/mirror_gre_bridge_1q.sh +++ linux-5.15.0/tools/testing/selftests/net/forwarding/mirror_gre_bridge_1q.sh @@ -61,9 +61,12 @@ vrf_prepare mirror_gre_topo_create + # Avoid changing br1's PVID while it is operational as a L3 interface. + ip link set dev br1 down ip link set dev $swp3 master br1 bridge vlan add dev br1 vid 555 pvid untagged self + ip link set dev br1 up ip address add dev br1 192.0.2.129/28 ip address add dev br1 2001:db8:2::1/64 only in patch2: unchanged: --- linux-5.15.0.orig/tools/testing/selftests/net/so_txtime.c +++ linux-5.15.0/tools/testing/selftests/net/so_txtime.c @@ -421,7 +421,7 @@ "Options:\n" " -4 only IPv4\n" " -6 only IPv6\n" - " -c monotonic (default) or tai\n" + " -c monotonic or tai (default)\n" " -D destination IP address (server)\n" " -S source IP address (client)\n" " -r run rx mode\n" @@ -475,7 +475,7 @@ cfg_rx = true; break; case 't': - cfg_start_time_ns = strtol(optarg, NULL, 0); + cfg_start_time_ns = strtoll(optarg, NULL, 0); break; case 'm': cfg_mark = strtol(optarg, NULL, 0); only in patch2: unchanged: --- linux-5.15.0.orig/tools/testing/selftests/vm/mremap_test.c +++ linux-5.15.0/tools/testing/selftests/vm/mremap_test.c @@ -6,9 +6,11 @@ #include #include +#include #include #include #include +#include #include "../kselftest.h" @@ -65,6 +67,112 @@ } /* + * Returns false if the requested remap region overlaps with an + * existing mapping (e.g text, stack) else returns true. + */ +static bool is_remap_region_valid(void *addr, unsigned long long size) +{ + void *remap_addr = NULL; + bool ret = true; + + /* Use MAP_FIXED_NOREPLACE flag to ensure region is not mapped */ + remap_addr = mmap(addr, size, PROT_READ | PROT_WRITE, + MAP_FIXED_NOREPLACE | MAP_ANONYMOUS | MAP_SHARED, + -1, 0); + + if (remap_addr == MAP_FAILED) { + if (errno == EEXIST) + ret = false; + } else { + munmap(remap_addr, size); + } + + return ret; +} + +/* Returns mmap_min_addr sysctl tunable from procfs */ +static unsigned long long get_mmap_min_addr(void) +{ + FILE *fp; + int n_matched; + static unsigned long long addr; + + if (addr) + return addr; + + fp = fopen("/proc/sys/vm/mmap_min_addr", "r"); + if (fp == NULL) { + ksft_print_msg("Failed to open /proc/sys/vm/mmap_min_addr: %s\n", + strerror(errno)); + exit(KSFT_SKIP); + } + + n_matched = fscanf(fp, "%llu", &addr); + if (n_matched != 1) { + ksft_print_msg("Failed to read /proc/sys/vm/mmap_min_addr: %s\n", + strerror(errno)); + fclose(fp); + exit(KSFT_SKIP); + } + + fclose(fp); + return addr; +} + +/* + * Returns false if the requested remap region overlaps with an + * existing mapping (e.g text, stack) else returns true. + */ +static bool is_remap_region_valid(void *addr, unsigned long long size) +{ + void *remap_addr = NULL; + bool ret = true; + + /* Use MAP_FIXED_NOREPLACE flag to ensure region is not mapped */ + remap_addr = mmap(addr, size, PROT_READ | PROT_WRITE, + MAP_FIXED_NOREPLACE | MAP_ANONYMOUS | MAP_SHARED, + -1, 0); + + if (remap_addr == MAP_FAILED) { + if (errno == EEXIST) + ret = false; + } else { + munmap(remap_addr, size); + } + + return ret; +} + +/* Returns mmap_min_addr sysctl tunable from procfs */ +static unsigned long long get_mmap_min_addr(void) +{ + FILE *fp; + int n_matched; + static unsigned long long addr; + + if (addr) + return addr; + + fp = fopen("/proc/sys/vm/mmap_min_addr", "r"); + if (fp == NULL) { + ksft_print_msg("Failed to open /proc/sys/vm/mmap_min_addr: %s\n", + strerror(errno)); + exit(KSFT_SKIP); + } + + n_matched = fscanf(fp, "%llu", &addr); + if (n_matched != 1) { + ksft_print_msg("Failed to read /proc/sys/vm/mmap_min_addr: %s\n", + strerror(errno)); + fclose(fp); + exit(KSFT_SKIP); + } + + fclose(fp); + return addr; +} + +/* * Returns the start address of the mapping on success, else returns * NULL on failure. */ @@ -72,11 +180,18 @@ { unsigned long long addr = 0ULL; void *src_addr = NULL; + unsigned long long mmap_min_addr; + + mmap_min_addr = get_mmap_min_addr(); + retry: addr += c.src_alignment; + if (addr < mmap_min_addr) + goto retry; + src_addr = mmap((void *) addr, c.region_size, PROT_READ | PROT_WRITE, - MAP_FIXED_NOREPLACE | MAP_ANONYMOUS | MAP_SHARED, - -1, 0); + MAP_FIXED_NOREPLACE | MAP_ANONYMOUS | MAP_SHARED, + -1, 0); if (src_addr == MAP_FAILED) { if (errno == EPERM || errno == EEXIST) goto retry; @@ -91,8 +206,10 @@ * alignment in the tests. */ if (((unsigned long long) src_addr & (c.src_alignment - 1)) || - !((unsigned long long) src_addr & c.src_alignment)) + !((unsigned long long) src_addr & c.src_alignment)) { + munmap(src_addr, c.region_size); goto retry; + } if (!src_addr) goto error; @@ -141,9 +258,20 @@ if (!((unsigned long long) addr & c.dest_alignment)) addr = (void *) ((unsigned long long) addr | c.dest_alignment); + /* Don't destroy existing mappings unless expected to overlap */ + while (!is_remap_region_valid(addr, c.region_size) && !c.overlapping) { + /* Check for unsigned overflow */ + if (addr + c.dest_alignment < addr) { + ksft_print_msg("Couldn't find a valid region to remap to\n"); + ret = -1; + goto out; + } + addr += c.dest_alignment; + } + clock_gettime(CLOCK_MONOTONIC, &t_start); dest_addr = mremap(src_addr, c.region_size, c.region_size, - MREMAP_MAYMOVE|MREMAP_FIXED, (char *) addr); + MREMAP_MAYMOVE|MREMAP_FIXED, (char *) addr); clock_gettime(CLOCK_MONOTONIC, &t_end); if (dest_addr == MAP_FAILED) {