From 867621ba203027338b525af6729719c544135336 Mon Sep 17 00:00:00 2001 From: Md Sadre Alam Date: Mon, 15 Jun 2026 11:39:08 +0530 Subject: dmaengine: qcom: bam_dma: Fix command element mask field for BAM v1.6.0+ BAM version 1.6.0 and later changed the behavior of the mask field in command elements for read operations. In older BAM versions, or prior implementation assumptions, the mask field was effectively ignored for read commands. However, starting from BAM v1.6.0, the mask field for read commands is repurposed to carry the upper 4 bits of the destination address, enabling support for 36-bit addressing. For write commands, the mask field continues to function as a traditional write mask. The current driver sets mask = 0xffffffff for all command elements. While this works for write operations, it breaks read operations on BAM v1.6.0+ hardware. In such cases, the hardware interprets the upper address bits as 0xf, resulting in an invalid destination address (0xf_xxxxxxxx instead of 0x0_xxxxxxxx). This leads to failures such as NAND enumeration issues observed on platforms like IPQ5424. Fix this by assigning the mask field based on command type: - For read commands: set mask = 0 (upper address bits = 0) - For write commands: retain mask = 0xffffffff Also update the bam_cmd_element structure documentation to reflect the dual purpose of the mask field across BAM versions. This ensures correct behavior on BAM v1.6.0+ while maintaining backward compatibility with older hardware. Fixes: dfebb055f73a2 ("dmaengine: qcom: bam_dma: wrapper functions for command descriptor") Tested-by: Lakshmi Sowjanya D Signed-off-by: Md Sadre Alam Reviewed-by: Frank Li Reviewed-by: Dmitry Baryshkov Cc: stable@vger.kernel.org Signed-off-by: Varadarajan Narayanan Link: https://patch.msgid.link/20260615060908.1263171-1-varadarajan.narayanan@oss.qualcomm.com Signed-off-by: Vinod Koul --- include/linux/dma/qcom_bam_dma.h | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/linux/dma/qcom_bam_dma.h b/include/linux/dma/qcom_bam_dma.h index 68fc0e643b1b..d9d07a9ab313 100644 --- a/include/linux/dma/qcom_bam_dma.h +++ b/include/linux/dma/qcom_bam_dma.h @@ -13,9 +13,12 @@ * supported by BAM DMA Engine. * * @cmd_and_addr - upper 8 bits command and lower 24 bits register address. - * @data - for write command: content to be written into peripheral register. - * for read command: dest addr to write peripheral register value. - * @mask - register mask. + * @data - For write command: content to be written into peripheral register. + * For read command: lower 32 bits of destination address. + * @mask - For write command: register write mask. + * For read command on BAM v1.6.0+: upper 4 bits of destination address. + * For read command on BAM < v1.6.0: ignored by hardware. + * Setting to 0 ensures 32-bit addressing compatibility. * @reserved - for future usage. * */ @@ -42,6 +45,10 @@ enum bam_command_type { * @addr: target address * @cmd: BAM command * @data: actual data for write and dest addr for read in le32 + * + * For BAM v1.6.0+, the mask field behavior depends on command type: + * - Write commands: mask = write mask (typically 0xffffffff) + * - Read commands: mask = upper 4 bits of destination address (0 for 32-bit) */ static inline void bam_prep_ce_le32(struct bam_cmd_element *bam_ce, u32 addr, @@ -50,7 +57,11 @@ bam_prep_ce_le32(struct bam_cmd_element *bam_ce, u32 addr, bam_ce->cmd_and_addr = cpu_to_le32((addr & 0xffffff) | ((cmd & 0xff) << 24)); bam_ce->data = data; - bam_ce->mask = cpu_to_le32(0xffffffff); + if (cmd == BAM_READ_COMMAND) + bam_ce->mask = cpu_to_le32(0x0); /* 32-bit addressing */ + else + bam_ce->mask = cpu_to_le32(0xffffffff); /* Write mask */ + bam_ce->reserved = 0; } /* @@ -60,7 +71,7 @@ bam_prep_ce_le32(struct bam_cmd_element *bam_ce, u32 addr, * @bam_ce: BAM command element * @addr: target address * @cmd: BAM command - * @data: actual data for write and dest addr for read + * @data: actual data for write and destination address for read */ static inline void bam_prep_ce(struct bam_cmd_element *bam_ce, u32 addr, -- cgit v1.2.3 From de4660898b7aa7e03d3b120a6bfa6b26211e4e77 Mon Sep 17 00:00:00 2001 From: Qi Zheng Date: Fri, 10 Jul 2026 23:43:18 +0800 Subject: mm: mglru: fix stale batch updates after memcg reparenting The mglru page table walker batches per-generation size deltas in walk->nr_pages while walking page tables without holding the lruvec lock. The reset_batch_size() later folds those deltas into walk->lruvec under the lruvec lock. The page table walker can run concurrently with the memcg reparenting path as follows: CPU0 CPU1 ==== ==== walk_mm --> walk_page_range --> update_batch_size --> walk->nr_pages += delta mem_cgroup_css_offline --> memcg_reparent_objcgs --> lock lruvec lru_gen_reparent_memcg --> reparent child folios to parent unlock lruvec lock lruvec reset_batch_size --> child lrugen->nr_pages += delta This will trigger the following warning in lru_gen_exit_memcg(): VM_WARN_ON_ONCE(memchr_inv(lruvec->lrugen.nr_pages, 0, sizeof(lruvec->lrugen.nr_pages))); And the user-visible impact of underestimated nr_pages in MGLRU was premature OOMs because MGLRU does not try to reclaim memory when nr_pages reaches zero, but there are still more pages. To fix it, make reset_batch_size() check CSS_DYING under RCU before flushing the pending batch. A non-dying memcg keeps the original lruvec stable against RCU-delayed offlining; a dying memcg redirects the deltas to the first non-dying ancestor. Link: https://lore.kernel.org/20260710154318.75388-1-qi.zheng@linux.dev Fixes: f304652609ea ("mm: vmscan: prepare for reparenting MGLRU folios") Signed-off-by: Qi Zheng Reported-by: Peiyang He Closes: https://lore.kernel.org/all/5A9E929D82717101+12fcf643-efb8-4b9a-a53a-1e28cc894f0b@smail.nju.edu.cn Reviewed-by: Harry Yoo (Oracle) Acked-by: Johannes Weiner Acked-by: Shakeel Butt Cc: Axel Rasmussen Cc: Barry Song Cc: David Hildenbrand Cc: Kairui Song Cc: Lorenzo Stoakes Cc: Michal Hocko Cc: Muchun Song Cc: Roman Gushchin Cc: Wei Xu Cc: Yuanchu Xie Cc: Signed-off-by: Andrew Morton --- include/linux/memcontrol.h | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'include') diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index e1f46a0016fc..957260677678 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -1472,6 +1472,31 @@ static inline void lruvec_lock_irq(struct lruvec *lruvec) spin_lock_irq(&lruvec->lru_lock); } +static inline struct lruvec *lruvec_live_lock_irq(struct lruvec *lruvec) +{ +#ifdef CONFIG_MEMCG + struct pglist_data *pgdat = lruvec_pgdat(lruvec); + struct mem_cgroup *memcg = lruvec_memcg(lruvec); + + rcu_read_lock(); + + /* + * The memcg can be NULL when the memory controller is disabled. + * Otherwise, the caller keeps the memcg owning @lruvec alive. + */ + while (unlikely(memcg && css_is_dying(&memcg->css))) { + memcg = parent_mem_cgroup(memcg); + lruvec = mem_cgroup_lruvec(memcg, pgdat); + } + + spin_lock_irq(&lruvec->lru_lock); +#else + lruvec_lock_irq(lruvec); +#endif + + return lruvec; +} + static inline void lruvec_unlock(struct lruvec *lruvec) { spin_unlock(&lruvec->lru_lock); -- cgit v1.2.3 From 11055a46f398779b69aa36afb7c9f4124529a075 Mon Sep 17 00:00:00 2001 From: Christian Loehle Date: Wed, 22 Jul 2026 10:38:24 +0100 Subject: ACPI: CPPC: Check all controls for fast switching ACPI 6.2, Section 6.2.11.2 permits _CPC registers to use flexible address spaces. Linux advertises that capability through _OSC and parses the address space of each _CPC register independently. A directly accessible DESIRED_PERF combined with PCC-backed limits is therefore a valid configuration. cppc_allow_fast_switch() only checks DESIRED_PERF, although the fast-switch callback passes DESIRED_PERF, MIN_PERF and MAX_PERF to cppc_set_perf(). If a limit uses PCC, that function can sleep while called from scheduler context. Allow fast switching only when every supported control used by the callback has an address space already accepted for fast access. Check the complete policy domain, including initialized CPUs that are currently offline and may later become the policy's managing CPU. Fixes: 658fa7b1c47a ("ACPI: CPPC: Add cppc_get_perf() API to read performance controls") Cc: stable@vger.kernel.org Signed-off-by: Christian Loehle Link: https://patch.msgid.link/20260722093825.1030594-2-christian.loehle@arm.com Signed-off-by: Rafael J. Wysocki --- include/acpi/cppc_acpi.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/acpi/cppc_acpi.h b/include/acpi/cppc_acpi.h index 8693890a7275..8c191b9ac18f 100644 --- a/include/acpi/cppc_acpi.h +++ b/include/acpi/cppc_acpi.h @@ -170,7 +170,7 @@ extern u64 cppc_get_dmi_max_khz(void); extern unsigned int cppc_perf_to_khz(struct cppc_perf_caps *caps, unsigned int perf); extern unsigned int cppc_khz_to_perf(struct cppc_perf_caps *caps, unsigned int freq); extern bool acpi_cpc_valid(void); -extern bool cppc_allow_fast_switch(void); +bool cppc_allow_fast_switch(const struct cpumask *cpus); extern int acpi_get_psd_map(unsigned int cpu, struct cppc_cpudata *cpu_data); extern int cppc_get_transition_latency(int cpu); extern bool cpc_ffh_supported(void); @@ -234,7 +234,8 @@ static inline bool acpi_cpc_valid(void) { return false; } -static inline bool cppc_allow_fast_switch(void) + +static inline bool cppc_allow_fast_switch(const struct cpumask *cpus) { return false; } -- cgit v1.2.3 From db3d0e0e5d4bc5ab4fe445b9f413d1b486508ca5 Mon Sep 17 00:00:00 2001 From: Xiang Mei Date: Sun, 12 Jul 2026 16:42:01 -0700 Subject: netfilter: nf_conntrack_sip: widen NAT rewrite delta to s32 in sip_help_tcp() sip_help_tcp() stores the size change of each NAT-rewritten SIP message in s16 diff and accumulates it in s16 tdiff, but a single message can grow by more than S16_MAX while the packet stays under the 65535 enlarge_skb() limit: nf_nat_sip() rewrites every matching URI, and a long Contact list expands the message by tens of kilobytes. diff then wraps, and "datalen = datalen + diff - msglen" yields a huge unsigned datalen, so the next iteration's ct_sip_get_header() reads past the linearized skb tail. Widen diff, tdiff and the seq_adjust hook to s32. Both are bounded by the 65535 byte packet limit, and the seqadj core is already s32 (nf_ct_seqadj_set() takes s32), so no previously accepted input is rejected. BUG: KASAN: use-after-free in ct_sip_get_header (net/netfilter/nf_conntrack_sip.c:464) Read of size 1 at addr ffff888010800000 by task ksoftirqd/1/25 ct_sip_get_header (net/netfilter/nf_conntrack_sip.c:464) sip_help_tcp (net/netfilter/nf_conntrack_sip.c:1694) nf_confirm (net/netfilter/nf_conntrack_proto.c:183) nf_hook_slow (net/netfilter/core.c:619) ip6_output (net/ipv6/ip6_output.c:246) ip6_forward (net/ipv6/ip6_output.c:690) ipv6_rcv (net/ipv6/ip6_input.c:351) __netif_receive_skb_one_core (net/core/dev.c:6212) process_backlog (net/core/dev.c:6676) __napi_poll (net/core/dev.c:7735) net_rx_action (net/core/dev.c:7955) handle_softirqs (kernel/softirq.c:622) run_ksoftirqd (kernel/softirq.c:1076) ... Fixes: f5b321bd37fb ("netfilter: nf_conntrack_sip: add TCP support") Reported-by: Weiming Shi Link: https://patch.msgid.link/netfilter-devel/20260712234201.3213635-1-xmei5@asu.edu Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Xiang Mei Signed-off-by: Pablo Neira Ayuso --- include/linux/netfilter/nf_conntrack_sip.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/netfilter/nf_conntrack_sip.h b/include/linux/netfilter/nf_conntrack_sip.h index dbc614dfe0d5..aafa0c04f917 100644 --- a/include/linux/netfilter/nf_conntrack_sip.h +++ b/include/linux/netfilter/nf_conntrack_sip.h @@ -115,7 +115,7 @@ struct nf_nat_sip_hooks { unsigned int *datalen); void (*seq_adjust)(struct sk_buff *skb, - unsigned int protoff, s16 off); + unsigned int protoff, s32 off); unsigned int (*expect)(struct sk_buff *skb, unsigned int protoff, -- cgit v1.2.3 From 4aa63842fc92de1bce59d4709a0d32e718890bb2 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 13 Jul 2026 00:26:04 +0200 Subject: netfilter: nf_conntrack_expect: add and use nf_ct_expect_related_pair() Add a new function to insert a pair of expectations, this is required by the SIP and H323 NAT helpers. The spinlock is held to check if there is a slot for both expectations, in such case, insert them. This removes the need for nf_ct_unexpect_related() inside the loop to find a pair of consecutive ports, otherwise inserting expectations whose dead flag is already set on can happen. Bump master_help->expecting for the expectation class after checking if the expectation fits in the master expectation list, which is needed for this new _pair() function variant to run the eviction routine including the preallocated slot for the first expectation in the pair. Fixes: b8b09dc2bf35 ("netfilter: nf_conntrack_expect: use conntrack GC to reap expectations") Reported-by: Jaeyeong Lee Link: https://patch.msgid.link/178377968720.33756.12204817361601593230@proton.me/ Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/nf_conntrack_expect.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include') diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h index c024345c9bd8..26d6babd92fc 100644 --- a/include/net/netfilter/nf_conntrack_expect.h +++ b/include/net/netfilter/nf_conntrack_expect.h @@ -161,6 +161,9 @@ static inline int nf_ct_expect_related(struct nf_conntrack_expect *expect, return nf_ct_expect_related_report(expect, 0, 0, flags); } +int nf_ct_expect_related_pair(struct nf_conntrack_expect *expect[], + unsigned int flag); + struct nf_conn_help; void nf_ct_expectation_gc(struct nf_conn_help *master_help); -- cgit v1.2.3 From d6f0248f04a96249660591e47fcf37ba98ac7ea3 Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Tue, 30 Jun 2026 14:57:54 -0700 Subject: mshv: fix hv_input_get_system_property struct Keep it in sync with the correct definition. The old code worked by chance. Fixes: e68bda71a2384 ("hyperv: Add new Hyper-V headers in include/hyperv") Cc: stable@kernel.org Signed-off-by: Wei Liu --- include/hyperv/hvhdk_mini.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/hyperv/hvhdk_mini.h b/include/hyperv/hvhdk_mini.h index b4cb2fa26e9b..035ba20870f7 100644 --- a/include/hyperv/hvhdk_mini.h +++ b/include/hyperv/hvhdk_mini.h @@ -184,8 +184,9 @@ enum hv_dynamic_processor_feature_property { struct hv_input_get_system_property { u32 property_id; /* enum hv_system_property */ + u32 reserved; union { - u32 as_uint32; + u64 as_uint64; #if IS_ENABLED(CONFIG_X86) /* enum hv_dynamic_processor_feature_property */ u32 hv_processor_feature; -- cgit v1.2.3 From cbfe2b24a1ea9de35032dbdd100fdc700f5be92d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20L=C3=B3pez?= Date: Wed, 15 Jul 2026 12:51:37 +0200 Subject: KVM: arm64: vgic: Fix race between LPI release and re-registration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix a potential race between decrementing an LPI's reference count and evicting that structure from the LPI xarray. LPI structures are maintained in the VGIC LPI xarray (dist->lpi_xa). When the reference count of an LPI structure drops to zero, vgic_release_lpi_locked() removes the structure from the xarray and frees it under the xarray lock. However, the release of an LPI can race with a concurrent LPI re-registration with the same INTID via vgic_add_lpi() on another CPU, since the reference count drop and the xarray eviction are not performed in a single atomic step. This can happen e.g. if the guest issues a DISCARD while the LPI is still referenced from a vCPU's active-pending list (ap_list), and the same INTID is re-mapped via MAPTI. Particularly, vgic_release_lpi_locked() is called from two distinct paths: direct release via vgic_put_irq(), and deferred release via vgic_release_deleted_lpis(). During direct release, the issue can result in deleting a newly registered LPI from the xarray: CPU0 (Releasing LPI) CPU1 (Adding new LPI) ==================== ===================== vgic_put_irq() __vgic_put_irq() refcount_dec_and_test() vgic_add_lpi() xa_lock_irqsave() old_irq = xa_load(.., intid) vgic_try_get_irq_ref(old_irq) == false new IRQ inserted --> __xa_store(.., intid, ..) xa_unlock_irqrestore() xa_lock_irqsave(); vgic_release_lpi_locked() __xa_erase(.., irq->intid) <-- BUG: new IRQ is erased kfree_rcu(old_irq) During the deferred release path, the old IRQ can be leaked: CPU0 (Releasing LPI) CPU1 (Adding new LPI) ==================== ===================== vgic_put_irq_norelease() __vgic_put_irq() refcount_dec_and_test() irq->pending_release = true vgic_add_lpi() xa_lock_irqsave() old_irq = xa_load(.., intid) vgic_try_get_irq_ref(oldirq) == false BUG: old IRQ overwritten --> __xa_store(.., intid, ..) xa_unlock_irqrestore() vgic_release_deleted_lpis() xa_lock_irqsave() xa_for_each() { .. } <-- old IRQ with pending_release = true is gone, so it cannot be released To fix the direct release path, move the reference count drop inside the xarray lock, making sure that vgic_add_lpi() never encounters the to-be-released LPI. In the deferred release path, the refcount drop must happen under a raw spinlock, so the xarray lock cannot be grabbed, and the same solution does not work. Instead, update vgic_add_lpi(), so that if it evicts an LPI from the xarray, it takes on the responsibility of freeing it. Consequently, an LPI may now be freed concurrently after a deferred release drops the refcount, so accessing the pending_release field is no longer safe from use-after-free. Delete all uses of the flag, and update vgic_release_deleted_lpis() to identify orphaned LPIs purely based on their refcount. Reported-by: Claude:claude-opus-4-6 Fixes: 3a08a6ca7c37 ("KVM: arm64: vgic-v3: Use bare refcount for VGIC LPIs") Fixes: d54594accf73 ("KVM: arm64: vgic-v3: Erase LPIs from xarray outside of raw spinlocks") Signed-off-by: Carlos López Link: https://patch.msgid.link/20260715105137.3973823-4-clopez@suse.de Signed-off-by: Marc Zyngier --- include/kvm/arm_vgic.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'include') diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h index fe49fb56dc3c..cefddc9c621d 100644 --- a/include/kvm/arm_vgic.h +++ b/include/kvm/arm_vgic.h @@ -247,9 +247,6 @@ struct vgic_irq { * affinity reg (v3). */ - bool pending_release:1; /* Used for LPIs only, unreferenced IRQ - * pending a release */ - bool pending_latch:1; /* The pending latch state used to calculate * the pending state for both level * and edge triggered IRQs. */ -- cgit v1.2.3 From f4f699790590bd0896c48a71e9232a65198f92f0 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 16 Jul 2026 10:13:37 +0200 Subject: netfilter: nf_tables: make nft_object rhltable per table The nft_object rhltable is global, this allows for accessing objects that are being dismangled from lookup path by other existing netns. Given the nft_obj_destroy() releases the object inmediately, this might lead to use-after-free of these objects that are being released. Make the existing rhltable per table to address this issue to deal with with the nft_rcv_nl_event() path too. Update nft_obj_lookup() to take the table as non-const, otherwise, compiler complains when passing the objname_ht to rhltable_lookup(). Fixes: 4d44175aa5bb ("netfilter: nf_tables: handle nft_object lookups via rhltable") Suggested-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/nf_tables.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index 9d844354c4d9..3be612145c13 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h @@ -1294,6 +1294,7 @@ static inline void nft_use_inc_restore(u32 *use) * @sets: sets in the table * @objects: stateful objects in the table * @flowtables: flow tables in the table + * @objname_ht: hashtable for objects lookup by name * @hgenerator: handle generator state * @handle: table handle * @use: number of chain references to this table @@ -1313,6 +1314,7 @@ struct nft_table { struct list_head sets; struct list_head objects; struct list_head flowtables; + struct rhltable objname_ht; u64 hgenerator; u64 handle; u32 use; @@ -1400,7 +1402,7 @@ static inline void *nft_obj_data(const struct nft_object *obj) #define nft_expr_obj(expr) *((struct nft_object **)nft_expr_priv(expr)) struct nft_object *nft_obj_lookup(const struct net *net, - const struct nft_table *table, + struct nft_table *table, const struct nlattr *nla, u32 objtype, u8 genmask); -- cgit v1.2.3 From e876b75b9020a97bbdc79721e7fc749024891c65 Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Wed, 22 Jul 2026 13:15:15 +0300 Subject: ipvs: fix the checksum validations ip_vs_in_icmp_v6() is missing checksum validation for ICMPv6 packets from clients. In fact, as for TCP/UDP we should validate the checksum for ICMP packets only when we mangle the packets on MASQ or on reply for tunnel. Also, Sashiko points out that handle_response_icmp() being common for IPv4 and IPv6 is missing the pseudo-header calculation while validating ICMPv6 messages from real servers which is a problem if checksum is not validated by the hardware. Fix the problems by creating ip_vs_checksum_common_check() helper and use it for TCP/UDP/ICMP both for IPv4 and IPv6. Rely on the nf_checksum() for validating the ICMP messages but use it also for TCP and UDP. Use correct IP offset for IP_VS_DBG_RL_PKT for TCP/UDP/SCTP. IPVS packets (TCP/UDP/SCTP/ICMP) do not need checksum validation on LOCAL_OUT (local clients or local real servers) and on FORWARD (traffic from servers on LAN). Do it only on LOCAL_IN, in case nf_checksum() is not called on PRE_ROUTING. Also, ip_vs_checksum_complete() can be marked static. Fixes: 2a3b791e6e11 ("IPVS: Add/adjust Netfilter hook functions and helpers for v6") Link: https://sashiko.dev/#/patchset/20260708180315.77413-1-ja%40ssi.bg Signed-off-by: Julian Anastasov Signed-off-by: Pablo Neira Ayuso --- include/net/ip_vs.h | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index 417ff51f62fc..d8f9ddb0fb38 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -25,7 +25,9 @@ #include /* for union nf_inet_addr */ #include #include /* for struct ipv6hdr */ +#include #include +#include #if IS_ENABLED(CONFIG_NF_CONNTRACK) #include #endif @@ -2066,8 +2068,6 @@ void ip_vs_nat_icmp_v6(struct sk_buff *skb, struct ip_vs_protocol *pp, struct ip_vs_conn *cp, int dir); #endif -__sum16 ip_vs_checksum_complete(struct sk_buff *skb, int offset); - static inline __wsum ip_vs_check_diff4(__be32 old, __be32 new, __wsum oldsum) { __be32 diff[2] = { ~old, new }; @@ -2093,6 +2093,33 @@ static inline __wsum ip_vs_check_diff2(__be16 old, __be16 new, __wsum oldsum) return csum_partial(diff, sizeof(diff), oldsum); } +static inline bool ip_vs_checksum_needed(struct sk_buff *skb, int af) +{ + /* Checksum unnecessary or already validated? */ + if (skb_csum_unnecessary(skb)) + return false; + /* LOCAL_OUT ? */ + if (!skb->dev || skb->dev->flags & IFF_LOOPBACK) + return false; + /* !LOCAL_IN (FORWARD) ? */ + if (af == AF_INET6) { + if (!(dst_rt6_info(skb_dst(skb))->rt6i_flags & RTF_LOCAL)) + return false; + } else { + if (!(skb_rtable(skb)->rt_flags & RTCF_LOCAL)) + return false; + } + return true; +} + +static inline bool ip_vs_checksum_common_check(struct sk_buff *skb, + int offset, int proto, int af) +{ + if (!ip_vs_checksum_needed(skb, af)) + return true; + return !nf_checksum(skb, NF_INET_LOCAL_IN, offset, proto, af); +} + /* Forget current conntrack (unconfirmed) and attach notrack entry */ static inline void ip_vs_notrack(struct sk_buff *skb) { -- cgit v1.2.3 From 15cab31a3730e05f0767b922a7450e5d784b2607 Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Wed, 22 Jul 2026 13:15:16 +0300 Subject: ipvs: fix places with wrong packet offsets The offsets we use to packet headers and payloads should be based on skb->data. We even already respect non-zero network offset in ip_vs_fill_iph_skb() but some places do it wrongly and support only zero offset which is expected for the IP layer where IPVS has hooks. Change all places that instead of skb->data use offsets based on the network header (skb_network_header, ip_hdr, etc) because this doubles the network offset as noted by Sashiko. For ip_vs_nat_icmp_v6() we can even rely on the IPv6 header parsing done by the caller. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Link: https://sashiko.dev/#/patchset/20260710143733.29741-2-fw%40strlen.de Signed-off-by: Julian Anastasov Signed-off-by: Pablo Neira Ayuso --- include/net/ip_vs.h | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index d8f9ddb0fb38..4a10a01d6e2f 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -1974,8 +1974,9 @@ int ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, int ip_vs_dr_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph); int ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, - struct ip_vs_protocol *pp, int offset, - unsigned int hooknum, struct ip_vs_iphdr *iph); + struct ip_vs_protocol *pp, unsigned int toff, + unsigned int wlen, unsigned int hooknum, + struct ip_vs_iphdr *ciph); void ip_vs_dest_dst_rcu_free(struct rcu_head *head); #ifdef CONFIG_IP_VS_IPV6 @@ -1988,8 +1989,9 @@ int ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, int ip_vs_dr_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph); int ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, - struct ip_vs_protocol *pp, int offset, - unsigned int hooknum, struct ip_vs_iphdr *iph); + struct ip_vs_protocol *pp, unsigned int toff, + unsigned int wlen, unsigned int hooknum, + struct ip_vs_iphdr *ciph); #endif #ifdef CONFIG_SYSCTL @@ -2061,11 +2063,12 @@ static inline bool ip_vs_conn_use_hash2(struct ip_vs_conn *cp) } void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp, - struct ip_vs_conn *cp, int dir); + struct ip_vs_conn *cp, int dir, unsigned int toff); #ifdef CONFIG_IP_VS_IPV6 void ip_vs_nat_icmp_v6(struct sk_buff *skb, struct ip_vs_protocol *pp, - struct ip_vs_conn *cp, int dir); + struct ip_vs_conn *cp, int dir, unsigned int toff, + struct ip_vs_iphdr *ciph); #endif static inline __wsum ip_vs_check_diff4(__be32 old, __be32 new, __wsum oldsum) -- cgit v1.2.3 From 342e24a339b90e8e339a0f8c151ca479b8565661 Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Wed, 22 Jul 2026 13:15:17 +0300 Subject: ipvs: do not mangle ICMP replies for non-first fragments Sashiko warns that ip_vs_nat_icmp() unconditionally mangles the payload for embedded non-first IPv4 fragments. The problem is in the very old inverted pp->dont_defrag check which should not continue when embedded is a non-first TCP/UDP/SCTP fragment. Check for embedded non-first fragment is also missing from ip_vs_out_icmp_v6(), it is needed before any connection lookups that expect ports after the network headers. Drop the blocking code from ip_vs_in_icmp_v6() which prevents ICMPv6 from local clients to use non-MASQ forwarding. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Link: https://sashiko.dev/#/patchset/20260720201122.79882-1-ja%40ssi.bg Signed-off-by: Julian Anastasov Signed-off-by: Pablo Neira Ayuso --- include/net/ip_vs.h | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index 4a10a01d6e2f..e6ca930a3507 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -1975,8 +1975,7 @@ int ip_vs_dr_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph); int ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp, unsigned int toff, - unsigned int wlen, unsigned int hooknum, - struct ip_vs_iphdr *ciph); + unsigned int hooknum, struct ip_vs_iphdr *ciph); void ip_vs_dest_dst_rcu_free(struct rcu_head *head); #ifdef CONFIG_IP_VS_IPV6 @@ -1990,8 +1989,7 @@ int ip_vs_dr_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph); int ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp, unsigned int toff, - unsigned int wlen, unsigned int hooknum, - struct ip_vs_iphdr *ciph); + unsigned int hooknum, struct ip_vs_iphdr *ciph); #endif #ifdef CONFIG_SYSCTL @@ -2063,12 +2061,13 @@ static inline bool ip_vs_conn_use_hash2(struct ip_vs_conn *cp) } void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp, - struct ip_vs_conn *cp, int dir, unsigned int toff); + struct ip_vs_conn *cp, int dir, unsigned int toff, + bool has_ports); #ifdef CONFIG_IP_VS_IPV6 void ip_vs_nat_icmp_v6(struct sk_buff *skb, struct ip_vs_protocol *pp, struct ip_vs_conn *cp, int dir, unsigned int toff, - struct ip_vs_iphdr *ciph); + bool has_ports, struct ip_vs_iphdr *ciph); #endif static inline __wsum ip_vs_check_diff4(__be32 old, __be32 new, __wsum oldsum) -- cgit v1.2.3 From bd44a6dcd4248883de90f5dad53ae80066e27096 Mon Sep 17 00:00:00 2001 From: Jason Xing Date: Sun, 19 Jul 2026 15:56:05 +0200 Subject: xsk: drain continuation descs after overflow in xsk_build_skb() Fix generic xmit path multi-buffer logic when packets are either too big (count of descriptors exceed MAX_SKB_FRAGS) or an invalid descriptor is included in fragmented packet. Introduce xdp_sock::drain_cont and act upon this flag - when it is set, keep on consuming descriptors from AF_XDP Tx ring and put them directly onto Cq. Previously these descriptors were silently lost and could never be reached again. Fixes: cf24f5a5feea ("xsk: add support for AF_XDP multi-buffer on Tx path") Closes: https://lore.kernel.org/all/20260425041726.85FB3C2BCB2@smtp.kernel.org/ Reviewed-by: Jason Xing Co-developed-by: Maciej Fijalkowski # wrapped cq addr submission onto routine Signed-off-by: Maciej Fijalkowski Signed-off-by: Jason Xing Acked-by: Stanislav Fomichev Link: https://patch.msgid.link/20260719135609.147823-3-maciej.fijalkowski@intel.com Signed-off-by: Jakub Kicinski --- include/net/xdp_sock.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/net/xdp_sock.h b/include/net/xdp_sock.h index ebac60a3d8a1..8b51876efbed 100644 --- a/include/net/xdp_sock.h +++ b/include/net/xdp_sock.h @@ -80,6 +80,7 @@ struct xdp_sock { * call of __xsk_generic_xmit(). */ struct sk_buff *skb; + bool drain_cont; struct list_head map_list; /* Protects map_list */ -- cgit v1.2.3 From 08c9a8e794b4694c100dafcb80e069e29ad81b64 Mon Sep 17 00:00:00 2001 From: Maciej Fijalkowski Date: Sun, 19 Jul 2026 15:56:06 +0200 Subject: xsk: provide sufficient space in pool->tx_descs The temporary Tx descriptor array in an XSK buffer pool is currently sized from the Tx ring of the socket that creates the pool. This is insufficient for shared-UMEM Tx. A later socket may have a larger Tx ring and submit a valid multi-buffer packet containing more descriptors than the first socket's ring, while still remaining within the device's xdp_zc_max_segs limit. A packet-framed batch parser bounded by the temporary array cannot reach the end-of-packet descriptor in that case. It leaves the packet on the Tx ring and encounters the same packet on every subsequent attempt, stalling Tx processing for that socket. Size the temporary descriptor array to the larger of the first Tx ring and the device's xdp_zc_max_segs capability. This keeps the array large enough to inspect one maximum-sized valid packet. Larger shared Tx rings do not require further resizing, as they can be processed over multiple batches. Following commit will actually address the data path side. Fixes: d5581966040f ("xsk: support ZC Tx multi-buffer in batch API") Reviewed-by: Jason Xing Signed-off-by: Maciej Fijalkowski Acked-by: Stanislav Fomichev Link: https://patch.msgid.link/20260719135609.147823-4-maciej.fijalkowski@intel.com Signed-off-by: Jakub Kicinski --- include/net/xsk_buff_pool.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/net/xsk_buff_pool.h b/include/net/xsk_buff_pool.h index ccb3b350001f..f5e737a83055 100644 --- a/include/net/xsk_buff_pool.h +++ b/include/net/xsk_buff_pool.h @@ -102,12 +102,14 @@ struct xsk_buff_pool { /* AF_XDP core. */ struct xsk_buff_pool *xp_create_and_assign_umem(struct xdp_sock *xs, - struct xdp_umem *umem); + struct xdp_umem *umem, + u32 max_segs); int xp_assign_dev(struct xsk_buff_pool *pool, struct net_device *dev, u16 queue_id, u16 flags); int xp_assign_dev_shared(struct xsk_buff_pool *pool, struct xdp_sock *umem_xs, struct net_device *dev, u16 queue_id); -int xp_alloc_tx_descs(struct xsk_buff_pool *pool, struct xdp_sock *xs); +int xp_alloc_tx_descs(struct xsk_buff_pool *pool, struct xdp_sock *xs, + u32 max_segs); void xp_destroy(struct xsk_buff_pool *pool); void xp_get_pool(struct xsk_buff_pool *pool); bool xp_put_pool(struct xsk_buff_pool *pool); -- cgit v1.2.3 From 72f2b4516faf55d4dfac2414649d3cffa5fd2c5e Mon Sep 17 00:00:00 2001 From: Maciej Fijalkowski Date: Sun, 19 Jul 2026 15:56:07 +0200 Subject: xsk: reclaim invalid Tx descriptors in ZC batch path The zero-copy Tx batch parser stops when it encounters an invalid descriptor. If this happens after one or more continuation descriptors, the Tx consumer can be advanced past fragments that are neither submitted to the driver nor returned to userspace through the completion ring. A similar problem occurs when a packet exceeds xdp_zc_max_segs. The descriptors consumed up to the limit are released without completion, and the remaining continuation descriptors can subsequently be interpreted as the beginning of another packet. Parse Tx batches in packet units and distinguish descriptors belonging to complete valid packets from descriptors consumed while draining an invalid or oversized packet. Return the former to the driver and append the latter to the CQ address area so userspace can reclaim their UMEM frames. Treat a standalone invalid descriptor as a one-descriptor reclaim-only packet. Advancing the Tx-ring consumer releases the ring slot, but does not by itself return ownership of the referenced UMEM frame to userspace. Once draining starts, continue until the packet's end-of-packet descriptor is consumed. Preserve the drain state on the socket when EOP has not yet been supplied, so draining can continue during a later call. Leave incomplete but otherwise valid packets on the Tx ring. Shared-UMEM pools using multi-buffer Tx also need packet-framed parsing. Walk their Tx sockets one packet at a time, preserving the existing per-socket fairness scheme, instead of using the legacy one-descriptor fallback. Keep that fallback for shared pools that do not use multi-buffer Tx. Since the drain state is maintained per socket and both the singular and shared paths can resume an interrupted drain, changing the socket list from singular to shared requires no special bind-time transition. CQ entries are positional, and drivers may complete only part of the Tx work returned by xsk_tx_peek_release_desc_batch(). Therefore, reclaim-only entries cannot be published immediately when earlier driver-visible descriptors are still outstanding. Track the number of driver-visible CQ entries preceding the reclaim entries. Let xsk_tx_completed() publish partial hardware Tx completions, and publish the reclaim entries only after every earlier Tx descriptor has completed. Complete a reclaim-only batch immediately when there is no driver-visible work in front of it, and prevent another Tx batch from being appended while reclaim entries remain pending. Also cap batch processing by the size of the pool's temporary descriptor array, as Tx rings belonging to sockets sharing a UMEM may have different sizes. This ensures that every invalid Tx descriptor consumed by the ZC batch path is either submitted to the driver as part of a valid packet or returned to userspace without violating CQ completion ordering. Reviewed-by: Jason Xing Signed-off-by: Maciej Fijalkowski Acked-by: Stanislav Fomichev Fixes: cf24f5a5feea ("xsk: add support for AF_XDP multi-buffer on Tx path") Link: https://patch.msgid.link/20260719135609.147823-5-maciej.fijalkowski@intel.com Signed-off-by: Jakub Kicinski --- include/net/xsk_buff_pool.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include') diff --git a/include/net/xsk_buff_pool.h b/include/net/xsk_buff_pool.h index f5e737a83055..2bb1d122b1bc 100644 --- a/include/net/xsk_buff_pool.h +++ b/include/net/xsk_buff_pool.h @@ -78,6 +78,9 @@ struct xsk_buff_pool { u32 chunk_size; u32 chunk_shift; u32 frame_len; + u32 tx_descs_nentries; + u32 reclaim_descs; + u32 tx_zc_pending_descs; u32 xdp_zc_max_segs; u8 tx_metadata_len; /* inherited from umem */ u8 cached_need_wakeup; -- cgit v1.2.3 From 738e6f32e61d80b554e37015ecb7bc620b88001c Mon Sep 17 00:00:00 2001 From: Peiyang He Date: Mon, 20 Jul 2026 16:50:16 +0800 Subject: iommu/iommufd: Fix IOPF group ownership UAF iopf_group_alloc() links each last-page IOPF group into the generic IOPF pending list before invoking the domain fault handler. iommufd_fault_iopf_handler() also queued an accepted group in the IOMMUFD deliver list without removing it from the generic pending list. When detach or HWPT replacement drops the device's IOPF reference count to zero, an IOMMU driver may call iopf_queue_remove_device(). That function responds to and frees groups through the generic pending list without removing the same groups from IOMMUFD's deliver list or response xarray. A later read, response, or cleanup can then access the freed group and cause a UAF. Fix this by dequeuing an accepted group from the generic pending list before IOMMUFD queues it for userspace response. Make iopf_group_response() send a response regardless of pending-list membership, so the dequeued group can still be completed by IOMMUFD. Link: https://patch.msgid.link/r/3CFD314D0FE4D7EC+20260720085017.3998878-2-peiyang_he@smail.nju.edu.cn Closes: https://lore.kernel.org/all/B4F28798E2E784CA+d29f723c-b2b5-4b67-8d1c-4f7b9b0b27cb@smail.nju.edu.cn/ Fixes: 34765cbc679c ("iommufd: Associate fault object with iommufd_hw_pgtable") Cc: stable@vger.kernel.org Tested-by: Peiyang He Assisted-by: Codex:gpt-5.6-sol Signed-off-by: Peiyang He Reviewed-by: Kevin Tian Signed-off-by: Jason Gunthorpe --- include/linux/iommu.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include') diff --git a/include/linux/iommu.h b/include/linux/iommu.h index d20aa6f6863a..ac43b8b93f14 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -1704,6 +1704,7 @@ void iopf_free_group(struct iopf_group *group); int iommu_report_device_fault(struct device *dev, struct iopf_fault *evt); void iopf_group_response(struct iopf_group *group, enum iommu_page_response_code status); +void iopf_group_dequeue(struct iopf_group *group); #else static inline int iopf_queue_add_device(struct iopf_queue *queue, struct device *dev) @@ -1749,5 +1750,9 @@ static inline void iopf_group_response(struct iopf_group *group, enum iommu_page_response_code status) { } + +static inline void iopf_group_dequeue(struct iopf_group *group) +{ +} #endif /* CONFIG_IOMMU_IOPF */ #endif /* __LINUX_IOMMU_H */ -- cgit v1.2.3 From 3dbbbf656b850c9c8de05df6ad4a1dfc6ff02845 Mon Sep 17 00:00:00 2001 From: Xingui Yang Date: Thu, 16 Jul 2026 16:11:45 +0800 Subject: scsi: libsas: Fix HA resume deadlock and hisi_sas disk-wake race Commit fbefe22811c3 ("scsi: libsas: Don't always drain event workqueue for HA resume") introduced sas_resume_ha_no_sync() to avoid a deadlock: the PHYE_RESUME_TIMEOUT handler, running on the HA event workqueue, calls sas_deform_port() -> sas_destruct_devices(), which removes SCSI devices and waits for the host to become runtime-active. But the host cannot resume until sas_resume_ha() -> sas_drain_work() returns, and the drain is blocked on that very handler. However skipping the drain reintroduces a race: hisi_sas returns from resume before all PHY UP work and libsas discovery work finish. The controller may then autosuspend while disks are still waking up. The disks issue IO to a suspended controller, the IO fails, and the disks get disabled. Fix the deadlock at its source by moving the PHYE_RESUME_TIMEOUT notification to after sas_drain_work(). By then the host resume is about to complete, so device removal through device_link no longer blocks on the resume and the cycle is broken. With the deadlock gone, restore sas_resume_ha() (the draining variant) in hisi_sas and remove sas_resume_ha_no_sync(). The reorder is safe for the other libsas consumers (isci, pm8001, aic94xx, mvsas). During suspend, sas_suspend_devices() calls sas_notify_lldd_dev_gone() for each device, which sets dev->lldd_dev to NULL. When scsi_unblock_requests re-enables I/O in resume, any I/O to a timed-out phy's disk is immediately rejected by the LLDD before reaching hardware: isci returns SAS_DEVICE_UNKNOWN (mapped to DID_BAD_TARGET), and pm8001 returns SAS_PHY_DOWN (mapped to DID_NO_CONNECT). Both complete directly via scsi_done() without entering SCSI EH. This is identical in both the old and new ordering since lldd_dev_gone runs during suspend, before resume. The reorder only affects when the PHYE_RESUME_TIMEOUT handler runs (synchronized by sas_drain_work() vs. asynchronous after resume returns), not whether I/O can reach the device. aic94xx and mvsas do not register any PM ops and never reach this code path. Fixes: fbefe22811c3 ("scsi: libsas: Don't always drain event workqueue for HA resume") Signed-off-by: Xingui Yang Reviewed-by: John Garry Link: https://patch.msgid.link/20260716081145.3950172-1-yangxingui@huawei.com Signed-off-by: Martin K. Petersen --- include/scsi/libsas.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include') diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 163f23c92b41..36d4cb567837 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -680,7 +680,6 @@ extern int sas_register_ha(struct sas_ha_struct *); extern int sas_unregister_ha(struct sas_ha_struct *); extern void sas_prep_resume_ha(struct sas_ha_struct *sas_ha); extern void sas_resume_ha(struct sas_ha_struct *sas_ha); -extern void sas_resume_ha_no_sync(struct sas_ha_struct *sas_ha); extern void sas_suspend_ha(struct sas_ha_struct *sas_ha); int sas_phy_reset(struct sas_phy *phy, int hard_reset); -- cgit v1.2.3 From 4ecef577d1ceddaa906720c71c06672433aba318 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 21 Jul 2026 15:36:30 +0100 Subject: ASoC: SDCA: Rename sdca_irq_allocate() to include devm Make it more clear sdca_irq_allocate() uses devm allocations by adding it into the name. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20260721143636.361814-2-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/sdca_interrupts.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/sound/sdca_interrupts.h b/include/sound/sdca_interrupts.h index a515cc3df097..28fd44eb9334 100644 --- a/include/sound/sdca_interrupts.h +++ b/include/sound/sdca_interrupts.h @@ -86,8 +86,9 @@ int sdca_irq_populate(struct sdca_function_data *function, void sdca_irq_cleanup(struct device *dev, struct sdca_function_data *function, struct sdca_interrupt_info *info); -struct sdca_interrupt_info *sdca_irq_allocate(struct device *dev, - struct regmap *regmap, int irq); + +struct sdca_interrupt_info *devm_sdca_irq_allocate(struct device *dev, + struct regmap *regmap, int irq); void sdca_irq_enable_early(struct sdca_function_data *function, struct sdca_interrupt_info *info); -- cgit v1.2.3 From f18e97fa7f125e0e7da130b4d0ff1edd48d7510a Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 21 Jul 2026 15:36:31 +0100 Subject: ASoC: SDCA: Add sdca_irq_cleanup_late() The SDCA IRQs are split into two groups, those registered at bus probe time (basically just FDL) and those registered at component time. There currently exists only a single cleanup function, if the FDL IRQ is freed at component time, then nothing would re-register it if the component is probed again. But the IRQs depending on a component need to be freed if the card is destroyed so they can't use stale components. Split the clean up into two functions one for the component level and one for the bus level. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20260721143636.361814-3-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/sdca_interrupts.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include') diff --git a/include/sound/sdca_interrupts.h b/include/sound/sdca_interrupts.h index 28fd44eb9334..38c6c58c2cc7 100644 --- a/include/sound/sdca_interrupts.h +++ b/include/sound/sdca_interrupts.h @@ -33,6 +33,7 @@ struct sdca_function_data; * @priv: Pointer to private data for use by the handler. * @irq: IRQ number allocated to this interrupt, also used internally to track * the IRQ being assigned. + * @early_request: Flag to indicate this IRQ was requested at bus probe time. */ struct sdca_interrupt { const char *name; @@ -48,6 +49,7 @@ struct sdca_interrupt { void *priv; int irq; + bool early_request; }; /** @@ -86,6 +88,9 @@ int sdca_irq_populate(struct sdca_function_data *function, void sdca_irq_cleanup(struct device *dev, struct sdca_function_data *function, struct sdca_interrupt_info *info); +void sdca_irq_cleanup_late(struct device *dev, + struct sdca_function_data *function, + struct sdca_interrupt_info *info); struct sdca_interrupt_info *devm_sdca_irq_allocate(struct device *dev, struct regmap *regmap, int irq); -- cgit v1.2.3 From 0880082c27b6251cc3fea307dffa6899ad163e8b Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 21 Jul 2026 15:36:32 +0100 Subject: ASoC: SDCA: Remove devm from primary IRQ cleanup To provide greater flexibility on when the IRQs are requested for client drivers don't use devm for the primary IRQ request/cleanup helper functions. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20260721143636.361814-4-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/sdca_fdl.h | 2 ++ include/sound/sdca_interrupts.h | 2 ++ include/sound/sdca_jack.h | 2 ++ 3 files changed, 6 insertions(+) (limited to 'include') diff --git a/include/sound/sdca_fdl.h b/include/sound/sdca_fdl.h index fbaf4b384c8a..dc33927b82bd 100644 --- a/include/sound/sdca_fdl.h +++ b/include/sound/sdca_fdl.h @@ -67,6 +67,8 @@ struct fdl_state { #if IS_ENABLED(CONFIG_SND_SOC_SDCA_FDL) int sdca_fdl_alloc_state(struct sdca_interrupt *interrupt); +void sdca_fdl_free_state(struct sdca_interrupt *interrupt); + int sdca_fdl_process(struct sdca_interrupt *interrupt); int sdca_fdl_sync(struct device *dev, struct sdca_function_data *function, struct sdca_interrupt_info *info); diff --git a/include/sound/sdca_interrupts.h b/include/sound/sdca_interrupts.h index 38c6c58c2cc7..8a44c19e917c 100644 --- a/include/sound/sdca_interrupts.h +++ b/include/sound/sdca_interrupts.h @@ -31,6 +31,7 @@ struct sdca_function_data; * @entity: Pointer to the Entity that the interrupt is associated with. * @control: Pointer to the Control that the interrupt is associated with. * @priv: Pointer to private data for use by the handler. + * @free_priv: Pointer to a function that can be used to free the priv data. * @irq: IRQ number allocated to this interrupt, also used internally to track * the IRQ being assigned. * @early_request: Flag to indicate this IRQ was requested at bus probe time. @@ -47,6 +48,7 @@ struct sdca_interrupt { struct sdca_control *control; void *priv; + void (*free_priv)(struct sdca_interrupt *interrupt); int irq; bool early_request; diff --git a/include/sound/sdca_jack.h b/include/sound/sdca_jack.h index 181541f0f4d8..59de40b7d7d0 100644 --- a/include/sound/sdca_jack.h +++ b/include/sound/sdca_jack.h @@ -28,6 +28,8 @@ struct jack_state { }; int sdca_jack_alloc_state(struct sdca_interrupt *interrupt); +void sdca_jack_free_state(struct sdca_interrupt *interrupt); + int sdca_jack_process(struct sdca_interrupt *interrupt); int sdca_jack_set_jack(struct sdca_interrupt_info *info, struct snd_soc_jack *jack); int sdca_jack_report(struct sdca_interrupt *interrupt); -- cgit v1.2.3 From 050406cbd676615ba71081bce69df710754d27e4 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 21 Jul 2026 15:36:33 +0100 Subject: ASoC: SDCA: Populate IRQ data earlier Currently, the IRQ data (attached Entity/Control/etc) is populated as the IRQ is requested. However, this can cause issues as occasionally the setup process wants to access specifics of an IRQ before the IRQ is actually enabled. To facilitate this cache all the IRQ data during sdca_irq_populate_early() and make sdca_irq_populate() simply request the outstanding IRQs. This also has the advantage that sdca_irq_populate() can now just iterate through the IRQ array which is much smaller/faster than going through every Entity in the Function for Controls. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20260721143636.361814-5-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/sdca_interrupts.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/sound/sdca_interrupts.h b/include/sound/sdca_interrupts.h index 8a44c19e917c..3b30146e21db 100644 --- a/include/sound/sdca_interrupts.h +++ b/include/sound/sdca_interrupts.h @@ -30,6 +30,7 @@ struct sdca_function_data; * @function: Pointer to the Function that the interrupt is associated with. * @entity: Pointer to the Entity that the interrupt is associated with. * @control: Pointer to the Control that the interrupt is associated with. + * @handler: Handler function to be called for the IRQ. * @priv: Pointer to private data for use by the handler. * @free_priv: Pointer to a function that can be used to free the priv data. * @irq: IRQ number allocated to this interrupt, also used internally to track @@ -46,6 +47,7 @@ struct sdca_interrupt { struct sdca_function_data *function; struct sdca_entity *entity; struct sdca_control *control; + irq_handler_t handler; void *priv; void (*free_priv)(struct sdca_interrupt *interrupt); -- cgit v1.2.3 From 3e81e2fb216327a73510a7aa5318023c379d479a Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 21 Jul 2026 15:36:34 +0100 Subject: ASoC: Add a component fixup_controls callback A card level fixup_controls callback was added in: commit df4d27b19b89 ("ASoC: Introduce 'fixup_controls' card method") This allowed the machine driver to take actions after all the card controls have been added. However, there are times when a codec driver would also want to do things like obtain references to controls for later use, which require all the controls to be present. Add a component level fixup_controls callback, echoing the card level option. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20260721143636.361814-6-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index aa423865dbe7..4b7d7954953d 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -78,6 +78,7 @@ struct snd_soc_component_driver { unsigned int num_dapm_routes; int (*probe)(struct snd_soc_component *component); + int (*fixup_controls)(struct snd_soc_component *component); void (*remove)(struct snd_soc_component *component); int (*suspend)(struct snd_soc_component *component); int (*resume)(struct snd_soc_component *component); @@ -380,6 +381,7 @@ void snd_soc_component_suspend(struct snd_soc_component *component); void snd_soc_component_resume(struct snd_soc_component *component); int snd_soc_component_is_suspended(struct snd_soc_component *component); int snd_soc_component_probe(struct snd_soc_component *component); +int snd_soc_component_fixup_controls(struct snd_soc_component *component); void snd_soc_component_remove(struct snd_soc_component *component); int snd_soc_component_of_xlate_dai_id(struct snd_soc_component *component, struct device_node *ep); -- cgit v1.2.3 From bf1b7821f85383a8804441f8fd5165be148f3ec8 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 21 Jul 2026 15:36:36 +0100 Subject: ASoC: SDCA: Move kcontrol search out of IRQ Now that the IRQs are always registered after all the ALSA controls are created it is possible to search for the control at the point the IRQ is requested. Move the control search out of the IRQ handler and do it at IRQ request time. This also fixes a potential issue when the card was torn down and reprobed without destroying the codec device, the kctl pointer stored by the IRQ handler would not be updated to the new control on the second probe. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20260721143636.361814-8-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/sdca_jack.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/sound/sdca_jack.h b/include/sound/sdca_jack.h index 59de40b7d7d0..871ba2d8146a 100644 --- a/include/sound/sdca_jack.h +++ b/include/sound/sdca_jack.h @@ -28,6 +28,7 @@ struct jack_state { }; int sdca_jack_alloc_state(struct sdca_interrupt *interrupt); +int sdca_jack_init_state(struct sdca_interrupt *interrupt); void sdca_jack_free_state(struct sdca_interrupt *interrupt); int sdca_jack_process(struct sdca_interrupt *interrupt); -- cgit v1.2.3 From 97ac08560d236ca17f6606d9e671118e5eae5721 Mon Sep 17 00:00:00 2001 From: Eric Joyner Date: Wed, 22 Jul 2026 21:13:42 -0700 Subject: ethtool: Embed FEC hist ranges as buffer in struct When a driver's .get_fec_stats() handler is called and the driver supports FEC histogram stats, the driver supplies the histogram bin ranges via a pointer. This pointer is assigned while under the netdev ops lock in fec_prepare_data(), but the actual data is only read after the lock is released; so this allows the driver to change the ranges (e.g. from another .get_fec_stats() call) while the current call chain is reading them in fec_fill_reply(). Fix this by adding an ethtool core-owned buffer, ranges_buf, to struct ethtool_fec_hist. Drivers whose ranges are built dynamically (currently just mlx5) fill ranges_buf and then point the existing ranges pointer at it, giving ethtool a consistent copy that stays valid after the netdev ops lock is dropped and later in fec_fill_reply(). Drivers whose ranges are compile-time constants (bnxt, netdevsim) are unaffected by the potential race and keep setting the existing ranges pointer to their constant array, without making copies. Fixes: cc2f08129925 ("ethtool: add FEC bins histogram report") Signed-off-by: Eric Joyner Reviewed-by: Vadim Fedorenko Link: https://patch.msgid.link/20260723041342.39238-1-eric.joyner@amd.com Signed-off-by: Jakub Kicinski --- include/linux/ethtool.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index 5d491a98265e..12683b5d125e 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -562,6 +562,7 @@ struct ethtool_fec_hist { u64 per_lane[ETHTOOL_MAX_LANES]; } values[ETHTOOL_FEC_HIST_MAX]; const struct ethtool_fec_hist_range *ranges; + struct ethtool_fec_hist_range ranges_buf[ETHTOOL_FEC_HIST_MAX]; }; /** * struct ethtool_fec_stats - statistics for IEEE 802.3 FEC -- cgit v1.2.3 From aec49a34d928a0ecdea85bd9f6b4114b668b68b8 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 24 Jul 2026 18:52:09 -0700 Subject: ata: libata: avoid kernel-doc warnings Modify comments to prevent kernel-doc warnings: - use "/*" for a non-kernel-doc comment - add a Returns: section for ata_id_major_version() Warning: include/linux/ata.h:770 Cannot find identifier on line: * Warning: include/linux/ata.h:782 function parameter 'id' not described in 'ata_id_sct_data_tables' Warning: include/linux/ata.h:782 expecting prototype for Word(). Prototype was for ata_id_sct_data_tables() instead Warning: include/linux/ata.h:820 No description found for return value of 'ata_id_major_version' Signed-off-by: Randy Dunlap Signed-off-by: Damien Le Moal --- include/linux/ata.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/linux/ata.h b/include/linux/ata.h index 8fd48bcb2a46..7daad4cad985 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -762,8 +762,7 @@ static inline bool ata_id_sense_reporting_enabled(const u16 *id) return id[ATA_ID_COMMAND_SET_4] & BIT(6); } -/** - * +/* * Word: 206 - SCT Command Transport * 15:12 - Vendor Specific * 11:6 - Reserved @@ -810,8 +809,9 @@ static inline bool ata_id_sct_supported(const u16 *id) * * The practical impact of this is that ata_id_major_version cannot * reliably report on drives below ATA3. + * + * Returns: major version of ATA drive level or %0 if unknown */ - static inline unsigned int ata_id_major_version(const u16 *id) { unsigned int mver; -- cgit v1.2.3 From 1e024d2b41ee32bc06818f7f09a3562c58842cf9 Mon Sep 17 00:00:00 2001 From: Matt Vollrath Date: Fri, 24 Jul 2026 03:39:42 -0400 Subject: ata: libata-eh: Increase STANDBY IMMEDIATE timeout Correct a previous change (see Fixes) which reduced the standby timeout from 30 to 5 seconds. Increase it to 15 seconds. I was troubleshooting an error spotted during system suspend: [ 1217.152867] ata1.00: Entering standby power mode [ 1222.322948] ata1.00: qc timeout after 5000 msecs (cmd 0xe0) [ 1222.324010] ata1.00: STANDBY IMMEDIATE failed (err_mask=0x4) This drive is a Samsung 870 EVO SSD in good SMART standing, and I wasn't aware of any reason it should be taking so long to standby. The issue is intermittent, but I observed it sometimes taking 7 seconds to manually standby. I assume this was interruption of background maintenance after a power outage. As a desktop user, I would prefer to wait the extra 2 seconds at suspend to let the drive finish its business rather than drop the rails from under it. The change from 30 to 5 seconds was implicit when switching suspend from START STOP UNIT to an internal command with no timeout table entry. No reason was stated for the change. Fixes: aa3998dbeb3a ("ata: libata-scsi: Disable scsi device manage_system_start_stop") Cc: stable@vger.kernel.org Signed-off-by: Matt Vollrath Assisted-by: Claude:claude-5-fable Signed-off-by: Damien Le Moal --- include/linux/libata.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/libata.h b/include/linux/libata.h index 96e626d6a7ca..6c0d385b2cde 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -425,7 +425,7 @@ enum { /* This should match the actual table size of * ata_eh_cmd_timeout_table in libata-eh.c. */ - ATA_EH_CMD_TIMEOUT_TABLE_SIZE = 8, + ATA_EH_CMD_TIMEOUT_TABLE_SIZE = 9, /* User visible DMA mask for DMA control. DO NOT renumber. */ ATA_DMA_MASK_ATA = (1 << 0), /* DMA on ATA Disk */ -- cgit v1.2.3 From 1d78d56c43ef3768183e8370e7367b162700e049 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 27 Jul 2026 14:07:15 +0100 Subject: netfs: Fix folio_queue ENOMEM in writeback by adding a mempool Fix the handling of folio_queue allocation failure in writeback by adding a mempool and passing in gfp_t flags to the rolling buffer functions that allocate memory, using the mempool if gfp != GFP_KERNEL. This is then extended upwards and the gfp to be used for a request is stored in the netfs_io_request struct and is then used for both requests and subrequests, eliminating the sleeping loops there. The failure caused: folio != NULL WARNING: fs/netfs/write_issue.c:603 at netfs_writepages+0x883/0xa10 fs/netfs/write_issue.c:603, CPU#3: syz.0.17/5919 Fixes: cd0277ed0c18 ("netfs: Use new folio_queue data type and iterator instead of xarray iter") Reported-by: syzbot+0da43efa72f88bd3a8af@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=0da43efa72f88bd3a8af Signed-off-by: David Howells Link: https://patch.msgid.link/20260727130716.1099906-5-dhowells@redhat.com Tested-by: syzbot+0da43efa72f88bd3a8af@syzkaller.appspotmail.com cc: Paulo Alcantara cc: Yun Zhou cc: Matthew Wilcox cc: Christoph Hellwig cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org Signed-off-by: Christian Brauner (Amutable) --- include/linux/netfs.h | 1 + include/linux/rolling_buffer.h | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/linux/netfs.h b/include/linux/netfs.h index 1bc120d61c5b..d0b62d53eea9 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -255,6 +255,7 @@ struct netfs_io_request { unsigned long long cleaned_to; /* Position we've cleaned folios to */ unsigned long long abandon_to; /* Position to abandon folios to */ const struct folio *no_unlock_folio; /* Don't unlock this folio after read */ + gfp_t gfp; /* GFP flags to use */ unsigned int direct_bv_count; /* Number of elements in direct_bv[] */ unsigned int debug_id; unsigned int rsize; /* Maximum read size (0 for none) */ diff --git a/include/linux/rolling_buffer.h b/include/linux/rolling_buffer.h index ac15b1ffdd83..9e5dad29669c 100644 --- a/include/linux/rolling_buffer.h +++ b/include/linux/rolling_buffer.h @@ -43,13 +43,13 @@ struct rolling_buffer_snapshot { #define ROLLBUF_MARK_2 BIT(1) int rolling_buffer_init(struct rolling_buffer *roll, unsigned int rreq_id, - unsigned int direction); -int rolling_buffer_make_space(struct rolling_buffer *roll); + unsigned int direction, gfp_t gfp); +int rolling_buffer_make_space(struct rolling_buffer *roll, gfp_t gfp); ssize_t rolling_buffer_load_from_ra(struct rolling_buffer *roll, struct readahead_control *ractl, struct folio_batch *put_batch); ssize_t rolling_buffer_append(struct rolling_buffer *roll, struct folio *folio, - unsigned int flags); + unsigned int flags, gfp_t gfp); struct folio_queue *rolling_buffer_delete_spent(struct rolling_buffer *roll); void rolling_buffer_clear(struct rolling_buffer *roll); -- cgit v1.2.3 From af24e338bf5dafb80f42baa9a0b9e9b57b1c5d9c Mon Sep 17 00:00:00 2001 From: Pauli Virtanen Date: Fri, 24 Jul 2026 23:20:34 +0300 Subject: Bluetooth: ISO: fix race of kfree vs kref_get_unless_zero hci_conn::iso_data is accessed and modified without lock or RCU. This leads to a race [Task hdev->workqueue] [Task 2] iso_recv iso_conn_put(conn) conn = LOAD hcon->iso_data iso_conn_free(conn) iso_conn_hold_unless_zero(conn) hcon->iso_data = NULL kfree(conn) kref_get_unless_zero(&conn->ref) /* UAF */ and also to races in iso_conn_add() vs. iso_conn_free(). Fix by adding spinlock hci_conn::proto_lock and using it to guard hci_conn::iso_data. Fixes: dc26097bdb86 ("Bluetooth: ISO: Use kref to track lifetime of iso_conn") Signed-off-by: Pauli Virtanen Signed-off-by: Luiz Augusto von Dentz --- include/net/bluetooth/hci_core.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index e7133ff87fbf..3df59849dcbe 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -767,9 +767,11 @@ struct hci_conn { struct dentry *debugfs; struct hci_dev *hdev; + + spinlock_t proto_lock; /* lock guarding protocol data */ void *l2cap_data; void *sco_data; - void *iso_data; + void *iso_data __guarded_by(&proto_lock); struct list_head link_list; struct hci_conn *parent; -- cgit v1.2.3 From 2e1d2e65e773d67dab163127f11a47dab0fbca9f Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Thu, 9 Jul 2026 10:01:33 +0900 Subject: ata: libata-scsi: terminate deferred commands on time out If a command times out while we have deferred non-NCQ commands waiting to be issued, the SCSI EH task is not immediately woken up as the waiting deferred commands are never issued nor completed, thus leaving the SCSI host in a busy state (shost->host_failed != scsi_host_busy(shost)) which prevents the SCSI EH task from being woken up. Eventually, when the deferred commands also time out, the SCSI EH task is woken up and the timeout processing occurs. Avoid this unnecessary SCSI EH task wake-up additional time by scheduling a retry of all waiting deferred QCs, using the eh_timed_out SCSI host template operation. The function ata_scsi_eh_timed_out() is introduced to implement this operation. However, terminating deferred commands with DID_REQUEUE to force a retry by calling the function ata_scsi_requeue_deferred_qc() may still keep the SCSI host in a busy state because the block layer may immediately re-issue these commands. The solution to this is to schedule libata EH for the port which suffered the command timeout to prevent accepting any new command. ata_scsi_requeue_deferred_qc() is modified to add a call to ata_port_schedule_eh() for this purpose. In addition to this change, ata_scsi_requeue_deferred_qc() is also modified to take a new timedout_scmd scsi command argument which indicates the SCSI command that timed out. With this additional argument, ata_scsi_requeue_deferred_qc() can now also terminate with DID_TIME_OUT any timed out deferred qc, which simplifies ata_scsi_cmd_error_handler(). In this case, ata_scsi_requeue_deferred_qc() returns SCSI_EH_DONE, with this return value propagated back to the ata_scsi_eh_timed_out() operation to indicate to scsi_timeout() that the timed out command was handled and no further processing is needed. For non-timed out deferred qc that need to be retried, ata_scsi_requeue_deferred_qc() returns SCSI_EH_NOT_HANDLED, thus indicating to scsi_timeout() that the timed out command needs to go through the SCSI EH (and libata EH) processing by adding it to the EH work queue with scsi_eh_scmd_add(). One side effect of these changes is that the function atapi_qc_complete() needs to be modified to ensure that a deferred ATAPI command that needs to be retried is completed with DID_REQUEUE instead of the default SAM_STAT_GOOD status, and a command that timed out is completed with DID_TIME_OUT instead of SAM_STAT_CHECK_CONDITION. Fixes: 0ea84089dbf6 ("ata: libata-scsi: avoid Non-NCQ command starvation") Cc: stable@vger.kernel.org Signed-off-by: Damien Le Moal Reviewed-by: Igor Pylypiv Tested-by: Igor Pylypiv Reviewed-by: Niklas Cassel Reviewed-by: Martin K. Petersen --- include/linux/libata.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/linux/libata.h b/include/linux/libata.h index 6c0d385b2cde..f10b3287b507 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -1153,6 +1153,7 @@ extern int ata_scsi_ioctl(struct scsi_device *dev, unsigned int cmd, #endif extern enum scsi_qc_status ata_scsi_queuecmd(struct Scsi_Host *h, struct scsi_cmnd *cmd); +enum scsi_timeout_action ata_scsi_eh_timed_out(struct scsi_cmnd *cmd); #if IS_REACHABLE(CONFIG_ATA) bool ata_scsi_dma_need_drain(struct request *rq); #else @@ -1464,6 +1465,7 @@ extern const struct attribute_group *ata_common_sdev_groups[]; .ioctl = ata_scsi_ioctl, \ ATA_SCSI_COMPAT_IOCTL \ .queuecommand = ata_scsi_queuecmd, \ + .eh_timed_out = ata_scsi_eh_timed_out, \ .dma_need_drain = ata_scsi_dma_need_drain, \ .this_id = ATA_SHT_THIS_ID, \ .emulated = ATA_SHT_EMULATED, \ -- cgit v1.2.3 From de202d2251bc181c6019b1ad3c0ba8133e5ec68d Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Thu, 9 Jul 2026 16:02:23 +0900 Subject: scsi: libsas: terminate deferred commands on time out If a command times out while we have deferred non-NCQ commands waiting to be issued, the SCSI EH task is not immediately woken up as the waiting deferred commands are never issued nor completed, thus leaving the SCSI host in a busy state (shost->host_failed != scsi_host_busy(shost)) which prevents the SCSI EH task from being woken up. Eventually, when the deferred commands also time out, the SCSI EH task is woken up and the timeout processing occurs. Avoid this unnecessary additional SCSI EH wake up time with the same method as implemented in libata-scsi, using the eh_timed_out SCSI host template operation. The function sas_eh_timed_out() implements this operation and executes the function ata_scsi_retry_deferred_qc() for SATA devices. Co-developed-by: Igor Pylypiv Signed-off-by: Igor Pylypiv Fixes: 0ea84089dbf6 ("ata: libata-scsi: avoid Non-NCQ command starvation") Cc: stable@vger.kernel.org Signed-off-by: Damien Le Moal Reviewed-by: John Garry Reviewed-by: Hannes Reinecke Tested-by: Igor Pylypiv Reviewed-by: Niklas Cassel Reviewed-by: Martin K. Petersen --- include/linux/libata.h | 2 ++ include/scsi/libsas.h | 2 ++ 2 files changed, 4 insertions(+) (limited to 'include') diff --git a/include/linux/libata.h b/include/linux/libata.h index f10b3287b507..1827502b9cf2 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -1153,6 +1153,8 @@ extern int ata_scsi_ioctl(struct scsi_device *dev, unsigned int cmd, #endif extern enum scsi_qc_status ata_scsi_queuecmd(struct Scsi_Host *h, struct scsi_cmnd *cmd); +enum scsi_timeout_action ata_scsi_retry_deferred_qc(struct ata_port *ap, + struct scsi_cmnd *scmd); enum scsi_timeout_action ata_scsi_eh_timed_out(struct scsi_cmnd *cmd); #if IS_REACHABLE(CONFIG_ATA) bool ata_scsi_dma_need_drain(struct request *rq); diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 163f23c92b41..c7017ae76c61 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -705,6 +705,7 @@ void sas_task_abort(struct sas_task *); int sas_eh_abort_handler(struct scsi_cmnd *cmd); int sas_eh_device_reset_handler(struct scsi_cmnd *cmd); int sas_eh_target_reset_handler(struct scsi_cmnd *cmd); +enum scsi_timeout_action sas_eh_timed_out(struct scsi_cmnd *cmd); extern void sas_target_destroy(struct scsi_target *); extern int sas_sdev_init(struct scsi_device *); @@ -743,6 +744,7 @@ void sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event, .this_id = -1, \ .eh_device_reset_handler = sas_eh_device_reset_handler, \ .eh_target_reset_handler = sas_eh_target_reset_handler, \ + .eh_timed_out = sas_eh_timed_out, \ .target_destroy = sas_target_destroy, \ .ioctl = sas_ioctl, \ -- cgit v1.2.3 From 6bc85579c3bbb2f088cbac849c5dc2a134dda736 Mon Sep 17 00:00:00 2001 From: Simon Schippers Date: Tue, 28 Jul 2026 11:22:38 +0200 Subject: Revert "ptr_ring: move free-space check into separate helper" This reverts commit fba362c17d9d9211fc51f272156bb84fc23bdf98. __ptr_ring_check_produce() has no users left after reverting commit 1d6e569b7d0c ("tun/tap & vhost-net: avoid ptr_ring tail-drop when a qdisc is present"). Signed-off-by: Simon Schippers Acked-by: Michael S. Tsirkin Link: https://patch.msgid.link/20260728092240.250257-3-simon.schippers@tu-dortmund.de Signed-off-by: Jakub Kicinski --- include/linux/ptr_ring.h | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) (limited to 'include') diff --git a/include/linux/ptr_ring.h b/include/linux/ptr_ring.h index c95e891903f0..d2c3629bbe45 100644 --- a/include/linux/ptr_ring.h +++ b/include/linux/ptr_ring.h @@ -96,20 +96,6 @@ static inline bool ptr_ring_full_bh(struct ptr_ring *r) return ret; } -/* Note: callers invoking this in a loop must use a compiler barrier, - * for example cpu_relax(). Callers must hold producer_lock. - */ -static inline int __ptr_ring_check_produce(struct ptr_ring *r) -{ - if (unlikely(!r->size)) - return -EINVAL; - - if (data_race(r->queue[r->producer])) - return -ENOSPC; - - return 0; -} - /* Note: callers invoking this in a loop must use a compiler barrier, * for example cpu_relax(). Callers must hold producer_lock. * Callers are responsible for making sure pointer that is being queued @@ -117,10 +103,8 @@ static inline int __ptr_ring_check_produce(struct ptr_ring *r) */ static inline int __ptr_ring_produce(struct ptr_ring *r, void *ptr) { - int p = __ptr_ring_check_produce(r); - - if (p) - return p; + if (unlikely(!r->size) || data_race(r->queue[r->producer])) + return -ENOSPC; /* Make sure the pointer we are storing points to a valid data. */ /* Pairs with the dependency ordering in __ptr_ring_consume. */ -- cgit v1.2.3 From 8f83be72d9f5ef16c4a908450d0d993e8ec99d34 Mon Sep 17 00:00:00 2001 From: Simon Schippers Date: Tue, 28 Jul 2026 11:22:39 +0200 Subject: Revert "vhost-net: wake queue of tun/tap after ptr_ring consume" This reverts commit baf808fe4fcd35767ab732b4ab2ea80dabfd97a6. There is no netdev queue left to wake after reverting commit 1d6e569b7d0c ("tun/tap & vhost-net: avoid ptr_ring tail-drop when a qdisc is present"). Signed-off-by: Simon Schippers Acked-by: Michael S. Tsirkin Link: https://patch.msgid.link/20260728092240.250257-4-simon.schippers@tu-dortmund.de Signed-off-by: Jakub Kicinski --- include/linux/if_tun.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'include') diff --git a/include/linux/if_tun.h b/include/linux/if_tun.h index 5f3e206c7a73..80166eb62f41 100644 --- a/include/linux/if_tun.h +++ b/include/linux/if_tun.h @@ -22,7 +22,6 @@ struct tun_msg_ctl { #if defined(CONFIG_TUN) || defined(CONFIG_TUN_MODULE) struct socket *tun_get_socket(struct file *); struct ptr_ring *tun_get_tx_ring(struct file *file); -void tun_wake_queue(struct file *file, int consumed); static inline bool tun_is_xdp_frame(void *ptr) { @@ -56,8 +55,6 @@ static inline struct ptr_ring *tun_get_tx_ring(struct file *f) return ERR_PTR(-EINVAL); } -static inline void tun_wake_queue(struct file *f, int consumed) {} - static inline bool tun_is_xdp_frame(void *ptr) { return false; -- cgit v1.2.3