From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 123E33AFD17 for ; Tue, 28 Jul 2026 12:11:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785240675; cv=none; b=H1ahirVTeYZ71PrT0eTk3k+PchyyXUcAez2q2Ex9r8aeZY6PT3bqomLHJPPn8Hv94A8k1NwCIi8awH6YXicjhyS7J/q5NGsQghR8SrW1pwd7yGGWsSaRrAxrLTTfQFTVSn+I73CrONH67TKm+uyPkQKKBjmYBtv8z/LSLwvyUnI= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785240675; c=relaxed/simple; bh=DIbc+CabhD95gcBOuOIIeCx8wJXLD/vCHFv7LtrPlnM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=VkjYy3hKqfP3y3NvotENtaoTyKNGwqjzjHyZJ6cC8DFLRVC9m6fhUtM+T98WM2UlOZbQKvOLHPfXcIRQBkrON/3Gz1J3qNNNq3tW6BvcPyv7m1d/kgSFGs2UIwPsIqz5KwtYRMBTU5vMY8Jbb+cDdWeHnczSCEpEnyf1Rsl0v6M= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=PXFYzls3; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="PXFYzls3" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 57D821F00A3D; Tue, 28 Jul 2026 12:11:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1785240674; bh=Y4Yj3zmcI1CRFGg7htHtp9s9uaCtrbEmGtqYC6dAHBw=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=PXFYzls3n/4z6dw28KUj+vN4ud/QVjRP3QDIFCZgwzqGxP4mf0KjAqLgKge88wZKw NNE2YGj15HkQBR4hjqkYuuZZPPh/74VZHQ3N6++KT8j9ipT3bhlunoqu13uLRS0Lmg 7s9l818erylFUpRP8NIbLFM+lWwWfD0aerZMYAngYVUwjFyDNMmBs5dQMRvRIlL7qx 94EbrQH5oIyVsiv9vnqHKGbMSOQ/bv1Zrb3irJcnvd+uFFXCcX9H/tCDGU+y8JYLBH J8403Ug6cR54VLurdazxKYYYeSy6YHOAclENoyXyX/x6yZKsu1iJwZvlnaeGSjbAVv PeytjL9L9Jb6w== From: Sasha Levin To: stable@vger.kernel.org Cc: Dexuan Cui , Haiyang Zhang , Paolo Abeni , Sasha Levin Subject: [PATCH 6.18.y 2/2] net: mana: Sync page pool RX frags for CPU Date: Tue, 28 Jul 2026 08:11:10 -0400 Message-ID: <20260728121110.3702926-2-sashal@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260728121110.3702926-1-sashal@kernel.org> References: <2026072020-cathedral-preoccupy-0b9c@gregkh> <20260728121110.3702926-1-sashal@kernel.org> Precedence: bulk X-Mailing-List: stable@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Dexuan Cui [ 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 Signed-off-by: Dexuan Cui Link: https://patch.msgid.link/20260702041237.617719-3-decui@microsoft.com Signed-off-by: Paolo Abeni Signed-off-by: Sasha Levin --- 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