* FAILED: patch "[PATCH] net: mana: Sync page pool RX frags for CPU" failed to apply to 6.18-stable tree
@ 2026-07-20 15:50 gregkh
2026-07-28 12:11 ` [PATCH 6.18.y 1/2] net: mana: Validate the packet length reported by the NIC Sasha Levin
0 siblings, 1 reply; 7+ messages in thread
From: gregkh @ 2026-07-20 15:50 UTC (permalink / raw)
To: decui, haiyangz, pabeni; +Cc: stable
The patch below does not apply to the 6.18-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.18.y
git checkout FETCH_HEAD
git cherry-pick -x c72a0f09c57f92113df69f9b902d11c9e4b132f5
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable@vger.kernel.org>' --in-reply-to '2026072020-cathedral-preoccupy-0b9c@gregkh' --subject-prefix 'PATCH 6.18.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From c72a0f09c57f92113df69f9b902d11c9e4b132f5 Mon Sep 17 00:00:00 2001
From: Dexuan Cui <decui@microsoft.com>
Date: Wed, 1 Jul 2026 21:12:37 -0700
Subject: [PATCH] net: mana: Sync page pool RX frags for CPU
MANA allocates RX buffers from page pool fragments when frag_count is
greater than 1. In that case the buffers remain DMA mapped by page pool
and the RX completion path does not call dma_unmap_single(). As a result,
the implicit sync-for-CPU normally performed by dma_unmap_single() is
missing before the packet data is passed to the networking stack.
This breaks RX on configurations which require explicit DMA syncing, for
example when booted with swiotlb=force.
Fix this by recording the page pool page and DMA sync offset when the RX
buffer is allocated, and syncing the received packet range for CPU access
before handing the RX buffer to the stack.
Fixes: 730ff06d3f5c ("net: mana: Use page pool fragments for RX buffers instead of full pages to improve memory efficiency.")
Cc: stable@vger.kernel.org
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Dexuan Cui <decui@microsoft.com>
Link: https://patch.msgid.link/20260702041237.617719-3-decui@microsoft.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index dd4d1c0c582e..9d9bfd116dab 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -2120,12 +2120,16 @@ static void mana_rx_skb(void *buf_va, bool from_pool,
}
static void *mana_get_rxfrag(struct mana_rxq *rxq, struct device *dev,
- dma_addr_t *da, bool *from_pool)
+ dma_addr_t *da, bool *from_pool,
+ struct page **pp_page, u32 *dma_sync_offset)
{
struct page *page;
u32 offset;
void *va;
+
*from_pool = false;
+ *pp_page = NULL;
+ *dma_sync_offset = 0;
/* Don't use fragments for jumbo frames or XDP where it's 1 fragment
* per page.
@@ -2163,31 +2167,47 @@ static void *mana_get_rxfrag(struct mana_rxq *rxq, struct device *dev,
va = page_to_virt(page) + offset;
*da = page_pool_get_dma_addr(page) + offset + rxq->headroom;
*from_pool = true;
+ *pp_page = page;
+ *dma_sync_offset = offset + rxq->headroom;
return va;
}
/* Allocate frag for rx buffer, and save the old buf */
static void mana_refill_rx_oob(struct device *dev, struct mana_rxq *rxq,
- struct mana_recv_buf_oob *rxoob, void **old_buf,
- bool *old_fp)
+ struct mana_recv_buf_oob *rxoob, u32 pktlen,
+ void **old_buf, bool *old_fp)
{
+ struct page *pp_page;
+ u32 dma_sync_offset;
bool from_pool;
dma_addr_t da;
void *va;
- va = mana_get_rxfrag(rxq, dev, &da, &from_pool);
+ va = mana_get_rxfrag(rxq, dev, &da, &from_pool, &pp_page,
+ &dma_sync_offset);
if (!va)
return;
- if (!rxoob->from_pool || rxq->frag_count == 1)
+ if (!rxoob->from_pool || rxq->frag_count == 1) {
dma_unmap_single(dev, rxoob->sgl[0].address, rxq->datasize,
DMA_FROM_DEVICE);
+ } else {
+ /* The page pool maps the whole page and only syncs for device
+ * automatically (PP_FLAG_DMA_SYNC_DEV). Sync the received bytes
+ * for the CPU before they are read: this is required if DMA
+ * is incoherent or bounce buffers are used.
+ */
+ page_pool_dma_sync_for_cpu(rxq->page_pool, rxoob->pp_page,
+ rxoob->dma_sync_offset, pktlen);
+ }
*old_buf = rxoob->buf_va;
*old_fp = rxoob->from_pool;
rxoob->buf_va = va;
rxoob->sgl[0].address = da;
rxoob->from_pool = from_pool;
+ rxoob->pp_page = pp_page;
+ rxoob->dma_sync_offset = dma_sync_offset;
}
static void mana_process_rx_cqe(struct mana_rxq *rxq, struct mana_cq *cq,
@@ -2258,7 +2278,8 @@ static void mana_process_rx_cqe(struct mana_rxq *rxq, struct mana_cq *cq,
/* Reuse the RX buffer since rxbuf_oob is unchanged. */
} else {
- mana_refill_rx_oob(dev, rxq, rxbuf_oob, &old_buf, &old_fp);
+ mana_refill_rx_oob(dev, rxq, rxbuf_oob, pktlen,
+ &old_buf, &old_fp);
/* Unsuccessful refill will have old_buf == NULL.
* In this case, mana_rx_skb() will drop the packet.
@@ -2668,6 +2689,8 @@ static int mana_fill_rx_oob(struct mana_recv_buf_oob *rx_oob, u32 mem_key,
struct mana_rxq *rxq, struct device *dev)
{
struct mana_port_context *mpc = netdev_priv(rxq->ndev);
+ struct page *pp_page = NULL;
+ u32 dma_sync_offset = 0;
bool from_pool = false;
dma_addr_t da;
void *va;
@@ -2675,13 +2698,16 @@ static int mana_fill_rx_oob(struct mana_recv_buf_oob *rx_oob, u32 mem_key,
if (mpc->rxbufs_pre)
va = mana_get_rxbuf_pre(rxq, &da);
else
- va = mana_get_rxfrag(rxq, dev, &da, &from_pool);
+ va = mana_get_rxfrag(rxq, dev, &da, &from_pool, &pp_page,
+ &dma_sync_offset);
if (!va)
return -ENOMEM;
rx_oob->buf_va = va;
rx_oob->from_pool = from_pool;
+ rx_oob->pp_page = pp_page;
+ rx_oob->dma_sync_offset = dma_sync_offset;
rx_oob->sgl[0].address = da;
rx_oob->sgl[0].size = rxq->datasize;
diff --git a/include/net/mana/mana.h b/include/net/mana/mana.h
index 13c87baf018e..04acb6791dbd 100644
--- a/include/net/mana/mana.h
+++ b/include/net/mana/mana.h
@@ -305,6 +305,14 @@ struct mana_recv_buf_oob {
void *buf_va;
bool from_pool; /* allocated from a page pool */
+ /* head page of the page_pool fragment; valid only when
+ * from_pool && frag_count > 1.
+ */
+ struct page *pp_page;
+ /* Fragment offset plus rxq->headroom, passed to
+ * page_pool_dma_sync_for_cpu().
+ */
+ u32 dma_sync_offset;
/* SGL of the buffer going to be sent as part of the work request. */
u32 num_sge;
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH 6.18.y 1/2] net: mana: Validate the packet length reported by the NIC
2026-07-20 15:50 FAILED: patch "[PATCH] net: mana: Sync page pool RX frags for CPU" failed to apply to 6.18-stable tree gregkh
@ 2026-07-28 12:11 ` Sasha Levin
2026-07-28 12:11 ` [PATCH 6.18.y 2/2] net: mana: Sync page pool RX frags for CPU Sasha Levin
0 siblings, 1 reply; 7+ messages in thread
From: Sasha Levin @ 2026-07-28 12:11 UTC (permalink / raw)
To: stable; +Cc: Dexuan Cui, Haiyang Zhang, Paolo Abeni, Sasha Levin
From: Dexuan Cui <decui@microsoft.com>
[ Upstream commit 2e2a83b4998af4384e677d3b2ac08565274279bf ]
Validate the packet length reported in the RX CQE before passing it
to skb processing. The CQE is supplied by the NIC device and should
not be blindly trusted.
Cc: stable@vger.kernel.org
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Dexuan Cui <decui@microsoft.com>
Fixes: ca9c54d2d6a5 ("net: mana: Add a driver for Microsoft Azure Network Adapter (MANA)")
Link: https://patch.msgid.link/20260702041237.617719-2-decui@microsoft.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Stable-dep-of: c72a0f09c57f ("net: mana: Sync page pool RX frags for CPU")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/microsoft/mana/mana_en.c | 23 +++++++++++++++----
1 file changed, 18 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index 62418f164dbac1..cbeb04ee727275 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -2160,12 +2160,25 @@ static void mana_process_rx_cqe(struct mana_rxq *rxq, struct mana_cq *cq,
rxbuf_oob = &rxq->rx_oobs[curr];
WARN_ON_ONCE(rxbuf_oob->wqe_inf.wqe_size_in_bu != 1);
- mana_refill_rx_oob(dev, rxq, rxbuf_oob, &old_buf, &old_fp);
+ if (unlikely(pktlen > rxq->datasize)) {
+ /* Increase it even if mana_rx_skb() isn't called. */
+ rxq->rx_cq.work_done++;
- /* Unsuccessful refill will have old_buf == NULL.
- * In this case, mana_rx_skb() will drop the packet.
- */
- mana_rx_skb(old_buf, old_fp, oob, rxq);
+ ++ndev->stats.rx_dropped;
+ netdev_warn_once(ndev,
+ "Dropped oversized RX packet: len=%u, datasize=%u\n",
+ pktlen, rxq->datasize);
+
+ /* Reuse the RX buffer since rxbuf_oob is unchanged. */
+ } else {
+
+ mana_refill_rx_oob(dev, rxq, rxbuf_oob, &old_buf, &old_fp);
+
+ /* Unsuccessful refill will have old_buf == NULL.
+ * In this case, mana_rx_skb() will drop the packet.
+ */
+ mana_rx_skb(old_buf, old_fp, oob, rxq);
+ }
drop:
mana_move_wq_tail(rxq->gdma_rq, rxbuf_oob->wqe_inf.wqe_size_in_bu);
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH 6.18.y 2/2] net: mana: Sync page pool RX frags for CPU
2026-07-28 12:11 ` [PATCH 6.18.y 1/2] net: mana: Validate the packet length reported by the NIC Sasha Levin
@ 2026-07-28 12:11 ` Sasha Levin
2026-07-30 12:22 ` Greg KH
0 siblings, 1 reply; 7+ messages in thread
From: Sasha Levin @ 2026-07-28 12:11 UTC (permalink / raw)
To: stable; +Cc: Dexuan Cui, Haiyang Zhang, Paolo Abeni, Sasha Levin
From: Dexuan Cui <decui@microsoft.com>
[ Upstream commit c72a0f09c57f92113df69f9b902d11c9e4b132f5 ]
MANA allocates RX buffers from page pool fragments when frag_count is
greater than 1. In that case the buffers remain DMA mapped by page pool
and the RX completion path does not call dma_unmap_single(). As a result,
the implicit sync-for-CPU normally performed by dma_unmap_single() is
missing before the packet data is passed to the networking stack.
This breaks RX on configurations which require explicit DMA syncing, for
example when booted with swiotlb=force.
Fix this by recording the page pool page and DMA sync offset when the RX
buffer is allocated, and syncing the received packet range for CPU access
before handing the RX buffer to the stack.
Fixes: 730ff06d3f5c ("net: mana: Use page pool fragments for RX buffers instead of full pages to improve memory efficiency.")
Cc: stable@vger.kernel.org
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Dexuan Cui <decui@microsoft.com>
Link: https://patch.msgid.link/20260702041237.617719-3-decui@microsoft.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/microsoft/mana/mana_en.c | 40 +++++++++++++++----
include/net/mana/mana.h | 8 ++++
2 files changed, 41 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index cbeb04ee727275..effee6c56c919d 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -2036,12 +2036,16 @@ static void mana_rx_skb(void *buf_va, bool from_pool,
}
static void *mana_get_rxfrag(struct mana_rxq *rxq, struct device *dev,
- dma_addr_t *da, bool *from_pool)
+ dma_addr_t *da, bool *from_pool,
+ struct page **pp_page, u32 *dma_sync_offset)
{
struct page *page;
u32 offset;
void *va;
+
*from_pool = false;
+ *pp_page = NULL;
+ *dma_sync_offset = 0;
/* Don't use fragments for jumbo frames or XDP where it's 1 fragment
* per page.
@@ -2079,31 +2083,47 @@ static void *mana_get_rxfrag(struct mana_rxq *rxq, struct device *dev,
va = page_to_virt(page) + offset;
*da = page_pool_get_dma_addr(page) + offset + rxq->headroom;
*from_pool = true;
+ *pp_page = page;
+ *dma_sync_offset = offset + rxq->headroom;
return va;
}
/* Allocate frag for rx buffer, and save the old buf */
static void mana_refill_rx_oob(struct device *dev, struct mana_rxq *rxq,
- struct mana_recv_buf_oob *rxoob, void **old_buf,
- bool *old_fp)
+ struct mana_recv_buf_oob *rxoob, u32 pktlen,
+ void **old_buf, bool *old_fp)
{
+ struct page *pp_page;
+ u32 dma_sync_offset;
bool from_pool;
dma_addr_t da;
void *va;
- va = mana_get_rxfrag(rxq, dev, &da, &from_pool);
+ va = mana_get_rxfrag(rxq, dev, &da, &from_pool, &pp_page,
+ &dma_sync_offset);
if (!va)
return;
- if (!rxoob->from_pool || rxq->frag_count == 1)
+ if (!rxoob->from_pool || rxq->frag_count == 1) {
dma_unmap_single(dev, rxoob->sgl[0].address, rxq->datasize,
DMA_FROM_DEVICE);
+ } else {
+ /* The page pool maps the whole page and only syncs for device
+ * automatically (PP_FLAG_DMA_SYNC_DEV). Sync the received bytes
+ * for the CPU before they are read: this is required if DMA
+ * is incoherent or bounce buffers are used.
+ */
+ page_pool_dma_sync_for_cpu(rxq->page_pool, rxoob->pp_page,
+ rxoob->dma_sync_offset, pktlen);
+ }
*old_buf = rxoob->buf_va;
*old_fp = rxoob->from_pool;
rxoob->buf_va = va;
rxoob->sgl[0].address = da;
rxoob->from_pool = from_pool;
+ rxoob->pp_page = pp_page;
+ rxoob->dma_sync_offset = dma_sync_offset;
}
static void mana_process_rx_cqe(struct mana_rxq *rxq, struct mana_cq *cq,
@@ -2172,7 +2192,8 @@ static void mana_process_rx_cqe(struct mana_rxq *rxq, struct mana_cq *cq,
/* Reuse the RX buffer since rxbuf_oob is unchanged. */
} else {
- mana_refill_rx_oob(dev, rxq, rxbuf_oob, &old_buf, &old_fp);
+ mana_refill_rx_oob(dev, rxq, rxbuf_oob, pktlen,
+ &old_buf, &old_fp);
/* Unsuccessful refill will have old_buf == NULL.
* In this case, mana_rx_skb() will drop the packet.
@@ -2548,6 +2569,8 @@ static int mana_fill_rx_oob(struct mana_recv_buf_oob *rx_oob, u32 mem_key,
struct mana_rxq *rxq, struct device *dev)
{
struct mana_port_context *mpc = netdev_priv(rxq->ndev);
+ struct page *pp_page = NULL;
+ u32 dma_sync_offset = 0;
bool from_pool = false;
dma_addr_t da;
void *va;
@@ -2555,13 +2578,16 @@ static int mana_fill_rx_oob(struct mana_recv_buf_oob *rx_oob, u32 mem_key,
if (mpc->rxbufs_pre)
va = mana_get_rxbuf_pre(rxq, &da);
else
- va = mana_get_rxfrag(rxq, dev, &da, &from_pool);
+ va = mana_get_rxfrag(rxq, dev, &da, &from_pool, &pp_page,
+ &dma_sync_offset);
if (!va)
return -ENOMEM;
rx_oob->buf_va = va;
rx_oob->from_pool = from_pool;
+ rx_oob->pp_page = pp_page;
+ rx_oob->dma_sync_offset = dma_sync_offset;
rx_oob->sgl[0].address = da;
rx_oob->sgl[0].size = rxq->datasize;
diff --git a/include/net/mana/mana.h b/include/net/mana/mana.h
index e199f1d44c8e30..a134b123527971 100644
--- a/include/net/mana/mana.h
+++ b/include/net/mana/mana.h
@@ -302,6 +302,14 @@ struct mana_recv_buf_oob {
void *buf_va;
bool from_pool; /* allocated from a page pool */
+ /* head page of the page_pool fragment; valid only when
+ * from_pool && frag_count > 1.
+ */
+ struct page *pp_page;
+ /* Fragment offset plus rxq->headroom, passed to
+ * page_pool_dma_sync_for_cpu().
+ */
+ u32 dma_sync_offset;
/* SGL of the buffer going to be sent as part of the work request. */
u32 num_sge;
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH 6.18.y 2/2] net: mana: Sync page pool RX frags for CPU
2026-07-28 12:11 ` [PATCH 6.18.y 2/2] net: mana: Sync page pool RX frags for CPU Sasha Levin
@ 2026-07-30 12:22 ` Greg KH
0 siblings, 0 replies; 7+ messages in thread
From: Greg KH @ 2026-07-30 12:22 UTC (permalink / raw)
To: Sasha Levin; +Cc: stable, Dexuan Cui, Haiyang Zhang, Paolo Abeni
On Tue, Jul 28, 2026 at 08:11:10AM -0400, Sasha Levin wrote:
> From: Dexuan Cui <decui@microsoft.com>
>
> [ Upstream commit c72a0f09c57f92113df69f9b902d11c9e4b132f5 ]
>
> MANA allocates RX buffers from page pool fragments when frag_count is
> greater than 1. In that case the buffers remain DMA mapped by page pool
> and the RX completion path does not call dma_unmap_single(). As a result,
> the implicit sync-for-CPU normally performed by dma_unmap_single() is
> missing before the packet data is passed to the networking stack.
>
> This breaks RX on configurations which require explicit DMA syncing, for
> example when booted with swiotlb=force.
>
> Fix this by recording the page pool page and DMA sync offset when the RX
> buffer is allocated, and syncing the received packet range for CPU access
> before handing the RX buffer to the stack.
>
> Fixes: 730ff06d3f5c ("net: mana: Use page pool fragments for RX buffers instead of full pages to improve memory efficiency.")
> Cc: stable@vger.kernel.org
> Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
> Signed-off-by: Dexuan Cui <decui@microsoft.com>
> Link: https://patch.msgid.link/20260702041237.617719-3-decui@microsoft.com
> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
> Signed-off-by: Sasha Levin <sashal@kernel.org>
> ---
> drivers/net/ethernet/microsoft/mana/mana_en.c | 40 +++++++++++++++----
> include/net/mana/mana.h | 8 ++++
> 2 files changed, 41 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
> index cbeb04ee727275..effee6c56c919d 100644
> --- a/drivers/net/ethernet/microsoft/mana/mana_en.c
> +++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
> @@ -2036,12 +2036,16 @@ static void mana_rx_skb(void *buf_va, bool from_pool,
> }
>
> static void *mana_get_rxfrag(struct mana_rxq *rxq, struct device *dev,
> - dma_addr_t *da, bool *from_pool)
> + dma_addr_t *da, bool *from_pool,
> + struct page **pp_page, u32 *dma_sync_offset)
> {
> struct page *page;
> u32 offset;
> void *va;
> +
> *from_pool = false;
> + *pp_page = NULL;
> + *dma_sync_offset = 0;
>
> /* Don't use fragments for jumbo frames or XDP where it's 1 fragment
> * per page.
> @@ -2079,31 +2083,47 @@ static void *mana_get_rxfrag(struct mana_rxq *rxq, struct device *dev,
> va = page_to_virt(page) + offset;
> *da = page_pool_get_dma_addr(page) + offset + rxq->headroom;
> *from_pool = true;
> + *pp_page = page;
> + *dma_sync_offset = offset + rxq->headroom;
>
> return va;
> }
>
> /* Allocate frag for rx buffer, and save the old buf */
> static void mana_refill_rx_oob(struct device *dev, struct mana_rxq *rxq,
> - struct mana_recv_buf_oob *rxoob, void **old_buf,
> - bool *old_fp)
> + struct mana_recv_buf_oob *rxoob, u32 pktlen,
> + void **old_buf, bool *old_fp)
> {
> + struct page *pp_page;
> + u32 dma_sync_offset;
> bool from_pool;
> dma_addr_t da;
> void *va;
>
> - va = mana_get_rxfrag(rxq, dev, &da, &from_pool);
> + va = mana_get_rxfrag(rxq, dev, &da, &from_pool, &pp_page,
> + &dma_sync_offset);
> if (!va)
> return;
> - if (!rxoob->from_pool || rxq->frag_count == 1)
> + if (!rxoob->from_pool || rxq->frag_count == 1) {
> dma_unmap_single(dev, rxoob->sgl[0].address, rxq->datasize,
> DMA_FROM_DEVICE);
> + } else {
> + /* The page pool maps the whole page and only syncs for device
> + * automatically (PP_FLAG_DMA_SYNC_DEV). Sync the received bytes
> + * for the CPU before they are read: this is required if DMA
> + * is incoherent or bounce buffers are used.
> + */
> + page_pool_dma_sync_for_cpu(rxq->page_pool, rxoob->pp_page,
> + rxoob->dma_sync_offset, pktlen);
> + }
> *old_buf = rxoob->buf_va;
> *old_fp = rxoob->from_pool;
>
> rxoob->buf_va = va;
> rxoob->sgl[0].address = da;
> rxoob->from_pool = from_pool;
> + rxoob->pp_page = pp_page;
> + rxoob->dma_sync_offset = dma_sync_offset;
> }
>
> static void mana_process_rx_cqe(struct mana_rxq *rxq, struct mana_cq *cq,
> @@ -2172,7 +2192,8 @@ static void mana_process_rx_cqe(struct mana_rxq *rxq, struct mana_cq *cq,
> /* Reuse the RX buffer since rxbuf_oob is unchanged. */
> } else {
>
> - mana_refill_rx_oob(dev, rxq, rxbuf_oob, &old_buf, &old_fp);
> + mana_refill_rx_oob(dev, rxq, rxbuf_oob, pktlen,
> + &old_buf, &old_fp);
>
> /* Unsuccessful refill will have old_buf == NULL.
> * In this case, mana_rx_skb() will drop the packet.
> @@ -2548,6 +2569,8 @@ static int mana_fill_rx_oob(struct mana_recv_buf_oob *rx_oob, u32 mem_key,
> struct mana_rxq *rxq, struct device *dev)
> {
> struct mana_port_context *mpc = netdev_priv(rxq->ndev);
> + struct page *pp_page = NULL;
> + u32 dma_sync_offset = 0;
> bool from_pool = false;
> dma_addr_t da;
> void *va;
> @@ -2555,13 +2578,16 @@ static int mana_fill_rx_oob(struct mana_recv_buf_oob *rx_oob, u32 mem_key,
> if (mpc->rxbufs_pre)
> va = mana_get_rxbuf_pre(rxq, &da);
> else
> - va = mana_get_rxfrag(rxq, dev, &da, &from_pool);
> + va = mana_get_rxfrag(rxq, dev, &da, &from_pool, &pp_page,
> + &dma_sync_offset);
>
> if (!va)
> return -ENOMEM;
>
> rx_oob->buf_va = va;
> rx_oob->from_pool = from_pool;
> + rx_oob->pp_page = pp_page;
> + rx_oob->dma_sync_offset = dma_sync_offset;
>
> rx_oob->sgl[0].address = da;
> rx_oob->sgl[0].size = rxq->datasize;
> diff --git a/include/net/mana/mana.h b/include/net/mana/mana.h
> index e199f1d44c8e30..a134b123527971 100644
> --- a/include/net/mana/mana.h
> +++ b/include/net/mana/mana.h
> @@ -302,6 +302,14 @@ struct mana_recv_buf_oob {
>
> void *buf_va;
> bool from_pool; /* allocated from a page pool */
> + /* head page of the page_pool fragment; valid only when
> + * from_pool && frag_count > 1.
> + */
> + struct page *pp_page;
> + /* Fragment offset plus rxq->headroom, passed to
> + * page_pool_dma_sync_for_cpu().
> + */
> + u32 dma_sync_offset;
>
> /* SGL of the buffer going to be sent as part of the work request. */
> u32 num_sge;
> --
> 2.53.0
>
>
Does not apply :(
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 6.18.y 1/2] net: mana: remove double CQ cleanup in mana_create_rxq error path
@ 2026-10-06 13:25 Hamza Mahfooz
2026-10-06 13:25 ` [PATCH 6.18.y 2/2] net: mana: Sync page pool RX frags for CPU Hamza Mahfooz
0 siblings, 1 reply; 7+ messages in thread
From: Hamza Mahfooz @ 2026-10-06 13:25 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, Sasha Levin, Dipayaan Roy, Haiyang Zhang,
Aditya Garg, Simon Horman, Paolo Abeni, Hamza Mahfooz
From: Dipayaan Roy <dipayanroy@linux.microsoft.com>
[ Upstream commit 3985c9a56da49af8b2e45cb1fa55c03c89b1d471 ]
In mana_create_rxq(), the error cleanup path calls mana_destroy_rxq()
followed by mana_deinit_cq(). This is incorrect for two reasons:
1. mana_destroy_rxq() already calls mana_deinit_cq() internally,
so the CQ's GDMA queue is destroyed twice.
2. mana_destroy_rxq() frees the rxq via kfree(rxq) before returning.
The subsequent mana_deinit_cq(apc, cq) then operates on freed memory
since cq points to &rxq->rx_cq, which is embedded in the
already-freed rxq structure — a use-after-free.
Remove the redundant mana_deinit_cq() call from the error path since
mana_destroy_rxq() already handles CQ cleanup. mana_deinit_cq() is
itself safe for an uninitialized CQ as it checks for a NULL gdma_cq
before proceeding.
Fixes: ca9c54d2d6a5 ("net: mana: Add a driver for Microsoft Azure Network Adapter (MANA)")
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Dipayaan Roy <dipayanroy@linux.microsoft.com>
Reviewed-by: Aditya Garg <gargaditya@linux.microsoft.com>
Link: https://patch.msgid.link/20260430035935.1859220-4-dipayanroy@linux.microsoft.com
Reviewed-by: Simon Horman <horms@kernel.org>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Hamza Mahfooz <hamzamahfooz@linux.microsoft.com>
---
drivers/net/ethernet/microsoft/mana/mana_en.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index 304815a61cf4..089bbe38feb9 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -3025,9 +3025,6 @@ static struct mana_rxq *mana_create_rxq(struct mana_port_context *apc,
mana_destroy_rxq(apc, rxq, false);
- if (cq)
- mana_deinit_cq(apc, cq);
-
return NULL;
}
--
2.56.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH 6.18.y 2/2] net: mana: Sync page pool RX frags for CPU
2026-10-06 13:25 [PATCH 6.18.y 1/2] net: mana: remove double CQ cleanup in mana_create_rxq error path Hamza Mahfooz
@ 2026-10-06 13:25 ` Hamza Mahfooz
2026-10-07 6:34 ` Greg Kroah-Hartman
2026-10-07 21:03 ` Sasha Levin
0 siblings, 2 replies; 7+ messages in thread
From: Hamza Mahfooz @ 2026-10-06 13:25 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, Sasha Levin, Dexuan Cui, Haiyang Zhang,
Paolo Abeni, Hamza Mahfooz
From: Dexuan Cui <decui@microsoft.com>
[ Upstream commit c72a0f09c57f92113df69f9b902d11c9e4b132f5 ]
MANA allocates RX buffers from page pool fragments when frag_count is
greater than 1. In that case the buffers remain DMA mapped by page pool
and the RX completion path does not call dma_unmap_single(). As a result,
the implicit sync-for-CPU normally performed by dma_unmap_single() is
missing before the packet data is passed to the networking stack.
This breaks RX on configurations which require explicit DMA syncing, for
example when booted with swiotlb=force.
Fix this by recording the page pool page and DMA sync offset when the RX
buffer is allocated, and syncing the received packet range for CPU access
before handing the RX buffer to the stack.
Fixes: 730ff06d3f5c ("net: mana: Use page pool fragments for RX buffers instead of full pages to improve memory efficiency.")
Cc: stable@vger.kernel.org
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Dexuan Cui <decui@microsoft.com>
Link: https://patch.msgid.link/20260702041237.617719-3-decui@microsoft.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
[ hmahfooz: resolve conflict with the earlier backport of 55d20f50a221
by passing pktlen to mana_refill_rx_oob() from
mana_process_one_rx_pkt() ]
Signed-off-by: Hamza Mahfooz <hamzamahfooz@linux.microsoft.com>
---
drivers/net/ethernet/microsoft/mana/mana_en.c | 40 +++++++++++++++----
include/net/mana/mana.h | 8 ++++
2 files changed, 41 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index 089bbe38feb9..be41e970b5ef 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -2072,12 +2072,16 @@ static void mana_rx_skb(void *buf_va, bool from_pool,
}
static void *mana_get_rxfrag(struct mana_rxq *rxq, struct device *dev,
- dma_addr_t *da, bool *from_pool)
+ dma_addr_t *da, bool *from_pool,
+ struct page **pp_page, u32 *dma_sync_offset)
{
struct page *page;
u32 offset;
void *va;
+
*from_pool = false;
+ *pp_page = NULL;
+ *dma_sync_offset = 0;
/* Don't use fragments for jumbo frames or XDP where it's 1 fragment
* per page.
@@ -2115,31 +2119,47 @@ static void *mana_get_rxfrag(struct mana_rxq *rxq, struct device *dev,
va = page_to_virt(page) + offset;
*da = page_pool_get_dma_addr(page) + offset + rxq->headroom;
*from_pool = true;
+ *pp_page = page;
+ *dma_sync_offset = offset + rxq->headroom;
return va;
}
/* Allocate frag for rx buffer, and save the old buf */
static void mana_refill_rx_oob(struct device *dev, struct mana_rxq *rxq,
- struct mana_recv_buf_oob *rxoob, void **old_buf,
- bool *old_fp)
+ struct mana_recv_buf_oob *rxoob, u32 pktlen,
+ void **old_buf, bool *old_fp)
{
+ struct page *pp_page;
+ u32 dma_sync_offset;
bool from_pool;
dma_addr_t da;
void *va;
- va = mana_get_rxfrag(rxq, dev, &da, &from_pool);
+ va = mana_get_rxfrag(rxq, dev, &da, &from_pool, &pp_page,
+ &dma_sync_offset);
if (!va)
return;
- if (!rxoob->from_pool || rxq->frag_count == 1)
+ if (!rxoob->from_pool || rxq->frag_count == 1) {
dma_unmap_single(dev, rxoob->sgl[0].address, rxq->datasize,
DMA_FROM_DEVICE);
+ } else {
+ /* The page pool maps the whole page and only syncs for device
+ * automatically (PP_FLAG_DMA_SYNC_DEV). Sync the received bytes
+ * for the CPU before they are read: this is required if DMA
+ * is incoherent or bounce buffers are used.
+ */
+ page_pool_dma_sync_for_cpu(rxq->page_pool, rxoob->pp_page,
+ rxoob->dma_sync_offset, pktlen);
+ }
*old_buf = rxoob->buf_va;
*old_fp = rxoob->from_pool;
rxoob->buf_va = va;
rxoob->sgl[0].address = da;
rxoob->from_pool = from_pool;
+ rxoob->pp_page = pp_page;
+ rxoob->dma_sync_offset = dma_sync_offset;
}
static void mana_process_one_rx_pkt(struct device *dev, struct mana_rxq *rxq,
@@ -2165,7 +2185,8 @@ static void mana_process_one_rx_pkt(struct device *dev, struct mana_rxq *rxq,
/* Reuse the RX buffer since rxbuf_oob is unchanged. */
} else {
- mana_refill_rx_oob(dev, rxq, rxbuf_oob, &old_buf, &old_fp);
+ mana_refill_rx_oob(dev, rxq, rxbuf_oob, pktlen,
+ &old_buf, &old_fp);
/* Unsuccessful refill will have old_buf == NULL.
* In this case, mana_rx_skb() will drop the packet.
@@ -2777,6 +2798,8 @@ static int mana_fill_rx_oob(struct mana_recv_buf_oob *rx_oob, u32 mem_key,
struct mana_rxq *rxq, struct device *dev)
{
struct mana_port_context *mpc = netdev_priv(rxq->ndev);
+ struct page *pp_page = NULL;
+ u32 dma_sync_offset = 0;
bool from_pool = false;
dma_addr_t da;
void *va;
@@ -2784,13 +2807,16 @@ static int mana_fill_rx_oob(struct mana_recv_buf_oob *rx_oob, u32 mem_key,
if (mpc->rxbufs_pre)
va = mana_get_rxbuf_pre(rxq, &da);
else
- va = mana_get_rxfrag(rxq, dev, &da, &from_pool);
+ va = mana_get_rxfrag(rxq, dev, &da, &from_pool, &pp_page,
+ &dma_sync_offset);
if (!va)
return -ENOMEM;
rx_oob->buf_va = va;
rx_oob->from_pool = from_pool;
+ rx_oob->pp_page = pp_page;
+ rx_oob->dma_sync_offset = dma_sync_offset;
rx_oob->sgl[0].address = da;
rx_oob->sgl[0].size = rxq->datasize;
diff --git a/include/net/mana/mana.h b/include/net/mana/mana.h
index 7663bcd7ec19..f8120ae6d037 100644
--- a/include/net/mana/mana.h
+++ b/include/net/mana/mana.h
@@ -348,6 +348,14 @@ struct mana_recv_buf_oob {
void *buf_va;
bool from_pool; /* allocated from a page pool */
+ /* head page of the page_pool fragment; valid only when
+ * from_pool && frag_count > 1.
+ */
+ struct page *pp_page;
+ /* Fragment offset plus rxq->headroom, passed to
+ * page_pool_dma_sync_for_cpu().
+ */
+ u32 dma_sync_offset;
/* SGL of the buffer going to be sent as part of the work request. */
u32 num_sge;
--
2.56.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH 6.18.y 2/2] net: mana: Sync page pool RX frags for CPU
2026-10-06 13:25 ` [PATCH 6.18.y 2/2] net: mana: Sync page pool RX frags for CPU Hamza Mahfooz
@ 2026-10-07 6:34 ` Greg Kroah-Hartman
2026-10-07 21:03 ` Sasha Levin
1 sibling, 0 replies; 7+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-07 6:34 UTC (permalink / raw)
To: Hamza Mahfooz; +Cc: stable, Sasha Levin, Dexuan Cui, Haiyang Zhang, Paolo Abeni
On Tue, Oct 06, 2026 at 09:25:23AM -0400, Hamza Mahfooz wrote:
> From: Dexuan Cui <decui@microsoft.com>
>
> [ Upstream commit c72a0f09c57f92113df69f9b902d11c9e4b132f5 ]
>
> MANA allocates RX buffers from page pool fragments when frag_count is
> greater than 1. In that case the buffers remain DMA mapped by page pool
> and the RX completion path does not call dma_unmap_single(). As a result,
> the implicit sync-for-CPU normally performed by dma_unmap_single() is
> missing before the packet data is passed to the networking stack.
>
> This breaks RX on configurations which require explicit DMA syncing, for
> example when booted with swiotlb=force.
>
> Fix this by recording the page pool page and DMA sync offset when the RX
> buffer is allocated, and syncing the received packet range for CPU access
> before handing the RX buffer to the stack.
>
> Fixes: 730ff06d3f5c ("net: mana: Use page pool fragments for RX buffers instead of full pages to improve memory efficiency.")
> Cc: stable@vger.kernel.org
> Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
> Signed-off-by: Dexuan Cui <decui@microsoft.com>
> Link: https://patch.msgid.link/20260702041237.617719-3-decui@microsoft.com
> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
> [ hmahfooz: resolve conflict with the earlier backport of 55d20f50a221
> by passing pktlen to mana_refill_rx_oob() from
> mana_process_one_rx_pkt() ]
> Signed-off-by: Hamza Mahfooz <hamzamahfooz@linux.microsoft.com>
> ---
> drivers/net/ethernet/microsoft/mana/mana_en.c | 40 +++++++++++++++----
> include/net/mana/mana.h | 8 ++++
> 2 files changed, 41 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
> index 089bbe38feb9..be41e970b5ef 100644
> --- a/drivers/net/ethernet/microsoft/mana/mana_en.c
> +++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
> @@ -2072,12 +2072,16 @@ static void mana_rx_skb(void *buf_va, bool from_pool,
> }
>
> static void *mana_get_rxfrag(struct mana_rxq *rxq, struct device *dev,
> - dma_addr_t *da, bool *from_pool)
> + dma_addr_t *da, bool *from_pool,
> + struct page **pp_page, u32 *dma_sync_offset)
> {
> struct page *page;
> u32 offset;
> void *va;
> +
> *from_pool = false;
> + *pp_page = NULL;
> + *dma_sync_offset = 0;
>
> /* Don't use fragments for jumbo frames or XDP where it's 1 fragment
> * per page.
> @@ -2115,31 +2119,47 @@ static void *mana_get_rxfrag(struct mana_rxq *rxq, struct device *dev,
> va = page_to_virt(page) + offset;
> *da = page_pool_get_dma_addr(page) + offset + rxq->headroom;
> *from_pool = true;
> + *pp_page = page;
> + *dma_sync_offset = offset + rxq->headroom;
>
> return va;
> }
>
> /* Allocate frag for rx buffer, and save the old buf */
> static void mana_refill_rx_oob(struct device *dev, struct mana_rxq *rxq,
> - struct mana_recv_buf_oob *rxoob, void **old_buf,
> - bool *old_fp)
> + struct mana_recv_buf_oob *rxoob, u32 pktlen,
> + void **old_buf, bool *old_fp)
> {
> + struct page *pp_page;
> + u32 dma_sync_offset;
> bool from_pool;
> dma_addr_t da;
> void *va;
>
> - va = mana_get_rxfrag(rxq, dev, &da, &from_pool);
> + va = mana_get_rxfrag(rxq, dev, &da, &from_pool, &pp_page,
> + &dma_sync_offset);
> if (!va)
> return;
> - if (!rxoob->from_pool || rxq->frag_count == 1)
> + if (!rxoob->from_pool || rxq->frag_count == 1) {
> dma_unmap_single(dev, rxoob->sgl[0].address, rxq->datasize,
> DMA_FROM_DEVICE);
> + } else {
> + /* The page pool maps the whole page and only syncs for device
> + * automatically (PP_FLAG_DMA_SYNC_DEV). Sync the received bytes
> + * for the CPU before they are read: this is required if DMA
> + * is incoherent or bounce buffers are used.
> + */
> + page_pool_dma_sync_for_cpu(rxq->page_pool, rxoob->pp_page,
> + rxoob->dma_sync_offset, pktlen);
> + }
> *old_buf = rxoob->buf_va;
> *old_fp = rxoob->from_pool;
>
> rxoob->buf_va = va;
> rxoob->sgl[0].address = da;
> rxoob->from_pool = from_pool;
> + rxoob->pp_page = pp_page;
> + rxoob->dma_sync_offset = dma_sync_offset;
> }
>
> static void mana_process_one_rx_pkt(struct device *dev, struct mana_rxq *rxq,
> @@ -2165,7 +2185,8 @@ static void mana_process_one_rx_pkt(struct device *dev, struct mana_rxq *rxq,
>
> /* Reuse the RX buffer since rxbuf_oob is unchanged. */
> } else {
> - mana_refill_rx_oob(dev, rxq, rxbuf_oob, &old_buf, &old_fp);
> + mana_refill_rx_oob(dev, rxq, rxbuf_oob, pktlen,
> + &old_buf, &old_fp);
>
> /* Unsuccessful refill will have old_buf == NULL.
> * In this case, mana_rx_skb() will drop the packet.
> @@ -2777,6 +2798,8 @@ static int mana_fill_rx_oob(struct mana_recv_buf_oob *rx_oob, u32 mem_key,
> struct mana_rxq *rxq, struct device *dev)
> {
> struct mana_port_context *mpc = netdev_priv(rxq->ndev);
> + struct page *pp_page = NULL;
> + u32 dma_sync_offset = 0;
> bool from_pool = false;
> dma_addr_t da;
> void *va;
> @@ -2784,13 +2807,16 @@ static int mana_fill_rx_oob(struct mana_recv_buf_oob *rx_oob, u32 mem_key,
> if (mpc->rxbufs_pre)
> va = mana_get_rxbuf_pre(rxq, &da);
> else
> - va = mana_get_rxfrag(rxq, dev, &da, &from_pool);
> + va = mana_get_rxfrag(rxq, dev, &da, &from_pool, &pp_page,
> + &dma_sync_offset);
>
> if (!va)
> return -ENOMEM;
>
> rx_oob->buf_va = va;
> rx_oob->from_pool = from_pool;
> + rx_oob->pp_page = pp_page;
> + rx_oob->dma_sync_offset = dma_sync_offset;
>
> rx_oob->sgl[0].address = da;
> rx_oob->sgl[0].size = rxq->datasize;
> diff --git a/include/net/mana/mana.h b/include/net/mana/mana.h
> index 7663bcd7ec19..f8120ae6d037 100644
> --- a/include/net/mana/mana.h
> +++ b/include/net/mana/mana.h
> @@ -348,6 +348,14 @@ struct mana_recv_buf_oob {
>
> void *buf_va;
> bool from_pool; /* allocated from a page pool */
> + /* head page of the page_pool fragment; valid only when
> + * from_pool && frag_count > 1.
> + */
> + struct page *pp_page;
> + /* Fragment offset plus rxq->headroom, passed to
> + * page_pool_dma_sync_for_cpu().
> + */
> + u32 dma_sync_offset;
>
> /* SGL of the buffer going to be sent as part of the work request. */
> u32 num_sge;
> --
Does not apply to the tree :(
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: [PATCH 6.18.y 2/2] net: mana: Sync page pool RX frags for CPU
2026-10-06 13:25 ` [PATCH 6.18.y 2/2] net: mana: Sync page pool RX frags for CPU Hamza Mahfooz
2026-10-07 6:34 ` Greg Kroah-Hartman
@ 2026-10-07 21:03 ` Sasha Levin
1 sibling, 0 replies; 7+ messages in thread
From: Sasha Levin @ 2026-10-07 21:03 UTC (permalink / raw)
To: stable
Cc: Sasha Levin, Greg Kroah-Hartman, Dexuan Cui, Haiyang Zhang,
Paolo Abeni, Hamza Mahfooz
> [ hmahfooz: resolve conflict with the earlier backport of 55d20f50a221
> by passing pktlen to mana_refill_rx_oob() from
> mana_process_one_rx_pkt() ]
Queued for 6.18, thanks.
Passed pktlen to mana_refill_rx_oob() from mana_process_rx_cqe().
--
Thanks,
Sasha
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-10-07 21:03 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-20 15:50 FAILED: patch "[PATCH] net: mana: Sync page pool RX frags for CPU" failed to apply to 6.18-stable tree gregkh
2026-07-28 12:11 ` [PATCH 6.18.y 1/2] net: mana: Validate the packet length reported by the NIC Sasha Levin
2026-07-28 12:11 ` [PATCH 6.18.y 2/2] net: mana: Sync page pool RX frags for CPU Sasha Levin
2026-07-30 12:22 ` Greg KH
-- strict thread matches above, loose matches on Subject: below --
2026-10-06 13:25 [PATCH 6.18.y 1/2] net: mana: remove double CQ cleanup in mana_create_rxq error path Hamza Mahfooz
2026-10-06 13:25 ` [PATCH 6.18.y 2/2] net: mana: Sync page pool RX frags for CPU Hamza Mahfooz
2026-10-07 6:34 ` Greg Kroah-Hartman
2026-10-07 21:03 ` Sasha Levin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox