* [PATCH 01/10] dmaengine: pl08x: Defer OF DMA controller registration until slave setup
2026-11-11 21:52 [PATCH 00/10] dmaengine: Fix teardown races, resource leaks, and error handling Lee Jones
@ 2026-11-11 21:52 ` Lee Jones
2026-11-11 21:52 ` [PATCH 02/10] dmaengine: ae4dma: Unregister DMA engine in ae4_pci_remove() Lee Jones
` (8 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Lee Jones @ 2026-11-11 21:52 UTC (permalink / raw)
To: lee, Vinod Koul, Frank Li, Peter Pearse, Linus Walleij,
Joachim Eastwood, dmaengine, linux-kernel
Cc: stable
pl08x_of_probe() registers the controller with
of_dma_controller_register() before pl08x_dma_init_virtual_channels()
initialises the slave channels list and before
dma_async_device_register() registers the slave DMA device, and
pl08x_probe() does not unregister the OF DMA controller if subsequent
initialisation fails.
Move of_dma_controller_register() after dma_async_device_register() for
the slave device and unwind slave device registration if OF controller
registration fails.
Fixes: aa4734da6674 ("dmaengine: pl08x: support dt channel assignment")
Closes: https://sashiko.dev/#/bug/linux-4e233fb9-3b0c-4442-b601-c6706c9f5aba
Cc: stable@vger.kernel.org
Signed-off-by: Lee Jones <lee@kernel.org>
---
drivers/dma/amba-pl08x.c | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index 543c2eb8cfa8..d8441e338502 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -2678,6 +2678,12 @@ static int pl08x_of_probe(struct amba_device *adev,
pl08x->pd = pd;
+ return 0;
+}
+
+static int pl08x_of_register(struct amba_device *adev,
+ struct pl08x_driver_data *pl08x)
+{
return of_dma_controller_register(adev->dev.of_node, pl08x_of_xlate,
pl08x);
}
@@ -2688,6 +2694,12 @@ static inline int pl08x_of_probe(struct amba_device *adev,
{
return -EINVAL;
}
+
+static inline int pl08x_of_register(struct amba_device *adev,
+ struct pl08x_driver_data *pl08x)
+{
+ return 0;
+}
#endif
static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
@@ -2944,6 +2956,15 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
__func__, ret);
goto out_no_slave_reg;
}
+ if (np) {
+ ret = pl08x_of_register(adev, pl08x);
+ if (ret) {
+ dev_warn(&pl08x->adev->dev,
+ "%s failed to register OF DMA controller - %d\n",
+ __func__, ret);
+ goto out_no_of_dma;
+ }
+ }
}
amba_set_drvdata(adev, pl08x);
@@ -2954,6 +2975,8 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
return 0;
+out_no_of_dma:
+ dma_async_device_unregister(&pl08x->slave);
out_no_slave_reg:
dma_async_device_unregister(&pl08x->memcpy);
out_no_memcpy_reg:
--
2.56.0.567.gdb80ae8cd5-goog
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH 02/10] dmaengine: ae4dma: Unregister DMA engine in ae4_pci_remove()
2026-11-11 21:52 [PATCH 00/10] dmaengine: Fix teardown races, resource leaks, and error handling Lee Jones
2026-11-11 21:52 ` [PATCH 01/10] dmaengine: pl08x: Defer OF DMA controller registration until slave setup Lee Jones
@ 2026-11-11 21:52 ` Lee Jones
2026-11-11 21:52 ` [PATCH 03/10] dmaengine: ptdma: Unmap descriptor in pt_do_cleanup() Lee Jones
` (7 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Lee Jones @ 2026-11-11 21:52 UTC (permalink / raw)
To: lee, Basavaraj Natikar, Vinod Koul, Frank Li, Sanjay R Mehta,
Gary R Hook, Raju Rangoju, Philipp Stanner, dmaengine,
linux-kernel
Cc: stable
ae4_core_init() registers the DMA device and creates the descriptor slab
cache via pt_dmaengine_register(), but ae4_pci_remove() never calls
pt_dmaengine_unregister(), leaking the descriptor cache and leaving a
dangling DMA device registered after device removal.
Export pt_dmaengine_unregister() and call it from ae4_pci_remove().
Fixes: 98f5a4432622 ("dmaengine: ae4dma: Register AE4DMA using pt_dmaengine_register")
Closes: https://sashiko.dev/#/bug/linux-10d41112-e133-4bc5-8e53-b3e96592c70d
Cc: stable@vger.kernel.org
Signed-off-by: Lee Jones <lee@kernel.org>
---
drivers/dma/amd/ae4dma/ae4dma-pci.c | 1 +
drivers/dma/amd/ptdma/ptdma-dmaengine.c | 1 +
2 files changed, 2 insertions(+)
diff --git a/drivers/dma/amd/ae4dma/ae4dma-pci.c b/drivers/dma/amd/ae4dma/ae4dma-pci.c
index 2c63907db228..8712f4f65e28 100644
--- a/drivers/dma/amd/ae4dma/ae4dma-pci.c
+++ b/drivers/dma/amd/ae4dma/ae4dma-pci.c
@@ -132,6 +132,7 @@ static void ae4_pci_remove(struct pci_dev *pdev)
{
struct ae4_device *ae4 = dev_get_drvdata(&pdev->dev);
+ pt_dmaengine_unregister(&ae4->pt);
ae4_destroy_work(ae4);
ae4_deinit(ae4);
}
diff --git a/drivers/dma/amd/ptdma/ptdma-dmaengine.c b/drivers/dma/amd/ptdma/ptdma-dmaengine.c
index 628c49ce5de9..22e7b3ae26a1 100644
--- a/drivers/dma/amd/ptdma/ptdma-dmaengine.c
+++ b/drivers/dma/amd/ptdma/ptdma-dmaengine.c
@@ -657,3 +657,4 @@ void pt_dmaengine_unregister(struct pt_device *pt)
kmem_cache_destroy(pt->dma_desc_cache);
}
+EXPORT_SYMBOL_GPL(pt_dmaengine_unregister);
--
2.56.0.567.gdb80ae8cd5-goog
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH 03/10] dmaengine: ptdma: Unmap descriptor in pt_do_cleanup()
2026-11-11 21:52 [PATCH 00/10] dmaengine: Fix teardown races, resource leaks, and error handling Lee Jones
2026-11-11 21:52 ` [PATCH 01/10] dmaengine: pl08x: Defer OF DMA controller registration until slave setup Lee Jones
2026-11-11 21:52 ` [PATCH 02/10] dmaengine: ae4dma: Unregister DMA engine in ae4_pci_remove() Lee Jones
@ 2026-11-11 21:52 ` Lee Jones
2026-11-11 21:52 ` [PATCH 04/10] dmaengine: ptdma: Remove completed descriptor under vc.lock in pt_cmd_callback_work() Lee Jones
` (6 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Lee Jones @ 2026-11-11 21:52 UTC (permalink / raw)
To: lee, Basavaraj Natikar, Vinod Koul, Frank Li, Sanjay R Mehta,
Gary R Hook, dmaengine, linux-kernel
Cc: stable
When descriptors are freed on abort via vchan_dma_desc_free_list(),
pt_do_cleanup() frees the descriptor without calling
dma_descriptor_unmap(), leaking any attached dmaengine_unmap_data and
DMA mappings.
Call dma_descriptor_unmap(&vd->tx) in pt_do_cleanup() before freeing the
descriptor.
Fixes: b0b4a6b10577 ("dmaengine: ptdma: register PTDMA controller as a DMA resource")
Closes: https://sashiko.dev/#/bug/linux-58b8113b-167a-4398-9be2-c2f3cbf73358
Cc: stable@vger.kernel.org
Signed-off-by: Lee Jones <lee@kernel.org>
---
drivers/dma/amd/ptdma/ptdma-dmaengine.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/dma/amd/ptdma/ptdma-dmaengine.c b/drivers/dma/amd/ptdma/ptdma-dmaengine.c
index 22e7b3ae26a1..405d3d3b7f8a 100644
--- a/drivers/dma/amd/ptdma/ptdma-dmaengine.c
+++ b/drivers/dma/amd/ptdma/ptdma-dmaengine.c
@@ -91,6 +91,7 @@ static void pt_do_cleanup(struct virt_dma_desc *vd)
struct pt_dma_desc *desc = to_pt_desc(vd);
struct pt_device *pt = desc->pt;
+ dma_descriptor_unmap(&vd->tx);
kmem_cache_free(pt->dma_desc_cache, desc);
}
--
2.56.0.567.gdb80ae8cd5-goog
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH 04/10] dmaengine: ptdma: Remove completed descriptor under vc.lock in pt_cmd_callback_work()
2026-11-11 21:52 [PATCH 00/10] dmaengine: Fix teardown races, resource leaks, and error handling Lee Jones
` (2 preceding siblings ...)
2026-11-11 21:52 ` [PATCH 03/10] dmaengine: ptdma: Unmap descriptor in pt_do_cleanup() Lee Jones
@ 2026-11-11 21:52 ` Lee Jones
2026-11-11 21:52 ` [PATCH 05/10] dmaengine: amlogic: Destroy free_wq after devres DMA device unregistration Lee Jones
` (5 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Lee Jones @ 2026-11-11 21:52 UTC (permalink / raw)
To: lee, Basavaraj Natikar, Vinod Koul, Frank Li, Sanjay R Mehta,
Gary R Hook, dmaengine, linux-kernel
Cc: stable
pt_cmd_callback_work() drops chan->vc.lock before calling
list_del(&desc->vd.node), racing with concurrent virt-dma list
operations such as pt_terminate_all().
Move list_del(&desc->vd.node) inside the chan->vc.lock critical section,
matching pt_handle_active_desc().
Fixes: 656543989457 ("dmaengine: ptdma: Utilize the AE4DMA engine's multi-queue functionality")
Closes: https://sashiko.dev/#/bug/linux-55f1563b-5563-492a-a291-1a5b772ffd42
Cc: stable@vger.kernel.org
Signed-off-by: Lee Jones <lee@kernel.org>
---
drivers/dma/amd/ptdma/ptdma-dmaengine.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/dma/amd/ptdma/ptdma-dmaengine.c b/drivers/dma/amd/ptdma/ptdma-dmaengine.c
index 405d3d3b7f8a..da50c7d15348 100644
--- a/drivers/dma/amd/ptdma/ptdma-dmaengine.c
+++ b/drivers/dma/amd/ptdma/ptdma-dmaengine.c
@@ -365,6 +365,7 @@ static void pt_cmd_callback_work(void *data, int err)
dma_cookie_complete(tx_desc);
dma_descriptor_unmap(tx_desc);
+ list_del(&desc->vd.node);
} else {
tx_desc = NULL;
}
@@ -373,7 +374,6 @@ static void pt_cmd_callback_work(void *data, int err)
if (tx_desc) {
dmaengine_desc_get_callback_invoke(tx_desc, NULL);
dma_run_dependencies(tx_desc);
- list_del(&desc->vd.node);
vchan_vdesc_fini(vd);
}
}
--
2.56.0.567.gdb80ae8cd5-goog
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH 05/10] dmaengine: amlogic: Destroy free_wq after devres DMA device unregistration
2026-11-11 21:52 [PATCH 00/10] dmaengine: Fix teardown races, resource leaks, and error handling Lee Jones
` (3 preceding siblings ...)
2026-11-11 21:52 ` [PATCH 04/10] dmaengine: ptdma: Remove completed descriptor under vc.lock in pt_cmd_callback_work() Lee Jones
@ 2026-11-11 21:52 ` Lee Jones
2026-11-11 21:52 ` [PATCH 06/10] dmaengine: arm-dma350: Query dma_cookie_status() under vc.lock in d350_tx_status() Lee Jones
` (4 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Lee Jones @ 2026-11-11 21:52 UTC (permalink / raw)
To: lee, Xianwei Zhao, Vinod Koul, Frank Li, linux-amlogic,
dmaengine, linux-kernel
Cc: stable
aml_dma_probe() registers the DMA device with
dmaenginem_async_device_register(), so dma_async_device_unregister() is
deferred until devres release after aml_dma_remove() returns. However,
aml_dma_remove() destroys aml_dma->free_wq directly, causing
aml_dma_free_desc() to queue work onto a destroyed workqueue when
channels and descriptors are released during devres teardown, and early
error returns in aml_dma_probe() also leak aml_dma->free_wq.
Allocate aml_dma->free_wq with devm_alloc_ordered_workqueue() so it is
destroyed on probe failure and after dmaenginem_async_device_register()
unwinds on removal.
Fixes: b84b5197e344 ("dmaengine: amlogic: Add general DMA driver for A9")
Closes: https://sashiko.dev/#/bug/linux-c216084a-f89a-48d5-bdea-584522d1bdda
Cc: stable@vger.kernel.org
Signed-off-by: Lee Jones <lee@kernel.org>
---
drivers/dma/amlogic-dma.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/dma/amlogic-dma.c b/drivers/dma/amlogic-dma.c
index 684121d13fca..791bd82743d3 100644
--- a/drivers/dma/amlogic-dma.c
+++ b/drivers/dma/amlogic-dma.c
@@ -620,7 +620,7 @@ static int aml_dma_probe(struct platform_device *pdev)
if (!aml_dma)
return -ENOMEM;
- aml_dma->free_wq = alloc_ordered_workqueue("aml_dma_free", 0);
+ aml_dma->free_wq = devm_alloc_ordered_workqueue(&pdev->dev, "aml_dma_free", 0);
if (!aml_dma->free_wq)
return -ENOMEM;
@@ -712,7 +712,6 @@ static void aml_dma_remove(struct platform_device *pdev)
if (aml_chan)
tasklet_kill(&aml_chan->vchan.task);
}
- destroy_workqueue(aml_dma->free_wq);
}
static const struct of_device_id aml_dma_ids[] = {
--
2.56.0.567.gdb80ae8cd5-goog
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH 06/10] dmaengine: arm-dma350: Query dma_cookie_status() under vc.lock in d350_tx_status()
2026-11-11 21:52 [PATCH 00/10] dmaengine: Fix teardown races, resource leaks, and error handling Lee Jones
` (4 preceding siblings ...)
2026-11-11 21:52 ` [PATCH 05/10] dmaengine: amlogic: Destroy free_wq after devres DMA device unregistration Lee Jones
@ 2026-11-11 21:52 ` Lee Jones
2026-11-11 21:52 ` [PATCH 07/10] dmaengine: bestcomm: Defer publishing bcom_eng until initialisation completes Lee Jones
` (3 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Lee Jones @ 2026-11-11 21:52 UTC (permalink / raw)
To: lee, Jacky Huang, Shan-Chun Hung, Vinod Koul, Frank Li,
Robin Murphy, linux-arm-kernel, dmaengine, linux-kernel
Cc: stable
Calling dma_cookie_status() before acquiring dch->vc.lock in
d350_tx_status() races with d350_irq() completing the active descriptor
and starting the next queued transfer, causing d350_tx_status() to
observe a stale DMA_IN_PROGRESS status and falsely return DMA_ERROR.
Move the dma_cookie_status() call inside the dch->vc.lock critical
section.
Fixes: 5d099706449d ("dmaengine: Add Arm DMA-350 driver")
Closes: https://sashiko.dev/#/bug/linux-524816d7-ed1c-4f2b-b4c3-65a7e8bb45a3
Cc: stable@vger.kernel.org
Signed-off-by: Lee Jones <lee@kernel.org>
---
drivers/dma/arm-dma350.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/dma/arm-dma350.c b/drivers/dma/arm-dma350.c
index 52f5242ea332..8c1725588f1d 100644
--- a/drivers/dma/arm-dma350.c
+++ b/drivers/dma/arm-dma350.c
@@ -381,9 +381,8 @@ static enum dma_status d350_tx_status(struct dma_chan *chan, dma_cookie_t cookie
unsigned long flags;
u32 residue = 0;
+ spin_lock_irqsave(&dch->vc.lock, flags);
status = dma_cookie_status(chan, cookie, state);
-
- spin_lock_irqsave(&dch->vc.lock, flags);
if (cookie == dch->cookie) {
status = dch->status;
if (status == DMA_IN_PROGRESS || status == DMA_PAUSED)
--
2.56.0.567.gdb80ae8cd5-goog
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH 07/10] dmaengine: bestcomm: Defer publishing bcom_eng until initialisation completes
2026-11-11 21:52 [PATCH 00/10] dmaengine: Fix teardown races, resource leaks, and error handling Lee Jones
` (5 preceding siblings ...)
2026-11-11 21:52 ` [PATCH 06/10] dmaengine: arm-dma350: Query dma_cookie_status() under vc.lock in d350_tx_status() Lee Jones
@ 2026-11-11 21:52 ` Lee Jones
2026-11-11 21:52 ` [PATCH 08/10] dmaengine: bestcomm: Check rh_create() return value in bcom_sram_init() Lee Jones
` (2 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Lee Jones @ 2026-11-11 21:52 UTC (permalink / raw)
To: lee, Vinod Koul, Frank Li, Sylvain Munaut, Andrey Volkov,
Dale Farnsworth, Grant Likely, dmaengine, linux-kernel
Cc: stable
mpc52xx_bcom_probe() assigns the newly allocated struct bcom_engine to
the global bcom_eng pointer before calling bcom_engine_init(). A
concurrent call to bcom_task_alloc() can observe a non-NULL bcom_eng
pointer before its spinlock and task descriptor table are initialised.
Initialise the engine via a local pointer and only publish bcom_eng
once initialisation has succeeded.
Fixes: 2f9ea1bde0d1 ("[POWERPC] bestcomm: core bestcomm support for Freescale MPC5200")
Closes: https://sashiko.dev/#/bug/linux-0a202799-4946-44bf-b035-fbb2e329e666
Cc: stable@vger.kernel.org
Signed-off-by: Lee Jones <lee@kernel.org>
---
drivers/dma/bestcomm/bestcomm.c | 69 +++++++++++++++++----------------
1 file changed, 36 insertions(+), 33 deletions(-)
diff --git a/drivers/dma/bestcomm/bestcomm.c b/drivers/dma/bestcomm/bestcomm.c
index 241a91936fe8..dbc3ce5fc446 100644
--- a/drivers/dma/bestcomm/bestcomm.c
+++ b/drivers/dma/bestcomm/bestcomm.c
@@ -270,7 +270,7 @@ static u32 fdt_ops[] = {
};
-static int bcom_engine_init(void)
+static int bcom_engine_init(struct bcom_engine *eng)
{
int task;
phys_addr_t tdt_pa, ctx_pa, var_pa, fdt_pa;
@@ -282,56 +282,59 @@ static int bcom_engine_init(void)
var_size = BCOM_MAX_TASKS * (BCOM_VAR_SIZE + BCOM_INC_SIZE);
fdt_size = BCOM_FDT_SIZE;
- bcom_eng->tdt = bcom_sram_alloc(tdt_size, sizeof(u32), &tdt_pa);
- bcom_eng->ctx = bcom_sram_alloc(ctx_size, BCOM_CTX_ALIGN, &ctx_pa);
- bcom_eng->var = bcom_sram_alloc(var_size, BCOM_VAR_ALIGN, &var_pa);
- bcom_eng->fdt = bcom_sram_alloc(fdt_size, BCOM_FDT_ALIGN, &fdt_pa);
+ eng->tdt = bcom_sram_alloc(tdt_size, sizeof(u32), &tdt_pa);
+ eng->ctx = bcom_sram_alloc(ctx_size, BCOM_CTX_ALIGN, &ctx_pa);
+ eng->var = bcom_sram_alloc(var_size, BCOM_VAR_ALIGN, &var_pa);
+ eng->fdt = bcom_sram_alloc(fdt_size, BCOM_FDT_ALIGN, &fdt_pa);
- if (!bcom_eng->tdt || !bcom_eng->ctx || !bcom_eng->var || !bcom_eng->fdt) {
+ if (!eng->tdt || !eng->ctx || !eng->var || !eng->fdt) {
printk(KERN_ERR "DMA: SRAM alloc failed in engine init !\n");
- bcom_sram_free(bcom_eng->tdt);
- bcom_sram_free(bcom_eng->ctx);
- bcom_sram_free(bcom_eng->var);
- bcom_sram_free(bcom_eng->fdt);
+ bcom_sram_free(eng->tdt);
+ bcom_sram_free(eng->ctx);
+ bcom_sram_free(eng->var);
+ bcom_sram_free(eng->fdt);
return -ENOMEM;
}
- memset_io(bcom_eng->tdt, 0x00, tdt_size);
- memset_io(bcom_eng->ctx, 0x00, ctx_size);
- memset_io(bcom_eng->var, 0x00, var_size);
- memset_io(bcom_eng->fdt, 0x00, fdt_size);
+ memset_io(eng->tdt, 0x00, tdt_size);
+ memset_io(eng->ctx, 0x00, ctx_size);
+ memset_io(eng->var, 0x00, var_size);
+ memset_io(eng->fdt, 0x00, fdt_size);
/* Copy the FDT for the EU#3 */
- memcpy_toio(&bcom_eng->fdt[48], fdt_ops, sizeof(fdt_ops));
+ memcpy_toio(&eng->fdt[48], fdt_ops, sizeof(fdt_ops));
/* Initialize Task base structure */
for (task=0; task<BCOM_MAX_TASKS; task++)
{
- out_be16(&bcom_eng->regs->tcr[task], 0);
- out_8(&bcom_eng->regs->ipr[task], 0);
+ out_be16(&eng->regs->tcr[task], 0);
+ out_8(&eng->regs->ipr[task], 0);
- bcom_eng->tdt[task].context = ctx_pa;
- bcom_eng->tdt[task].var = var_pa;
- bcom_eng->tdt[task].fdt = fdt_pa;
+ eng->tdt[task].context = ctx_pa;
+ eng->tdt[task].var = var_pa;
+ eng->tdt[task].fdt = fdt_pa;
var_pa += BCOM_VAR_SIZE + BCOM_INC_SIZE;
ctx_pa += BCOM_CTX_SIZE;
}
- out_be32(&bcom_eng->regs->taskBar, tdt_pa);
+ out_be32(&eng->regs->taskBar, tdt_pa);
/* Init 'always' initiator */
- out_8(&bcom_eng->regs->ipr[BCOM_INITIATOR_ALWAYS], BCOM_IPR_ALWAYS);
+ out_8(&eng->regs->ipr[BCOM_INITIATOR_ALWAYS], BCOM_IPR_ALWAYS);
+
+ /* Init lock */
+ spin_lock_init(&eng->lock);
+
+ /* Ensure all engine fields are visible before publishing bcom_eng */
+ smp_store_release(&bcom_eng, eng);
/* Disable COMM Bus Prefetch on the original 5200; it's broken */
if ((mfspr(SPRN_SVR) & MPC5200_SVR_MASK) == MPC5200_SVR)
bcom_disable_prefetch();
- /* Init lock */
- spin_lock_init(&bcom_eng->lock);
-
return 0;
}
@@ -363,6 +366,7 @@ bcom_engine_cleanup(void)
static int mpc52xx_bcom_probe(struct platform_device *op)
{
+ struct bcom_engine *eng;
struct device_node *ofn_sram;
struct resource *res_bcom;
void __iomem *regs;
@@ -398,20 +402,20 @@ static int mpc52xx_bcom_probe(struct platform_device *op)
}
/* Get a clean struct */
- bcom_eng = kzalloc_obj(struct bcom_engine);
- if (!bcom_eng) {
+ eng = kzalloc_obj(struct bcom_engine);
+ if (!eng) {
rv = -ENOMEM;
goto error_sramclean;
}
/* Save the node */
- bcom_eng->ofnode = op->dev.of_node;
+ eng->ofnode = op->dev.of_node;
- bcom_eng->regs = regs;
- bcom_eng->regs_base = res_bcom->start;
+ eng->regs = regs;
+ eng->regs_base = res_bcom->start;
/* Now, do the real init */
- rv = bcom_engine_init();
+ rv = bcom_engine_init(eng);
if (rv)
goto error_sramclean;
@@ -423,8 +427,7 @@ static int mpc52xx_bcom_probe(struct platform_device *op)
/* Error path */
error_sramclean:
- kfree(bcom_eng);
- bcom_eng = NULL;
+ kfree(eng);
bcom_sram_cleanup();
error_ofput:
of_node_put(op->dev.of_node);
--
2.56.0.567.gdb80ae8cd5-goog
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH 08/10] dmaengine: bestcomm: Check rh_create() return value in bcom_sram_init()
2026-11-11 21:52 [PATCH 00/10] dmaengine: Fix teardown races, resource leaks, and error handling Lee Jones
` (6 preceding siblings ...)
2026-11-11 21:52 ` [PATCH 07/10] dmaengine: bestcomm: Defer publishing bcom_eng until initialisation completes Lee Jones
@ 2026-11-11 21:52 ` Lee Jones
2026-11-11 21:52 ` [PATCH 09/10] dmaengine: jz4780: Fix descriptor cleanup on hwdesc setup failure Lee Jones
2026-11-11 21:52 ` [PATCH 10/10] dmaengine: dmatest: Avoid unsigned underflow in min_odd() Lee Jones
9 siblings, 0 replies; 11+ messages in thread
From: Lee Jones @ 2026-11-11 21:52 UTC (permalink / raw)
To: lee, Vinod Koul, Frank Li, Sylvain Munaut, Grant Likely,
dmaengine, linux-kernel
Cc: stable
rh_create() returns ERR_PTR(-ENOMEM) on allocation failure.
bcom_sram_init() assigns this return value directly to bcom_sram->rh
without checking IS_ERR() and passes it to rh_attach_region(), which
dereferences the error pointer.
Check IS_ERR(bcom_sram->rh) after rh_create() and unmap the SRAM region
on failure.
Fixes: 2f9ea1bde0d1 ("[POWERPC] bestcomm: core bestcomm support for Freescale MPC5200")
Closes: https://sashiko.dev/#/bug/linux-c3caaf6f-9a88-4451-b40e-d061c1fdeabd
Cc: stable@vger.kernel.org
Signed-off-by: Lee Jones <lee@kernel.org>
---
drivers/dma/bestcomm/sram.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/dma/bestcomm/sram.c b/drivers/dma/bestcomm/sram.c
index 09ef5142c26c..df4d90cee465 100644
--- a/drivers/dma/bestcomm/sram.c
+++ b/drivers/dma/bestcomm/sram.c
@@ -88,6 +88,10 @@ int bcom_sram_init(struct device_node *sram_node, char *owner)
/* Create an rheap (defaults to 32 bits word alignment) */
bcom_sram->rh = rh_create(4);
+ if (IS_ERR(bcom_sram->rh)) {
+ rv = PTR_ERR(bcom_sram->rh);
+ goto error_unmap;
+ }
/* Attach the free zones */
regaddr_p = NULL;
@@ -111,6 +115,8 @@ int bcom_sram_init(struct device_node *sram_node, char *owner)
return 0;
+error_unmap:
+ iounmap((void __iomem *)bcom_sram->base_virt);
error_release:
release_mem_region(res.start, resource_size(&res));
error_free:
--
2.56.0.567.gdb80ae8cd5-goog
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH 09/10] dmaengine: jz4780: Fix descriptor cleanup on hwdesc setup failure
2026-11-11 21:52 [PATCH 00/10] dmaengine: Fix teardown races, resource leaks, and error handling Lee Jones
` (7 preceding siblings ...)
2026-11-11 21:52 ` [PATCH 08/10] dmaengine: bestcomm: Check rh_create() return value in bcom_sram_init() Lee Jones
@ 2026-11-11 21:52 ` Lee Jones
2026-11-11 21:52 ` [PATCH 10/10] dmaengine: dmatest: Avoid unsigned underflow in min_odd() Lee Jones
9 siblings, 0 replies; 11+ messages in thread
From: Lee Jones @ 2026-11-11 21:52 UTC (permalink / raw)
To: lee, Paul Cercueil, Vinod Koul, Frank Li, Alex Smith,
Zubair Lutfullah Kakakhel, linux-mips, dmaengine, linux-kernel
Cc: stable
When jz4780_dma_setup_hwdesc() fails in jz4780_dma_prep_slave_sg() or
jz4780_dma_prep_dma_cyclic(), the error paths pass &jzchan->desc->vdesc
to jz4780_dma_desc_free() instead of the newly allocated &desc->vdesc.
This leaks the newly allocated descriptor and either dereferences NULL
when jzchan->desc is NULL or frees the currently active descriptor while
it is still in flight. Furthermore, jz4780_dma_desc_free() derives
jzchan from vdesc->tx.chan, which is not yet initialised before
vchan_tx_prep() is called.
Initialise desc->vdesc.tx.chan in jz4780_dma_desc_alloc() and pass
&desc->vdesc to jz4780_dma_desc_free() in the preparation error paths.
Fixes: d894fc6046fe ("dmaengine: jz4780: add driver for the Ingenic JZ4780 DMA controller")
Closes: https://sashiko.dev/#/bug/linux-b39121ef-5ffb-401a-9d04-0afccd467bde
Cc: stable@vger.kernel.org
Signed-off-by: Lee Jones <lee@kernel.org>
---
drivers/dma/dma-jz4780.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/dma/dma-jz4780.c b/drivers/dma/dma-jz4780.c
index ac2094e65ecf..c3974c825ba7 100644
--- a/drivers/dma/dma-jz4780.c
+++ b/drivers/dma/dma-jz4780.c
@@ -248,6 +248,7 @@ jz4780_dma_desc_alloc(struct jz4780_dma_chan *jzchan, unsigned int count,
return NULL;
}
+ desc->vdesc.tx.chan = &jzchan->vchan.chan;
desc->count = count;
desc->type = type;
@@ -379,7 +380,7 @@ static struct dma_async_tx_descriptor *jz4780_dma_prep_slave_sg(
sg_dma_len(&sgl[i]),
direction);
if (err < 0) {
- jz4780_dma_desc_free(&jzchan->desc->vdesc);
+ jz4780_dma_desc_free(&desc->vdesc);
return NULL;
}
@@ -426,7 +427,7 @@ static struct dma_async_tx_descriptor *jz4780_dma_prep_dma_cyclic(
err = jz4780_dma_setup_hwdesc(jzchan, &desc->desc[i], buf_addr,
period_len, direction);
if (err < 0) {
- jz4780_dma_desc_free(&jzchan->desc->vdesc);
+ jz4780_dma_desc_free(&desc->vdesc);
return NULL;
}
--
2.56.0.567.gdb80ae8cd5-goog
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH 10/10] dmaengine: dmatest: Avoid unsigned underflow in min_odd()
2026-11-11 21:52 [PATCH 00/10] dmaengine: Fix teardown races, resource leaks, and error handling Lee Jones
` (8 preceding siblings ...)
2026-11-11 21:52 ` [PATCH 09/10] dmaengine: jz4780: Fix descriptor cleanup on hwdesc setup failure Lee Jones
@ 2026-11-11 21:52 ` Lee Jones
9 siblings, 0 replies; 11+ messages in thread
From: Lee Jones @ 2026-11-11 21:52 UTC (permalink / raw)
To: lee, Vinod Koul, Frank Li, Akinobu Mita, dmaengine, linux-kernel; +Cc: stable
When either argument to min_odd() is zero (for example when a DMA device
reports max_xor or max_pq as 0), val evaluates to 0 and val - 1
underflows to UINT_MAX. In dmatest_func(), this sets src->cnt to
UINT_MAX, which wraps around the (src->cnt + dst->cnt) >= 255 check and
causes dmatest_alloc_test_data() to pass 0 to kcalloc() and dereference
ZERO_SIZE_PTR.
Return 0 from min_odd() when the minimum value is 0, and abort
dmatest_func() if src->cnt is 0.
Fixes: 8be9e32b310c ("dmatest: adjust invalid module parameters for number of source buffers")
Closes: https://sashiko.dev/#/bug/linux-ca967586-4fc1-47a3-8616-4a9d21fe7455
Cc: stable@vger.kernel.org
Signed-off-by: Lee Jones <lee@kernel.org>
---
drivers/dma/dmatest.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
index 2ae3469397f3..5f768bb9a29f 100644
--- a/drivers/dma/dmatest.c
+++ b/drivers/dma/dmatest.c
@@ -457,6 +457,9 @@ static unsigned int min_odd(unsigned int x, unsigned int y)
{
unsigned int val = min(x, y);
+ if (!val)
+ return 0;
+
return val % 2 ? val : val - 1;
}
@@ -650,6 +653,9 @@ static int dmatest_func(void *data)
} else
goto err_thread_type;
+ if (!src->cnt)
+ goto err_free_coefs;
+
/* Check if buffer count fits into map count variable (u8) */
if ((src->cnt + dst->cnt) >= 255) {
pr_err("too many buffers (%d of 255 supported)\n",
--
2.56.0.567.gdb80ae8cd5-goog
^ permalink raw reply [flat|nested] 11+ messages in thread