From: Ratheesh Kannoth <rkannoth@marvell.com>
To: <davem@davemloft.net>, <gakula@marvell.com>,
<linux-kernel@vger.kernel.org>, <netdev@vger.kernel.org>,
<sgoutham@marvell.com>
Cc: <andrew+netdev@lunn.ch>, <edumazet@google.com>, <kuba@kernel.org>,
<pabeni@redhat.com>, Ratheesh Kannoth <rkannoth@marvell.com>
Subject: [PATCH v3 net] octeontx2-af: allocate qmem from page allocator to avoid CMA
Date: Thu, 27 Aug 2026 12:35:53 +0530 [thread overview]
Message-ID: <20260827070554.3919891-1-rkannoth@marvell.com> (raw)
qmem_alloc() uses dma_alloc_attrs() with DMA_ATTR_FORCE_CONTIGUOUS for
physically contiguous DMA memory (e.g. CN10K LMTST regions spanning page
boundaries). With CMA enabled, those allocations are drawn from the CMA
pool. qmem backs NIX/NPA queue contexts, admin queues, and LMTST regions,
so total usage scales with enabled interfaces and is hard to provision in
CMA.
Add otx2_dma_alloc_coherent() and otx2_dma_free_coherent() helpers that
allocate compound pages from the buddy allocator via __get_free_pages()
with __GFP_COMP, __GFP_ZERO, and __GFP_RECLAIM (qmem_alloc() runs in
GFP_KERNEL context), select DMA-reachable memory with dma_coherent_ok()
(retrying with GFP_DMA32), and map the contiguous physical range for DMA
through dma_map_phys() and dma_unmap_phys() with DMA_ATTR_REQUIRE_COHERENT
so SMMU/IOMMU page table entries are installed on IOMMU-backed platforms.
Switch qmem_alloc() and qmem_free() to these helpers instead of
dma_alloc_attrs()/dma_free_attrs() with DMA_ATTR_FORCE_CONTIGUOUS.
Allocations requiring more than MAX_PAGE_ORDER pages are still rejected,
as the buddy allocator cannot serve them without CMA.
Fixes: 73d33dbc0723 ("octeontx2-af: Use DMA_ATTR_FORCE_CONTIGUOUS attribute in DMA alloc")
Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
---
v2 -> v3: Addressed sashiko comments
https://sashiko.dev/#/patchset/20260825045616.3723078-1-rkannoth%40marvell.com
---
.../ethernet/marvell/octeontx2/af/common.h | 81 +++++++++++++++++--
1 file changed, 75 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/common.h b/drivers/net/ethernet/marvell/octeontx2/af/common.h
index 779413a383b7..c6a6aae436a3 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/common.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/common.h
@@ -7,6 +7,10 @@
#ifndef COMMON_H
#define COMMON_H
+#include <linux/dma-mapping.h>
+#include <linux/gfp.h>
+#include <linux/mm.h>
+
#include "rvu_struct.h"
#define OTX2_ALIGN 128 /* Align to cacheline */
@@ -44,6 +48,72 @@ struct qmem {
u32 qsize;
};
+/* Buddy-backed coherent DMA alloc (Option 3): pages from __get_free_pages(),
+ * DMA-reachable RAM via dma_coherent_ok(), and bus/SMMU mappings via
+ * dma_map_phys() -> iommu_dma_map_phys() -> iommu_map() on SMMU systems.
+ */
+#define OTX2_DMA_COHERENT_ATTRS DMA_ATTR_REQUIRE_COHERENT
+
+static inline void *otx2_dma_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t gfp)
+{
+ dma_addr_t dma_addr;
+ unsigned int order;
+ phys_addr_t paddr;
+ void *vaddr;
+ gfp_t alloc_gfp;
+
+ if (!dev || !dma_handle || !size)
+ return NULL;
+
+ size = PAGE_ALIGN(size);
+ order = get_order(size);
+ if (order > MAX_PAGE_ORDER)
+ return NULL;
+
+ alloc_gfp = (gfp & ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM)) |
+ __GFP_ZERO | __GFP_COMP | __GFP_RECLAIM;
+
+ vaddr = (void *)__get_free_pages(alloc_gfp, order);
+ while (vaddr &&
+ !dma_coherent_ok(dev, page_to_phys(virt_to_page(vaddr)), size)) {
+ free_pages((unsigned long)vaddr, order);
+ if (alloc_gfp & GFP_DMA32)
+ return NULL;
+ alloc_gfp |= GFP_DMA32;
+ vaddr = (void *)__get_free_pages(alloc_gfp, order);
+ }
+ if (!vaddr)
+ return NULL;
+
+ paddr = page_to_phys(virt_to_page(vaddr));
+ dma_addr = dma_map_phys(dev, paddr, size, DMA_BIDIRECTIONAL,
+ OTX2_DMA_COHERENT_ATTRS);
+ if (dma_mapping_error(dev, dma_addr)) {
+ free_pages((unsigned long)vaddr, order);
+ return NULL;
+ }
+
+ *dma_handle = dma_addr;
+ return vaddr;
+}
+
+static inline void otx2_dma_free_coherent(struct device *dev, size_t size,
+ void *vaddr, dma_addr_t dma_handle)
+{
+ unsigned int order;
+
+ if (!dev || !vaddr)
+ return;
+
+ size = PAGE_ALIGN(size);
+ order = get_order(size);
+
+ dma_unmap_phys(dev, dma_handle, size, DMA_BIDIRECTIONAL,
+ OTX2_DMA_COHERENT_ATTRS);
+ free_pages((unsigned long)vaddr, order);
+}
+
static inline int qmem_alloc(struct device *dev, struct qmem **q,
int qsize, int entry_sz)
{
@@ -60,8 +130,8 @@ static inline int qmem_alloc(struct device *dev, struct qmem **q,
qmem->entry_sz = entry_sz;
qmem->alloc_sz = (qsize * entry_sz) + OTX2_ALIGN;
- qmem->base = dma_alloc_attrs(dev, qmem->alloc_sz, &qmem->iova,
- GFP_KERNEL, DMA_ATTR_FORCE_CONTIGUOUS);
+ qmem->base = otx2_dma_alloc_coherent(dev, qmem->alloc_sz, &qmem->iova,
+ GFP_KERNEL);
if (!qmem->base)
return -ENOMEM;
@@ -80,10 +150,9 @@ static inline void qmem_free(struct device *dev, struct qmem *qmem)
return;
if (qmem->base)
- dma_free_attrs(dev, qmem->alloc_sz,
- qmem->base - qmem->align,
- qmem->iova - qmem->align,
- DMA_ATTR_FORCE_CONTIGUOUS);
+ otx2_dma_free_coherent(dev, qmem->alloc_sz,
+ qmem->base - qmem->align,
+ qmem->iova - qmem->align);
devm_kfree(dev, qmem);
}
--
2.43.0
next reply other threads:[~2026-08-27 7:06 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-27 7:05 Ratheesh Kannoth [this message]
2026-08-31 2:38 ` [PATCH v3 net] octeontx2-af: allocate qmem from page allocator to avoid CMA Ratheesh Kannoth
2026-09-03 3:18 ` kernel test robot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260827070554.3919891-1-rkannoth@marvell.com \
--to=rkannoth@marvell.com \
--cc=andrew+netdev@lunn.ch \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=gakula@marvell.com \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=sgoutham@marvell.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.