mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 00/10] dmaengine: Fix teardown races, resource leaks, and error handling
@ 2026-11-11 21:52 Lee Jones
  2026-11-11 21:52 ` [PATCH 01/10] dmaengine: pl08x: Defer OF DMA controller registration until slave setup Lee Jones
                   ` (9 more replies)
  0 siblings, 10 replies; 11+ messages in thread
From: Lee Jones @ 2026-11-11 21:52 UTC (permalink / raw)
  To: lee
  Cc: linux-kernel, Akinobu Mita, Alex Smith, Andrey Volkov,
	Basavaraj Natikar, Colin Ian King, Dale Farnsworth, dmaengine,
	Frank Li, Gary R Hook, Grant Likely, Jacky Huang,
	Joachim Eastwood, Linus Walleij, linux-amlogic, linux-arm-kernel,
	linux-mips, Paul Cercueil, Peter Pearse, Philipp Stanner,
	Raju Rangoju, Robin Murphy, Sanjay R Mehta, Shan-Chun Hung,
	Sylvain Munaut, Vinod Koul, Xianwei Zhao,
	Zubair Lutfullah Kakakhel

These issues were reported by Sashiko.

Cc: Akinobu Mita <akinobu.mita@gmail.com>
Cc: Alex Smith <alex@alex-smith.me.uk>
Cc: Andrey Volkov <avolkov@varma-el.com>
Cc: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
Cc: Colin Ian King <colin.i.king@gmail.com>
Cc: Dale Farnsworth <dfarnsworth@mvista.com>
Cc: dmaengine@vger.kernel.org
Cc: Frank Li <Frank.Li@kernel.org>
Cc: Gary R Hook <gary.hook@amd.com>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Jacky Huang <ychuang3@nuvoton.com>
Cc: Joachim Eastwood <manabian@gmail.com>
Cc: Linus Walleij <linusw@kernel.org>
Cc: linux-amlogic@lists.infradead.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-mips@vger.kernel.org
Cc: Paul Cercueil <paul@crapouillou.net>
Cc: Peter Pearse <peter.pearse@arm.com>
Cc: Philipp Stanner <pstanner@redhat.com>
Cc: Raju Rangoju <Raju.Rangoju@amd.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Sanjay R Mehta <sanju.mehta@amd.com>
Cc: Shan-Chun Hung <schung@nuvoton.com>
Cc: Sylvain Munaut <tnt@246tNt.com>
Cc: Vinod Koul <vkoul@kernel.org>
Cc: Xianwei Zhao <xianwei.zhao@amlogic.com>
Cc: Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>

Lee Jones (10):
  dmaengine: pl08x: Defer OF DMA controller registration until slave
    setup
  dmaengine: ae4dma: Unregister DMA engine in ae4_pci_remove()
  dmaengine: ptdma: Unmap descriptor in pt_do_cleanup()
  dmaengine: ptdma: Remove completed descriptor under vc.lock in
    pt_cmd_callback_work()
  dmaengine: amlogic: Destroy free_wq after devres DMA device
    unregistration
  dmaengine: arm-dma350: Query dma_cookie_status() under vc.lock in
    d350_tx_status()
  dmaengine: bestcomm: Defer publishing bcom_eng until initialisation
    completes
  dmaengine: bestcomm: Check rh_create() return value in
    bcom_sram_init()
  dmaengine: jz4780: Fix descriptor cleanup on hwdesc setup failure
  dmaengine: dmatest: Avoid unsigned underflow in min_odd()

 drivers/dma/amba-pl08x.c                | 23 +++++++++
 drivers/dma/amd/ae4dma/ae4dma-pci.c     |  1 +
 drivers/dma/amd/ptdma/ptdma-dmaengine.c |  4 +-
 drivers/dma/amlogic-dma.c               |  3 +-
 drivers/dma/arm-dma350.c                |  3 +-
 drivers/dma/bestcomm/bestcomm.c         | 69 +++++++++++++------------
 drivers/dma/bestcomm/sram.c             |  6 +++
 drivers/dma/dma-jz4780.c                |  5 +-
 drivers/dma/dmatest.c                   |  6 +++
 9 files changed, 80 insertions(+), 40 deletions(-)

-- 
2.56.0.567.gdb80ae8cd5-goog


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [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

end of thread, other threads:[~2026-11-11 21:55 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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 ` [PATCH 03/10] dmaengine: ptdma: Unmap descriptor in pt_do_cleanup() 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
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 ` [PATCH 06/10] dmaengine: arm-dma350: Query dma_cookie_status() under vc.lock in d350_tx_status() Lee Jones
2026-11-11 21:52 ` [PATCH 07/10] dmaengine: bestcomm: Defer publishing bcom_eng until initialisation completes Lee Jones
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 ` [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

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®