d40_lcla_allocate() calculates the number of pages needed for LCLA, but
passes that raw page count as the allocation order to __get_free_pages().
The same value is later passed to free_pages().

Store the allocation order with get_order() instead, and use a separate
byte size for allocation diagnostics, fallback kmalloc() sizing and DMA
mapping.

Reported-by: [email protected]
Closes: 
https://lore.kernel.org/dmaengine/[email protected]/
Assisted-by: Codex:gpt-5-5
Signed-off-by: Linus Walleij <[email protected]>
---
 drivers/dma/ste_dma40.c | 33 ++++++++++++++++-----------------
 1 file changed, 16 insertions(+), 17 deletions(-)

diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 384c2f3805b0..804eb5eab06b 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -411,8 +411,8 @@ struct d40_desc {
  * @dma_addr: DMA address, if mapped
  * @base_unaligned: The original kmalloc pointer, if kmalloc is used.
  * This pointer is only there for clean-up on error.
- * @pages: The number of pages needed for all physical channels.
- * Only used later for clean-up on error
+ * @alloc_order: Order used for the LCLA page allocation.
+ * Only used later for clean-up on error.
  * @lock: Lock to protect the content in this struct.
  * @alloc_map: big map over which LCLA entry is own by which job.
  */
@@ -420,7 +420,7 @@ struct d40_lcla_pool {
        void            *base;
        dma_addr_t      dma_addr;
        void            *base_unaligned;
-       int              pages;
+       unsigned int     alloc_order;
        spinlock_t       lock;
        struct d40_desc **alloc_map;
 };
@@ -3372,6 +3372,7 @@ static void __init d40_hw_init(struct d40_base *base)
 static int __init d40_lcla_allocate(struct d40_base *base)
 {
        struct d40_lcla_pool *pool = &base->lcla_pool;
+       size_t lcla_size = SZ_1K * base->num_phy_chans;
        unsigned long *page_list;
        int i, j;
        int ret;
@@ -3387,20 +3388,20 @@ static int __init d40_lcla_allocate(struct d40_base 
*base)
        if (!page_list)
                return -ENOMEM;
 
-       /* Calculating how many pages that are required */
-       base->lcla_pool.pages = SZ_1K * base->num_phy_chans / PAGE_SIZE;
+       base->lcla_pool.alloc_order = get_order(lcla_size);
 
        for (i = 0; i < MAX_LCLA_ALLOC_ATTEMPTS; i++) {
                page_list[i] = __get_free_pages(GFP_KERNEL,
-                                               base->lcla_pool.pages);
+                                               base->lcla_pool.alloc_order);
                if (!page_list[i]) {
 
-                       d40_err(base->dev, "Failed to allocate %d pages.\n",
-                               base->lcla_pool.pages);
+                       d40_err(base->dev, "Failed to allocate %zu bytes.\n",
+                               lcla_size);
                        ret = -ENOMEM;
 
                        for (j = 0; j < i; j++)
-                               free_pages(page_list[j], base->lcla_pool.pages);
+                               free_pages(page_list[j],
+                                          base->lcla_pool.alloc_order);
                        goto free_page_list;
                }
 
@@ -3410,7 +3411,7 @@ static int __init d40_lcla_allocate(struct d40_base *base)
        }
 
        for (j = 0; j < i; j++)
-               free_pages(page_list[j], base->lcla_pool.pages);
+               free_pages(page_list[j], base->lcla_pool.alloc_order);
 
        if (i < MAX_LCLA_ALLOC_ATTEMPTS) {
                base->lcla_pool.base = (void *)page_list[i];
@@ -3420,10 +3421,9 @@ static int __init d40_lcla_allocate(struct d40_base 
*base)
                 * alignment, try with allocating a big buffer.
                 */
                dev_warn(base->dev,
-                        "[%s] Failed to get %d pages @ 18 bit align.\n",
-                        __func__, base->lcla_pool.pages);
-               base->lcla_pool.base_unaligned = kmalloc(SZ_1K *
-                                                        base->num_phy_chans +
+                        "[%s] Failed to get %zu bytes @ 18 bit align.\n",
+                        __func__, lcla_size);
+               base->lcla_pool.base_unaligned = kmalloc(lcla_size +
                                                         LCLA_ALIGNMENT,
                                                         GFP_KERNEL);
                if (!base->lcla_pool.base_unaligned) {
@@ -3435,8 +3435,7 @@ static int __init d40_lcla_allocate(struct d40_base *base)
                                                 LCLA_ALIGNMENT);
        }
 
-       pool->dma_addr = dma_map_single(base->dev, pool->base,
-                                       SZ_1K * base->num_phy_chans,
+       pool->dma_addr = dma_map_single(base->dev, pool->base, lcla_size,
                                        DMA_TO_DEVICE);
        if (dma_mapping_error(base->dev, pool->dma_addr)) {
                pool->dma_addr = 0;
@@ -3670,7 +3669,7 @@ static int __init d40_probe(struct platform_device *pdev)
 
        if (!base->lcla_pool.base_unaligned && base->lcla_pool.base)
                free_pages((unsigned long)base->lcla_pool.base,
-                          base->lcla_pool.pages);
+                          base->lcla_pool.alloc_order);
 
        kfree(base->lcla_pool.base_unaligned);
 

-- 
2.55.0


Reply via email to