--- /dev/null
+From stable+bounces-263423-greg=kroah.com@vger.kernel.org Mon Jun 15 23:33:08 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jun 2026 14:01:58 -0400
+Subject: hv_netvsc: use kmap_local_page in netvsc_copy_to_send_buf
+To: stable@vger.kernel.org
+Cc: Anton Leontev <leontyevantony@gmail.com>, Paolo Abeni <pabeni@redhat.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260615180158.2315829-1-sashal@kernel.org>
+
+From: Anton Leontev <leontyevantony@gmail.com>
+
+[ Upstream commit 004e9ecfe6c5384f9e0b2f6f6389d42ec22789af ]
+
+netvsc_copy_to_send_buf() copies page buffer entries into the VMBus
+send buffer using phys_to_virt() on the entry PFN. Entries for the
+RNDIS header and the skb linear data come from kmalloc'd memory and
+are always in the kernel direct map, but entries for skb fragments
+reference page cache or user pages, which on 32-bit x86 with
+CONFIG_HIGHMEM=y can live above the LOWMEM boundary. For such a page
+phys_to_virt() returns an address outside the direct map and the
+subsequent memcpy() faults on the transmit softirq path, which is
+fatal.
+
+Map the pages with kmap_local_page() instead, handling two properties
+of the page buffer entries:
+
+ - pb[i].pfn is a Hyper-V PFN at HV_HYP_PAGE_SIZE (4K) granularity,
+ not a native PFN. Reconstruct the physical address first and derive
+ the native page from it, so the mapping stays correct where
+ PAGE_SIZE > HV_HYP_PAGE_SIZE (e.g. arm64 with 64K pages).
+
+ - Since commit 41a6328b2c55 ("hv_netvsc: Preserve contiguous PFN
+ grouping in the page buffer array"), an entry describes a full
+ physically contiguous fragment and pb[i].len can exceed PAGE_SIZE,
+ while kmap_local_page() maps a single page. Copy page by page,
+ splitting at native page boundaries.
+
+The copy path only handles packets smaller than the send section size
+(6144 bytes by default); larger packets take the cp_partial path where
+only the RNDIS header is copied. So entries here are bounded by the
+section size and a copy is split at most once on 4K-page systems. On
+!CONFIG_HIGHMEM configs kmap_local_page() folds to page_address() and
+no mapping work is added.
+
+Fixes: c25aaf814a63 ("hyperv: Enable sendbuf mechanism on the send path")
+Cc: stable@vger.kernel.org
+Signed-off-by: Anton Leontev <leontyevantony@gmail.com>
+Link: https://patch.msgid.link/20260604165938.32033-1-leontyevantony@gmail.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+[ adapted `phys_to_page(paddr)` to `pfn_to_page(PHYS_PFN(paddr))` ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/hyperv/netvsc.c | 19 +++++++++++++++----
+ 1 file changed, 15 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/hyperv/netvsc.c
++++ b/drivers/net/hyperv/netvsc.c
+@@ -12,6 +12,7 @@
+ #include <linux/sched.h>
+ #include <linux/wait.h>
+ #include <linux/mm.h>
++#include <linux/highmem.h>
+ #include <linux/delay.h>
+ #include <linux/io.h>
+ #include <linux/slab.h>
+@@ -964,12 +965,22 @@ static void netvsc_copy_to_send_buf(stru
+ }
+
+ for (i = 0; i < page_count; i++) {
+- char *src = phys_to_virt(pb[i].pfn << HV_HYP_PAGE_SHIFT);
+- u32 offset = pb[i].offset;
++ phys_addr_t paddr = (pb[i].pfn << HV_HYP_PAGE_SHIFT) +
++ pb[i].offset;
+ u32 len = pb[i].len;
+
+- memcpy(dest, (src + offset), len);
+- dest += len;
++ while (len) {
++ struct page *page = pfn_to_page(PHYS_PFN(paddr));
++ u32 off = offset_in_page(paddr);
++ u32 chunk = min_t(u32, len, PAGE_SIZE - off);
++ char *src = kmap_local_page(page);
++
++ memcpy(dest, src + off, chunk);
++ kunmap_local(src);
++ dest += chunk;
++ paddr += chunk;
++ len -= chunk;
++ }
+ }
+
+ if (padding)
--- /dev/null
+From c58e9456e30c7098cbcd9f04571992be8a2e4e63 Mon Sep 17 00:00:00 2001
+From: Jassi Brar <jassisinghbrar@gmail.com>
+Date: Fri, 27 Mar 2026 17:00:40 -0500
+Subject: mailbox: Fix NULL message support in mbox_send_message()
+
+From: Jassi Brar <jassisinghbrar@gmail.com>
+
+commit c58e9456e30c7098cbcd9f04571992be8a2e4e63 upstream.
+
+The active_req field serves double duty as both the "is a TX in
+flight" flag (NULL means idle) and the storage for the in-flight
+message pointer. When a client sends NULL via mbox_send_message(),
+active_req is set to NULL, which the framework misinterprets as
+"no active request". This breaks the TX state machine by:
+
+ - tx_tick() short-circuits on (!mssg), skipping the tx_done
+ callback and the tx_complete completion
+ - txdone_hrtimer() skips the channel entirely since active_req
+ is NULL, so poll-based TX-done detection never fires.
+
+Fix this by introducing a MBOX_NO_MSG sentinel value that means
+"no active request," freeing NULL to be valid message data. The
+sentinel is defined in the subsystem-internal mailbox.h so that
+controller drivers within drivers/mailbox/ can reference it, but
+it is not exposed to clients outside the subsystem.
+
+Fifteen in-tree callers send NULL (doorbell-style IPCs on Qualcomm,
+Tegra, TI, Xilinx, i.MX, SCMI, and PCC platforms). All were
+audited for regression:
+
+ - Most already work around the bug via knows_txdone=true with a
+ manual mbox_client_txdone() call, making the framework's
+ tracking irrelevant. These are unaffected.
+
+ - Poll-based callers (Xilinx zynqmp/r5) are strictly better off:
+ the poll timer now correctly detects NULL-active channels
+ instead of silently skipping them.
+
+ - irq-qcom-mpm.c was a pre-existing bug -- the only Qualcomm
+ caller that omitted the knows_txdone + mbox_client_txdone()
+ pattern. Fixed in a companion commit ("irqchip/qcom-mpm: Fix
+ missing mailbox TX done acknowledgment").
+
+ - No caller sets both a tx_done callback and sends NULL, nor
+ combines tx_block=true with NULL sends, so the newly reachable
+ callback/completion paths are never exercised.
+
+Also update tegra-hsp's flush callback, which directly inspects
+active_req to wait for the channel to drain: the old "!= NULL"
+check becomes "!= MBOX_NO_MSG", otherwise flush spins until
+timeout since the sentinel is non-NULL.
+
+The only tradeoff is that 'MBOX_NO_MSG' can not be used as a message
+by clients.
+
+Reported-by: Joonwon Kang <joonwonkang@google.com>
+Reviewed-by: Douglas Anderson <dianders@chromium.org>
+Signed-off-by: Jassi Brar <jassisinghbrar@gmail.com>
+Signed-off-by: Joonwon Kang <joonwonkang@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/mailbox/mailbox.c | 15 ++++++++-------
+ drivers/mailbox/tegra-hsp.c | 2 +-
+ include/linux/mailbox_controller.h | 3 +++
+ 3 files changed, 12 insertions(+), 8 deletions(-)
+
+--- a/drivers/mailbox/mailbox.c
++++ b/drivers/mailbox/mailbox.c
+@@ -59,7 +59,7 @@ static void msg_submit(struct mbox_chan
+
+ spin_lock_irqsave(&chan->lock, flags);
+
+- if (!chan->msg_count || chan->active_req)
++ if (!chan->msg_count || chan->active_req != MBOX_NO_MSG)
+ goto exit;
+
+ count = chan->msg_count;
+@@ -97,13 +97,13 @@ static void tx_tick(struct mbox_chan *ch
+
+ spin_lock_irqsave(&chan->lock, flags);
+ mssg = chan->active_req;
+- chan->active_req = NULL;
++ chan->active_req = MBOX_NO_MSG;
+ spin_unlock_irqrestore(&chan->lock, flags);
+
+ /* Submit next message */
+ msg_submit(chan);
+
+- if (!mssg)
++ if (mssg == MBOX_NO_MSG)
+ return;
+
+ /* Notify the client */
+@@ -125,7 +125,7 @@ static enum hrtimer_restart txdone_hrtim
+ for (i = 0; i < mbox->num_chans; i++) {
+ struct mbox_chan *chan = &mbox->chans[i];
+
+- if (chan->active_req && chan->cl) {
++ if (chan->active_req != MBOX_NO_MSG && chan->cl) {
+ txdone = chan->mbox->ops->last_tx_done(chan);
+ if (txdone)
+ tx_tick(chan, 0);
+@@ -257,7 +257,7 @@ int mbox_send_message(struct mbox_chan *
+ {
+ int t;
+
+- if (!chan || !chan->cl)
++ if (!chan || !chan->cl || mssg == MBOX_NO_MSG)
+ return -EINVAL;
+
+ t = add_to_rbuf(chan, mssg);
+@@ -331,7 +331,7 @@ static int __mbox_bind_client(struct mbo
+ spin_lock_irqsave(&chan->lock, flags);
+ chan->msg_free = 0;
+ chan->msg_count = 0;
+- chan->active_req = NULL;
++ chan->active_req = MBOX_NO_MSG;
+ chan->cl = cl;
+ init_completion(&chan->tx_complete);
+
+@@ -492,7 +492,7 @@ void mbox_free_channel(struct mbox_chan
+ /* The queued TX requests are simply aborted, no callbacks are made */
+ spin_lock_irqsave(&chan->lock, flags);
+ chan->cl = NULL;
+- chan->active_req = NULL;
++ chan->active_req = MBOX_NO_MSG;
+ if (chan->txdone_method == TXDONE_BY_ACK)
+ chan->txdone_method = TXDONE_BY_POLL;
+
+@@ -548,6 +548,7 @@ int mbox_controller_register(struct mbox
+
+ chan->cl = NULL;
+ chan->mbox = mbox;
++ chan->active_req = MBOX_NO_MSG;
+ chan->txdone_method = txdone;
+ spin_lock_init(&chan->lock);
+ }
+--- a/drivers/mailbox/tegra-hsp.c
++++ b/drivers/mailbox/tegra-hsp.c
+@@ -497,7 +497,7 @@ static int tegra_hsp_mailbox_flush(struc
+ mbox_chan_txdone(chan, 0);
+
+ /* Wait until channel is empty */
+- if (chan->active_req != NULL)
++ if (chan->active_req != MBOX_NO_MSG)
+ continue;
+
+ return 0;
+--- a/include/linux/mailbox_controller.h
++++ b/include/linux/mailbox_controller.h
+@@ -11,6 +11,9 @@
+
+ struct mbox_chan;
+
++/* Sentinel value distinguishing "no active request" from "NULL message data" */
++#define MBOX_NO_MSG ((void *)-1)
++
+ /**
+ * struct mbox_chan_ops - methods to control mailbox channels
+ * @send_data: The API asks the MBOX controller driver, in atomic
--- /dev/null
+From stable+bounces-263201-greg=kroah.com@vger.kernel.org Mon Jun 15 18:59:29 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jun 2026 09:28:59 -0400
+Subject: mm/memory-failure: fix hugetlb_lock AA deadlock in get_huge_page_for_hwpoison
+To: stable@vger.kernel.org
+Cc: Wupeng Ma <mawupeng1@huawei.com>, "Oscar Salvador (SUSE)" <osalvador@kernel.org>, Muchun Song <muchun.song@linux.dev>, Kefeng Wang <wangkefeng.wang@huawei.com>, Miaohe Lin <linmiaohe@huawei.com>, David Hildenbrand <david@kernel.org>, Liam Howlett <liam.howlett@oracle.com>, Lorenzo Stoakes <ljs@kernel.org>, Michal Hocko <mhocko@suse.com>, Mike Rapoport <rppt@kernel.org>, Naoya Horiguchi <nao.horiguchi@gmail.com>, Suren Baghdasaryan <surenb@google.com>, Vlastimil Babka <vbabka@kernel.org>, Andrew Morton <akpm@linux-foundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260615132859.2064439-1-sashal@kernel.org>
+
+From: Wupeng Ma <mawupeng1@huawei.com>
+
+[ Upstream commit 3c2d42b8ee345b17a4ba56b0f6492d1ff4c1178e ]
+
+Two concurrent madvise(MADV_HWPOISON) calls on the same hugetlb page can
+trigger a recursive spinlock self-deadlock (AA deadlock) on hugetlb_lock
+when racing with a concurrent unmap:
+
+ thread#0 thread#1
+ -------- --------
+ madvise(folio, MADV_HWPOISON)
+ -> poisons the folio successfully
+ madvise(folio, MADV_HWPOISON) unmap(folio)
+ try_memory_failure_hugetlb
+ get_huge_page_for_hwpoison
+ spin_lock_irq(&hugetlb_lock) <- held
+ __get_huge_page_for_hwpoison
+ hugetlb_update_hwpoison()
+ -> MF_HUGETLB_FOLIO_PRE_POISONED
+ goto out:
+ folio_put()
+ refcount: 1 -> 0
+ free_huge_folio()
+ spin_lock_irqsave(&hugetlb_lock)
+ -> AA DEADLOCK!
+
+The out: path in __get_huge_page_for_hwpoison() calls folio_put() to drop
+the GUP reference while the hugetlb_lock is still held by the hugetlb.c
+wrapper get_huge_page_for_hwpoison(). If concurrent unmap has released
+the page table mapping reference, folio_put() drops the folio refcount to
+zero, triggering free_huge_folio() which attempts to re-acquire the
+non-recursive hugetlb_lock.
+
+Fix this by moving hugetlb_lock acquisition from the hugetlb.c wrapper
+into get_huge_page_for_hwpoison(). Place spin_unlock_irq() before the
+folio_put() at the out: label so the folio is always released outside the
+lock.
+
+[akpm@linux-foundation.org: fix race, rename label per Miaohe]
+ Link: https://sashiko.dev/#/patchset/20260522010305.4099834-1-mawupeng1@huawei.com
+ Link: https://lore.kernel.org/f39f405e-4b4b-8f79-70fe-a2b5b62114eb@huawei.com
+Link: https://lore.kernel.org/20260522010305.4099834-1-mawupeng1@huawei.com
+Fixes: 405ce051236c ("mm/hwpoison: fix race between hugetlb free/demotion and memory_failure_hugetlb()")
+Signed-off-by: Wupeng Ma <mawupeng1@huawei.com>
+Acked-by: Oscar Salvador (SUSE) <osalvador@kernel.org>
+Acked-by: Muchun Song <muchun.song@linux.dev>
+Reviewed-by: Kefeng Wang <wangkefeng.wang@huawei.com>
+Acked-by: Miaohe Lin <linmiaohe@huawei.com>
+Cc: David Hildenbrand <david@kernel.org>
+Cc: Liam Howlett <liam.howlett@oracle.com>
+Cc: Lorenzo Stoakes <ljs@kernel.org>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: Mike Rapoport <rppt@kernel.org>
+Cc: Naoya Horiguchi <nao.horiguchi@gmail.com>
+Cc: Suren Baghdasaryan <surenb@google.com>
+Cc: Vlastimil Babka <vbabka@kernel.org>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/hugetlb.h | 8 --------
+ include/linux/mm.h | 8 --------
+ mm/hugetlb.c | 11 -----------
+ mm/memory-failure.c | 19 ++++++++++---------
+ 4 files changed, 10 insertions(+), 36 deletions(-)
+
+--- a/include/linux/hugetlb.h
++++ b/include/linux/hugetlb.h
+@@ -155,8 +155,6 @@ long hugetlb_unreserve_pages(struct inod
+ long freed);
+ bool isolate_hugetlb(struct folio *folio, struct list_head *list);
+ int get_hwpoison_hugetlb_folio(struct folio *folio, bool *hugetlb, bool unpoison);
+-int get_huge_page_for_hwpoison(unsigned long pfn, int flags,
+- bool *migratable_cleared);
+ void folio_putback_active_hugetlb(struct folio *folio);
+ void move_hugetlb_state(struct folio *old_folio, struct folio *new_folio, int reason);
+ void hugetlb_fix_reserve_counts(struct inode *inode);
+@@ -429,12 +427,6 @@ static inline int get_hwpoison_hugetlb_f
+ {
+ return 0;
+ }
+-
+-static inline int get_huge_page_for_hwpoison(unsigned long pfn, int flags,
+- bool *migratable_cleared)
+-{
+- return 0;
+-}
+
+ static inline void folio_putback_active_hugetlb(struct folio *folio)
+ {
+--- a/include/linux/mm.h
++++ b/include/linux/mm.h
+@@ -3995,8 +3995,6 @@ extern int soft_offline_page(unsigned lo
+ */
+ extern const struct attribute_group memory_failure_attr_group;
+ extern void memory_failure_queue(unsigned long pfn, int flags);
+-extern int __get_huge_page_for_hwpoison(unsigned long pfn, int flags,
+- bool *migratable_cleared);
+ void num_poisoned_pages_inc(unsigned long pfn);
+ void num_poisoned_pages_sub(unsigned long pfn, long i);
+ #else
+@@ -4004,12 +4002,6 @@ static inline void memory_failure_queue(
+ {
+ }
+
+-static inline int __get_huge_page_for_hwpoison(unsigned long pfn, int flags,
+- bool *migratable_cleared)
+-{
+- return 0;
+-}
+-
+ static inline void num_poisoned_pages_inc(unsigned long pfn)
+ {
+ }
+--- a/mm/hugetlb.c
++++ b/mm/hugetlb.c
+@@ -7459,17 +7459,6 @@ int get_hwpoison_hugetlb_folio(struct fo
+ return ret;
+ }
+
+-int get_huge_page_for_hwpoison(unsigned long pfn, int flags,
+- bool *migratable_cleared)
+-{
+- int ret;
+-
+- spin_lock_irq(&hugetlb_lock);
+- ret = __get_huge_page_for_hwpoison(pfn, flags, migratable_cleared);
+- spin_unlock_irq(&hugetlb_lock);
+- return ret;
+-}
+-
+ void folio_putback_active_hugetlb(struct folio *folio)
+ {
+ spin_lock_irq(&hugetlb_lock);
+--- a/mm/memory-failure.c
++++ b/mm/memory-failure.c
+@@ -2020,20 +2020,19 @@ void folio_clear_hugetlb_hwpoison(struct
+ folio_free_raw_hwp(folio, true);
+ }
+
+-/*
+- * Called from hugetlb code with hugetlb_lock held.
+- */
+-int __get_huge_page_for_hwpoison(unsigned long pfn, int flags,
++static int get_huge_page_for_hwpoison(unsigned long pfn, int flags,
+ bool *migratable_cleared)
+ {
+ struct page *page = pfn_to_page(pfn);
+- struct folio *folio = page_folio(page);
++ struct folio *folio;
+ bool count_increased = false;
+ int ret, rc;
+
++ spin_lock_irq(&hugetlb_lock);
++ folio = page_folio(page);
+ if (!folio_test_hugetlb(folio)) {
+ ret = MF_HUGETLB_NON_HUGEPAGE;
+- goto out;
++ goto out_unlock;
+ } else if (flags & MF_COUNT_INCREASED) {
+ ret = MF_HUGETLB_IN_USED;
+ count_increased = true;
+@@ -2049,13 +2048,13 @@ int __get_huge_page_for_hwpoison(unsigne
+ } else {
+ ret = MF_HUGETLB_RETRY;
+ if (!(flags & MF_NO_RETRY))
+- goto out;
++ goto out_unlock;
+ }
+
+ rc = hugetlb_update_hwpoison(folio, page);
+ if (rc >= MF_HUGETLB_FOLIO_PRE_POISONED) {
+ ret = rc;
+- goto out;
++ goto out_unlock;
+ }
+
+ /*
+@@ -2067,8 +2066,10 @@ int __get_huge_page_for_hwpoison(unsigne
+ *migratable_cleared = true;
+ }
+
++ spin_unlock_irq(&hugetlb_lock);
+ return ret;
+-out:
++out_unlock:
++ spin_unlock_irq(&hugetlb_lock);
+ if (count_increased)
+ folio_put(folio);
+ return ret;
--- /dev/null
+From stable+bounces-263202-greg=kroah.com@vger.kernel.org Mon Jun 15 19:04:59 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jun 2026 09:34:53 -0400
+Subject: netfilter: nft_fib: fix stale stack leak via the OIFNAME register
+To: stable@vger.kernel.org
+Cc: Davide Ornaghi <d.ornaghi97@gmail.com>, Florian Westphal <fw@strlen.de>, Pablo Neira Ayuso <pablo@netfilter.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260615133453.2065964-1-sashal@kernel.org>
+
+From: Davide Ornaghi <d.ornaghi97@gmail.com>
+
+[ Upstream commit ab185e0c4fb82dfba6fb86f8271e06f931d9c64c ]
+
+For NFT_FIB_RESULT_OIFNAME the destination register is declared with
+len = IFNAMSIZ (four 32-bit registers), but on the lookup-fail,
+RTN_LOCAL and oif-mismatch paths nft_fib{4,6}_eval() only writes one
+register via "*dest = 0". The remaining three registers are left as
+whatever was on the stack in nft_do_chain()'s struct nft_regs, and a
+downstream expression that loads the register span can leak that
+uninitialised kernel stack to userspace.
+
+The NFTA_FIB_F_PRESENT existence check has the same shape: it is only
+meaningful for NFT_FIB_RESULT_OIF, yet it was accepted for any result type
+while the eval stores a single byte via nft_reg_store8(), leaving the rest
+of the declared span stale.
+
+Fix both:
+
+ - replace the bare "*dest = 0" in the eval with nft_fib_store_result(),
+ which strscpy_pad()s the whole IFNAMSIZ for OIFNAME (and is already
+ used on the other early-return path), and
+
+ - restrict NFTA_FIB_F_PRESENT to NFT_FIB_RESULT_OIF and declare its
+ destination as a single u8, so the marked span matches the one byte
+ the eval writes.
+
+Fixes: f6d0cbcf09c5 ("netfilter: nf_tables: add fib expression")
+Suggested-by: Florian Westphal <fw@strlen.de>
+Cc: stable@vger.kernel.org
+Signed-off-by: Davide Ornaghi <d.ornaghi97@gmail.com>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+[ kept the tree's older `ip6_route_lookup()`/`rt6_info` IPv6 context and changed only `*dest = 0;` to `nft_fib_store_result(dest, priv, NULL);` ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/netfilter/nft_fib_ipv4.c | 2 +-
+ net/ipv6/netfilter/nft_fib_ipv6.c | 2 +-
+ net/netfilter/nft_fib.c | 6 ++++++
+ 3 files changed, 8 insertions(+), 2 deletions(-)
+
+--- a/net/ipv4/netfilter/nft_fib_ipv4.c
++++ b/net/ipv4/netfilter/nft_fib_ipv4.c
+@@ -127,7 +127,7 @@ void nft_fib4_eval(const struct nft_expr
+ fl4.saddr = get_saddr(iph->daddr);
+ }
+
+- *dest = 0;
++ nft_fib_store_result(dest, priv, NULL);
+
+ if (fib_lookup(nft_net(pkt), &fl4, &res, FIB_LOOKUP_IGNORE_LINKSTATE))
+ return;
+--- a/net/ipv6/netfilter/nft_fib_ipv6.c
++++ b/net/ipv6/netfilter/nft_fib_ipv6.c
+@@ -192,7 +192,7 @@ void nft_fib6_eval(const struct nft_expr
+
+ lookup_flags = nft_fib6_flowi_init(&fl6, priv, pkt, oif, iph);
+
+- *dest = 0;
++ nft_fib_store_result(dest, priv, NULL);
+ rt = (void *)ip6_route_lookup(nft_net(pkt), &fl6, pkt->skb,
+ lookup_flags);
+ if (rt->dst.error)
+--- a/net/netfilter/nft_fib.c
++++ b/net/netfilter/nft_fib.c
+@@ -107,6 +107,12 @@ int nft_fib_init(const struct nft_ctx *c
+ return -EINVAL;
+ }
+
++ if (priv->flags & NFTA_FIB_F_PRESENT) {
++ if (priv->result != NFT_FIB_RESULT_OIF)
++ return -EINVAL;
++ len = sizeof(u8);
++ }
++
+ err = nft_parse_register_store(ctx, tb[NFTA_FIB_DREG], &priv->dreg,
+ NULL, NFT_DATA_VALUE, len);
+ if (err < 0)
--- /dev/null
+From stable+bounces-263468-greg=kroah.com@vger.kernel.org Tue Jun 16 02:59:18 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jun 2026 17:29:10 -0400
+Subject: RDMA: During rereg_mr ensure that REREG_ACCESS is compatible
+To: stable@vger.kernel.org
+Cc: Jason Gunthorpe <jgg@nvidia.com>, Philip Tsukerman <philiptsukerman@gmail.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260615212910.2473729-4-sashal@kernel.org>
+
+From: Jason Gunthorpe <jgg@nvidia.com>
+
+[ Upstream commit badad6fad60def1b9805559dd81dbab3d97b82aa ]
+
+If IB_MR_REREG_ACCESS changes from RO to RW then the umem has to be
+re-evaluated to ensure it is properly pinned as RW. Since the umem is
+hidden inside each driver's mr struct add a ib_umem_check_rereg() function
+that each driver has to call before processing IB_MR_REREG_ACCESS.
+
+mlx4 has to retain its duplicate ib_access_writable check because it
+implements IB_MR_REREG_ACCESS | IB_MR_REREG_TRANS by changing both items
+in place sequentially while the MR is live, so it will continue to not
+support this combination.
+
+Cc: stable@vger.kernel.org
+Fixes: b40656aa7d55 ("RDMA/umem: remove FOLL_FORCE usage")
+Link: https://patch.msgid.link/r/0-v1-06fb1a2d6cf5+107-rereg_access_jgg@nvidia.com
+Reported-by: Philip Tsukerman <philiptsukerman@gmail.com>
+Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/infiniband/core/umem.c | 16 ++++++++++++++++
+ drivers/infiniband/hw/hns/hns_roce_mr.c | 4 ++++
+ drivers/infiniband/hw/irdma/verbs.c | 4 ++++
+ drivers/infiniband/hw/mlx4/mr.c | 4 ++++
+ drivers/infiniband/hw/mlx5/mr.c | 4 ++++
+ drivers/infiniband/sw/rxe/rxe_verbs.c | 5 +++++
+ include/rdma/ib_umem.h | 8 ++++++++
+ 7 files changed, 45 insertions(+)
+
+--- a/drivers/infiniband/core/umem.c
++++ b/drivers/infiniband/core/umem.c
+@@ -326,3 +326,19 @@ int ib_umem_copy_from(void *dst, struct
+ return 0;
+ }
+ EXPORT_SYMBOL(ib_umem_copy_from);
++
++/*
++ * Called during rereg mr if the driver is able to re-use a umem for
++ * IB_MR_REREG_ACCESS.
++ */
++int ib_umem_check_rereg(struct ib_umem *umem, int flags, int new_access_flags)
++{
++ if (!umem)
++ return 0;
++
++ if ((flags & IB_MR_REREG_ACCESS) && !(flags & IB_MR_REREG_TRANS))
++ if (ib_access_writable(new_access_flags) && !umem->writable)
++ return -EACCES;
++ return 0;
++}
++EXPORT_SYMBOL(ib_umem_check_rereg);
+--- a/drivers/infiniband/hw/hns/hns_roce_mr.c
++++ b/drivers/infiniband/hw/hns/hns_roce_mr.c
+@@ -292,6 +292,10 @@ struct ib_mr *hns_roce_rereg_user_mr(str
+ goto err_out;
+ }
+
++ ret = ib_umem_check_rereg(mr->pbl_mtr.umem, flags, mr_access_flags);
++ if (ret)
++ goto err_out;
++
+ mailbox = hns_roce_alloc_cmd_mailbox(hr_dev);
+ ret = PTR_ERR_OR_ZERO(mailbox);
+ if (ret)
+--- a/drivers/infiniband/hw/irdma/verbs.c
++++ b/drivers/infiniband/hw/irdma/verbs.c
+@@ -3245,6 +3245,10 @@ static struct ib_mr *irdma_rereg_user_mr
+ if (flags & ~(IB_MR_REREG_TRANS | IB_MR_REREG_PD | IB_MR_REREG_ACCESS))
+ return ERR_PTR(-EOPNOTSUPP);
+
++ ret = ib_umem_check_rereg(iwmr->region, flags, new_access);
++ if (ret)
++ return ERR_PTR(ret);
++
+ ret = irdma_hwdereg_mr(ib_mr);
+ if (ret)
+ return ERR_PTR(ret);
+--- a/drivers/infiniband/hw/mlx4/mr.c
++++ b/drivers/infiniband/hw/mlx4/mr.c
+@@ -466,6 +466,10 @@ struct ib_mr *mlx4_ib_rereg_user_mr(stru
+ struct mlx4_mpt_entry **pmpt_entry = &mpt_entry;
+ int err;
+
++ err = ib_umem_check_rereg(mmr->umem, flags, mr_access_flags);
++ if (err)
++ return ERR_PTR(err);
++
+ /* Since we synchronize this call and mlx4_ib_dereg_mr via uverbs,
+ * we assume that the calls can't run concurrently. Otherwise, a
+ * race exists.
+--- a/drivers/infiniband/hw/mlx5/mr.c
++++ b/drivers/infiniband/hw/mlx5/mr.c
+@@ -1829,6 +1829,10 @@ struct ib_mr *mlx5_ib_rereg_user_mr(stru
+ if (flags & ~(IB_MR_REREG_TRANS | IB_MR_REREG_PD | IB_MR_REREG_ACCESS))
+ return ERR_PTR(-EOPNOTSUPP);
+
++ err = ib_umem_check_rereg(mr->umem, flags, new_access_flags);
++ if (err)
++ return ERR_PTR(err);
++
+ if (!(flags & IB_MR_REREG_ACCESS))
+ new_access_flags = mr->access_flags;
+ if (!(flags & IB_MR_REREG_PD))
+--- a/drivers/infiniband/sw/rxe/rxe_verbs.c
++++ b/drivers/infiniband/sw/rxe/rxe_verbs.c
+@@ -1312,6 +1312,7 @@ static struct ib_mr *rxe_rereg_user_mr(s
+ struct rxe_mr *mr = to_rmr(ibmr);
+ struct rxe_pd *old_pd = to_rpd(ibmr->pd);
+ struct rxe_pd *pd = to_rpd(ibpd);
++ int err;
+
+ /* for now only support the two easy cases:
+ * rereg_pd and rereg_access
+@@ -1321,6 +1322,10 @@ static struct ib_mr *rxe_rereg_user_mr(s
+ return ERR_PTR(-EOPNOTSUPP);
+ }
+
++ err = ib_umem_check_rereg(mr->umem, flags, access);
++ if (err)
++ return ERR_PTR(err);
++
+ if (flags & IB_MR_REREG_PD) {
+ rxe_put(old_pd);
+ rxe_get(pd);
+--- a/include/rdma/ib_umem.h
++++ b/include/rdma/ib_umem.h
+@@ -163,6 +163,8 @@ void ib_umem_dmabuf_revoke_lock(struct i
+ void ib_umem_dmabuf_revoke_unlock(struct ib_umem_dmabuf *umem_dmabuf);
+ void ib_umem_dmabuf_revoke(struct ib_umem_dmabuf *umem_dmabuf);
+
++int ib_umem_check_rereg(struct ib_umem *umem, int flags, int new_access_flags);
++
+ #else /* CONFIG_INFINIBAND_USER_MEM */
+
+ #include <linux/err.h>
+@@ -225,5 +227,11 @@ static inline void ib_umem_dmabuf_revoke
+ static inline void ib_umem_dmabuf_revoke_unlock(struct ib_umem_dmabuf *umem_dmabuf) {}
+ static inline void ib_umem_dmabuf_revoke(struct ib_umem_dmabuf *umem_dmabuf) {}
+
++static inline int ib_umem_check_rereg(struct ib_umem *umem, int flags,
++ int new_access_flags)
++{
++ return -EOPNOTSUPP;
++}
++
+ #endif /* CONFIG_INFINIBAND_USER_MEM */
+ #endif /* IB_UMEM_H */
--- /dev/null
+From stable+bounces-263483-greg=kroah.com@vger.kernel.org Tue Jun 16 04:24:24 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jun 2026 18:52:14 -0400
+Subject: RDMA: Move DMA block iterator logic into dedicated files
+To: stable@vger.kernel.org
+Cc: Leon Romanovsky <leonro@nvidia.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260615225215.2520173-2-sashal@kernel.org>
+
+From: Leon Romanovsky <leonro@nvidia.com>
+
+[ Upstream commit 6094ea64c69520ed1e770e7c79c43412de202bfa ]
+
+The DMA iterator logic was mixed into verbs and umem-specific code,
+forcing all users to include rdma/ib_umem.h. Move the block iterator
+logic into iter.c and rdma/iter.h so that rdma/ib_umem.h and
+rdma/ib_verbs.h can be separated in a follow-up patch.
+
+Link: https://patch.msgid.link/20260213-refactor-umem-v1-1-f3be85847922@nvidia.com
+Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
+Stable-dep-of: 15fe76e23615 ("RDMA/umem: Fix truncation for block sizes >= 4G")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/infiniband/core/Makefile | 2
+ drivers/infiniband/core/iter.c | 43 +++++++++++++
+ drivers/infiniband/core/verbs.c | 38 -----------
+ drivers/infiniband/hw/bnxt_re/qplib_res.c | 2
+ drivers/infiniband/hw/cxgb4/mem.c | 2
+ drivers/infiniband/hw/efa/efa_verbs.c | 2
+ drivers/infiniband/hw/erdma/erdma_verbs.c | 2
+ drivers/infiniband/hw/hns/hns_roce_alloc.c | 2
+ drivers/infiniband/hw/irdma/main.h | 2
+ drivers/infiniband/hw/mana/mana_ib.h | 2
+ drivers/infiniband/hw/mlx4/mr.c | 1
+ drivers/infiniband/hw/mlx5/mem.c | 1
+ drivers/infiniband/hw/mlx5/umr.c | 1
+ drivers/infiniband/hw/mthca/mthca_provider.c | 2
+ drivers/infiniband/hw/ocrdma/ocrdma_verbs.c | 2
+ drivers/infiniband/hw/qedr/verbs.c | 2
+ drivers/infiniband/hw/vmw_pvrdma/pvrdma.h | 2
+ include/rdma/ib_umem.h | 32 ---------
+ include/rdma/ib_verbs.h | 48 --------------
+ include/rdma/iter.h | 88 +++++++++++++++++++++++++++
+ 20 files changed, 146 insertions(+), 130 deletions(-)
+ create mode 100644 drivers/infiniband/core/iter.c
+ create mode 100644 include/rdma/iter.h
+
+--- a/drivers/infiniband/core/Makefile
++++ b/drivers/infiniband/core/Makefile
+@@ -12,7 +12,7 @@ ib_core-y := packer.o ud_header.o verb
+ roce_gid_mgmt.o mr_pool.o addr.o sa_query.o \
+ multicast.o mad.o smi.o agent.o mad_rmpp.o \
+ nldev.o restrack.o counters.o ib_core_uverbs.o \
+- trace.o lag.o
++ trace.o lag.o iter.o
+
+ ib_core-$(CONFIG_SECURITY_INFINIBAND) += security.o
+ ib_core-$(CONFIG_CGROUP_RDMA) += cgroup.o
+--- /dev/null
++++ b/drivers/infiniband/core/iter.c
+@@ -0,0 +1,43 @@
++// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
++/* Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. */
++
++#include <linux/export.h>
++#include <rdma/iter.h>
++
++void __rdma_block_iter_start(struct ib_block_iter *biter,
++ struct scatterlist *sglist, unsigned int nents,
++ unsigned long pgsz)
++{
++ memset(biter, 0, sizeof(struct ib_block_iter));
++ biter->__sg = sglist;
++ biter->__sg_nents = nents;
++
++ /* Driver provides best block size to use */
++ biter->__pg_bit = __fls(pgsz);
++}
++EXPORT_SYMBOL(__rdma_block_iter_start);
++
++bool __rdma_block_iter_next(struct ib_block_iter *biter)
++{
++ unsigned int block_offset;
++ unsigned int delta;
++
++ if (!biter->__sg_nents || !biter->__sg)
++ return false;
++
++ biter->__dma_addr = sg_dma_address(biter->__sg) + biter->__sg_advance;
++ block_offset = biter->__dma_addr & (BIT_ULL(biter->__pg_bit) - 1);
++ delta = BIT_ULL(biter->__pg_bit) - block_offset;
++
++ while (biter->__sg_nents && biter->__sg &&
++ sg_dma_len(biter->__sg) - biter->__sg_advance <= delta) {
++ delta -= sg_dma_len(biter->__sg) - biter->__sg_advance;
++ biter->__sg_advance = 0;
++ biter->__sg = sg_next(biter->__sg);
++ biter->__sg_nents--;
++ }
++ biter->__sg_advance += delta;
++
++ return true;
++}
++EXPORT_SYMBOL(__rdma_block_iter_next);
+--- a/drivers/infiniband/core/verbs.c
++++ b/drivers/infiniband/core/verbs.c
+@@ -3093,44 +3093,6 @@ int rdma_init_netdev(struct ib_device *d
+ }
+ EXPORT_SYMBOL(rdma_init_netdev);
+
+-void __rdma_block_iter_start(struct ib_block_iter *biter,
+- struct scatterlist *sglist, unsigned int nents,
+- unsigned long pgsz)
+-{
+- memset(biter, 0, sizeof(struct ib_block_iter));
+- biter->__sg = sglist;
+- biter->__sg_nents = nents;
+-
+- /* Driver provides best block size to use */
+- biter->__pg_bit = __fls(pgsz);
+-}
+-EXPORT_SYMBOL(__rdma_block_iter_start);
+-
+-bool __rdma_block_iter_next(struct ib_block_iter *biter)
+-{
+- unsigned int block_offset;
+- unsigned int delta;
+-
+- if (!biter->__sg_nents || !biter->__sg)
+- return false;
+-
+- biter->__dma_addr = sg_dma_address(biter->__sg) + biter->__sg_advance;
+- block_offset = biter->__dma_addr & (BIT_ULL(biter->__pg_bit) - 1);
+- delta = BIT_ULL(biter->__pg_bit) - block_offset;
+-
+- while (biter->__sg_nents && biter->__sg &&
+- sg_dma_len(biter->__sg) - biter->__sg_advance <= delta) {
+- delta -= sg_dma_len(biter->__sg) - biter->__sg_advance;
+- biter->__sg_advance = 0;
+- biter->__sg = sg_next(biter->__sg);
+- biter->__sg_nents--;
+- }
+- biter->__sg_advance += delta;
+-
+- return true;
+-}
+-EXPORT_SYMBOL(__rdma_block_iter_next);
+-
+ /**
+ * rdma_alloc_hw_stats_struct - Helper function to allocate dynamic struct
+ * for the drivers.
+--- a/drivers/infiniband/hw/bnxt_re/qplib_res.c
++++ b/drivers/infiniband/hw/bnxt_re/qplib_res.c
+@@ -46,7 +46,7 @@
+ #include <linux/if_vlan.h>
+ #include <linux/vmalloc.h>
+ #include <rdma/ib_verbs.h>
+-#include <rdma/ib_umem.h>
++#include <rdma/iter.h>
+
+ #include "roce_hsi.h"
+ #include "qplib_res.h"
+--- a/drivers/infiniband/hw/cxgb4/mem.c
++++ b/drivers/infiniband/hw/cxgb4/mem.c
+@@ -32,9 +32,9 @@
+
+ #include <linux/module.h>
+ #include <linux/moduleparam.h>
+-#include <rdma/ib_umem.h>
+ #include <linux/atomic.h>
+ #include <rdma/ib_user_verbs.h>
++#include <rdma/iter.h>
+
+ #include "iw_cxgb4.h"
+
+--- a/drivers/infiniband/hw/efa/efa_verbs.c
++++ b/drivers/infiniband/hw/efa/efa_verbs.c
+@@ -9,9 +9,9 @@
+ #include <linux/log2.h>
+
+ #include <rdma/ib_addr.h>
+-#include <rdma/ib_umem.h>
+ #include <rdma/ib_user_verbs.h>
+ #include <rdma/ib_verbs.h>
++#include <rdma/iter.h>
+ #include <rdma/uverbs_ioctl.h>
+ #define UVERBS_MODULE_NAME efa_ib
+ #include <rdma/uverbs_named_ioctl.h>
+--- a/drivers/infiniband/hw/erdma/erdma_verbs.c
++++ b/drivers/infiniband/hw/erdma/erdma_verbs.c
+@@ -12,7 +12,7 @@
+ #include <linux/vmalloc.h>
+ #include <net/addrconf.h>
+ #include <rdma/erdma-abi.h>
+-#include <rdma/ib_umem.h>
++#include <rdma/iter.h>
+ #include <rdma/uverbs_ioctl.h>
+
+ #include "erdma.h"
+--- a/drivers/infiniband/hw/hns/hns_roce_alloc.c
++++ b/drivers/infiniband/hw/hns/hns_roce_alloc.c
+@@ -32,7 +32,7 @@
+ */
+
+ #include <linux/vmalloc.h>
+-#include <rdma/ib_umem.h>
++#include <rdma/iter.h>
+ #include "hns_roce_device.h"
+
+ void hns_roce_buf_free(struct hns_roce_dev *hr_dev, struct hns_roce_buf *buf)
+--- a/drivers/infiniband/hw/irdma/main.h
++++ b/drivers/infiniband/hw/irdma/main.h
+@@ -37,8 +37,8 @@
+ #include <rdma/rdma_cm.h>
+ #include <rdma/iw_cm.h>
+ #include <rdma/ib_user_verbs.h>
+-#include <rdma/ib_umem.h>
+ #include <rdma/ib_cache.h>
++#include <rdma/iter.h>
+ #include <rdma/uverbs_ioctl.h>
+ #include "osdep.h"
+ #include "defs.h"
+--- a/drivers/infiniband/hw/mana/mana_ib.h
++++ b/drivers/infiniband/hw/mana/mana_ib.h
+@@ -8,7 +8,7 @@
+
+ #include <rdma/ib_verbs.h>
+ #include <rdma/ib_mad.h>
+-#include <rdma/ib_umem.h>
++#include <rdma/iter.h>
+ #include <rdma/mana-abi.h>
+ #include <rdma/uverbs_ioctl.h>
+
+--- a/drivers/infiniband/hw/mlx4/mr.c
++++ b/drivers/infiniband/hw/mlx4/mr.c
+@@ -33,6 +33,7 @@
+
+ #include <linux/slab.h>
+ #include <rdma/ib_user_verbs.h>
++#include <rdma/iter.h>
+
+ #include "mlx4_ib.h"
+
+--- a/drivers/infiniband/hw/mlx5/mem.c
++++ b/drivers/infiniband/hw/mlx5/mem.c
+@@ -31,6 +31,7 @@
+ */
+
+ #include <rdma/ib_umem_odp.h>
++#include <rdma/iter.h>
+ #include "mlx5_ib.h"
+
+ /*
+--- a/drivers/infiniband/hw/mlx5/umr.c
++++ b/drivers/infiniband/hw/mlx5/umr.c
+@@ -2,6 +2,7 @@
+ /* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. */
+
+ #include <rdma/ib_umem_odp.h>
++#include <rdma/iter.h>
+ #include "mlx5_ib.h"
+ #include "umr.h"
+ #include "wr.h"
+--- a/drivers/infiniband/hw/mthca/mthca_provider.c
++++ b/drivers/infiniband/hw/mthca/mthca_provider.c
+@@ -35,8 +35,8 @@
+ */
+
+ #include <rdma/ib_smi.h>
+-#include <rdma/ib_umem.h>
+ #include <rdma/ib_user_verbs.h>
++#include <rdma/iter.h>
+ #include <rdma/uverbs_ioctl.h>
+
+ #include <linux/sched.h>
+--- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
++++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
+@@ -45,9 +45,9 @@
+ #include <rdma/ib_verbs.h>
+ #include <rdma/ib_user_verbs.h>
+ #include <rdma/iw_cm.h>
+-#include <rdma/ib_umem.h>
+ #include <rdma/ib_addr.h>
+ #include <rdma/ib_cache.h>
++#include <rdma/iter.h>
+ #include <rdma/uverbs_ioctl.h>
+
+ #include "ocrdma.h"
+--- a/drivers/infiniband/hw/qedr/verbs.c
++++ b/drivers/infiniband/hw/qedr/verbs.c
+@@ -39,9 +39,9 @@
+ #include <rdma/ib_verbs.h>
+ #include <rdma/ib_user_verbs.h>
+ #include <rdma/iw_cm.h>
+-#include <rdma/ib_umem.h>
+ #include <rdma/ib_addr.h>
+ #include <rdma/ib_cache.h>
++#include <rdma/iter.h>
+ #include <rdma/uverbs_ioctl.h>
+
+ #include <linux/qed/common_hsi.h>
+--- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma.h
++++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma.h
+@@ -53,8 +53,8 @@
+ #include <linux/pci.h>
+ #include <linux/semaphore.h>
+ #include <linux/workqueue.h>
+-#include <rdma/ib_umem.h>
+ #include <rdma/ib_verbs.h>
++#include <rdma/iter.h>
+ #include <rdma/vmw_pvrdma-abi.h>
+
+ #include "pvrdma_ring.h"
+--- a/include/rdma/ib_umem.h
++++ b/include/rdma/ib_umem.h
+@@ -71,38 +71,6 @@ static inline size_t ib_umem_num_pages(s
+ {
+ return ib_umem_num_dma_blocks(umem, PAGE_SIZE);
+ }
+-
+-static inline void __rdma_umem_block_iter_start(struct ib_block_iter *biter,
+- struct ib_umem *umem,
+- unsigned long pgsz)
+-{
+- __rdma_block_iter_start(biter, umem->sgt_append.sgt.sgl,
+- umem->sgt_append.sgt.nents, pgsz);
+- biter->__sg_advance = ib_umem_offset(umem) & ~(pgsz - 1);
+- biter->__sg_numblocks = ib_umem_num_dma_blocks(umem, pgsz);
+-}
+-
+-static inline bool __rdma_umem_block_iter_next(struct ib_block_iter *biter)
+-{
+- return __rdma_block_iter_next(biter) && biter->__sg_numblocks--;
+-}
+-
+-/**
+- * rdma_umem_for_each_dma_block - iterate over contiguous DMA blocks of the umem
+- * @umem: umem to iterate over
+- * @biter: block iterator variable
+- * @pgsz: Page size to split the list into
+- *
+- * pgsz must be <= PAGE_SIZE or computed by ib_umem_find_best_pgsz(). The
+- * returned DMA blocks will be aligned to pgsz and span the range:
+- * ALIGN_DOWN(umem->address, pgsz) to ALIGN(umem->address + umem->length, pgsz)
+- *
+- * Performs exactly ib_umem_num_dma_blocks() iterations.
+- */
+-#define rdma_umem_for_each_dma_block(umem, biter, pgsz) \
+- for (__rdma_umem_block_iter_start(biter, umem, pgsz); \
+- __rdma_umem_block_iter_next(biter);)
+-
+ #ifdef CONFIG_INFINIBAND_USER_MEM
+
+ struct ib_umem *ib_umem_get(struct ib_device *device, unsigned long addr,
+--- a/include/rdma/ib_verbs.h
++++ b/include/rdma/ib_verbs.h
+@@ -2849,22 +2849,6 @@ struct ib_client {
+ u8 no_kverbs_req:1;
+ };
+
+-/*
+- * IB block DMA iterator
+- *
+- * Iterates the DMA-mapped SGL in contiguous memory blocks aligned
+- * to a HW supported page size.
+- */
+-struct ib_block_iter {
+- /* internal states */
+- struct scatterlist *__sg; /* sg holding the current aligned block */
+- dma_addr_t __dma_addr; /* unaligned DMA address of this block */
+- size_t __sg_numblocks; /* ib_umem_num_dma_blocks() */
+- unsigned int __sg_nents; /* number of SG entries */
+- unsigned int __sg_advance; /* number of bytes to advance in sg in next step */
+- unsigned int __pg_bit; /* alignment of current block */
+-};
+-
+ struct ib_device *_ib_alloc_device(size_t size);
+ #define ib_alloc_device(drv_struct, member) \
+ container_of(_ib_alloc_device(sizeof(struct drv_struct) + \
+@@ -2886,38 +2870,6 @@ void ib_unregister_device_queued(struct
+ int ib_register_client (struct ib_client *client);
+ void ib_unregister_client(struct ib_client *client);
+
+-void __rdma_block_iter_start(struct ib_block_iter *biter,
+- struct scatterlist *sglist,
+- unsigned int nents,
+- unsigned long pgsz);
+-bool __rdma_block_iter_next(struct ib_block_iter *biter);
+-
+-/**
+- * rdma_block_iter_dma_address - get the aligned dma address of the current
+- * block held by the block iterator.
+- * @biter: block iterator holding the memory block
+- */
+-static inline dma_addr_t
+-rdma_block_iter_dma_address(struct ib_block_iter *biter)
+-{
+- return biter->__dma_addr & ~(BIT_ULL(biter->__pg_bit) - 1);
+-}
+-
+-/**
+- * rdma_for_each_block - iterate over contiguous memory blocks of the sg list
+- * @sglist: sglist to iterate over
+- * @biter: block iterator holding the memory block
+- * @nents: maximum number of sg entries to iterate over
+- * @pgsz: best HW supported page size to use
+- *
+- * Callers may use rdma_block_iter_dma_address() to get each
+- * blocks aligned DMA address.
+- */
+-#define rdma_for_each_block(sglist, biter, nents, pgsz) \
+- for (__rdma_block_iter_start(biter, sglist, nents, \
+- pgsz); \
+- __rdma_block_iter_next(biter);)
+-
+ /**
+ * ib_get_client_data - Get IB client context
+ * @device:Device to get context for
+--- /dev/null
++++ b/include/rdma/iter.h
+@@ -0,0 +1,88 @@
++/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
++/* Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. */
++
++#ifndef _RDMA_ITER_H_
++#define _RDMA_ITER_H_
++
++#include <linux/scatterlist.h>
++#include <rdma/ib_umem.h>
++
++/**
++ * IB block DMA iterator
++ *
++ * Iterates the DMA-mapped SGL in contiguous memory blocks aligned
++ * to a HW supported page size.
++ */
++struct ib_block_iter {
++ /* internal states */
++ struct scatterlist *__sg; /* sg holding the current aligned block */
++ dma_addr_t __dma_addr; /* unaligned DMA address of this block */
++ size_t __sg_numblocks; /* ib_umem_num_dma_blocks() */
++ unsigned int __sg_nents; /* number of SG entries */
++ unsigned int __sg_advance; /* number of bytes to advance in sg in next step */
++ unsigned int __pg_bit; /* alignment of current block */
++};
++
++void __rdma_block_iter_start(struct ib_block_iter *biter,
++ struct scatterlist *sglist,
++ unsigned int nents,
++ unsigned long pgsz);
++bool __rdma_block_iter_next(struct ib_block_iter *biter);
++
++/**
++ * rdma_block_iter_dma_address - get the aligned dma address of the current
++ * block held by the block iterator.
++ * @biter: block iterator holding the memory block
++ */
++static inline dma_addr_t
++rdma_block_iter_dma_address(struct ib_block_iter *biter)
++{
++ return biter->__dma_addr & ~(BIT_ULL(biter->__pg_bit) - 1);
++}
++
++/**
++ * rdma_for_each_block - iterate over contiguous memory blocks of the sg list
++ * @sglist: sglist to iterate over
++ * @biter: block iterator holding the memory block
++ * @nents: maximum number of sg entries to iterate over
++ * @pgsz: best HW supported page size to use
++ *
++ * Callers may use rdma_block_iter_dma_address() to get each
++ * blocks aligned DMA address.
++ */
++#define rdma_for_each_block(sglist, biter, nents, pgsz) \
++ for (__rdma_block_iter_start(biter, sglist, nents, \
++ pgsz); \
++ __rdma_block_iter_next(biter);)
++
++static inline void __rdma_umem_block_iter_start(struct ib_block_iter *biter,
++ struct ib_umem *umem,
++ unsigned long pgsz)
++{
++ __rdma_block_iter_start(biter, umem->sgt_append.sgt.sgl,
++ umem->sgt_append.sgt.nents, pgsz);
++ biter->__sg_advance = ib_umem_offset(umem) & ~(pgsz - 1);
++ biter->__sg_numblocks = ib_umem_num_dma_blocks(umem, pgsz);
++}
++
++static inline bool __rdma_umem_block_iter_next(struct ib_block_iter *biter)
++{
++ return __rdma_block_iter_next(biter) && biter->__sg_numblocks--;
++}
++
++/**
++ * rdma_umem_for_each_dma_block - iterate over contiguous DMA blocks of the umem
++ * @umem: umem to iterate over
++ * @pgsz: Page size to split the list into
++ *
++ * pgsz must be <= PAGE_SIZE or computed by ib_umem_find_best_pgsz(). The
++ * returned DMA blocks will be aligned to pgsz and span the range:
++ * ALIGN_DOWN(umem->address, pgsz) to ALIGN(umem->address + umem->length, pgsz)
++ *
++ * Performs exactly ib_umem_num_dma_blocks() iterations.
++ */
++#define rdma_umem_for_each_dma_block(umem, biter, pgsz) \
++ for (__rdma_umem_block_iter_start(biter, umem, pgsz); \
++ __rdma_umem_block_iter_next(biter);)
++
++#endif /* _RDMA_ITER_H_ */
--- /dev/null
+From stable+bounces-263467-greg=kroah.com@vger.kernel.org Tue Jun 16 02:59:18 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jun 2026 17:29:09 -0400
+Subject: RDMA/umem: Add helpers for umem dmabuf revoke lock
+To: stable@vger.kernel.org
+Cc: Jacob Moroni <jmoroni@google.com>, Leon Romanovsky <leon@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260615212910.2473729-3-sashal@kernel.org>
+
+From: Jacob Moroni <jmoroni@google.com>
+
+[ Upstream commit 3a0b171302eea1732a168e26db3b8461f51cc1f9 ]
+
+Added helpers to acquire and release the umem dmabuf revoke
+lock. The intent is to avoid the need for drivers to peek
+into the ib_umem_dmabuf internals to get the dma_resv_lock
+and bring us one step closer to abstracting ib_umem_dmabuf
+away from drivers in general.
+
+Signed-off-by: Jacob Moroni <jmoroni@google.com>
+Link: https://patch.msgid.link/20260305170826.3803155-5-jmoroni@google.com
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Stable-dep-of: badad6fad60d ("RDMA: During rereg_mr ensure that REREG_ACCESS is compatible")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/infiniband/core/umem_dmabuf.c | 16 ++++++++++++++++
+ include/rdma/ib_umem.h | 4 ++++
+ 2 files changed, 20 insertions(+)
+
+--- a/drivers/infiniband/core/umem_dmabuf.c
++++ b/drivers/infiniband/core/umem_dmabuf.c
+@@ -276,6 +276,22 @@ struct ib_umem_dmabuf *ib_umem_dmabuf_ge
+ }
+ EXPORT_SYMBOL(ib_umem_dmabuf_get_pinned);
+
++void ib_umem_dmabuf_revoke_lock(struct ib_umem_dmabuf *umem_dmabuf)
++{
++ struct dma_buf *dmabuf = umem_dmabuf->attach->dmabuf;
++
++ dma_resv_lock(dmabuf->resv, NULL);
++}
++EXPORT_SYMBOL(ib_umem_dmabuf_revoke_lock);
++
++void ib_umem_dmabuf_revoke_unlock(struct ib_umem_dmabuf *umem_dmabuf)
++{
++ struct dma_buf *dmabuf = umem_dmabuf->attach->dmabuf;
++
++ dma_resv_unlock(dmabuf->resv);
++}
++EXPORT_SYMBOL(ib_umem_dmabuf_revoke_unlock);
++
+ void ib_umem_dmabuf_revoke(struct ib_umem_dmabuf *umem_dmabuf)
+ {
+ struct dma_buf *dmabuf = umem_dmabuf->attach->dmabuf;
+--- a/include/rdma/ib_umem.h
++++ b/include/rdma/ib_umem.h
+@@ -159,6 +159,8 @@ ib_umem_dmabuf_get_pinned_with_dma_devic
+ int ib_umem_dmabuf_map_pages(struct ib_umem_dmabuf *umem_dmabuf);
+ void ib_umem_dmabuf_unmap_pages(struct ib_umem_dmabuf *umem_dmabuf);
+ void ib_umem_dmabuf_release(struct ib_umem_dmabuf *umem_dmabuf);
++void ib_umem_dmabuf_revoke_lock(struct ib_umem_dmabuf *umem_dmabuf);
++void ib_umem_dmabuf_revoke_unlock(struct ib_umem_dmabuf *umem_dmabuf);
+ void ib_umem_dmabuf_revoke(struct ib_umem_dmabuf *umem_dmabuf);
+
+ #else /* CONFIG_INFINIBAND_USER_MEM */
+@@ -219,6 +221,8 @@ static inline int ib_umem_dmabuf_map_pag
+ }
+ static inline void ib_umem_dmabuf_unmap_pages(struct ib_umem_dmabuf *umem_dmabuf) { }
+ static inline void ib_umem_dmabuf_release(struct ib_umem_dmabuf *umem_dmabuf) { }
++static inline void ib_umem_dmabuf_revoke_lock(struct ib_umem_dmabuf *umem_dmabuf) {}
++static inline void ib_umem_dmabuf_revoke_unlock(struct ib_umem_dmabuf *umem_dmabuf) {}
+ static inline void ib_umem_dmabuf_revoke(struct ib_umem_dmabuf *umem_dmabuf) {}
+
+ #endif /* CONFIG_INFINIBAND_USER_MEM */
--- /dev/null
+From stable+bounces-263465-greg=kroah.com@vger.kernel.org Tue Jun 16 02:59:40 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jun 2026 17:29:07 -0400
+Subject: RDMA/umem: Add ib_umem_dmabuf_get_pinned_and_lock helper
+To: stable@vger.kernel.org
+Cc: Jacob Moroni <jmoroni@google.com>, Leon Romanovsky <leon@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260615212910.2473729-1-sashal@kernel.org>
+
+From: Jacob Moroni <jmoroni@google.com>
+
+[ Upstream commit 553dfa8cbd0c6d36adae042d9738ddf8f8765ac7 ]
+
+Move the inner logic of ib_umem_dmabuf_get_pinned_with_dma_device()
+to a new static function that returns with the lock held upon success.
+
+The intent is to allow reuse for the future get_pinned_revocable_and_lock
+function.
+
+Signed-off-by: Jacob Moroni <jmoroni@google.com>
+Link: https://patch.msgid.link/20260305170826.3803155-2-jmoroni@google.com
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Stable-dep-of: badad6fad60d ("RDMA: During rereg_mr ensure that REREG_ACCESS is compatible")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/infiniband/core/umem_dmabuf.c | 35 +++++++++++++++++++++++++---------
+ 1 file changed, 26 insertions(+), 9 deletions(-)
+
+--- a/drivers/infiniband/core/umem_dmabuf.c
++++ b/drivers/infiniband/core/umem_dmabuf.c
+@@ -198,18 +198,19 @@ static struct dma_buf_attach_ops ib_umem
+ .move_notify = ib_umem_dmabuf_unsupported_move_notify,
+ };
+
+-struct ib_umem_dmabuf *
+-ib_umem_dmabuf_get_pinned_with_dma_device(struct ib_device *device,
+- struct device *dma_device,
+- unsigned long offset, size_t size,
+- int fd, int access)
++static struct ib_umem_dmabuf *
++ib_umem_dmabuf_get_pinned_and_lock(struct ib_device *device,
++ struct device *dma_device,
++ unsigned long offset,
++ size_t size, int fd, int access,
++ const struct dma_buf_attach_ops *ops)
+ {
+ struct ib_umem_dmabuf *umem_dmabuf;
+ int err;
+
+- umem_dmabuf = ib_umem_dmabuf_get_with_dma_device(device, dma_device, offset,
+- size, fd, access,
+- &ib_umem_dmabuf_attach_pinned_ops);
++ umem_dmabuf =
++ ib_umem_dmabuf_get_with_dma_device(device, dma_device, offset,
++ size, fd, access, ops);
+ if (IS_ERR(umem_dmabuf))
+ return umem_dmabuf;
+
+@@ -222,7 +223,6 @@ ib_umem_dmabuf_get_pinned_with_dma_devic
+ err = ib_umem_dmabuf_map_pages(umem_dmabuf);
+ if (err)
+ goto err_release;
+- dma_resv_unlock(umem_dmabuf->attach->dmabuf->resv);
+
+ return umem_dmabuf;
+
+@@ -231,6 +231,23 @@ err_release:
+ ib_umem_release(&umem_dmabuf->umem);
+ return ERR_PTR(err);
+ }
++
++struct ib_umem_dmabuf *
++ib_umem_dmabuf_get_pinned_with_dma_device(struct ib_device *device,
++ struct device *dma_device,
++ unsigned long offset, size_t size,
++ int fd, int access)
++{
++ struct ib_umem_dmabuf *umem_dmabuf =
++ ib_umem_dmabuf_get_pinned_and_lock(device, dma_device, offset,
++ size, fd, access,
++ &ib_umem_dmabuf_attach_pinned_ops);
++ if (IS_ERR(umem_dmabuf))
++ return umem_dmabuf;
++
++ dma_resv_unlock(umem_dmabuf->attach->dmabuf->resv);
++ return umem_dmabuf;
++}
+ EXPORT_SYMBOL(ib_umem_dmabuf_get_pinned_with_dma_device);
+
+ struct ib_umem_dmabuf *ib_umem_dmabuf_get_pinned(struct ib_device *device,
--- /dev/null
+From stable+bounces-263481-greg=kroah.com@vger.kernel.org Tue Jun 16 04:24:17 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jun 2026 18:52:13 -0400
+Subject: RDMA/umem: fix kernel-doc warnings
+To: stable@vger.kernel.org
+Cc: Randy Dunlap <rdunlap@infradead.org>, Leon Romanovsky <leon@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260615225215.2520173-1-sashal@kernel.org>
+
+From: Randy Dunlap <rdunlap@infradead.org>
+
+[ Upstream commit ff46d1392750444fab5ae5a0194764ffdc4ac0d2 ]
+
+Add or correct kernel-doc comments to eliminate warnings:
+
+Warning: include/rdma/ib_umem.h:104 function parameter 'biter' not
+ described in 'rdma_umem_for_each_dma_block'
+Warning: include/rdma/ib_umem.h:140 function parameter 'pgsz_bitmap' not
+ described in 'ib_umem_find_best_pgoff'
+Warning: include/rdma/ib_umem.h:141 No description found for return
+ value of 'ib_umem_find_best_pgoff'
+
+Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
+Link: https://patch.msgid.link/20260224003120.3173892-1-rdunlap@infradead.org
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Stable-dep-of: 15fe76e23615 ("RDMA/umem: Fix truncation for block sizes >= 4G")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/rdma/ib_umem.h | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/include/rdma/ib_umem.h
++++ b/include/rdma/ib_umem.h
+@@ -90,6 +90,7 @@ static inline bool __rdma_umem_block_ite
+ /**
+ * rdma_umem_for_each_dma_block - iterate over contiguous DMA blocks of the umem
+ * @umem: umem to iterate over
++ * @biter: block iterator variable
+ * @pgsz: Page size to split the list into
+ *
+ * pgsz must be <= PAGE_SIZE or computed by ib_umem_find_best_pgsz(). The
+@@ -117,7 +118,7 @@ unsigned long ib_umem_find_best_pgsz(str
+ * ib_umem_find_best_pgoff - Find best HW page size
+ *
+ * @umem: umem struct
+- * @pgsz_bitmap bitmap of HW supported page sizes
++ * @pgsz_bitmap: bitmap of HW supported page sizes
+ * @pgoff_bitmask: Mask of bits that can be represented with an offset
+ *
+ * This is very similar to ib_umem_find_best_pgsz() except instead of accepting
+@@ -130,6 +131,9 @@ unsigned long ib_umem_find_best_pgsz(str
+ *
+ * If the pgoff_bitmask requires either alignment in the low bit or an
+ * unavailable page size for the high bits, this function returns 0.
++ *
++ * Returns: best HW page size for the parameters or 0 if none available
++ * for the given parameters.
+ */
+ static inline unsigned long ib_umem_find_best_pgoff(struct ib_umem *umem,
+ unsigned long pgsz_bitmap,
--- /dev/null
+From stable+bounces-263482-greg=kroah.com@vger.kernel.org Tue Jun 16 04:22:23 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jun 2026 18:52:15 -0400
+Subject: RDMA/umem: Fix truncation for block sizes >= 4G
+To: stable@vger.kernel.org
+Cc: Jason Gunthorpe <jgg@nvidia.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260615225215.2520173-3-sashal@kernel.org>
+
+From: Jason Gunthorpe <jgg@nvidia.com>
+
+[ Upstream commit 15fe76e23615f502d051ef0768f86babaf08746c ]
+
+When the iommu is used the linearization of the mapping can give a single
+block that is very large split across multiple SG entries.
+
+When __rdma_block_iter_next() reassembles the split SG entries it is
+overflowing the 32 bit stack values and computed the wrong DMA addresses
+for blocks after the truncation.
+
+Use the right types to hold DMA addresses.
+
+Link: https://patch.msgid.link/r/1-v1-88303e9e509f+f7-ib_umem_types_jgg@nvidia.com
+Cc: stable@vger.kernel.org
+Fixes: a808273a495c ("RDMA/verbs: Add a DMA iterator to return aligned contiguous memory blocks")
+Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/infiniband/core/iter.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/infiniband/core/iter.c
++++ b/drivers/infiniband/core/iter.c
+@@ -19,8 +19,8 @@ EXPORT_SYMBOL(__rdma_block_iter_start);
+
+ bool __rdma_block_iter_next(struct ib_block_iter *biter)
+ {
+- unsigned int block_offset;
+- unsigned int delta;
++ dma_addr_t block_offset;
++ dma_addr_t delta;
+
+ if (!biter->__sg_nents || !biter->__sg)
+ return false;
--- /dev/null
+From stable+bounces-263466-greg=kroah.com@vger.kernel.org Tue Jun 16 02:59:43 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jun 2026 17:29:08 -0400
+Subject: RDMA/umem: Move umem dmabuf revoke logic into helper function
+To: stable@vger.kernel.org
+Cc: Jacob Moroni <jmoroni@google.com>, Leon Romanovsky <leon@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260615212910.2473729-2-sashal@kernel.org>
+
+From: Jacob Moroni <jmoroni@google.com>
+
+[ Upstream commit 797291a66ce346c96114b72222fc290d402da005 ]
+
+This same logic will eventually be reused from within the
+invalidate_mappings callback which already has the dma_resv_lock
+held, so break it out into a separate function so it can be reused.
+
+Signed-off-by: Jacob Moroni <jmoroni@google.com>
+Link: https://patch.msgid.link/20260305170826.3803155-3-jmoroni@google.com
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Stable-dep-of: badad6fad60d ("RDMA: During rereg_mr ensure that REREG_ACCESS is compatible")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/infiniband/core/umem_dmabuf.c | 26 +++++++++++++++++---------
+ 1 file changed, 17 insertions(+), 9 deletions(-)
+
+--- a/drivers/infiniband/core/umem_dmabuf.c
++++ b/drivers/infiniband/core/umem_dmabuf.c
+@@ -198,6 +198,22 @@ static struct dma_buf_attach_ops ib_umem
+ .move_notify = ib_umem_dmabuf_unsupported_move_notify,
+ };
+
++static void ib_umem_dmabuf_revoke_locked(struct dma_buf_attachment *attach)
++{
++ struct ib_umem_dmabuf *umem_dmabuf = attach->importer_priv;
++
++ dma_resv_assert_held(attach->dmabuf->resv);
++
++ if (umem_dmabuf->revoked)
++ return;
++ ib_umem_dmabuf_unmap_pages(umem_dmabuf);
++ if (umem_dmabuf->pinned) {
++ dma_buf_unpin(umem_dmabuf->attach);
++ umem_dmabuf->pinned = 0;
++ }
++ umem_dmabuf->revoked = 1;
++}
++
+ static struct ib_umem_dmabuf *
+ ib_umem_dmabuf_get_pinned_and_lock(struct ib_device *device,
+ struct device *dma_device,
+@@ -265,15 +281,7 @@ void ib_umem_dmabuf_revoke(struct ib_ume
+ struct dma_buf *dmabuf = umem_dmabuf->attach->dmabuf;
+
+ dma_resv_lock(dmabuf->resv, NULL);
+- if (umem_dmabuf->revoked)
+- goto end;
+- ib_umem_dmabuf_unmap_pages(umem_dmabuf);
+- if (umem_dmabuf->pinned) {
+- dma_buf_unpin(umem_dmabuf->attach);
+- umem_dmabuf->pinned = 0;
+- }
+- umem_dmabuf->revoked = 1;
+-end:
++ ib_umem_dmabuf_revoke_locked(umem_dmabuf->attach);
+ dma_resv_unlock(dmabuf->resv);
+ }
+ EXPORT_SYMBOL(ib_umem_dmabuf_revoke);
--- /dev/null
+From stable+bounces-263417-greg=kroah.com@vger.kernel.org Mon Jun 15 23:07:37 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jun 2026 13:37:30 -0400
+Subject: sched_ext: Don't warn on NULL cgrp_moving_from in scx_cgroup_move_task()
+To: stable@vger.kernel.org
+Cc: Tejun Heo <tj@kernel.org>, Matt Fleming <mfleming@cloudflare.com>, Andrea Righi <arighi@nvidia.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260615173730.2303601-1-sashal@kernel.org>
+
+From: Tejun Heo <tj@kernel.org>
+
+[ Upstream commit 02e545c4297a26dbbc41df81b831e7f605bcd306 ]
+
+A WARN fires when systemd's user manager writes "+cpu +memory +pids" to
+its own subtree_control while a sched_ext scheduler is loaded:
+
+ WARNING: at kernel/sched/ext.c:3227 scx_cgroup_move_task+0xa8/0xb0
+ scx_cgroup_move_task+0xa8/0xb0
+ sched_move_task+0x134/0x290
+ cpu_cgroup_attach+0x39/0x70
+ cgroup_migrate_execute+0x37d/0x450
+ cgroup_update_dfl_csses+0x1e3/0x270
+ cgroup_subtree_control_write+0x3e7/0x440
+
+scx_cgroup_can_attach() arms cgrp_moving_from only when a task's cpu
+cgroup changes. It can still be NULL when scx_cgroup_move_task() runs,
+through this sequence:
+
+ Step Result
+ --------------------------------- ----------------------------------
+ 1. cpu enabled on cgroup G cpu css = A
+ 2. cpu toggled off then on for G A killed, B created (same cgroup)
+ 3. an exiting task keeps A alive migration skips it, A now stale
+ 4. +memory migrates G stale A vs current B pulls cpu in
+ 5. cpu attach runs for all tasks hits a live, cpu-unchanged task
+ 6. scx_cgroup_move_task() on it cgrp_moving_from NULL -> WARN
+
+The mismatch is that scx_cgroup_can_attach() keys on cgroup identity
+while migration drives the move on css identity, so a NULL cgrp_moving_from
+here is a legitimate css-only migration, not a missing prep.
+
+The call is already gated on cgrp_moving_from, so just drop the warning.
+ops.cgroup_prep_move() and ops.cgroup_move() stay paired.
+
+Fixes: 819513666966 ("sched_ext: Add cgroup support")
+Cc: stable@vger.kernel.org # v6.12+
+Reported-by: Matt Fleming <mfleming@cloudflare.com>
+Closes: https://lore.kernel.org/all/20260601124156.2205704-1-mfleming@cloudflare.com/
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Reviewed-by: Andrea Righi <arighi@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/sched/ext.c | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+--- a/kernel/sched/ext.c
++++ b/kernel/sched/ext.c
+@@ -4069,10 +4069,13 @@ void scx_cgroup_move_task(struct task_st
+ return;
+
+ /*
+- * @p must have ops.cgroup_prep_move() called on it and thus
+- * cgrp_moving_from set.
++ * scx_cgroup_can_attach() sets cgrp_moving_from only when the task's
++ * cgroup changes. Migration keys off css rather than cgroup identity,
++ * so it can hand an unchanged-cgroup task here with cgrp_moving_from
++ * NULL. Nothing to report to the BPF scheduler then, so skip it and
++ * keep prep_move and move paired.
+ */
+- if (SCX_HAS_OP(cgroup_move) && !WARN_ON_ONCE(!p->scx.cgrp_moving_from))
++ if (SCX_HAS_OP(cgroup_move) && p->scx.cgrp_moving_from)
+ SCX_CALL_OP_TASK(SCX_KF_UNLOCKED, cgroup_move, p,
+ p->scx.cgrp_moving_from, tg_cgrp(task_group(p)));
+ p->scx.cgrp_moving_from = NULL;
drm-amd-display-use-krealloc_array-in-dal_vector_reserve.patch
fs-fcntl-fix-softirq-unsafe-lock-order-in-fasync-signaling.patch
driver-core-reject-devices-with-unregistered-buses.patch
+mailbox-fix-null-message-support-in-mbox_send_message.patch
+wifi-iwlwifi-fix-22000-series-smem-parsing.patch
+hv_netvsc-use-kmap_local_page-in-netvsc_copy_to_send_buf.patch
+sched_ext-don-t-warn-on-null-cgrp_moving_from-in-scx_cgroup_move_task.patch
+netfilter-nft_fib-fix-stale-stack-leak-via-the-oifname-register.patch
+mm-memory-failure-fix-hugetlb_lock-aa-deadlock-in-get_huge_page_for_hwpoison.patch
+rdma-umem-add-ib_umem_dmabuf_get_pinned_and_lock-helper.patch
+rdma-umem-move-umem-dmabuf-revoke-logic-into-helper-function.patch
+rdma-umem-add-helpers-for-umem-dmabuf-revoke-lock.patch
+rdma-during-rereg_mr-ensure-that-rereg_access-is-compatible.patch
+rdma-umem-fix-kernel-doc-warnings.patch
+rdma-move-dma-block-iterator-logic-into-dedicated-files.patch
+rdma-umem-fix-truncation-for-block-sizes-4g.patch
mm-hugetlb-avoid-false-positive-lockdep-assertion.patch
sched_ext-don-t-warn-on-null-cgrp_moving_from-in-scx.patch
--- /dev/null
+From 58192b9ce09b0f0f86e2036683bd542130b91a98 Mon Sep 17 00:00:00 2001
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Mon, 10 Nov 2025 15:02:19 +0200
+Subject: wifi: iwlwifi: fix 22000 series SMEM parsing
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+commit 58192b9ce09b0f0f86e2036683bd542130b91a98 upstream.
+
+If the firmware were to report three LMACs (which doesn't
+exist in hardware) then using "fwrt->smem_cfg.lmac[2]" is
+an overrun of the array. Reject such and use IWL_FW_CHECK
+instead of WARN_ON in this function.
+
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
+Link: https://patch.msgid.link/20251110150012.16e8c2d70c26.Iadfcc1aedf43c5175b3f0757bea5aa232454f1ac@changeid
+Signed-off-by: Nazar Kalashnikov <sivartiwe@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/wireless/intel/iwlwifi/fw/smem.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/intel/iwlwifi/fw/smem.c
++++ b/drivers/net/wireless/intel/iwlwifi/fw/smem.c
+@@ -6,6 +6,7 @@
+ */
+ #include "iwl-drv.h"
+ #include "runtime.h"
++#include "dbg.h"
+ #include "fw/api/commands.h"
+
+ static void iwl_parse_shared_mem_22000(struct iwl_fw_runtime *fwrt,
+@@ -17,7 +18,9 @@ static void iwl_parse_shared_mem_22000(s
+ u8 api_ver = iwl_fw_lookup_notif_ver(fwrt->fw, SYSTEM_GROUP,
+ SHARED_MEM_CFG_CMD, 0);
+
+- if (WARN_ON(lmac_num > ARRAY_SIZE(mem_cfg->lmac_smem)))
++ /* Note: notification has 3 entries, but we only expect 2 */
++ if (IWL_FW_CHECK(fwrt, lmac_num > ARRAY_SIZE(fwrt->smem_cfg.lmac),
++ "FW advertises %d LMACs\n", lmac_num))
+ return;
+
+ fwrt->smem_cfg.num_lmacs = lmac_num;
+@@ -26,7 +29,8 @@ static void iwl_parse_shared_mem_22000(s
+ fwrt->smem_cfg.rxfifo2_size = le32_to_cpu(mem_cfg->rxfifo2_size);
+
+ if (api_ver >= 4 &&
+- !WARN_ON_ONCE(iwl_rx_packet_payload_len(pkt) < sizeof(*mem_cfg))) {
++ !IWL_FW_CHECK(fwrt, iwl_rx_packet_payload_len(pkt) < sizeof(*mem_cfg),
++ "bad shared mem notification size\n")) {
+ fwrt->smem_cfg.rxfifo2_control_size =
+ le32_to_cpu(mem_cfg->rxfifo2_control_size);
+ }