From: Feng Tang <feng.tang@linux.alibaba.com>
To: Marek Szyprowski <m.szyprowski@samsung.com>,
Robin Murphy <robin.murphy@arm.com>,
Christoph Hellwig <hch@lst.de>,
iommu@lists.linux.dev, linux-kernel@vger.kernel.org
Cc: Feng Tang <feng.tang@linux.alibaba.com>
Subject: [PATCH v1] dma-contiguous: try local node first for dma_alloc_contiguous()
Date: Tue, 14 Apr 2026 17:03:10 +0800 [thread overview]
Message-ID: <20260414090310.92055-1-feng.tang@linux.alibaba.com> (raw)
There was a bug report on a multi-numa-nodes ARM server that when
IOMMU is disabled, the dma_alloc_coherent() function always returns
memory from node 0 even for devices attaching to other nodes, while
they can get local dma memory when IOMMU is on with the same API.
The reason is, when IOMMU is disabled, the dma_alloc_coherent() will
go the direct way and call dma_alloc_contiguous(). The system doesn't
have any explicit cma setting (like per-numa cma), and only has a
default 64MB cma reserved area (on node 0), where kernel will try
first to allocate memory from.
Make the dma allocation more locality friendly by trying first the
numa aware allocation alloc_pages_node() before falling back to the
reserved cma area.
One more thought is to check the node of the reserved cma area and
only call alloc_pages_nodes() when it isn't the same node that the
device attaches to.
Signed-off-by: Feng Tang <feng.tang@linux.alibaba.com>
---
kernel/dma/contiguous.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/kernel/dma/contiguous.c b/kernel/dma/contiguous.c
index c56004d314dc..0180f40f094e 100644
--- a/kernel/dma/contiguous.c
+++ b/kernel/dma/contiguous.c
@@ -371,8 +371,9 @@ static struct page *cma_alloc_aligned(struct cma *cma, size_t size, gfp_t gfp)
*/
struct page *dma_alloc_contiguous(struct device *dev, size_t size, gfp_t gfp)
{
-#ifdef CONFIG_DMA_NUMA_CMA
+#ifdef CONFIG_NUMA
int nid = dev_to_node(dev);
+ struct page *page;
#endif
/* CMA can be used only in the context which permits sleeping */
@@ -386,7 +387,6 @@ struct page *dma_alloc_contiguous(struct device *dev, size_t size, gfp_t gfp)
#ifdef CONFIG_DMA_NUMA_CMA
if (nid != NUMA_NO_NODE && !(gfp & (GFP_DMA | GFP_DMA32))) {
struct cma *cma = dma_contiguous_pernuma_area[nid];
- struct page *page;
if (cma) {
page = cma_alloc_aligned(cma, size, gfp);
@@ -402,6 +402,14 @@ struct page *dma_alloc_contiguous(struct device *dev, size_t size, gfp_t gfp)
}
}
#endif
+
+#ifdef CONFIG_NUMA
+ /* Try first to allocate memory on the same node as the device */
+ page = alloc_pages_node(nid, gfp, get_order(size));
+ if (page)
+ return page;
+#endif
+
if (!dma_contiguous_default_area)
return NULL;
--
2.39.5 (Apple Git-154)
next reply other threads:[~2026-04-14 9:03 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-14 9:03 Feng Tang [this message]
2026-04-14 12:32 ` Robin Murphy
2026-04-14 13:42 ` Feng Tang
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=20260414090310.92055-1-feng.tang@linux.alibaba.com \
--to=feng.tang@linux.alibaba.com \
--cc=hch@lst.de \
--cc=iommu@lists.linux.dev \
--cc=linux-kernel@vger.kernel.org \
--cc=m.szyprowski@samsung.com \
--cc=robin.murphy@arm.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®