* [PATCH v2 net] octeontx2-af: allocate qmem from page allocator to avoid CMA
@ 2026-08-25 4:56 Ratheesh Kannoth
2026-08-27 5:53 ` Ratheesh Kannoth
0 siblings, 1 reply; 2+ messages in thread
From: Ratheesh Kannoth @ 2026-08-25 4:56 UTC (permalink / raw)
To: davem, gakula, linux-kernel, netdev, sgoutham
Cc: andrew+netdev, edumazet, kuba, pabeni, Ratheesh Kannoth
qmem_alloc() uses dma_alloc_attrs() with DMA_ATTR_FORCE_CONTIGUOUS so
CN10K LMTST regions get physically contiguous DMA memory across page
boundaries. On platforms with CMA enabled, that attribute causes
allocations to be drawn from the CMA pool. qmem is used for NIX and
NPA queue contexts, admin queues, and LMTST regions, so the footprint
grows with the number of enabled interfaces and is difficult to
provision in CMA.
Add otx2_dma_alloc_coherent() and otx2_dma_free_coherent() helpers
that allocate compound pages with __get_free_pages(__GFP_COMP),
DMA-map them with dma_map_page(), and retry with GFP_DMA32 when the
physical address exceeds the device DMA mask. Switch qmem_alloc()
and qmem_free() to use them instead of
dma_alloc_attrs()/dma_free_attrs().
Fixes: 73d33dbc0723 ("octeontx2-af: Use DMA_ATTR_FORCE_CONTIGUOUS attribute in DMA alloc")
Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
---
.../ethernet/marvell/octeontx2/af/common.h | 79 +++++++++++++++++--
1 file changed, 73 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..30dd882a0149 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,70 @@ struct qmem {
u32 qsize;
};
+/* dma_alloc_coherent()/dma_free_coherent() equivalents backed by
+ * __get_free_pages(). The region is mapped for DMA with
+ * dma_map_page()/dma_unmap_page().
+ */
+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;
+ struct page *page;
+ void *vaddr;
+ u64 mask;
+
+ if (!dev || !dma_handle || !size)
+ return NULL;
+
+ size = PAGE_ALIGN(size);
+ order = get_order(size);
+ if (order > MAX_PAGE_ORDER)
+ return NULL;
+
+ gfp |= __GFP_COMP | __GFP_ZERO | __GFP_RECLAIM;
+ vaddr = (void *)__get_free_pages(gfp, order);
+ if (!vaddr)
+ return NULL;
+
+ paddr = virt_to_phys((void *)vaddr);
+ mask = dma_get_required_mask(dev);
+ if (paddr + size > mask) {
+ free_pages((unsigned long)vaddr, order);
+ gfp |= GFP_DMA32;
+
+ vaddr = (void *)__get_free_pages(gfp, order);
+ if (!vaddr)
+ return NULL;
+ }
+
+ page = virt_to_page(vaddr);
+ dma_addr = dma_map_page(dev, page, 0, size, DMA_BIDIRECTIONAL);
+ 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_page(dev, dma_handle, size, DMA_BIDIRECTIONAL);
+ free_pages((unsigned long)vaddr, order);
+}
+
static inline int qmem_alloc(struct device *dev, struct qmem **q,
int qsize, int entry_sz)
{
@@ -60,8 +128,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 +148,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
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH v2 net] octeontx2-af: allocate qmem from page allocator to avoid CMA
2026-08-25 4:56 [PATCH v2 net] octeontx2-af: allocate qmem from page allocator to avoid CMA Ratheesh Kannoth
@ 2026-08-27 5:53 ` Ratheesh Kannoth
0 siblings, 0 replies; 2+ messages in thread
From: Ratheesh Kannoth @ 2026-08-27 5:53 UTC (permalink / raw)
To: davem, gakula, linux-kernel, netdev, sgoutham
Cc: andrew+netdev, edumazet, kuba, pabeni
On 2026-08-25 at 10:26:16, Ratheesh Kannoth (rkannoth@marvell.com) wrote:
> qmem_alloc() uses dma_alloc_attrs() with DMA_ATTR_FORCE_CONTIGUOUS so
> CN10K LMTST regions get physically contiguous DMA memory across page
> boundaries. On platforms with CMA enabled, that attribute causes
> allocations to be drawn from the CMA pool. qmem is used for NIX and
> NPA queue contexts, admin queues, and LMTST regions, so the footprint
> grows with the number of enabled interfaces and is difficult to
> provision in CMA.
>
> Add otx2_dma_alloc_coherent() and otx2_dma_free_coherent() helpers
> that allocate compound pages with __get_free_pages(__GFP_COMP),
> DMA-map them with dma_map_page(), and retry with GFP_DMA32 when the
> physical address exceeds the device DMA mask. Switch qmem_alloc()
> and qmem_free() to use them instead of
> dma_alloc_attrs()/dma_free_attrs().
>
> Fixes: 73d33dbc0723 ("octeontx2-af: Use DMA_ATTR_FORCE_CONTIGUOUS attribute in DMA alloc")
> Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
Will address sashiko comments in v3
pw-bot: changes-requested
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-08-27 5:54 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-25 4:56 [PATCH v2 net] octeontx2-af: allocate qmem from page allocator to avoid CMA Ratheesh Kannoth
2026-08-27 5:53 ` Ratheesh Kannoth
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox