linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/11] i.MX SDMA cleanups and fixes
@ 2025-09-03 13:06 Marco Felsch
  2025-09-03 13:06 ` [PATCH 01/11] dmaengine: imx-sdma: drop legacy device_node np check Marco Felsch
                   ` (10 more replies)
  0 siblings, 11 replies; 23+ messages in thread
From: Marco Felsch @ 2025-09-03 13:06 UTC (permalink / raw)
  To: Vinod Koul, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Jiada Wang
  Cc: dmaengine, imx, linux-arm-kernel, linux-kernel, Marco Felsch

Hi,

the current i.MX SDMA driver doesn't honor current active DMA users once
the i.MX SDMA driver is getting removed. Which can lead into very
situations e.g. hang the whole system.

This is fixed by cleaning up the driver and adding devlink support to
the SDMA driver.

This series also fixes the i.MX SDMA handling on i.MX8M* devices, which
do have multiple SPBA buses.

Regards,
  Marco

Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
Marco Felsch (11):
      dmaengine: imx-sdma: drop legacy device_node np check
      dmaengine: imx-sdma: sdma_remove minor cleanups
      dmaengine: imx-sdma: cosmetic cleanup
      dmaengine: imx-sdma: make use of devm_kzalloc for script_addrs
      dmaengine: imx-sdma: make use of devm_clk_get_prepared()
      dmaengine: imx-sdma: make use of devm_add_action_or_reset to unregiser the dma_device
      dmaengine: imx-sdma: make use of dev_err_probe()
      dmaengine: imx-sdma: fix missing of_dma_controller_free()
      dmaengine: add support for device_link
      dmaengine: imx-sdma: drop remove callback
      dmaengine: imx-sdma: fix spba-bus handling for i.MX8M

 drivers/dma/dmaengine.c |   8 +++
 drivers/dma/imx-sdma.c  | 188 +++++++++++++++++++++++-------------------------
 2 files changed, 97 insertions(+), 99 deletions(-)
---
base-commit: 038d61fd642278bab63ee8ef722c50d10ab01e8f
change-id: 20250903-v6-16-topic-sdma-4c8fd3bb0738

Best regards,
-- 
Marco Felsch <m.felsch@pengutronix.de>


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

* [PATCH 01/11] dmaengine: imx-sdma: drop legacy device_node np check
  2025-09-03 13:06 [PATCH 00/11] i.MX SDMA cleanups and fixes Marco Felsch
@ 2025-09-03 13:06 ` Marco Felsch
  2025-09-03 14:48   ` Frank Li
  2025-09-03 13:06 ` [PATCH 02/11] dmaengine: imx-sdma: sdma_remove minor cleanups Marco Felsch
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: Marco Felsch @ 2025-09-03 13:06 UTC (permalink / raw)
  To: Vinod Koul, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Jiada Wang
  Cc: dmaengine, imx, linux-arm-kernel, linux-kernel, Marco Felsch

The legacy 'if (np)' was required in past where we had pdata and dt.
Nowadays the driver binds only to dt platforms. So using a new kernel
but still use pdata is not possible, therefore we can drop the legacy
'if' code path.

Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 drivers/dma/imx-sdma.c | 32 ++++++++++++++------------------
 1 file changed, 14 insertions(+), 18 deletions(-)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 02a85d6f1bea2df7d355858094c0c0b0bd07148e..89b4b1266726a9c8a552dc48670825ae00717e1c 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -2325,11 +2325,9 @@ static int sdma_probe(struct platform_device *pdev)
 			vchan_init(&sdmac->vc, &sdma->dma_device);
 	}
 
-	if (np) {
-		sdma->iram_pool = of_gen_pool_get(np, "iram", 0);
-		if (sdma->iram_pool)
-			dev_info(&pdev->dev, "alloc bd from iram.\n");
-	}
+	sdma->iram_pool = of_gen_pool_get(np, "iram", 0);
+	if (sdma->iram_pool)
+		dev_info(&pdev->dev, "alloc bd from iram.\n");
 
 	ret = sdma_init(sdma);
 	if (ret)
@@ -2369,21 +2367,19 @@ static int sdma_probe(struct platform_device *pdev)
 		goto err_init;
 	}
 
-	if (np) {
-		ret = of_dma_controller_register(np, sdma_xlate, sdma);
-		if (ret) {
-			dev_err(&pdev->dev, "failed to register controller\n");
-			goto err_register;
-		}
+	ret = of_dma_controller_register(np, sdma_xlate, sdma);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register controller\n");
+		goto err_register;
+	}
 
-		spba_bus = of_find_compatible_node(NULL, NULL, "fsl,spba-bus");
-		ret = of_address_to_resource(spba_bus, 0, &spba_res);
-		if (!ret) {
-			sdma->spba_start_addr = spba_res.start;
-			sdma->spba_end_addr = spba_res.end;
-		}
-		of_node_put(spba_bus);
+	spba_bus = of_find_compatible_node(NULL, NULL, "fsl,spba-bus");
+	ret = of_address_to_resource(spba_bus, 0, &spba_res);
+	if (!ret) {
+		sdma->spba_start_addr = spba_res.start;
+		sdma->spba_end_addr = spba_res.end;
 	}
+	of_node_put(spba_bus);
 
 	/*
 	 * Because that device tree does not encode ROM script address,

-- 
2.47.2


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

* [PATCH 02/11] dmaengine: imx-sdma: sdma_remove minor cleanups
  2025-09-03 13:06 [PATCH 00/11] i.MX SDMA cleanups and fixes Marco Felsch
  2025-09-03 13:06 ` [PATCH 01/11] dmaengine: imx-sdma: drop legacy device_node np check Marco Felsch
@ 2025-09-03 13:06 ` Marco Felsch
  2025-09-03 14:50   ` Frank Li
  2025-09-03 13:06 ` [PATCH 03/11] dmaengine: imx-sdma: cosmetic cleanup Marco Felsch
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: Marco Felsch @ 2025-09-03 13:06 UTC (permalink / raw)
  To: Vinod Koul, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Jiada Wang
  Cc: dmaengine, imx, linux-arm-kernel, linux-kernel, Marco Felsch

We don't need to set the pdev driver data to NULL since the device will
be freed anyways.

Also drop the tasklet_kill() since this is done by the virt-dma driver
during the vchan_synchronize().

Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 drivers/dma/imx-sdma.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 89b4b1266726a9c8a552dc48670825ae00717e1c..422086632d3445b2ce3f2e5df9b2130174a311e8 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -2423,11 +2423,8 @@ static void sdma_remove(struct platform_device *pdev)
 	for (i = 0; i < MAX_DMA_CHANNELS; i++) {
 		struct sdma_channel *sdmac = &sdma->channel[i];
 
-		tasklet_kill(&sdmac->vc.task);
 		sdma_free_chan_resources(&sdmac->vc.chan);
 	}
-
-	platform_set_drvdata(pdev, NULL);
 }
 
 static struct platform_driver sdma_driver = {

-- 
2.47.2


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

* [PATCH 03/11] dmaengine: imx-sdma: cosmetic cleanup
  2025-09-03 13:06 [PATCH 00/11] i.MX SDMA cleanups and fixes Marco Felsch
  2025-09-03 13:06 ` [PATCH 01/11] dmaengine: imx-sdma: drop legacy device_node np check Marco Felsch
  2025-09-03 13:06 ` [PATCH 02/11] dmaengine: imx-sdma: sdma_remove minor cleanups Marco Felsch
@ 2025-09-03 13:06 ` Marco Felsch
  2025-09-03 14:55   ` Frank Li
  2025-09-03 13:06 ` [PATCH 04/11] dmaengine: imx-sdma: make use of devm_kzalloc for script_addrs Marco Felsch
                   ` (7 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: Marco Felsch @ 2025-09-03 13:06 UTC (permalink / raw)
  To: Vinod Koul, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Jiada Wang
  Cc: dmaengine, imx, linux-arm-kernel, linux-kernel, Marco Felsch

Make use of local struct device pointer to not dereference the
platform_device pointer everytime.

Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 drivers/dma/imx-sdma.c | 31 ++++++++++++++++---------------
 1 file changed, 16 insertions(+), 15 deletions(-)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 422086632d3445b2ce3f2e5df9b2130174a311e8..a85739d279f51fdb517fce90b3dc67673cf2b56c 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -2234,7 +2234,8 @@ static struct dma_chan *sdma_xlate(struct of_phandle_args *dma_spec,
 
 static int sdma_probe(struct platform_device *pdev)
 {
-	struct device_node *np = pdev->dev.of_node;
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
 	struct device_node *spba_bus;
 	const char *fw_name;
 	int ret;
@@ -2244,18 +2245,18 @@ static int sdma_probe(struct platform_device *pdev)
 	struct sdma_engine *sdma;
 	s32 *saddr_arr;
 
-	ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+	ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
 	if (ret)
 		return ret;
 
-	sdma = devm_kzalloc(&pdev->dev, sizeof(*sdma), GFP_KERNEL);
+	sdma = devm_kzalloc(dev, sizeof(*sdma), GFP_KERNEL);
 	if (!sdma)
 		return -ENOMEM;
 
 	spin_lock_init(&sdma->channel_0_lock);
 
-	sdma->dev = &pdev->dev;
-	sdma->drvdata = of_device_get_match_data(sdma->dev);
+	sdma->dev = dev;
+	sdma->drvdata = of_device_get_match_data(dev);
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0)
@@ -2265,11 +2266,11 @@ static int sdma_probe(struct platform_device *pdev)
 	if (IS_ERR(sdma->regs))
 		return PTR_ERR(sdma->regs);
 
-	sdma->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
+	sdma->clk_ipg = devm_clk_get(dev, "ipg");
 	if (IS_ERR(sdma->clk_ipg))
 		return PTR_ERR(sdma->clk_ipg);
 
-	sdma->clk_ahb = devm_clk_get(&pdev->dev, "ahb");
+	sdma->clk_ahb = devm_clk_get(dev, "ahb");
 	if (IS_ERR(sdma->clk_ahb))
 		return PTR_ERR(sdma->clk_ahb);
 
@@ -2281,8 +2282,8 @@ static int sdma_probe(struct platform_device *pdev)
 	if (ret)
 		goto err_clk;
 
-	ret = devm_request_irq(&pdev->dev, irq, sdma_int_handler, 0,
-				dev_name(&pdev->dev), sdma);
+	ret = devm_request_irq(dev, irq, sdma_int_handler, 0,
+			       dev_name(dev), sdma);
 	if (ret)
 		goto err_irq;
 
@@ -2327,7 +2328,7 @@ static int sdma_probe(struct platform_device *pdev)
 
 	sdma->iram_pool = of_gen_pool_get(np, "iram", 0);
 	if (sdma->iram_pool)
-		dev_info(&pdev->dev, "alloc bd from iram.\n");
+		dev_info(dev, "alloc bd from iram.\n");
 
 	ret = sdma_init(sdma);
 	if (ret)
@@ -2340,7 +2341,7 @@ static int sdma_probe(struct platform_device *pdev)
 	if (sdma->drvdata->script_addrs)
 		sdma_add_scripts(sdma, sdma->drvdata->script_addrs);
 
-	sdma->dma_device.dev = &pdev->dev;
+	sdma->dma_device.dev = dev;
 
 	sdma->dma_device.device_alloc_chan_resources = sdma_alloc_chan_resources;
 	sdma->dma_device.device_free_chan_resources = sdma_free_chan_resources;
@@ -2363,13 +2364,13 @@ static int sdma_probe(struct platform_device *pdev)
 
 	ret = dma_async_device_register(&sdma->dma_device);
 	if (ret) {
-		dev_err(&pdev->dev, "unable to register\n");
+		dev_err(dev, "unable to register\n");
 		goto err_init;
 	}
 
 	ret = of_dma_controller_register(np, sdma_xlate, sdma);
 	if (ret) {
-		dev_err(&pdev->dev, "failed to register controller\n");
+		dev_err(dev, "failed to register controller\n");
 		goto err_register;
 	}
 
@@ -2389,11 +2390,11 @@ static int sdma_probe(struct platform_device *pdev)
 	ret = of_property_read_string(np, "fsl,sdma-ram-script-name",
 				      &fw_name);
 	if (ret) {
-		dev_warn(&pdev->dev, "failed to get firmware name\n");
+		dev_warn(dev, "failed to get firmware name\n");
 	} else {
 		ret = sdma_get_firmware(sdma, fw_name);
 		if (ret)
-			dev_warn(&pdev->dev, "failed to get firmware from device tree\n");
+			dev_warn(dev, "failed to get firmware from device tree\n");
 	}
 
 	return 0;

-- 
2.47.2


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

* [PATCH 04/11] dmaengine: imx-sdma: make use of devm_kzalloc for script_addrs
  2025-09-03 13:06 [PATCH 00/11] i.MX SDMA cleanups and fixes Marco Felsch
                   ` (2 preceding siblings ...)
  2025-09-03 13:06 ` [PATCH 03/11] dmaengine: imx-sdma: cosmetic cleanup Marco Felsch
@ 2025-09-03 13:06 ` Marco Felsch
  2025-09-03 15:00   ` Frank Li
  2025-09-03 13:06 ` [PATCH 05/11] dmaengine: imx-sdma: make use of devm_clk_get_prepared() Marco Felsch
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: Marco Felsch @ 2025-09-03 13:06 UTC (permalink / raw)
  To: Vinod Koul, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Jiada Wang
  Cc: dmaengine, imx, linux-arm-kernel, linux-kernel, Marco Felsch

Shuffle the allocation of script_addrs and make use of devm_kzalloc() to
drop the local error handling as well as the kfree() during the remove.

Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 drivers/dma/imx-sdma.c | 19 +++++++------------
 1 file changed, 7 insertions(+), 12 deletions(-)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index a85739d279f51fdb517fce90b3dc67673cf2b56c..b6e649fda71dbce12a2106c94887f90d0aaaf600 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -2253,6 +2253,10 @@ static int sdma_probe(struct platform_device *pdev)
 	if (!sdma)
 		return -ENOMEM;
 
+	sdma->script_addrs = devm_kzalloc(dev, sizeof(*sdma->script_addrs), GFP_KERNEL);
+	if (!sdma->script_addrs)
+		return -ENOMEM;
+
 	spin_lock_init(&sdma->channel_0_lock);
 
 	sdma->dev = dev;
@@ -2289,12 +2293,6 @@ static int sdma_probe(struct platform_device *pdev)
 
 	sdma->irq = irq;
 
-	sdma->script_addrs = kzalloc(sizeof(*sdma->script_addrs), GFP_KERNEL);
-	if (!sdma->script_addrs) {
-		ret = -ENOMEM;
-		goto err_irq;
-	}
-
 	/* initially no scripts available */
 	saddr_arr = (s32 *)sdma->script_addrs;
 	for (i = 0; i < sizeof(*sdma->script_addrs) / sizeof(s32); i++)
@@ -2332,11 +2330,11 @@ static int sdma_probe(struct platform_device *pdev)
 
 	ret = sdma_init(sdma);
 	if (ret)
-		goto err_init;
+		goto err_irq;
 
 	ret = sdma_event_remap(sdma);
 	if (ret)
-		goto err_init;
+		goto err_irq;
 
 	if (sdma->drvdata->script_addrs)
 		sdma_add_scripts(sdma, sdma->drvdata->script_addrs);
@@ -2365,7 +2363,7 @@ static int sdma_probe(struct platform_device *pdev)
 	ret = dma_async_device_register(&sdma->dma_device);
 	if (ret) {
 		dev_err(dev, "unable to register\n");
-		goto err_init;
+		goto err_irq;
 	}
 
 	ret = of_dma_controller_register(np, sdma_xlate, sdma);
@@ -2401,8 +2399,6 @@ static int sdma_probe(struct platform_device *pdev)
 
 err_register:
 	dma_async_device_unregister(&sdma->dma_device);
-err_init:
-	kfree(sdma->script_addrs);
 err_irq:
 	clk_unprepare(sdma->clk_ahb);
 err_clk:
@@ -2417,7 +2413,6 @@ static void sdma_remove(struct platform_device *pdev)
 
 	devm_free_irq(&pdev->dev, sdma->irq, sdma);
 	dma_async_device_unregister(&sdma->dma_device);
-	kfree(sdma->script_addrs);
 	clk_unprepare(sdma->clk_ahb);
 	clk_unprepare(sdma->clk_ipg);
 	/* Kill the tasklet */

-- 
2.47.2


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

* [PATCH 05/11] dmaengine: imx-sdma: make use of devm_clk_get_prepared()
  2025-09-03 13:06 [PATCH 00/11] i.MX SDMA cleanups and fixes Marco Felsch
                   ` (3 preceding siblings ...)
  2025-09-03 13:06 ` [PATCH 04/11] dmaengine: imx-sdma: make use of devm_kzalloc for script_addrs Marco Felsch
@ 2025-09-03 13:06 ` Marco Felsch
  2025-09-03 15:01   ` Frank Li
  2025-09-03 13:06 ` [PATCH 06/11] dmaengine: imx-sdma: make use of devm_add_action_or_reset to unregiser the dma_device Marco Felsch
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: Marco Felsch @ 2025-09-03 13:06 UTC (permalink / raw)
  To: Vinod Koul, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Jiada Wang
  Cc: dmaengine, imx, linux-arm-kernel, linux-kernel, Marco Felsch

Make use of the devm_clk_get_prepared() to cleanup the error handling
during probe() and to automatically unprepare the clock during remove.

Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 drivers/dma/imx-sdma.c | 27 +++++++--------------------
 1 file changed, 7 insertions(+), 20 deletions(-)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index b6e649fda71dbce12a2106c94887f90d0aaaf600..5a571d3f33158813e0c56484600a49b19a6a72e2 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -2270,26 +2270,18 @@ static int sdma_probe(struct platform_device *pdev)
 	if (IS_ERR(sdma->regs))
 		return PTR_ERR(sdma->regs);
 
-	sdma->clk_ipg = devm_clk_get(dev, "ipg");
+	sdma->clk_ipg = devm_clk_get_prepared(dev, "ipg");
 	if (IS_ERR(sdma->clk_ipg))
 		return PTR_ERR(sdma->clk_ipg);
 
-	sdma->clk_ahb = devm_clk_get(dev, "ahb");
+	sdma->clk_ahb = devm_clk_get_prepared(dev, "ahb");
 	if (IS_ERR(sdma->clk_ahb))
 		return PTR_ERR(sdma->clk_ahb);
 
-	ret = clk_prepare(sdma->clk_ipg);
-	if (ret)
-		return ret;
-
-	ret = clk_prepare(sdma->clk_ahb);
-	if (ret)
-		goto err_clk;
-
 	ret = devm_request_irq(dev, irq, sdma_int_handler, 0,
 			       dev_name(dev), sdma);
 	if (ret)
-		goto err_irq;
+		return ret;
 
 	sdma->irq = irq;
 
@@ -2330,11 +2322,11 @@ static int sdma_probe(struct platform_device *pdev)
 
 	ret = sdma_init(sdma);
 	if (ret)
-		goto err_irq;
+		return ret;
 
 	ret = sdma_event_remap(sdma);
 	if (ret)
-		goto err_irq;
+		return ret;
 
 	if (sdma->drvdata->script_addrs)
 		sdma_add_scripts(sdma, sdma->drvdata->script_addrs);
@@ -2363,7 +2355,7 @@ static int sdma_probe(struct platform_device *pdev)
 	ret = dma_async_device_register(&sdma->dma_device);
 	if (ret) {
 		dev_err(dev, "unable to register\n");
-		goto err_irq;
+		return ret;
 	}
 
 	ret = of_dma_controller_register(np, sdma_xlate, sdma);
@@ -2399,10 +2391,7 @@ static int sdma_probe(struct platform_device *pdev)
 
 err_register:
 	dma_async_device_unregister(&sdma->dma_device);
-err_irq:
-	clk_unprepare(sdma->clk_ahb);
-err_clk:
-	clk_unprepare(sdma->clk_ipg);
+
 	return ret;
 }
 
@@ -2413,8 +2402,6 @@ static void sdma_remove(struct platform_device *pdev)
 
 	devm_free_irq(&pdev->dev, sdma->irq, sdma);
 	dma_async_device_unregister(&sdma->dma_device);
-	clk_unprepare(sdma->clk_ahb);
-	clk_unprepare(sdma->clk_ipg);
 	/* Kill the tasklet */
 	for (i = 0; i < MAX_DMA_CHANNELS; i++) {
 		struct sdma_channel *sdmac = &sdma->channel[i];

-- 
2.47.2


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

* [PATCH 06/11] dmaengine: imx-sdma: make use of devm_add_action_or_reset to unregiser the dma_device
  2025-09-03 13:06 [PATCH 00/11] i.MX SDMA cleanups and fixes Marco Felsch
                   ` (4 preceding siblings ...)
  2025-09-03 13:06 ` [PATCH 05/11] dmaengine: imx-sdma: make use of devm_clk_get_prepared() Marco Felsch
@ 2025-09-03 13:06 ` Marco Felsch
  2025-09-03 14:53   ` Frank Li
  2025-09-03 13:06 ` [PATCH 07/11] dmaengine: imx-sdma: make use of dev_err_probe() Marco Felsch
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: Marco Felsch @ 2025-09-03 13:06 UTC (permalink / raw)
  To: Vinod Koul, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Jiada Wang
  Cc: dmaengine, imx, linux-arm-kernel, linux-kernel, Marco Felsch

Make use of the devm_add_action_or_reset() to register a custom devm_
release hook. This is required since we want to turn of the IRQs before
doing the dma_async_device_unregister().

This removes the last goto error handling within the probe function and
further trims the remove() function. Instead of freeing the irq, we can
disable it and let the devm-irq do the job to free the irq, since the
only purpose was to have the irqs disabled before calling
dma_async_device_unregister().

Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 drivers/dma/imx-sdma.c | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 5a571d3f33158813e0c56484600a49b19a6a72e2..f6bb2f88a62781c0431336c365fa30c46f1401ad 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -2232,6 +2232,14 @@ static struct dma_chan *sdma_xlate(struct of_phandle_args *dma_spec,
 				     ofdma->of_node);
 }
 
+static void sdma_dma_device_unregister_action(void *data)
+{
+	struct sdma_engine *sdma = data;
+
+	disable_irq(sdma->irq);
+	dma_async_device_unregister(&sdma->dma_device);
+}
+
 static int sdma_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -2358,10 +2366,12 @@ static int sdma_probe(struct platform_device *pdev)
 		return ret;
 	}
 
+	devm_add_action_or_reset(dev, sdma_dma_device_unregister_action, sdma);
+
 	ret = of_dma_controller_register(np, sdma_xlate, sdma);
 	if (ret) {
 		dev_err(dev, "failed to register controller\n");
-		goto err_register;
+		return ret;
 	}
 
 	spba_bus = of_find_compatible_node(NULL, NULL, "fsl,spba-bus");
@@ -2388,11 +2398,6 @@ static int sdma_probe(struct platform_device *pdev)
 	}
 
 	return 0;
-
-err_register:
-	dma_async_device_unregister(&sdma->dma_device);
-
-	return ret;
 }
 
 static void sdma_remove(struct platform_device *pdev)
@@ -2400,8 +2405,6 @@ static void sdma_remove(struct platform_device *pdev)
 	struct sdma_engine *sdma = platform_get_drvdata(pdev);
 	int i;
 
-	devm_free_irq(&pdev->dev, sdma->irq, sdma);
-	dma_async_device_unregister(&sdma->dma_device);
 	/* Kill the tasklet */
 	for (i = 0; i < MAX_DMA_CHANNELS; i++) {
 		struct sdma_channel *sdmac = &sdma->channel[i];

-- 
2.47.2


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

* [PATCH 07/11] dmaengine: imx-sdma: make use of dev_err_probe()
  2025-09-03 13:06 [PATCH 00/11] i.MX SDMA cleanups and fixes Marco Felsch
                   ` (5 preceding siblings ...)
  2025-09-03 13:06 ` [PATCH 06/11] dmaengine: imx-sdma: make use of devm_add_action_or_reset to unregiser the dma_device Marco Felsch
@ 2025-09-03 13:06 ` Marco Felsch
  2025-09-03 15:04   ` Frank Li
  2025-09-03 13:06 ` [PATCH 08/11] dmaengine: imx-sdma: fix missing of_dma_controller_free() Marco Felsch
                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: Marco Felsch @ 2025-09-03 13:06 UTC (permalink / raw)
  To: Vinod Koul, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Jiada Wang
  Cc: dmaengine, imx, linux-arm-kernel, linux-kernel, Marco Felsch

Convert the probe function to dev_err_probe() which helps users to
identify issues better.

Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 drivers/dma/imx-sdma.c | 28 ++++++++++++----------------
 1 file changed, 12 insertions(+), 16 deletions(-)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index f6bb2f88a62781c0431336c365fa30c46f1401ad..e30dd46cf6522ee2aa4d3aca9868a01afbd29615 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -2255,7 +2255,7 @@ static int sdma_probe(struct platform_device *pdev)
 
 	ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
 	if (ret)
-		return ret;
+		return dev_err_probe(dev, ret, "Failed to set DMA mask\n");
 
 	sdma = devm_kzalloc(dev, sizeof(*sdma), GFP_KERNEL);
 	if (!sdma)
@@ -2272,24 +2272,24 @@ static int sdma_probe(struct platform_device *pdev)
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0)
-		return irq;
+		return dev_err_probe(dev, irq, "Failed to get IRQ\n");
 
 	sdma->regs = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(sdma->regs))
-		return PTR_ERR(sdma->regs);
+		return dev_err_probe(dev, PTR_ERR(sdma->regs), "ioremap failed\n");
 
 	sdma->clk_ipg = devm_clk_get_prepared(dev, "ipg");
 	if (IS_ERR(sdma->clk_ipg))
-		return PTR_ERR(sdma->clk_ipg);
+		return dev_err_probe(dev, PTR_ERR(sdma->clk_ipg), "IPG clk_get_prepared failed\n");
 
 	sdma->clk_ahb = devm_clk_get_prepared(dev, "ahb");
 	if (IS_ERR(sdma->clk_ahb))
-		return PTR_ERR(sdma->clk_ahb);
+		return dev_err_probe(dev, PTR_ERR(sdma->clk_ahb), "AHB clk_get_prepared failed\n");
 
 	ret = devm_request_irq(dev, irq, sdma_int_handler, 0,
 			       dev_name(dev), sdma);
 	if (ret)
-		return ret;
+		return dev_err_probe(dev, ret, "Failed to request IRQ\n");
 
 	sdma->irq = irq;
 
@@ -2330,11 +2330,11 @@ static int sdma_probe(struct platform_device *pdev)
 
 	ret = sdma_init(sdma);
 	if (ret)
-		return ret;
+		return dev_err_probe(dev, ret, "sdma_init failed\n");
 
 	ret = sdma_event_remap(sdma);
 	if (ret)
-		return ret;
+		return dev_err_probe(dev, ret, "sdma_event_remap failed\n");
 
 	if (sdma->drvdata->script_addrs)
 		sdma_add_scripts(sdma, sdma->drvdata->script_addrs);
@@ -2361,18 +2361,14 @@ static int sdma_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, sdma);
 
 	ret = dma_async_device_register(&sdma->dma_device);
-	if (ret) {
-		dev_err(dev, "unable to register\n");
-		return ret;
-	}
+	if (ret)
+		return dev_err_probe(dev, ret, "unable to register\n");
 
 	devm_add_action_or_reset(dev, sdma_dma_device_unregister_action, sdma);
 
 	ret = of_dma_controller_register(np, sdma_xlate, sdma);
-	if (ret) {
-		dev_err(dev, "failed to register controller\n");
-		return ret;
-	}
+	if (ret)
+		return dev_err_probe(dev, ret, "failed to register controller\n");
 
 	spba_bus = of_find_compatible_node(NULL, NULL, "fsl,spba-bus");
 	ret = of_address_to_resource(spba_bus, 0, &spba_res);

-- 
2.47.2


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

* [PATCH 08/11] dmaengine: imx-sdma: fix missing of_dma_controller_free()
  2025-09-03 13:06 [PATCH 00/11] i.MX SDMA cleanups and fixes Marco Felsch
                   ` (6 preceding siblings ...)
  2025-09-03 13:06 ` [PATCH 07/11] dmaengine: imx-sdma: make use of dev_err_probe() Marco Felsch
@ 2025-09-03 13:06 ` Marco Felsch
  2025-09-03 15:08   ` Frank Li
  2025-09-03 13:06 ` [PATCH 09/11] dmaengine: add support for device_link Marco Felsch
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: Marco Felsch @ 2025-09-03 13:06 UTC (permalink / raw)
  To: Vinod Koul, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Jiada Wang
  Cc: dmaengine, imx, linux-arm-kernel, linux-kernel, Marco Felsch

Add the missing of_dma_controller_free() to free the resources allocated
via of_dma_controller_register(). The missing free was introduced long
time ago  by commit 23e118113782 ("dma: imx-sdma: use
module_platform_driver for SDMA driver") while adding a proper .remove()
implementation.

Fixes: 23e118113782 ("dma: imx-sdma: use module_platform_driver for SDMA driver")
Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 drivers/dma/imx-sdma.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index e30dd46cf6522ee2aa4d3aca9868a01afbd29615..6c6d38b202dd2deffc36b1bd27bc7c60de3d7403 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -2232,6 +2232,13 @@ static struct dma_chan *sdma_xlate(struct of_phandle_args *dma_spec,
 				     ofdma->of_node);
 }
 
+static void sdma_dma_of_dma_controller_unregister_action(void *data)
+{
+	struct sdma_engine *sdma = data;
+
+	of_dma_controller_free(sdma->dev->of_node);
+}
+
 static void sdma_dma_device_unregister_action(void *data)
 {
 	struct sdma_engine *sdma = data;
@@ -2370,6 +2377,8 @@ static int sdma_probe(struct platform_device *pdev)
 	if (ret)
 		return dev_err_probe(dev, ret, "failed to register controller\n");
 
+	devm_add_action_or_reset(dev, sdma_dma_of_dma_controller_unregister_action, sdma);
+
 	spba_bus = of_find_compatible_node(NULL, NULL, "fsl,spba-bus");
 	ret = of_address_to_resource(spba_bus, 0, &spba_res);
 	if (!ret) {

-- 
2.47.2


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

* [PATCH 09/11] dmaengine: add support for device_link
  2025-09-03 13:06 [PATCH 00/11] i.MX SDMA cleanups and fixes Marco Felsch
                   ` (7 preceding siblings ...)
  2025-09-03 13:06 ` [PATCH 08/11] dmaengine: imx-sdma: fix missing of_dma_controller_free() Marco Felsch
@ 2025-09-03 13:06 ` Marco Felsch
  2025-09-03 14:46   ` Frank Li
  2025-09-03 13:06 ` [PATCH 10/11] dmaengine: imx-sdma: drop remove callback Marco Felsch
  2025-09-03 13:06 ` [PATCH 11/11] dmaengine: imx-sdma: fix spba-bus handling for i.MX8M Marco Felsch
  10 siblings, 1 reply; 23+ messages in thread
From: Marco Felsch @ 2025-09-03 13:06 UTC (permalink / raw)
  To: Vinod Koul, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Jiada Wang
  Cc: dmaengine, imx, linux-arm-kernel, linux-kernel, Marco Felsch

Add support to create device_links between dmaengine suppliers and the
dma consumers. This shifts the device dep-chain teardown/bringup logic
to the driver core.

Moving this to the core allows the dmaengine drivers to simplify the
.remove() hooks and also to ensure that no dmaengine driver is ever
removed before the consumer is removed.

Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 drivers/dma/dmaengine.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index 758fcd0546d8bde8e8dddc6039848feeb1e24475..a50652bc70b8ce9d4edabfaa781b3432ee47d31e 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -817,6 +817,7 @@ struct dma_chan *dma_request_chan(struct device *dev, const char *name)
 	struct fwnode_handle *fwnode = dev_fwnode(dev);
 	struct dma_device *d, *_d;
 	struct dma_chan *chan = NULL;
+	struct device_link *dl;
 
 	if (is_of_node(fwnode))
 		chan = of_dma_request_slave_channel(to_of_node(fwnode), name);
@@ -858,6 +859,13 @@ struct dma_chan *dma_request_chan(struct device *dev, const char *name)
 	/* No functional issue if it fails, users are supposed to test before use */
 #endif
 
+	dl = device_link_add(dev, chan->device->dev, DL_FLAG_AUTOREMOVE_CONSUMER);
+	if (!dl) {
+		dev_err(dev, "failed to create device link to %s\n",
+			dev_name(chan->device->dev));
+		return ERR_PTR(-EINVAL);
+	}
+
 	chan->name = kasprintf(GFP_KERNEL, "dma:%s", name);
 	if (!chan->name)
 		return chan;

-- 
2.47.2


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

* [PATCH 10/11] dmaengine: imx-sdma: drop remove callback
  2025-09-03 13:06 [PATCH 00/11] i.MX SDMA cleanups and fixes Marco Felsch
                   ` (8 preceding siblings ...)
  2025-09-03 13:06 ` [PATCH 09/11] dmaengine: add support for device_link Marco Felsch
@ 2025-09-03 13:06 ` Marco Felsch
  2025-09-03 15:15   ` Frank Li
  2025-09-03 13:06 ` [PATCH 11/11] dmaengine: imx-sdma: fix spba-bus handling for i.MX8M Marco Felsch
  10 siblings, 1 reply; 23+ messages in thread
From: Marco Felsch @ 2025-09-03 13:06 UTC (permalink / raw)
  To: Vinod Koul, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Jiada Wang
  Cc: dmaengine, imx, linux-arm-kernel, linux-kernel, Marco Felsch

The whole driver was converted to the devm APIs except for this last
for-loop. This loop is buggy due to three reasons:
 1) It removes the channels without removing the users first. This can
    lead to very bad situations.
 2) The loop starts at 0 and which is channel0 which is a special
    control channel not registered via vchan_init(). Therefore the
    remove() always Oops because of NULL pointer exception.
 3) sdma_free_chan_resources() disable the clks unconditional without
    checking if the clks are enabled. This is done for all
    MAX_DMA_CHANNELS which hang the system if there is at least one unused
    channel.

Since the dmaengine core supports devlinks we already addressed the
first issue.

The devlink support also addresses the third issue because during the
consumer teardown phase each requested channel is dropped accordingly so
the dmaengine driver doesn't need to this.

The second issue is fixed by not doing anything on channel0.

To sum-up, all issues are fixed by dropping the .remove() callback and
let the frameworks do their job.

Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 drivers/dma/imx-sdma.c | 14 --------------
 1 file changed, 14 deletions(-)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 6c6d38b202dd2deffc36b1bd27bc7c60de3d7403..c31785977351163d6fddf4d8b2f90dfebb508400 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -2405,25 +2405,11 @@ static int sdma_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static void sdma_remove(struct platform_device *pdev)
-{
-	struct sdma_engine *sdma = platform_get_drvdata(pdev);
-	int i;
-
-	/* Kill the tasklet */
-	for (i = 0; i < MAX_DMA_CHANNELS; i++) {
-		struct sdma_channel *sdmac = &sdma->channel[i];
-
-		sdma_free_chan_resources(&sdmac->vc.chan);
-	}
-}
-
 static struct platform_driver sdma_driver = {
 	.driver		= {
 		.name	= "imx-sdma",
 		.of_match_table = sdma_dt_ids,
 	},
-	.remove		= sdma_remove,
 	.probe		= sdma_probe,
 };
 

-- 
2.47.2


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

* [PATCH 11/11] dmaengine: imx-sdma: fix spba-bus handling for i.MX8M
  2025-09-03 13:06 [PATCH 00/11] i.MX SDMA cleanups and fixes Marco Felsch
                   ` (9 preceding siblings ...)
  2025-09-03 13:06 ` [PATCH 10/11] dmaengine: imx-sdma: drop remove callback Marco Felsch
@ 2025-09-03 13:06 ` Marco Felsch
  2025-09-04  4:31   ` kernel test robot
  10 siblings, 1 reply; 23+ messages in thread
From: Marco Felsch @ 2025-09-03 13:06 UTC (permalink / raw)
  To: Vinod Koul, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Jiada Wang
  Cc: dmaengine, imx, linux-arm-kernel, linux-kernel, Marco Felsch

Starting with i.MX8M* devices there are multiple spba-busses so we can't
just search the whole DT for the first spba-bus match and take it.
Instead we need to check for each device to which bus it belongs and
setup the spba_{start,end}_addr accordingly per sdma_channel.

While on it, don't ignore errors from of_address_to_resource() if they
are valid.

Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 drivers/dma/imx-sdma.c | 56 ++++++++++++++++++++++++++++++++++----------------
 1 file changed, 38 insertions(+), 18 deletions(-)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index c31785977351163d6fddf4d8b2f90dfebb508400..3ef415aa578a96e35a969ac2488d08bcab9fadc3 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -461,6 +461,8 @@ struct sdma_channel {
 	dma_addr_t			per_address, per_address2;
 	unsigned long			event_mask[2];
 	unsigned long			watermark_level;
+	u32				spba_start_addr;
+	u32				spba_end_addr;
 	u32				shp_addr, per_addr;
 	enum dma_status			status;
 	struct imx_dma_data		data;
@@ -534,8 +536,6 @@ struct sdma_engine {
 	u32				script_number;
 	struct sdma_script_start_addrs	*script_addrs;
 	const struct sdma_driver_data	*drvdata;
-	u32				spba_start_addr;
-	u32				spba_end_addr;
 	unsigned int			irq;
 	dma_addr_t			bd0_phys;
 	struct sdma_buffer_descriptor	*bd0;
@@ -1236,8 +1236,6 @@ static void sdma_channel_synchronize(struct dma_chan *chan)
 
 static void sdma_set_watermarklevel_for_p2p(struct sdma_channel *sdmac)
 {
-	struct sdma_engine *sdma = sdmac->sdma;
-
 	int lwml = sdmac->watermark_level & SDMA_WATERMARK_LEVEL_LWML;
 	int hwml = (sdmac->watermark_level & SDMA_WATERMARK_LEVEL_HWML) >> 16;
 
@@ -1263,12 +1261,12 @@ static void sdma_set_watermarklevel_for_p2p(struct sdma_channel *sdmac)
 		swap(sdmac->event_mask[0], sdmac->event_mask[1]);
 	}
 
-	if (sdmac->per_address2 >= sdma->spba_start_addr &&
-			sdmac->per_address2 <= sdma->spba_end_addr)
+	if (sdmac->per_address2 >= sdmac->spba_start_addr &&
+			sdmac->per_address2 <= sdmac->spba_end_addr)
 		sdmac->watermark_level |= SDMA_WATERMARK_LEVEL_SP;
 
-	if (sdmac->per_address >= sdma->spba_start_addr &&
-			sdmac->per_address <= sdma->spba_end_addr)
+	if (sdmac->per_address >= sdmac->spba_start_addr &&
+			sdmac->per_address <= sdmac->spba_end_addr)
 		sdmac->watermark_level |= SDMA_WATERMARK_LEVEL_DP;
 
 	sdmac->watermark_level |= SDMA_WATERMARK_LEVEL_CONT;
@@ -1447,6 +1445,31 @@ static void sdma_desc_free(struct virt_dma_desc *vd)
 	kfree(desc);
 }
 
+static int sdma_config_spba_slave(struct dma_chan *chan)
+{
+	struct sdma_channel *sdmac = to_sdma_chan(chan);
+	struct device_node *spba_bus;
+	struct resource spba_res;
+	int ret;
+
+	spba_bus = of_get_parent(chan->slave->of_node);
+	/* Device doesn't belong to the spba-bus */
+	if (!of_device_is_compatible(spba_bus, "fsl,spba-bus"))
+		return 0;
+
+	ret = of_address_to_resource(spba_bus, 0, &spba_res);
+	of_node_put(spba_bus);
+	if (ret) {
+		dev_err(sdmac->sdma->dev, "Failed to get spba-bus resources\n");
+		return -EINVAL;
+	}
+
+	sdmac->spba_start_addr = spba_res.start;
+	sdmac->spba_end_addr = spba_res.end;
+
+	return 0;
+}
+
 static int sdma_alloc_chan_resources(struct dma_chan *chan)
 {
 	struct sdma_channel *sdmac = to_sdma_chan(chan);
@@ -1527,6 +1550,8 @@ static void sdma_free_chan_resources(struct dma_chan *chan)
 
 	sdmac->event_id0 = 0;
 	sdmac->event_id1 = 0;
+	sdmac->spba_start_addr = 0;
+	sdmac->spba_end_addr = 0;
 
 	sdma_set_channel_priority(sdmac, 0);
 
@@ -1837,6 +1862,7 @@ static int sdma_config(struct dma_chan *chan,
 {
 	struct sdma_channel *sdmac = to_sdma_chan(chan);
 	struct sdma_engine *sdma = sdmac->sdma;
+	int ret;
 
 	memcpy(&sdmac->slave_config, dmaengine_cfg, sizeof(*dmaengine_cfg));
 
@@ -1867,6 +1893,10 @@ static int sdma_config(struct dma_chan *chan,
 		sdma_event_enable(sdmac, sdmac->event_id1);
 	}
 
+	ret = sdma_config_spba_slave(chan);
+	if (ret)
+		return ret;
+
 	return 0;
 }
 
@@ -2251,11 +2281,9 @@ static int sdma_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct device_node *np = dev->of_node;
-	struct device_node *spba_bus;
 	const char *fw_name;
 	int ret;
 	int irq;
-	struct resource spba_res;
 	int i;
 	struct sdma_engine *sdma;
 	s32 *saddr_arr;
@@ -2379,14 +2407,6 @@ static int sdma_probe(struct platform_device *pdev)
 
 	devm_add_action_or_reset(dev, sdma_dma_of_dma_controller_unregister_action, sdma);
 
-	spba_bus = of_find_compatible_node(NULL, NULL, "fsl,spba-bus");
-	ret = of_address_to_resource(spba_bus, 0, &spba_res);
-	if (!ret) {
-		sdma->spba_start_addr = spba_res.start;
-		sdma->spba_end_addr = spba_res.end;
-	}
-	of_node_put(spba_bus);
-
 	/*
 	 * Because that device tree does not encode ROM script address,
 	 * the RAM script in firmware is mandatory for device tree

-- 
2.47.2


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

* Re: [PATCH 09/11] dmaengine: add support for device_link
  2025-09-03 13:06 ` [PATCH 09/11] dmaengine: add support for device_link Marco Felsch
@ 2025-09-03 14:46   ` Frank Li
  0 siblings, 0 replies; 23+ messages in thread
From: Frank Li @ 2025-09-03 14:46 UTC (permalink / raw)
  To: Marco Felsch
  Cc: Vinod Koul, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Jiada Wang, dmaengine, imx, linux-arm-kernel,
	linux-kernel

On Wed, Sep 03, 2025 at 03:06:17PM +0200, Marco Felsch wrote:
> Add support to create device_links between dmaengine suppliers and the
> dma consumers. This shifts the device dep-chain teardown/bringup logic
> to the driver core.
>
> Moving this to the core allows the dmaengine drivers to simplify the
> .remove() hooks and also to ensure that no dmaengine driver is ever
> removed before the consumer is removed.
>
> Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> ---

Thank you work for devlink between dmaengine and devices. I have similar
idea.

This patch should be first patch.

The below what planned commit message in my local tree.

Implementing runtime PM for DMA channels is challenging. If a channel
resumes at allocation and suspends at free, the DMA engine often remains on
because most drivers request a channel at probe.

Tracking the number of pending DMA descriptors is also problematic, as some
consumers append new descriptors in atomic contexts, such as IRQ handlers,
where runtime resume cannot be called.

Using a device link simplifies this issue. If a consumer requires data
transfer, it must be in a runtime-resumed state, ensuring that the DMA
channel is also active by device link. This allows safe operations, like
appending new descriptors. Conversely, when the consumer no longer requires
data transfer, both it and the supplier (DMA channel) can enter a suspended
state if no other consumer is using it.

Introduce the `create_link` flag to enable this feature.

also suggest add create_link flag to enable this feature in case some
side impact to other dma-engine. After some time test, we can enable it
default.

>  drivers/dma/dmaengine.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
>
> diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
> index 758fcd0546d8bde8e8dddc6039848feeb1e24475..a50652bc70b8ce9d4edabfaa781b3432ee47d31e 100644
> --- a/drivers/dma/dmaengine.c
> +++ b/drivers/dma/dmaengine.c
> @@ -817,6 +817,7 @@ struct dma_chan *dma_request_chan(struct device *dev, const char *name)
>  	struct fwnode_handle *fwnode = dev_fwnode(dev);
>  	struct dma_device *d, *_d;
>  	struct dma_chan *chan = NULL;
> +	struct device_link *dl;
>
>  	if (is_of_node(fwnode))
>  		chan = of_dma_request_slave_channel(to_of_node(fwnode), name);
> @@ -858,6 +859,13 @@ struct dma_chan *dma_request_chan(struct device *dev, const char *name)
>  	/* No functional issue if it fails, users are supposed to test before use */
>  #endif
>
> +	dl = device_link_add(dev, chan->device->dev, DL_FLAG_AUTOREMOVE_CONSUMER);

chan->device->dev is dmaengine devices. But some dmaengine's each channel
have device, consumer should link to chan's device, not dmaengine device
because some dmaengine support per channel clock\power management.

chan's device's parent devices is dmaengine devices. it should also work
for sdma case


        if (chan->device->create_devlink) {
                u32 flags = DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME | DL_FLAG_AUTOREMOVE_CONSUMER;

                if (pm_runtime_active(dev))
                        flags |= DL_FLAG_RPM_ACTIVE;

When create device link (apply channel), consume may active.


                dl = device_link_add(chan->slave, &chan->dev->device, flags);
        }

Need update kernel doc

diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index bb146c5ac3e4c..ffb3a8f0070ba 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -323,7 +323,8 @@ struct dma_router {
  * @cookie: last cookie value returned to client
  * @completed_cookie: last completed cookie for this channel
  * @chan_id: channel ID for sysfs
- * @dev: class device for sysfs
+ * @dev: class device for sysfs, also use for pre channel runtime pm and
+ *       use custom/different dma-mapping

Frank


> +	if (!dl) {
> +		dev_err(dev, "failed to create device link to %s\n",
> +			dev_name(chan->device->dev));
> +		return ERR_PTR(-EINVAL);
> +	}
>  	chan->name = kasprintf(GFP_KERNEL, "dma:%s", name);
>  	if (!chan->name)
>  		return chan;
>
> --
> 2.47.2
>

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

* Re: [PATCH 01/11] dmaengine: imx-sdma: drop legacy device_node np check
  2025-09-03 13:06 ` [PATCH 01/11] dmaengine: imx-sdma: drop legacy device_node np check Marco Felsch
@ 2025-09-03 14:48   ` Frank Li
  0 siblings, 0 replies; 23+ messages in thread
From: Frank Li @ 2025-09-03 14:48 UTC (permalink / raw)
  To: Marco Felsch
  Cc: Vinod Koul, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Jiada Wang, dmaengine, imx, linux-arm-kernel,
	linux-kernel

On Wed, Sep 03, 2025 at 03:06:09PM +0200, Marco Felsch wrote:
> The legacy 'if (np)' was required in past where we had pdata and dt.
> Nowadays the driver binds only to dt platforms. So using a new kernel
> but still use pdata is not possible, therefore we can drop the legacy
> 'if' code path.
>
> Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>

Reviewed-by: Frank Li <Frank.Li@nxp.com>

> ---
>  drivers/dma/imx-sdma.c | 32 ++++++++++++++------------------
>  1 file changed, 14 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
> index 02a85d6f1bea2df7d355858094c0c0b0bd07148e..89b4b1266726a9c8a552dc48670825ae00717e1c 100644
> --- a/drivers/dma/imx-sdma.c
> +++ b/drivers/dma/imx-sdma.c
> @@ -2325,11 +2325,9 @@ static int sdma_probe(struct platform_device *pdev)
>  			vchan_init(&sdmac->vc, &sdma->dma_device);
>  	}
>
> -	if (np) {
> -		sdma->iram_pool = of_gen_pool_get(np, "iram", 0);
> -		if (sdma->iram_pool)
> -			dev_info(&pdev->dev, "alloc bd from iram.\n");
> -	}
> +	sdma->iram_pool = of_gen_pool_get(np, "iram", 0);
> +	if (sdma->iram_pool)
> +		dev_info(&pdev->dev, "alloc bd from iram.\n");
>
>  	ret = sdma_init(sdma);
>  	if (ret)
> @@ -2369,21 +2367,19 @@ static int sdma_probe(struct platform_device *pdev)
>  		goto err_init;
>  	}
>
> -	if (np) {
> -		ret = of_dma_controller_register(np, sdma_xlate, sdma);
> -		if (ret) {
> -			dev_err(&pdev->dev, "failed to register controller\n");
> -			goto err_register;
> -		}
> +	ret = of_dma_controller_register(np, sdma_xlate, sdma);
> +	if (ret) {
> +		dev_err(&pdev->dev, "failed to register controller\n");
> +		goto err_register;
> +	}
>
> -		spba_bus = of_find_compatible_node(NULL, NULL, "fsl,spba-bus");
> -		ret = of_address_to_resource(spba_bus, 0, &spba_res);
> -		if (!ret) {
> -			sdma->spba_start_addr = spba_res.start;
> -			sdma->spba_end_addr = spba_res.end;
> -		}
> -		of_node_put(spba_bus);
> +	spba_bus = of_find_compatible_node(NULL, NULL, "fsl,spba-bus");
> +	ret = of_address_to_resource(spba_bus, 0, &spba_res);
> +	if (!ret) {
> +		sdma->spba_start_addr = spba_res.start;
> +		sdma->spba_end_addr = spba_res.end;
>  	}
> +	of_node_put(spba_bus);
>
>  	/*
>  	 * Because that device tree does not encode ROM script address,
>
> --
> 2.47.2
>

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

* Re: [PATCH 02/11] dmaengine: imx-sdma: sdma_remove minor cleanups
  2025-09-03 13:06 ` [PATCH 02/11] dmaengine: imx-sdma: sdma_remove minor cleanups Marco Felsch
@ 2025-09-03 14:50   ` Frank Li
  0 siblings, 0 replies; 23+ messages in thread
From: Frank Li @ 2025-09-03 14:50 UTC (permalink / raw)
  To: Marco Felsch
  Cc: Vinod Koul, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Jiada Wang, dmaengine, imx, linux-arm-kernel,
	linux-kernel

On Wed, Sep 03, 2025 at 03:06:10PM +0200, Marco Felsch wrote:
> We don't need to set the pdev driver data to NULL since the device will
> be freed anyways.
>
> Also drop the tasklet_kill() since this is done by the virt-dma driver
> during the vchan_synchronize().
>
> Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>

Reviewed-by: Frank Li <Frank.Li@nxp.com>

> ---
>  drivers/dma/imx-sdma.c | 3 ---
>  1 file changed, 3 deletions(-)
>
> diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
> index 89b4b1266726a9c8a552dc48670825ae00717e1c..422086632d3445b2ce3f2e5df9b2130174a311e8 100644
> --- a/drivers/dma/imx-sdma.c
> +++ b/drivers/dma/imx-sdma.c
> @@ -2423,11 +2423,8 @@ static void sdma_remove(struct platform_device *pdev)
>  	for (i = 0; i < MAX_DMA_CHANNELS; i++) {
>  		struct sdma_channel *sdmac = &sdma->channel[i];
>
> -		tasklet_kill(&sdmac->vc.task);
>  		sdma_free_chan_resources(&sdmac->vc.chan);
>  	}
> -
> -	platform_set_drvdata(pdev, NULL);
>  }
>
>  static struct platform_driver sdma_driver = {
>
> --
> 2.47.2
>

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

* Re: [PATCH 06/11] dmaengine: imx-sdma: make use of devm_add_action_or_reset to unregiser the dma_device
  2025-09-03 13:06 ` [PATCH 06/11] dmaengine: imx-sdma: make use of devm_add_action_or_reset to unregiser the dma_device Marco Felsch
@ 2025-09-03 14:53   ` Frank Li
  0 siblings, 0 replies; 23+ messages in thread
From: Frank Li @ 2025-09-03 14:53 UTC (permalink / raw)
  To: Marco Felsch
  Cc: Vinod Koul, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Jiada Wang, dmaengine, imx, linux-arm-kernel,
	linux-kernel

On Wed, Sep 03, 2025 at 03:06:14PM +0200, Marco Felsch wrote:
> Make use of the devm_add_action_or_reset() to register a custom devm_
> release hook. This is required since we want to turn of the IRQs before

turn off?

> doing the dma_async_device_unregister().
>
> This removes the last goto error handling within the probe function and

Remove the last ..

> further trims the remove() function. Instead of freeing the irq, we can
> disable it and let the devm-irq do the job to free the irq, since the
> only purpose was to have the irqs disabled before calling
> dma_async_device_unregister().
>
> Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> ---
>  drivers/dma/imx-sdma.c | 19 +++++++++++--------
>  1 file changed, 11 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
> index 5a571d3f33158813e0c56484600a49b19a6a72e2..f6bb2f88a62781c0431336c365fa30c46f1401ad 100644
> --- a/drivers/dma/imx-sdma.c
> +++ b/drivers/dma/imx-sdma.c
> @@ -2232,6 +2232,14 @@ static struct dma_chan *sdma_xlate(struct of_phandle_args *dma_spec,
>  				     ofdma->of_node);
>  }
>
> +static void sdma_dma_device_unregister_action(void *data)
> +{
> +	struct sdma_engine *sdma = data;
> +
> +	disable_irq(sdma->irq);
> +	dma_async_device_unregister(&sdma->dma_device);
> +}
> +
>  static int sdma_probe(struct platform_device *pdev)
>  {
>  	struct device *dev = &pdev->dev;
> @@ -2358,10 +2366,12 @@ static int sdma_probe(struct platform_device *pdev)
>  		return ret;
>  	}
>
> +	devm_add_action_or_reset(dev, sdma_dma_device_unregister_action, sdma);
> +

need check return value.

Frank

>  	ret = of_dma_controller_register(np, sdma_xlate, sdma);
>  	if (ret) {
>  		dev_err(dev, "failed to register controller\n");
> -		goto err_register;
> +		return ret;
>  	}
>
>  	spba_bus = of_find_compatible_node(NULL, NULL, "fsl,spba-bus");
> @@ -2388,11 +2398,6 @@ static int sdma_probe(struct platform_device *pdev)
>  	}
>
>  	return 0;
> -
> -err_register:
> -	dma_async_device_unregister(&sdma->dma_device);
> -
> -	return ret;
>  }
>
>  static void sdma_remove(struct platform_device *pdev)
> @@ -2400,8 +2405,6 @@ static void sdma_remove(struct platform_device *pdev)
>  	struct sdma_engine *sdma = platform_get_drvdata(pdev);
>  	int i;
>
> -	devm_free_irq(&pdev->dev, sdma->irq, sdma);
> -	dma_async_device_unregister(&sdma->dma_device);
>  	/* Kill the tasklet */
>  	for (i = 0; i < MAX_DMA_CHANNELS; i++) {
>  		struct sdma_channel *sdmac = &sdma->channel[i];
>
> --
> 2.47.2
>

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

* Re: [PATCH 03/11] dmaengine: imx-sdma: cosmetic cleanup
  2025-09-03 13:06 ` [PATCH 03/11] dmaengine: imx-sdma: cosmetic cleanup Marco Felsch
@ 2025-09-03 14:55   ` Frank Li
  0 siblings, 0 replies; 23+ messages in thread
From: Frank Li @ 2025-09-03 14:55 UTC (permalink / raw)
  To: Marco Felsch
  Cc: Vinod Koul, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Jiada Wang, dmaengine, imx, linux-arm-kernel,
	linux-kernel

On Wed, Sep 03, 2025 at 03:06:11PM +0200, Marco Felsch wrote:
> Make use of local struct device pointer to not dereference the
> platform_device pointer everytime.
>
> Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> ---
>  drivers/dma/imx-sdma.c | 31 ++++++++++++++++---------------
>  1 file changed, 16 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
> index 422086632d3445b2ce3f2e5df9b2130174a311e8..a85739d279f51fdb517fce90b3dc67673cf2b56c 100644
> --- a/drivers/dma/imx-sdma.c
> +++ b/drivers/dma/imx-sdma.c
> @@ -2234,7 +2234,8 @@ static struct dma_chan *sdma_xlate(struct of_phandle_args *dma_spec,
>
>  static int sdma_probe(struct platform_device *pdev)
>  {
> -	struct device_node *np = pdev->dev.of_node;
> +	struct device *dev = &pdev->dev;
> +	struct device_node *np = dev->of_node;
>  	struct device_node *spba_bus;
>  	const char *fw_name;
>  	int ret;
> @@ -2244,18 +2245,18 @@ static int sdma_probe(struct platform_device *pdev)
>  	struct sdma_engine *sdma;
>  	s32 *saddr_arr;
>
> -	ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
> +	ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
>  	if (ret)
>  		return ret;

Not related this patch, you can remove this check later because
dma_coerce_mask_and_coherent() never return failure when >= 32bit.

Reviewed-by: Frank Li <Frank.Li@nxp.com>
>
> -	sdma = devm_kzalloc(&pdev->dev, sizeof(*sdma), GFP_KERNEL);
> +	sdma = devm_kzalloc(dev, sizeof(*sdma), GFP_KERNEL);
>  	if (!sdma)
>  		return -ENOMEM;
>
>  	spin_lock_init(&sdma->channel_0_lock);
>
> -	sdma->dev = &pdev->dev;
> -	sdma->drvdata = of_device_get_match_data(sdma->dev);
> +	sdma->dev = dev;
> +	sdma->drvdata = of_device_get_match_data(dev);
>
>  	irq = platform_get_irq(pdev, 0);
>  	if (irq < 0)
> @@ -2265,11 +2266,11 @@ static int sdma_probe(struct platform_device *pdev)
>  	if (IS_ERR(sdma->regs))
>  		return PTR_ERR(sdma->regs);
>
> -	sdma->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
> +	sdma->clk_ipg = devm_clk_get(dev, "ipg");
>  	if (IS_ERR(sdma->clk_ipg))
>  		return PTR_ERR(sdma->clk_ipg);
>
> -	sdma->clk_ahb = devm_clk_get(&pdev->dev, "ahb");
> +	sdma->clk_ahb = devm_clk_get(dev, "ahb");
>  	if (IS_ERR(sdma->clk_ahb))
>  		return PTR_ERR(sdma->clk_ahb);
>
> @@ -2281,8 +2282,8 @@ static int sdma_probe(struct platform_device *pdev)
>  	if (ret)
>  		goto err_clk;
>
> -	ret = devm_request_irq(&pdev->dev, irq, sdma_int_handler, 0,
> -				dev_name(&pdev->dev), sdma);
> +	ret = devm_request_irq(dev, irq, sdma_int_handler, 0,
> +			       dev_name(dev), sdma);
>  	if (ret)
>  		goto err_irq;
>
> @@ -2327,7 +2328,7 @@ static int sdma_probe(struct platform_device *pdev)
>
>  	sdma->iram_pool = of_gen_pool_get(np, "iram", 0);
>  	if (sdma->iram_pool)
> -		dev_info(&pdev->dev, "alloc bd from iram.\n");
> +		dev_info(dev, "alloc bd from iram.\n");
>
>  	ret = sdma_init(sdma);
>  	if (ret)
> @@ -2340,7 +2341,7 @@ static int sdma_probe(struct platform_device *pdev)
>  	if (sdma->drvdata->script_addrs)
>  		sdma_add_scripts(sdma, sdma->drvdata->script_addrs);
>
> -	sdma->dma_device.dev = &pdev->dev;
> +	sdma->dma_device.dev = dev;
>
>  	sdma->dma_device.device_alloc_chan_resources = sdma_alloc_chan_resources;
>  	sdma->dma_device.device_free_chan_resources = sdma_free_chan_resources;
> @@ -2363,13 +2364,13 @@ static int sdma_probe(struct platform_device *pdev)
>
>  	ret = dma_async_device_register(&sdma->dma_device);
>  	if (ret) {
> -		dev_err(&pdev->dev, "unable to register\n");
> +		dev_err(dev, "unable to register\n");
>  		goto err_init;
>  	}
>
>  	ret = of_dma_controller_register(np, sdma_xlate, sdma);
>  	if (ret) {
> -		dev_err(&pdev->dev, "failed to register controller\n");
> +		dev_err(dev, "failed to register controller\n");
>  		goto err_register;
>  	}
>
> @@ -2389,11 +2390,11 @@ static int sdma_probe(struct platform_device *pdev)
>  	ret = of_property_read_string(np, "fsl,sdma-ram-script-name",
>  				      &fw_name);
>  	if (ret) {
> -		dev_warn(&pdev->dev, "failed to get firmware name\n");
> +		dev_warn(dev, "failed to get firmware name\n");
>  	} else {
>  		ret = sdma_get_firmware(sdma, fw_name);
>  		if (ret)
> -			dev_warn(&pdev->dev, "failed to get firmware from device tree\n");
> +			dev_warn(dev, "failed to get firmware from device tree\n");
>  	}
>
>  	return 0;
>
> --
> 2.47.2
>

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

* Re: [PATCH 04/11] dmaengine: imx-sdma: make use of devm_kzalloc for script_addrs
  2025-09-03 13:06 ` [PATCH 04/11] dmaengine: imx-sdma: make use of devm_kzalloc for script_addrs Marco Felsch
@ 2025-09-03 15:00   ` Frank Li
  0 siblings, 0 replies; 23+ messages in thread
From: Frank Li @ 2025-09-03 15:00 UTC (permalink / raw)
  To: Marco Felsch
  Cc: Vinod Koul, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Jiada Wang, dmaengine, imx, linux-arm-kernel,
	linux-kernel

On Wed, Sep 03, 2025 at 03:06:12PM +0200, Marco Felsch wrote:
> Shuffle the allocation of script_addrs and make use of devm_kzalloc() to
> drop the local error handling as well as the kfree() during the remove.
>
> Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

>  drivers/dma/imx-sdma.c | 19 +++++++------------
>  1 file changed, 7 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
> index a85739d279f51fdb517fce90b3dc67673cf2b56c..b6e649fda71dbce12a2106c94887f90d0aaaf600 100644
> --- a/drivers/dma/imx-sdma.c
> +++ b/drivers/dma/imx-sdma.c
> @@ -2253,6 +2253,10 @@ static int sdma_probe(struct platform_device *pdev)
>  	if (!sdma)
>  		return -ENOMEM;
>
> +	sdma->script_addrs = devm_kzalloc(dev, sizeof(*sdma->script_addrs), GFP_KERNEL);
> +	if (!sdma->script_addrs)
> +		return -ENOMEM;
> +
>  	spin_lock_init(&sdma->channel_0_lock);
>
>  	sdma->dev = dev;
> @@ -2289,12 +2293,6 @@ static int sdma_probe(struct platform_device *pdev)
>
>  	sdma->irq = irq;
>
> -	sdma->script_addrs = kzalloc(sizeof(*sdma->script_addrs), GFP_KERNEL);
> -	if (!sdma->script_addrs) {
> -		ret = -ENOMEM;
> -		goto err_irq;
> -	}
> -
>  	/* initially no scripts available */
>  	saddr_arr = (s32 *)sdma->script_addrs;
>  	for (i = 0; i < sizeof(*sdma->script_addrs) / sizeof(s32); i++)
> @@ -2332,11 +2330,11 @@ static int sdma_probe(struct platform_device *pdev)
>
>  	ret = sdma_init(sdma);
>  	if (ret)
> -		goto err_init;
> +		goto err_irq;
>
>  	ret = sdma_event_remap(sdma);
>  	if (ret)
> -		goto err_init;
> +		goto err_irq;
>
>  	if (sdma->drvdata->script_addrs)
>  		sdma_add_scripts(sdma, sdma->drvdata->script_addrs);
> @@ -2365,7 +2363,7 @@ static int sdma_probe(struct platform_device *pdev)
>  	ret = dma_async_device_register(&sdma->dma_device);
>  	if (ret) {
>  		dev_err(dev, "unable to register\n");
> -		goto err_init;
> +		goto err_irq;
>  	}
>
>  	ret = of_dma_controller_register(np, sdma_xlate, sdma);
> @@ -2401,8 +2399,6 @@ static int sdma_probe(struct platform_device *pdev)
>
>  err_register:
>  	dma_async_device_unregister(&sdma->dma_device);
> -err_init:
> -	kfree(sdma->script_addrs);
>  err_irq:
>  	clk_unprepare(sdma->clk_ahb);
>  err_clk:
> @@ -2417,7 +2413,6 @@ static void sdma_remove(struct platform_device *pdev)
>
>  	devm_free_irq(&pdev->dev, sdma->irq, sdma);
>  	dma_async_device_unregister(&sdma->dma_device);
> -	kfree(sdma->script_addrs);
>  	clk_unprepare(sdma->clk_ahb);
>  	clk_unprepare(sdma->clk_ipg);
>  	/* Kill the tasklet */
>
> --
> 2.47.2
>

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

* Re: [PATCH 05/11] dmaengine: imx-sdma: make use of devm_clk_get_prepared()
  2025-09-03 13:06 ` [PATCH 05/11] dmaengine: imx-sdma: make use of devm_clk_get_prepared() Marco Felsch
@ 2025-09-03 15:01   ` Frank Li
  0 siblings, 0 replies; 23+ messages in thread
From: Frank Li @ 2025-09-03 15:01 UTC (permalink / raw)
  To: Marco Felsch
  Cc: Vinod Koul, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Jiada Wang, dmaengine, imx, linux-arm-kernel,
	linux-kernel

On Wed, Sep 03, 2025 at 03:06:13PM +0200, Marco Felsch wrote:
> Make use of the devm_clk_get_prepared() to cleanup the error handling
> during probe() and to automatically unprepare the clock during remove.
>
> Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>

Reviewed-by: Frank Li <Frank.Li@nxp.com>

> ---
>  drivers/dma/imx-sdma.c | 27 +++++++--------------------
>  1 file changed, 7 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
> index b6e649fda71dbce12a2106c94887f90d0aaaf600..5a571d3f33158813e0c56484600a49b19a6a72e2 100644
> --- a/drivers/dma/imx-sdma.c
> +++ b/drivers/dma/imx-sdma.c
> @@ -2270,26 +2270,18 @@ static int sdma_probe(struct platform_device *pdev)
>  	if (IS_ERR(sdma->regs))
>  		return PTR_ERR(sdma->regs);
>
> -	sdma->clk_ipg = devm_clk_get(dev, "ipg");
> +	sdma->clk_ipg = devm_clk_get_prepared(dev, "ipg");
>  	if (IS_ERR(sdma->clk_ipg))
>  		return PTR_ERR(sdma->clk_ipg);
>
> -	sdma->clk_ahb = devm_clk_get(dev, "ahb");
> +	sdma->clk_ahb = devm_clk_get_prepared(dev, "ahb");
>  	if (IS_ERR(sdma->clk_ahb))
>  		return PTR_ERR(sdma->clk_ahb);
>
> -	ret = clk_prepare(sdma->clk_ipg);
> -	if (ret)
> -		return ret;
> -
> -	ret = clk_prepare(sdma->clk_ahb);
> -	if (ret)
> -		goto err_clk;
> -
>  	ret = devm_request_irq(dev, irq, sdma_int_handler, 0,
>  			       dev_name(dev), sdma);
>  	if (ret)
> -		goto err_irq;
> +		return ret;
>
>  	sdma->irq = irq;
>
> @@ -2330,11 +2322,11 @@ static int sdma_probe(struct platform_device *pdev)
>
>  	ret = sdma_init(sdma);
>  	if (ret)
> -		goto err_irq;
> +		return ret;
>
>  	ret = sdma_event_remap(sdma);
>  	if (ret)
> -		goto err_irq;
> +		return ret;
>
>  	if (sdma->drvdata->script_addrs)
>  		sdma_add_scripts(sdma, sdma->drvdata->script_addrs);
> @@ -2363,7 +2355,7 @@ static int sdma_probe(struct platform_device *pdev)
>  	ret = dma_async_device_register(&sdma->dma_device);
>  	if (ret) {
>  		dev_err(dev, "unable to register\n");
> -		goto err_irq;
> +		return ret;
>  	}
>
>  	ret = of_dma_controller_register(np, sdma_xlate, sdma);
> @@ -2399,10 +2391,7 @@ static int sdma_probe(struct platform_device *pdev)
>
>  err_register:
>  	dma_async_device_unregister(&sdma->dma_device);
> -err_irq:
> -	clk_unprepare(sdma->clk_ahb);
> -err_clk:
> -	clk_unprepare(sdma->clk_ipg);
> +
>  	return ret;
>  }
>
> @@ -2413,8 +2402,6 @@ static void sdma_remove(struct platform_device *pdev)
>
>  	devm_free_irq(&pdev->dev, sdma->irq, sdma);
>  	dma_async_device_unregister(&sdma->dma_device);
> -	clk_unprepare(sdma->clk_ahb);
> -	clk_unprepare(sdma->clk_ipg);
>  	/* Kill the tasklet */
>  	for (i = 0; i < MAX_DMA_CHANNELS; i++) {
>  		struct sdma_channel *sdmac = &sdma->channel[i];
>
> --
> 2.47.2
>

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

* Re: [PATCH 07/11] dmaengine: imx-sdma: make use of dev_err_probe()
  2025-09-03 13:06 ` [PATCH 07/11] dmaengine: imx-sdma: make use of dev_err_probe() Marco Felsch
@ 2025-09-03 15:04   ` Frank Li
  0 siblings, 0 replies; 23+ messages in thread
From: Frank Li @ 2025-09-03 15:04 UTC (permalink / raw)
  To: Marco Felsch
  Cc: Vinod Koul, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Jiada Wang, dmaengine, imx, linux-arm-kernel,
	linux-kernel

On Wed, Sep 03, 2025 at 03:06:15PM +0200, Marco Felsch wrote:
> Convert the probe function to dev_err_probe() which helps users to
> identify issues better.

I think it is not "convert"

Add dev_err_probe() at return path of probe to help user to ...

Reviewed-by: Frank Li <Frank.Li@nxp.com>
>
> Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> ---
>  drivers/dma/imx-sdma.c | 28 ++++++++++++----------------
>  1 file changed, 12 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
> index f6bb2f88a62781c0431336c365fa30c46f1401ad..e30dd46cf6522ee2aa4d3aca9868a01afbd29615 100644
> --- a/drivers/dma/imx-sdma.c
> +++ b/drivers/dma/imx-sdma.c
> @@ -2255,7 +2255,7 @@ static int sdma_probe(struct platform_device *pdev)
>
>  	ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
>  	if (ret)
> -		return ret;
> +		return dev_err_probe(dev, ret, "Failed to set DMA mask\n");
>
>  	sdma = devm_kzalloc(dev, sizeof(*sdma), GFP_KERNEL);
>  	if (!sdma)
> @@ -2272,24 +2272,24 @@ static int sdma_probe(struct platform_device *pdev)
>
>  	irq = platform_get_irq(pdev, 0);
>  	if (irq < 0)
> -		return irq;
> +		return dev_err_probe(dev, irq, "Failed to get IRQ\n");
>
>  	sdma->regs = devm_platform_ioremap_resource(pdev, 0);
>  	if (IS_ERR(sdma->regs))
> -		return PTR_ERR(sdma->regs);
> +		return dev_err_probe(dev, PTR_ERR(sdma->regs), "ioremap failed\n");
>
>  	sdma->clk_ipg = devm_clk_get_prepared(dev, "ipg");
>  	if (IS_ERR(sdma->clk_ipg))
> -		return PTR_ERR(sdma->clk_ipg);
> +		return dev_err_probe(dev, PTR_ERR(sdma->clk_ipg), "IPG clk_get_prepared failed\n");
>
>  	sdma->clk_ahb = devm_clk_get_prepared(dev, "ahb");
>  	if (IS_ERR(sdma->clk_ahb))
> -		return PTR_ERR(sdma->clk_ahb);
> +		return dev_err_probe(dev, PTR_ERR(sdma->clk_ahb), "AHB clk_get_prepared failed\n");
>
>  	ret = devm_request_irq(dev, irq, sdma_int_handler, 0,
>  			       dev_name(dev), sdma);
>  	if (ret)
> -		return ret;
> +		return dev_err_probe(dev, ret, "Failed to request IRQ\n");
>
>  	sdma->irq = irq;
>
> @@ -2330,11 +2330,11 @@ static int sdma_probe(struct platform_device *pdev)
>
>  	ret = sdma_init(sdma);
>  	if (ret)
> -		return ret;
> +		return dev_err_probe(dev, ret, "sdma_init failed\n");
>
>  	ret = sdma_event_remap(sdma);
>  	if (ret)
> -		return ret;
> +		return dev_err_probe(dev, ret, "sdma_event_remap failed\n");
>
>  	if (sdma->drvdata->script_addrs)
>  		sdma_add_scripts(sdma, sdma->drvdata->script_addrs);
> @@ -2361,18 +2361,14 @@ static int sdma_probe(struct platform_device *pdev)
>  	platform_set_drvdata(pdev, sdma);
>
>  	ret = dma_async_device_register(&sdma->dma_device);
> -	if (ret) {
> -		dev_err(dev, "unable to register\n");
> -		return ret;
> -	}
> +	if (ret)
> +		return dev_err_probe(dev, ret, "unable to register\n");
>
>  	devm_add_action_or_reset(dev, sdma_dma_device_unregister_action, sdma);
>
>  	ret = of_dma_controller_register(np, sdma_xlate, sdma);
> -	if (ret) {
> -		dev_err(dev, "failed to register controller\n");
> -		return ret;
> -	}
> +	if (ret)
> +		return dev_err_probe(dev, ret, "failed to register controller\n");
>
>  	spba_bus = of_find_compatible_node(NULL, NULL, "fsl,spba-bus");
>  	ret = of_address_to_resource(spba_bus, 0, &spba_res);
>
> --
> 2.47.2
>

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

* Re: [PATCH 08/11] dmaengine: imx-sdma: fix missing of_dma_controller_free()
  2025-09-03 13:06 ` [PATCH 08/11] dmaengine: imx-sdma: fix missing of_dma_controller_free() Marco Felsch
@ 2025-09-03 15:08   ` Frank Li
  0 siblings, 0 replies; 23+ messages in thread
From: Frank Li @ 2025-09-03 15:08 UTC (permalink / raw)
  To: Marco Felsch
  Cc: Vinod Koul, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Jiada Wang, dmaengine, imx, linux-arm-kernel,
	linux-kernel

On Wed, Sep 03, 2025 at 03:06:16PM +0200, Marco Felsch wrote:
> Add the missing of_dma_controller_free() to free the resources allocated
> via of_dma_controller_register(). The missing free was introduced long
> time ago  by commit 23e118113782 ("dma: imx-sdma: use
> module_platform_driver for SDMA driver") while adding a proper .remove()
> implementation.
>
> Fixes: 23e118113782 ("dma: imx-sdma: use module_platform_driver for SDMA driver")

Look it is hard to back port to old kernel.  Can move it to before cleanup?

> Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> ---
>  drivers/dma/imx-sdma.c | 9 +++++++++
>  1 file changed, 9 insertions(+)
>
> diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
> index e30dd46cf6522ee2aa4d3aca9868a01afbd29615..6c6d38b202dd2deffc36b1bd27bc7c60de3d7403 100644
> --- a/drivers/dma/imx-sdma.c
> +++ b/drivers/dma/imx-sdma.c
> @@ -2232,6 +2232,13 @@ static struct dma_chan *sdma_xlate(struct of_phandle_args *dma_spec,
>  				     ofdma->of_node);
>  }
>
> +static void sdma_dma_of_dma_controller_unregister_action(void *data)
> +{
> +	struct sdma_engine *sdma = data;
> +
> +	of_dma_controller_free(sdma->dev->of_node);
> +}
> +
>  static void sdma_dma_device_unregister_action(void *data)
>  {
>  	struct sdma_engine *sdma = data;
> @@ -2370,6 +2377,8 @@ static int sdma_probe(struct platform_device *pdev)
>  	if (ret)
>  		return dev_err_probe(dev, ret, "failed to register controller\n");
>
> +	devm_add_action_or_reset(dev, sdma_dma_of_dma_controller_unregister_action, sdma);
> +
>  	spba_bus = of_find_compatible_node(NULL, NULL, "fsl,spba-bus");
>  	ret = of_address_to_resource(spba_bus, 0, &spba_res);
>  	if (!ret) {
>
> --
> 2.47.2
>

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

* Re: [PATCH 10/11] dmaengine: imx-sdma: drop remove callback
  2025-09-03 13:06 ` [PATCH 10/11] dmaengine: imx-sdma: drop remove callback Marco Felsch
@ 2025-09-03 15:15   ` Frank Li
  0 siblings, 0 replies; 23+ messages in thread
From: Frank Li @ 2025-09-03 15:15 UTC (permalink / raw)
  To: Marco Felsch
  Cc: Vinod Koul, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Jiada Wang, dmaengine, imx, linux-arm-kernel,
	linux-kernel

On Wed, Sep 03, 2025 at 03:06:18PM +0200, Marco Felsch wrote:
> The whole driver was converted to the devm APIs except for this last
> for-loop. This loop is buggy due to three reasons:
>  1) It removes the channels without removing the users first. This can
>     lead to very bad situations.
>  2) The loop starts at 0 and which is channel0 which is a special
>     control channel not registered via vchan_init(). Therefore the
>     remove() always Oops because of NULL pointer exception.
>  3) sdma_free_chan_resources() disable the clks unconditional without
>     checking if the clks are enabled. This is done for all
>     MAX_DMA_CHANNELS which hang the system if there is at least one unused
>     channel.
>
> Since the dmaengine core supports devlinks we already addressed the
> first issue.
>
> The devlink support also addresses the third issue because during the
> consumer teardown phase each requested channel is dropped accordingly so
> the dmaengine driver doesn't need to this.
>
> The second issue is fixed by not doing anything on channel0.
>
> To sum-up, all issues are fixed by dropping the .remove() callback and
> let the frameworks do their job.

I not realize devlink have this beanfit also. devlink may need more review,
which change some default behavior. I suggest put dmaengin dmalink at this
patch to new serial.

It is easily omited by other dmaengine owner if mixed it to cleanup serial.

Reviewed-by: Frank Li <Frank.Li@nxp.com>
>
> Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> ---
>  drivers/dma/imx-sdma.c | 14 --------------
>  1 file changed, 14 deletions(-)
>
> diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
> index 6c6d38b202dd2deffc36b1bd27bc7c60de3d7403..c31785977351163d6fddf4d8b2f90dfebb508400 100644
> --- a/drivers/dma/imx-sdma.c
> +++ b/drivers/dma/imx-sdma.c
> @@ -2405,25 +2405,11 @@ static int sdma_probe(struct platform_device *pdev)
>  	return 0;
>  }
>
> -static void sdma_remove(struct platform_device *pdev)
> -{
> -	struct sdma_engine *sdma = platform_get_drvdata(pdev);
> -	int i;
> -
> -	/* Kill the tasklet */
> -	for (i = 0; i < MAX_DMA_CHANNELS; i++) {
> -		struct sdma_channel *sdmac = &sdma->channel[i];
> -
> -		sdma_free_chan_resources(&sdmac->vc.chan);
> -	}
> -}
> -
>  static struct platform_driver sdma_driver = {
>  	.driver		= {
>  		.name	= "imx-sdma",
>  		.of_match_table = sdma_dt_ids,
>  	},
> -	.remove		= sdma_remove,
>  	.probe		= sdma_probe,
>  };
>
>
> --
> 2.47.2
>

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

* Re: [PATCH 11/11] dmaengine: imx-sdma: fix spba-bus handling for i.MX8M
  2025-09-03 13:06 ` [PATCH 11/11] dmaengine: imx-sdma: fix spba-bus handling for i.MX8M Marco Felsch
@ 2025-09-04  4:31   ` kernel test robot
  0 siblings, 0 replies; 23+ messages in thread
From: kernel test robot @ 2025-09-04  4:31 UTC (permalink / raw)
  To: Marco Felsch, Vinod Koul, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, Jiada Wang
  Cc: oe-kbuild-all, dmaengine, imx, linux-arm-kernel, linux-kernel,
	Marco Felsch

Hi Marco,

kernel test robot noticed the following build warnings:

[auto build test WARNING on 038d61fd642278bab63ee8ef722c50d10ab01e8f]

url:    https://github.com/intel-lab-lkp/linux/commits/Marco-Felsch/dmaengine-imx-sdma-drop-legacy-device_node-np-check/20250903-212133
base:   038d61fd642278bab63ee8ef722c50d10ab01e8f
patch link:    https://lore.kernel.org/r/20250903-v6-16-topic-sdma-v1-11-ac7bab629e8b%40pengutronix.de
patch subject: [PATCH 11/11] dmaengine: imx-sdma: fix spba-bus handling for i.MX8M
config: arm-randconfig-002-20250904 (https://download.01.org/0day-ci/archive/20250904/202509041238.qCKW7MeD-lkp@intel.com/config)
compiler: arm-linux-gnueabi-gcc (GCC) 13.4.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250904/202509041238.qCKW7MeD-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202509041238.qCKW7MeD-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> Warning: drivers/dma/imx-sdma.c:477 struct member 'spba_start_addr' not described in 'sdma_channel'
>> Warning: drivers/dma/imx-sdma.c:477 struct member 'spba_end_addr' not described in 'sdma_channel'

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

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

end of thread, other threads:[~2025-09-04  4:32 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-03 13:06 [PATCH 00/11] i.MX SDMA cleanups and fixes Marco Felsch
2025-09-03 13:06 ` [PATCH 01/11] dmaengine: imx-sdma: drop legacy device_node np check Marco Felsch
2025-09-03 14:48   ` Frank Li
2025-09-03 13:06 ` [PATCH 02/11] dmaengine: imx-sdma: sdma_remove minor cleanups Marco Felsch
2025-09-03 14:50   ` Frank Li
2025-09-03 13:06 ` [PATCH 03/11] dmaengine: imx-sdma: cosmetic cleanup Marco Felsch
2025-09-03 14:55   ` Frank Li
2025-09-03 13:06 ` [PATCH 04/11] dmaengine: imx-sdma: make use of devm_kzalloc for script_addrs Marco Felsch
2025-09-03 15:00   ` Frank Li
2025-09-03 13:06 ` [PATCH 05/11] dmaengine: imx-sdma: make use of devm_clk_get_prepared() Marco Felsch
2025-09-03 15:01   ` Frank Li
2025-09-03 13:06 ` [PATCH 06/11] dmaengine: imx-sdma: make use of devm_add_action_or_reset to unregiser the dma_device Marco Felsch
2025-09-03 14:53   ` Frank Li
2025-09-03 13:06 ` [PATCH 07/11] dmaengine: imx-sdma: make use of dev_err_probe() Marco Felsch
2025-09-03 15:04   ` Frank Li
2025-09-03 13:06 ` [PATCH 08/11] dmaengine: imx-sdma: fix missing of_dma_controller_free() Marco Felsch
2025-09-03 15:08   ` Frank Li
2025-09-03 13:06 ` [PATCH 09/11] dmaengine: add support for device_link Marco Felsch
2025-09-03 14:46   ` Frank Li
2025-09-03 13:06 ` [PATCH 10/11] dmaengine: imx-sdma: drop remove callback Marco Felsch
2025-09-03 15:15   ` Frank Li
2025-09-03 13:06 ` [PATCH 11/11] dmaengine: imx-sdma: fix spba-bus handling for i.MX8M Marco Felsch
2025-09-04  4:31   ` kernel test robot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).