* [PATCH 5.15.y 02/10] dma-direct: refactor the !coherent checks in dma_direct_alloc
2026-09-10 14:39 ` [PATCH 5.15.y 01/10] dma-direct: clean up the remapping checks in dma_direct_alloc Sasha Levin
@ 2026-09-10 14:39 ` Sasha Levin
2026-09-10 14:39 ` [PATCH 5.15.y 03/10] dma-direct: fail allocations that can't be made coherent Sasha Levin
` (7 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Sasha Levin @ 2026-09-10 14:39 UTC (permalink / raw)
To: stable; +Cc: Christoph Hellwig, Robin Murphy, Sasha Levin
From: Christoph Hellwig <hch@lst.de>
[ Upstream commit a86d10942db2e0099a369b367fe62898f95987a8 ]
Add a big central !dev_is_dma_coherent(dev) block to deal with as much
as of the uncached allocation schemes and document the schemes a bit
better.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Robin Murphy <robin.murphy@arm.com>
Stable-dep-of: 94a04ad732c9 ("dma-direct: return struct page from dma_direct_alloc_from_pool()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
kernel/dma/direct.c | 66 ++++++++++++++++++++++++++++-----------------
1 file changed, 41 insertions(+), 25 deletions(-)
diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c
index fd47717af82fd..517ca0e61a57c 100644
--- a/kernel/dma/direct.c
+++ b/kernel/dma/direct.c
@@ -204,29 +204,49 @@ void *dma_direct_alloc(struct device *dev, size_t size,
!force_dma_unencrypted(dev) && !is_swiotlb_for_alloc(dev))
return dma_direct_alloc_no_mapping(dev, size, dma_handle, gfp);
- if (!IS_ENABLED(CONFIG_ARCH_HAS_DMA_SET_UNCACHED) &&
- !IS_ENABLED(CONFIG_DMA_DIRECT_REMAP) &&
- !IS_ENABLED(CONFIG_DMA_GLOBAL_POOL) &&
- !dev_is_dma_coherent(dev) &&
- !is_swiotlb_for_alloc(dev))
- return arch_dma_alloc(dev, size, dma_handle, gfp, attrs);
+ if (!dev_is_dma_coherent(dev)) {
+ /*
+ * Fallback to the arch handler if it exists. This should
+ * eventually go away.
+ */
+ if (!IS_ENABLED(CONFIG_ARCH_HAS_DMA_SET_UNCACHED) &&
+ !IS_ENABLED(CONFIG_DMA_DIRECT_REMAP) &&
+ !IS_ENABLED(CONFIG_DMA_GLOBAL_POOL) &&
+ !is_swiotlb_for_alloc(dev))
+ return arch_dma_alloc(dev, size, dma_handle, gfp,
+ attrs);
- if (IS_ENABLED(CONFIG_DMA_GLOBAL_POOL) &&
- !dev_is_dma_coherent(dev))
- return dma_alloc_from_global_coherent(dev, size, dma_handle);
+ /*
+ * If there is a global pool, always allocate from it for
+ * non-coherent devices.
+ */
+ if (IS_ENABLED(CONFIG_DMA_GLOBAL_POOL))
+ return dma_alloc_from_global_coherent(dev, size,
+ dma_handle);
+
+ /*
+ * Otherwise remap if the architecture is asking for it. But
+ * given that remapping memory is a blocking operation we'll
+ * instead have to dip into the atomic pools.
+ */
+ remap = IS_ENABLED(CONFIG_DMA_DIRECT_REMAP);
+ if (remap) {
+ if (!gfpflags_allow_blocking(gfp) &&
+ !is_swiotlb_for_alloc(dev))
+ return dma_direct_alloc_from_pool(dev, size,
+ dma_handle, gfp);
+ } else {
+ if (IS_ENABLED(CONFIG_ARCH_HAS_DMA_SET_UNCACHED))
+ set_uncached = true;
+ }
+ }
/*
- * Remapping or decrypting memory may block. If either is required and
- * we can't block, allocate the memory from the atomic pools.
- * If restricted DMA (i.e., is_swiotlb_for_alloc) is required, one must
- * set up another device coherent pool by shared-dma-pool and use
- * dma_alloc_from_dev_coherent instead.
+ * Decrypting memory may block, so allocate the memory from the atomic
+ * pools if we can't block.
*/
if (IS_ENABLED(CONFIG_DMA_COHERENT_POOL) &&
- !gfpflags_allow_blocking(gfp) &&
- (force_dma_unencrypted(dev) ||
- (IS_ENABLED(CONFIG_DMA_DIRECT_REMAP) &&
- !dev_is_dma_coherent(dev))) &&
+ force_dma_unencrypted(dev) && !gfpflags_allow_blocking(gfp) &&
!is_swiotlb_for_alloc(dev))
return dma_direct_alloc_from_pool(dev, size, dma_handle, gfp);
@@ -234,10 +254,7 @@ void *dma_direct_alloc(struct device *dev, size_t size,
page = __dma_direct_alloc_pages(dev, size, gfp & ~__GFP_ZERO, true);
if (!page)
return NULL;
-
- if (!dev_is_dma_coherent(dev) && IS_ENABLED(CONFIG_DMA_DIRECT_REMAP)) {
- remap = true;
- } else if (PageHighMem(page)) {
+ if (PageHighMem(page)) {
/*
* Depending on the cma= arguments and per-arch setup,
* dma_alloc_contiguous could return highmem pages.
@@ -249,9 +266,8 @@ void *dma_direct_alloc(struct device *dev, size_t size,
goto out_free_pages;
}
remap = true;
- } else if (!dev_is_dma_coherent(dev) &&
- IS_ENABLED(CONFIG_ARCH_HAS_DMA_SET_UNCACHED))
- set_uncached = true;
+ set_uncached = false;
+ }
if (remap) {
/* remove any dirty cache lines on the kernel alias */
--
2.53.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 5.15.y 03/10] dma-direct: fail allocations that can't be made coherent
2026-09-10 14:39 ` [PATCH 5.15.y 01/10] dma-direct: clean up the remapping checks in dma_direct_alloc Sasha Levin
2026-09-10 14:39 ` [PATCH 5.15.y 02/10] dma-direct: refactor the !coherent " Sasha Levin
@ 2026-09-10 14:39 ` Sasha Levin
2026-09-10 14:39 ` [PATCH 5.15.y 04/10] dma-direct: warn if there is no pool for force unencrypted allocations Sasha Levin
` (6 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Sasha Levin @ 2026-09-10 14:39 UTC (permalink / raw)
To: stable; +Cc: Christoph Hellwig, Robin Murphy, Sasha Levin
From: Christoph Hellwig <hch@lst.de>
[ Upstream commit 955f58f7406ad912825fc344c7825fd904b124a0 ]
If the architecture can't remap or set an address uncached there is no way
to fullfill a request for a coherent allocation. Return NULL in that case.
Note that this case currently does not happen, so this is a theoretical
fixup and/or a preparation for eventually supporting platforms that
can't support coherent allocations with the generic code.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Robin Murphy <robin.murphy@arm.com>
Stable-dep-of: 94a04ad732c9 ("dma-direct: return struct page from dma_direct_alloc_from_pool()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
kernel/dma/direct.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c
index 517ca0e61a57c..0d6467b6553b7 100644
--- a/kernel/dma/direct.c
+++ b/kernel/dma/direct.c
@@ -236,8 +236,9 @@ void *dma_direct_alloc(struct device *dev, size_t size,
return dma_direct_alloc_from_pool(dev, size,
dma_handle, gfp);
} else {
- if (IS_ENABLED(CONFIG_ARCH_HAS_DMA_SET_UNCACHED))
- set_uncached = true;
+ if (!IS_ENABLED(CONFIG_ARCH_HAS_DMA_SET_UNCACHED))
+ return NULL;
+ set_uncached = true;
}
}
--
2.53.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 5.15.y 04/10] dma-direct: warn if there is no pool for force unencrypted allocations
2026-09-10 14:39 ` [PATCH 5.15.y 01/10] dma-direct: clean up the remapping checks in dma_direct_alloc Sasha Levin
2026-09-10 14:39 ` [PATCH 5.15.y 02/10] dma-direct: refactor the !coherent " Sasha Levin
2026-09-10 14:39 ` [PATCH 5.15.y 03/10] dma-direct: fail allocations that can't be made coherent Sasha Levin
@ 2026-09-10 14:39 ` Sasha Levin
2026-09-10 14:39 ` [PATCH 5.15.y 05/10] dma-direct: drop two CONFIG_DMA_RESTRICTED_POOL conditionals Sasha Levin
` (5 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Sasha Levin @ 2026-09-10 14:39 UTC (permalink / raw)
To: stable; +Cc: Christoph Hellwig, Robin Murphy, Sasha Levin
From: Christoph Hellwig <hch@lst.de>
[ Upstream commit 78bc72787ab9e638173aeb1f589578105d3a43c9 ]
Instead of blindly running into a blocking operation for a non-blocking gfp,
return NULL and spew an error. Note that Kconfig prevents this for all
currently relevant platforms, and this is just a debug check.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Robin Murphy <robin.murphy@arm.com>
Stable-dep-of: 94a04ad732c9 ("dma-direct: return struct page from dma_direct_alloc_from_pool()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
kernel/dma/direct.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c
index 0d6467b6553b7..5a71b6edfd1cd 100644
--- a/kernel/dma/direct.c
+++ b/kernel/dma/direct.c
@@ -162,6 +162,9 @@ static void *dma_direct_alloc_from_pool(struct device *dev, size_t size,
u64 phys_mask;
void *ret;
+ if (WARN_ON_ONCE(!IS_ENABLED(CONFIG_DMA_COHERENT_POOL)))
+ return NULL;
+
gfp |= dma_direct_optimal_gfp_mask(dev, dev->coherent_dma_mask,
&phys_mask);
page = dma_alloc_from_pool(dev, size, &ret, gfp, dma_coherent_ok);
@@ -246,8 +249,7 @@ void *dma_direct_alloc(struct device *dev, size_t size,
* Decrypting memory may block, so allocate the memory from the atomic
* pools if we can't block.
*/
- if (IS_ENABLED(CONFIG_DMA_COHERENT_POOL) &&
- force_dma_unencrypted(dev) && !gfpflags_allow_blocking(gfp) &&
+ if (force_dma_unencrypted(dev) && !gfpflags_allow_blocking(gfp) &&
!is_swiotlb_for_alloc(dev))
return dma_direct_alloc_from_pool(dev, size, dma_handle, gfp);
@@ -357,8 +359,7 @@ struct page *dma_direct_alloc_pages(struct device *dev, size_t size,
struct page *page;
void *ret;
- if (IS_ENABLED(CONFIG_DMA_COHERENT_POOL) &&
- force_dma_unencrypted(dev) && !gfpflags_allow_blocking(gfp) &&
+ if (force_dma_unencrypted(dev) && !gfpflags_allow_blocking(gfp) &&
!is_swiotlb_for_alloc(dev))
return dma_direct_alloc_from_pool(dev, size, dma_handle, gfp);
--
2.53.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 5.15.y 05/10] dma-direct: drop two CONFIG_DMA_RESTRICTED_POOL conditionals
2026-09-10 14:39 ` [PATCH 5.15.y 01/10] dma-direct: clean up the remapping checks in dma_direct_alloc Sasha Levin
` (2 preceding siblings ...)
2026-09-10 14:39 ` [PATCH 5.15.y 04/10] dma-direct: warn if there is no pool for force unencrypted allocations Sasha Levin
@ 2026-09-10 14:39 ` Sasha Levin
2026-09-10 14:39 ` [PATCH 5.15.y 06/10] dma-direct: factor the swiotlb code out of __dma_direct_alloc_pages Sasha Levin
` (4 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Sasha Levin @ 2026-09-10 14:39 UTC (permalink / raw)
To: stable; +Cc: Christoph Hellwig, Robin Murphy, Sasha Levin
From: Christoph Hellwig <hch@lst.de>
[ Upstream commit f5d3939a5916c0a8a0b47dcbc33963dbffe74f90 ]
swiotlb_alloc and swiotlb_free are properly stubbed out if
CONFIG_DMA_RESTRICTED_POOL is not set, so skip the extra checks.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Robin Murphy <robin.murphy@arm.com>
Stable-dep-of: 94a04ad732c9 ("dma-direct: return struct page from dma_direct_alloc_from_pool()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
kernel/dma/direct.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c
index 5a71b6edfd1cd..8ed15fd0abf83 100644
--- a/kernel/dma/direct.c
+++ b/kernel/dma/direct.c
@@ -97,8 +97,7 @@ static int dma_set_encrypted(struct device *dev, void *vaddr, size_t size)
static void __dma_direct_free_pages(struct device *dev, struct page *page,
size_t size)
{
- if (IS_ENABLED(CONFIG_DMA_RESTRICTED_POOL) &&
- swiotlb_free(dev, page, size))
+ if (swiotlb_free(dev, page, size))
return;
dma_free_contiguous(dev, page, size);
}
@@ -114,8 +113,7 @@ static struct page *__dma_direct_alloc_pages(struct device *dev, size_t size,
gfp |= dma_direct_optimal_gfp_mask(dev, dev->coherent_dma_mask,
&phys_limit);
- if (IS_ENABLED(CONFIG_DMA_RESTRICTED_POOL) &&
- is_swiotlb_for_alloc(dev)) {
+ if (is_swiotlb_for_alloc(dev)) {
page = swiotlb_alloc(dev, size);
if (page && !dma_coherent_ok(dev, page_to_phys(page), size)) {
__dma_direct_free_pages(dev, page, size);
--
2.53.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 5.15.y 06/10] dma-direct: factor the swiotlb code out of __dma_direct_alloc_pages
2026-09-10 14:39 ` [PATCH 5.15.y 01/10] dma-direct: clean up the remapping checks in dma_direct_alloc Sasha Levin
` (3 preceding siblings ...)
2026-09-10 14:39 ` [PATCH 5.15.y 05/10] dma-direct: drop two CONFIG_DMA_RESTRICTED_POOL conditionals Sasha Levin
@ 2026-09-10 14:39 ` Sasha Levin
2026-09-10 14:39 ` [PATCH 5.15.y 07/10] dma-direct: add a dma_direct_use_pool helper Sasha Levin
` (3 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Sasha Levin @ 2026-09-10 14:39 UTC (permalink / raw)
To: stable; +Cc: Christoph Hellwig, Robin Murphy, Sasha Levin
From: Christoph Hellwig <hch@lst.de>
[ Upstream commit aea7e2a86a94b2583e1e812c596140034398a169 ]
Add a new helper to deal with the swiotlb case. This keeps the code
nicely boundled and removes the not required call to
dma_direct_optimal_gfp_mask for the swiotlb case.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Robin Murphy <robin.murphy@arm.com>
Stable-dep-of: 94a04ad732c9 ("dma-direct: return struct page from dma_direct_alloc_from_pool()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
kernel/dma/direct.c | 24 +++++++++++++++---------
1 file changed, 15 insertions(+), 9 deletions(-)
diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c
index 8ed15fd0abf83..0f9b9a52b274c 100644
--- a/kernel/dma/direct.c
+++ b/kernel/dma/direct.c
@@ -102,6 +102,18 @@ static void __dma_direct_free_pages(struct device *dev, struct page *page,
dma_free_contiguous(dev, page, size);
}
+static struct page *dma_direct_alloc_swiotlb(struct device *dev, size_t size)
+{
+ struct page *page = swiotlb_alloc(dev, size);
+
+ if (page && !dma_coherent_ok(dev, page_to_phys(page), size)) {
+ swiotlb_free(dev, page, size);
+ return NULL;
+ }
+
+ return page;
+}
+
static struct page *__dma_direct_alloc_pages(struct device *dev, size_t size,
gfp_t gfp, bool allow_highmem)
{
@@ -111,17 +123,11 @@ static struct page *__dma_direct_alloc_pages(struct device *dev, size_t size,
WARN_ON_ONCE(!PAGE_ALIGNED(size));
+ if (is_swiotlb_for_alloc(dev))
+ return dma_direct_alloc_swiotlb(dev, size);
+
gfp |= dma_direct_optimal_gfp_mask(dev, dev->coherent_dma_mask,
&phys_limit);
- if (is_swiotlb_for_alloc(dev)) {
- page = swiotlb_alloc(dev, size);
- if (page && !dma_coherent_ok(dev, page_to_phys(page), size)) {
- __dma_direct_free_pages(dev, page, size);
- return NULL;
- }
- return page;
- }
-
page = dma_alloc_contiguous(dev, size, gfp);
if (page) {
if (!dma_coherent_ok(dev, page_to_phys(page), size) ||
--
2.53.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 5.15.y 07/10] dma-direct: add a dma_direct_use_pool helper
2026-09-10 14:39 ` [PATCH 5.15.y 01/10] dma-direct: clean up the remapping checks in dma_direct_alloc Sasha Levin
` (4 preceding siblings ...)
2026-09-10 14:39 ` [PATCH 5.15.y 06/10] dma-direct: factor the swiotlb code out of __dma_direct_alloc_pages Sasha Levin
@ 2026-09-10 14:39 ` Sasha Levin
2026-09-10 14:39 ` [PATCH 5.15.y 08/10] dma-direct: cleanup parameters to dma_direct_optimal_gfp_mask Sasha Levin
` (2 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Sasha Levin @ 2026-09-10 14:39 UTC (permalink / raw)
To: stable; +Cc: Christoph Hellwig, Robin Murphy, Sasha Levin
From: Christoph Hellwig <hch@lst.de>
[ Upstream commit 28e4576d556bca543b0996e9edd4b767397e24c6 ]
Add a helper to check if a potentially blocking operation should
dip into the atomic pools.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Robin Murphy <robin.murphy@arm.com>
Stable-dep-of: 94a04ad732c9 ("dma-direct: return struct page from dma_direct_alloc_from_pool()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
kernel/dma/direct.c | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c
index 0f9b9a52b274c..97bd785560239 100644
--- a/kernel/dma/direct.c
+++ b/kernel/dma/direct.c
@@ -159,6 +159,15 @@ static struct page *__dma_direct_alloc_pages(struct device *dev, size_t size,
return page;
}
+/*
+ * Check if a potentially blocking operations needs to dip into the atomic
+ * pools for the given device/gfp.
+ */
+static bool dma_direct_use_pool(struct device *dev, gfp_t gfp)
+{
+ return !gfpflags_allow_blocking(gfp) && !is_swiotlb_for_alloc(dev);
+}
+
static void *dma_direct_alloc_from_pool(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp)
{
@@ -238,8 +247,7 @@ void *dma_direct_alloc(struct device *dev, size_t size,
*/
remap = IS_ENABLED(CONFIG_DMA_DIRECT_REMAP);
if (remap) {
- if (!gfpflags_allow_blocking(gfp) &&
- !is_swiotlb_for_alloc(dev))
+ if (dma_direct_use_pool(dev, gfp))
return dma_direct_alloc_from_pool(dev, size,
dma_handle, gfp);
} else {
@@ -253,8 +261,7 @@ void *dma_direct_alloc(struct device *dev, size_t size,
* Decrypting memory may block, so allocate the memory from the atomic
* pools if we can't block.
*/
- if (force_dma_unencrypted(dev) && !gfpflags_allow_blocking(gfp) &&
- !is_swiotlb_for_alloc(dev))
+ if (force_dma_unencrypted(dev) && dma_direct_use_pool(dev, gfp))
return dma_direct_alloc_from_pool(dev, size, dma_handle, gfp);
/* we always manually zero the memory once we are done */
@@ -363,8 +370,7 @@ struct page *dma_direct_alloc_pages(struct device *dev, size_t size,
struct page *page;
void *ret;
- if (force_dma_unencrypted(dev) && !gfpflags_allow_blocking(gfp) &&
- !is_swiotlb_for_alloc(dev))
+ if (force_dma_unencrypted(dev) && dma_direct_use_pool(dev, gfp))
return dma_direct_alloc_from_pool(dev, size, dma_handle, gfp);
page = __dma_direct_alloc_pages(dev, size, gfp, false);
--
2.53.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 5.15.y 08/10] dma-direct: cleanup parameters to dma_direct_optimal_gfp_mask
2026-09-10 14:39 ` [PATCH 5.15.y 01/10] dma-direct: clean up the remapping checks in dma_direct_alloc Sasha Levin
` (5 preceding siblings ...)
2026-09-10 14:39 ` [PATCH 5.15.y 07/10] dma-direct: add a dma_direct_use_pool helper Sasha Levin
@ 2026-09-10 14:39 ` Sasha Levin
2026-09-10 14:39 ` [PATCH 5.15.y 09/10] dma-direct: simplify the use atomic pool logic in dma_direct_alloc Sasha Levin
2026-09-10 14:39 ` [PATCH 5.15.y 10/10] dma-direct: return struct page from dma_direct_alloc_from_pool() Sasha Levin
8 siblings, 0 replies; 11+ messages in thread
From: Sasha Levin @ 2026-09-10 14:39 UTC (permalink / raw)
To: stable; +Cc: Petr Tesarik, Christoph Hellwig, Sasha Levin
From: Petr Tesarik <petrtesarik@huaweicloud.com>
[ Upstream commit 25a4ce564921db0973b74c04e0ea23bd2ee12a3a ]
Since both callers of dma_direct_optimal_gfp_mask() pass
dev->coherent_dma_mask as the second argument, it is better to
remove that parameter altogether.
Not only is reducing number of parameters good for readability, but
the new function signature is also more logical: The optimal flags
depend only on data contained in struct device.
While touching this code, let's also rename phys_mask to phys_limit
in dma_direct_alloc_from_pool(), because it is indeed a limit.
Signed-off-by: Petr Tesarik <petrtesarik@huaweicloud.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Stable-dep-of: 94a04ad732c9 ("dma-direct: return struct page from dma_direct_alloc_from_pool()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
kernel/dma/direct.c | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c
index 97bd785560239..5c4c0c9f1c6d6 100644
--- a/kernel/dma/direct.c
+++ b/kernel/dma/direct.c
@@ -44,10 +44,11 @@ u64 dma_direct_get_required_mask(struct device *dev)
return (1ULL << (fls64(max_dma) - 1)) * 2 - 1;
}
-static gfp_t dma_direct_optimal_gfp_mask(struct device *dev, u64 dma_mask,
- u64 *phys_limit)
+static gfp_t dma_direct_optimal_gfp_mask(struct device *dev, u64 *phys_limit)
{
- u64 dma_limit = min_not_zero(dma_mask, dev->bus_dma_limit);
+ u64 dma_limit = min_not_zero(
+ dev->coherent_dma_mask,
+ dev->bus_dma_limit);
/*
* Optimistically try the zone that the physical address mask falls
@@ -126,8 +127,7 @@ static struct page *__dma_direct_alloc_pages(struct device *dev, size_t size,
if (is_swiotlb_for_alloc(dev))
return dma_direct_alloc_swiotlb(dev, size);
- gfp |= dma_direct_optimal_gfp_mask(dev, dev->coherent_dma_mask,
- &phys_limit);
+ gfp |= dma_direct_optimal_gfp_mask(dev, &phys_limit);
page = dma_alloc_contiguous(dev, size, gfp);
if (page) {
if (!dma_coherent_ok(dev, page_to_phys(page), size) ||
@@ -172,14 +172,13 @@ static void *dma_direct_alloc_from_pool(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp)
{
struct page *page;
- u64 phys_mask;
+ u64 phys_limit;
void *ret;
if (WARN_ON_ONCE(!IS_ENABLED(CONFIG_DMA_COHERENT_POOL)))
return NULL;
- gfp |= dma_direct_optimal_gfp_mask(dev, dev->coherent_dma_mask,
- &phys_mask);
+ gfp |= dma_direct_optimal_gfp_mask(dev, &phys_limit);
page = dma_alloc_from_pool(dev, size, &ret, gfp, dma_coherent_ok);
if (!page)
return NULL;
--
2.53.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 5.15.y 09/10] dma-direct: simplify the use atomic pool logic in dma_direct_alloc
2026-09-10 14:39 ` [PATCH 5.15.y 01/10] dma-direct: clean up the remapping checks in dma_direct_alloc Sasha Levin
` (6 preceding siblings ...)
2026-09-10 14:39 ` [PATCH 5.15.y 08/10] dma-direct: cleanup parameters to dma_direct_optimal_gfp_mask Sasha Levin
@ 2026-09-10 14:39 ` Sasha Levin
2026-09-10 14:39 ` [PATCH 5.15.y 10/10] dma-direct: return struct page from dma_direct_alloc_from_pool() Sasha Levin
8 siblings, 0 replies; 11+ messages in thread
From: Sasha Levin @ 2026-09-10 14:39 UTC (permalink / raw)
To: stable; +Cc: Christoph Hellwig, Robin Murphy, Greg Ungerer, Sasha Levin
From: Christoph Hellwig <hch@lst.de>
[ Upstream commit b1da46d70e5427a9ba5eae28bcca29a20e68a442 ]
The logic in dma_direct_alloc when to use the atomic pool vs remapping
grew a bit unreadable. Consolidate it into a single check, and clean
up the set_uncached vs remap logic a bit as well.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Robin Murphy <robin.murphy@arm.com>
Reviewed-by: Greg Ungerer <gerg@linux-m68k.org>
Tested-by: Greg Ungerer <gerg@linux-m68k.org>
Stable-dep-of: 94a04ad732c9 ("dma-direct: return struct page from dma_direct_alloc_from_pool()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
kernel/dma/direct.c | 25 ++++++++++---------------
1 file changed, 10 insertions(+), 15 deletions(-)
diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c
index 5c4c0c9f1c6d6..30848d158d0a4 100644
--- a/kernel/dma/direct.c
+++ b/kernel/dma/direct.c
@@ -240,27 +240,22 @@ void *dma_direct_alloc(struct device *dev, size_t size,
dma_handle);
/*
- * Otherwise remap if the architecture is asking for it. But
- * given that remapping memory is a blocking operation we'll
- * instead have to dip into the atomic pools.
+ * Otherwise we require the architecture to either be able to
+ * mark arbitrary parts of the kernel direct mapping uncached,
+ * or remapped it uncached.
*/
+ set_uncached = IS_ENABLED(CONFIG_ARCH_HAS_DMA_SET_UNCACHED);
remap = IS_ENABLED(CONFIG_DMA_DIRECT_REMAP);
- if (remap) {
- if (dma_direct_use_pool(dev, gfp))
- return dma_direct_alloc_from_pool(dev, size,
- dma_handle, gfp);
- } else {
- if (!IS_ENABLED(CONFIG_ARCH_HAS_DMA_SET_UNCACHED))
- return NULL;
- set_uncached = true;
- }
+ if (!set_uncached && !remap)
+ return NULL;
}
/*
- * Decrypting memory may block, so allocate the memory from the atomic
- * pools if we can't block.
+ * Remapping or decrypting memory may block, allocate the memory from
+ * the atomic pools instead if we aren't allowed block.
*/
- if (force_dma_unencrypted(dev) && dma_direct_use_pool(dev, gfp))
+ if ((remap || force_dma_unencrypted(dev)) &&
+ dma_direct_use_pool(dev, gfp))
return dma_direct_alloc_from_pool(dev, size, dma_handle, gfp);
/* we always manually zero the memory once we are done */
--
2.53.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 5.15.y 10/10] dma-direct: return struct page from dma_direct_alloc_from_pool()
2026-09-10 14:39 ` [PATCH 5.15.y 01/10] dma-direct: clean up the remapping checks in dma_direct_alloc Sasha Levin
` (7 preceding siblings ...)
2026-09-10 14:39 ` [PATCH 5.15.y 09/10] dma-direct: simplify the use atomic pool logic in dma_direct_alloc Sasha Levin
@ 2026-09-10 14:39 ` Sasha Levin
8 siblings, 0 replies; 11+ messages in thread
From: Sasha Levin @ 2026-09-10 14:39 UTC (permalink / raw)
To: stable
Cc: Aneesh Kumar K.V (Arm), Michael Kelley, Mostafa Saleh,
Jason Gunthorpe, Marek Szyprowski, Sasha Levin
From: "Aneesh Kumar K.V (Arm)" <aneesh.kumar@kernel.org>
[ Upstream commit 94a04ad732c9f8b9554270fc4038a06737de5c22 ]
Commit 5b138c534fda ("dma-direct: factor out a dma_direct_alloc_from_pool
helper") changed dma_direct_alloc_from_pool() to return the CPU address
from dma_alloc_from_pool(). That fits dma_direct_alloc(), but
dma_direct_alloc_pages() also uses the helper and expects a struct page *.
Fix this by making dma_direct_alloc_from_pool() return the struct page *
again, and pass the CPU address back through an out-parameter for the
dma_direct_alloc() caller.
Fixes: 5b138c534fda ("dma-direct: factor out a dma_direct_alloc_from_pool helper")
Cc: stable@vger.kernel.org
Tested-by: Michael Kelley <mhklinux@outlook.com>
Tested-by: Mostafa Saleh <smostafa@google.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>
Reviewed-by: Mostafa Saleh <smostafa@google.com>
Link: https://lore.kernel.org/r/20260717180442.110954-2-aneesh.kumar@kernel.org
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
kernel/dma/direct.c | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c
index 30848d158d0a4..f1956ee185405 100644
--- a/kernel/dma/direct.c
+++ b/kernel/dma/direct.c
@@ -168,22 +168,21 @@ static bool dma_direct_use_pool(struct device *dev, gfp_t gfp)
return !gfpflags_allow_blocking(gfp) && !is_swiotlb_for_alloc(dev);
}
-static void *dma_direct_alloc_from_pool(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t gfp)
+static struct page *dma_direct_alloc_from_pool(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, void **cpu_addr, gfp_t gfp)
{
struct page *page;
u64 phys_limit;
- void *ret;
if (WARN_ON_ONCE(!IS_ENABLED(CONFIG_DMA_COHERENT_POOL)))
return NULL;
gfp |= dma_direct_optimal_gfp_mask(dev, &phys_limit);
- page = dma_alloc_from_pool(dev, size, &ret, gfp, dma_coherent_ok);
+ page = dma_alloc_from_pool(dev, size, cpu_addr, gfp, dma_coherent_ok);
if (!page)
return NULL;
*dma_handle = phys_to_dma_direct(dev, page_to_phys(page));
- return ret;
+ return page;
}
static void *dma_direct_alloc_no_mapping(struct device *dev, size_t size,
@@ -255,8 +254,11 @@ void *dma_direct_alloc(struct device *dev, size_t size,
* the atomic pools instead if we aren't allowed block.
*/
if ((remap || force_dma_unencrypted(dev)) &&
- dma_direct_use_pool(dev, gfp))
- return dma_direct_alloc_from_pool(dev, size, dma_handle, gfp);
+ dma_direct_use_pool(dev, gfp)) {
+ page = dma_direct_alloc_from_pool(dev, size, dma_handle,
+ &ret, gfp);
+ return page ? ret : NULL;
+ }
/* we always manually zero the memory once we are done */
page = __dma_direct_alloc_pages(dev, size, gfp & ~__GFP_ZERO, true);
@@ -365,7 +367,7 @@ struct page *dma_direct_alloc_pages(struct device *dev, size_t size,
void *ret;
if (force_dma_unencrypted(dev) && dma_direct_use_pool(dev, gfp))
- return dma_direct_alloc_from_pool(dev, size, dma_handle, gfp);
+ return dma_direct_alloc_from_pool(dev, size, dma_handle, &ret, gfp);
page = __dma_direct_alloc_pages(dev, size, gfp, false);
if (!page)
--
2.53.0
^ permalink raw reply related [flat|nested] 11+ messages in thread