* [PATCH v6 01/18] dmaengine: sh: rz-dmac: Move interrupt request after everything is set up
[not found] <20260526084710.3491480-1-claudiu.beznea@kernel.org>
@ 2026-05-26 8:46 ` Claudiu Beznea
2026-05-26 8:54 ` Biju Das
2026-05-28 13:44 ` Tommaso Merciai
2026-05-26 8:46 ` [PATCH v6 02/18] dmaengine: sh: rz-dmac: Fix incorrect NULL check for list_first_entry() Claudiu Beznea
1 sibling, 2 replies; 9+ messages in thread
From: Claudiu Beznea @ 2026-05-26 8:46 UTC (permalink / raw)
To: vkoul, Frank.Li, lgirdwood, broonie, perex, tiwai, biju.das.jz,
prabhakar.mahadev-lad.rj, p.zabel, geert+renesas,
kuninori.morimoto.gx, long.luu.ur
Cc: claudiu.beznea, claudiu.beznea, dmaengine, linux-kernel,
linux-sound, linux-renesas-soc, Claudiu Beznea, stable, Frank Li,
John Madieu
From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
Once the interrupt is requested, the interrupt handler may run immediately.
Since the IRQ handler can access channel->ch_base, which is initialized
only after requesting the IRQ, this may lead to invalid memory access.
Likewise, the IRQ thread may access uninitialized data (the ld_free,
ld_queue, and ld_active lists), which may also lead to issues.
Request the interrupts only after everything is set up. To keep the error
path simpler, use dmam_alloc_coherent() instead of dma_alloc_coherent().
Fixes: 5000d37042a6 ("dmaengine: sh: Add DMAC driver for RZ/G2L SoC")
Cc: stable@vger.kernel.org
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Tested-by: John Madieu <john.madieu.xa@bp.renesas.com>
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
Changes in v6:
- collected tags
Changes in v5:
- none
Changes in v4:
- none, this patch is new
drivers/dma/sh/rz-dmac.c | 88 +++++++++++++++-------------------------
1 file changed, 33 insertions(+), 55 deletions(-)
diff --git a/drivers/dma/sh/rz-dmac.c b/drivers/dma/sh/rz-dmac.c
index 625ff29024de..9f206a33dcc6 100644
--- a/drivers/dma/sh/rz-dmac.c
+++ b/drivers/dma/sh/rz-dmac.c
@@ -981,25 +981,6 @@ static int rz_dmac_chan_probe(struct rz_dmac *dmac,
channel->index = index;
channel->mid_rid = -EINVAL;
- /* Request the channel interrupt. */
- scnprintf(pdev_irqname, sizeof(pdev_irqname), "ch%u", index);
- irq = platform_get_irq_byname(pdev, pdev_irqname);
- if (irq < 0)
- return irq;
-
- irqname = devm_kasprintf(dmac->dev, GFP_KERNEL, "%s:%u",
- dev_name(dmac->dev), index);
- if (!irqname)
- return -ENOMEM;
-
- ret = devm_request_threaded_irq(dmac->dev, irq, rz_dmac_irq_handler,
- rz_dmac_irq_handler_thread, 0,
- irqname, channel);
- if (ret) {
- dev_err(dmac->dev, "failed to request IRQ %u (%d)\n", irq, ret);
- return ret;
- }
-
/* Set io base address for each channel */
if (index < 8) {
channel->ch_base = dmac->base + CHANNEL_0_7_OFFSET +
@@ -1012,9 +993,9 @@ static int rz_dmac_chan_probe(struct rz_dmac *dmac,
}
/* Allocate descriptors */
- lmdesc = dma_alloc_coherent(&pdev->dev,
- sizeof(struct rz_lmdesc) * DMAC_NR_LMDESC,
- &channel->lmdesc.base_dma, GFP_KERNEL);
+ lmdesc = dmam_alloc_coherent(&pdev->dev,
+ sizeof(struct rz_lmdesc) * DMAC_NR_LMDESC,
+ &channel->lmdesc.base_dma, GFP_KERNEL);
if (!lmdesc) {
dev_err(&pdev->dev, "Can't allocate memory (lmdesc)\n");
return -ENOMEM;
@@ -1030,7 +1011,24 @@ static int rz_dmac_chan_probe(struct rz_dmac *dmac,
INIT_LIST_HEAD(&channel->ld_free);
INIT_LIST_HEAD(&channel->ld_active);
- return 0;
+ /* Request the channel interrupt. */
+ scnprintf(pdev_irqname, sizeof(pdev_irqname), "ch%u", index);
+ irq = platform_get_irq_byname(pdev, pdev_irqname);
+ if (irq < 0)
+ return irq;
+
+ irqname = devm_kasprintf(dmac->dev, GFP_KERNEL, "%s:%u",
+ dev_name(dmac->dev), index);
+ if (!irqname)
+ return -ENOMEM;
+
+ ret = devm_request_threaded_irq(dmac->dev, irq, rz_dmac_irq_handler,
+ rz_dmac_irq_handler_thread, 0,
+ irqname, channel);
+ if (ret)
+ dev_err(dmac->dev, "failed to request IRQ %u (%d)\n", irq, ret);
+
+ return ret;
}
static void rz_dmac_put_device(void *_dev)
@@ -1099,7 +1097,6 @@ static int rz_dmac_probe(struct platform_device *pdev)
const char *irqname = "error";
struct dma_device *engine;
struct rz_dmac *dmac;
- int channel_num;
int ret;
int irq;
u8 i;
@@ -1132,18 +1129,6 @@ static int rz_dmac_probe(struct platform_device *pdev)
return PTR_ERR(dmac->ext_base);
}
- /* Register interrupt handler for error */
- irq = platform_get_irq_byname_optional(pdev, irqname);
- if (irq > 0) {
- ret = devm_request_irq(&pdev->dev, irq, rz_dmac_irq_handler, 0,
- irqname, NULL);
- if (ret) {
- dev_err(&pdev->dev, "failed to request IRQ %u (%d)\n",
- irq, ret);
- return ret;
- }
- }
-
/* Initialize the channels. */
INIT_LIST_HEAD(&dmac->engine.channels);
@@ -1169,6 +1154,18 @@ static int rz_dmac_probe(struct platform_device *pdev)
goto err;
}
+ /* Register interrupt handler for error */
+ irq = platform_get_irq_byname_optional(pdev, irqname);
+ if (irq > 0) {
+ ret = devm_request_irq(&pdev->dev, irq, rz_dmac_irq_handler, 0,
+ irqname, NULL);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to request IRQ %u (%d)\n",
+ irq, ret);
+ goto err;
+ }
+ }
+
/* Register the DMAC as a DMA provider for DT. */
ret = of_dma_controller_register(pdev->dev.of_node, rz_dmac_of_xlate,
NULL);
@@ -1210,16 +1207,6 @@ static int rz_dmac_probe(struct platform_device *pdev)
dma_register_err:
of_dma_controller_free(pdev->dev.of_node);
err:
- channel_num = i ? i - 1 : 0;
- for (i = 0; i < channel_num; i++) {
- struct rz_dmac_chan *channel = &dmac->channels[i];
-
- dma_free_coherent(&pdev->dev,
- sizeof(struct rz_lmdesc) * DMAC_NR_LMDESC,
- channel->lmdesc.base,
- channel->lmdesc.base_dma);
- }
-
reset_control_assert(dmac->rstc);
err_pm_runtime_put:
pm_runtime_put(&pdev->dev);
@@ -1232,18 +1219,9 @@ static int rz_dmac_probe(struct platform_device *pdev)
static void rz_dmac_remove(struct platform_device *pdev)
{
struct rz_dmac *dmac = platform_get_drvdata(pdev);
- unsigned int i;
dma_async_device_unregister(&dmac->engine);
of_dma_controller_free(pdev->dev.of_node);
- for (i = 0; i < dmac->n_channels; i++) {
- struct rz_dmac_chan *channel = &dmac->channels[i];
-
- dma_free_coherent(&pdev->dev,
- sizeof(struct rz_lmdesc) * DMAC_NR_LMDESC,
- channel->lmdesc.base,
- channel->lmdesc.base_dma);
- }
reset_control_assert(dmac->rstc);
pm_runtime_put(&pdev->dev);
pm_runtime_disable(&pdev->dev);
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v6 02/18] dmaengine: sh: rz-dmac: Fix incorrect NULL check for list_first_entry()
[not found] <20260526084710.3491480-1-claudiu.beznea@kernel.org>
2026-05-26 8:46 ` [PATCH v6 01/18] dmaengine: sh: rz-dmac: Move interrupt request after everything is set up Claudiu Beznea
@ 2026-05-26 8:46 ` Claudiu Beznea
2026-05-28 13:45 ` Tommaso Merciai
1 sibling, 1 reply; 9+ messages in thread
From: Claudiu Beznea @ 2026-05-26 8:46 UTC (permalink / raw)
To: vkoul, Frank.Li, lgirdwood, broonie, perex, tiwai, biju.das.jz,
prabhakar.mahadev-lad.rj, p.zabel, geert+renesas,
kuninori.morimoto.gx, long.luu.ur
Cc: claudiu.beznea, claudiu.beznea, dmaengine, linux-kernel,
linux-sound, linux-renesas-soc, Claudiu Beznea, stable,
John Madieu
From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
list_first_entry() does not return NULL when the list is empty,
making the existing NULL check invalid. Use list_first_entry_or_null()
instead.
Fixes: 21323b118c16 ("dmaengine: sh: rz-dmac: Add device_tx_status() callback")
Cc: stable@vger.kernel.org
Tested-by: John Madieu <john.madieu.xa@bp.renesas.com>
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
Changes in v6:
- collected tags
- updated the patch title and description to reflect better the changes
Changes in v5:
- none
Changes in v4:
- none, this patch is new
drivers/dma/sh/rz-dmac.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/dma/sh/rz-dmac.c b/drivers/dma/sh/rz-dmac.c
index 9f206a33dcc6..6d80cb668957 100644
--- a/drivers/dma/sh/rz-dmac.c
+++ b/drivers/dma/sh/rz-dmac.c
@@ -723,8 +723,8 @@ static u32 rz_dmac_chan_get_residue(struct rz_dmac_chan *channel,
u32 crla, crtb, i;
/* Get current processing virtual descriptor */
- current_desc = list_first_entry(&channel->ld_active,
- struct rz_dmac_desc, node);
+ current_desc = list_first_entry_or_null(&channel->ld_active,
+ struct rz_dmac_desc, node);
if (!current_desc)
return 0;
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* RE: [PATCH v6 01/18] dmaengine: sh: rz-dmac: Move interrupt request after everything is set up
2026-05-26 8:46 ` [PATCH v6 01/18] dmaengine: sh: rz-dmac: Move interrupt request after everything is set up Claudiu Beznea
@ 2026-05-26 8:54 ` Biju Das
2026-05-26 9:45 ` Claudiu Beznea
2026-05-28 13:44 ` Tommaso Merciai
1 sibling, 1 reply; 9+ messages in thread
From: Biju Das @ 2026-05-26 8:54 UTC (permalink / raw)
To: Claudiu Beznea, vkoul@kernel.org, Frank.Li@kernel.org,
lgirdwood@gmail.com, broonie@kernel.org, perex@perex.cz,
tiwai@suse.com, Prabhakar Mahadev Lad, p.zabel@pengutronix.de,
geert+renesas@glider.be, Kuninori Morimoto, Long Luu
Cc: Claudiu.Beznea, dmaengine@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-sound@vger.kernel.org,
linux-renesas-soc@vger.kernel.org, Claudiu Beznea,
stable@vger.kernel.org, Frank Li, John Madieu
Hi Claudiu,
> -----Original Message-----
> From: Claudiu Beznea <claudiu.beznea@kernel.org>
> Sent: 26 May 2026 09:47
> Subject: [PATCH v6 01/18] dmaengine: sh: rz-dmac: Move interrupt request after everything is set up
>
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>
> Once the interrupt is requested, the interrupt handler may run immediately.
Do you mean spurious interrupt?
After DMA driver probe only, consumer device can access the DMA handle
right? or am I missing something here?
Cheers,
Biju
Cheers,
Biju
> Since the IRQ handler can access channel->ch_base, which is initialized only after requesting the IRQ,
> this may lead to invalid memory access.
> Likewise, the IRQ thread may access uninitialized data (the ld_free, ld_queue, and ld_active lists),
> which may also lead to issues.
>
> Request the interrupts only after everything is set up. To keep the error path simpler, use
> dmam_alloc_coherent() instead of dma_alloc_coherent().
>
> Fixes: 5000d37042a6 ("dmaengine: sh: Add DMAC driver for RZ/G2L SoC")
> Cc: stable@vger.kernel.org
> Reviewed-by: Frank Li <Frank.Li@nxp.com>
> Tested-by: John Madieu <john.madieu.xa@bp.renesas.com>
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> ---
>
> Changes in v6:
> - collected tags
>
> Changes in v5:
> - none
>
> Changes in v4:
> - none, this patch is new
>
> drivers/dma/sh/rz-dmac.c | 88 +++++++++++++++-------------------------
> 1 file changed, 33 insertions(+), 55 deletions(-)
>
> diff --git a/drivers/dma/sh/rz-dmac.c b/drivers/dma/sh/rz-dmac.c index 625ff29024de..9f206a33dcc6
> 100644
> --- a/drivers/dma/sh/rz-dmac.c
> +++ b/drivers/dma/sh/rz-dmac.c
> @@ -981,25 +981,6 @@ static int rz_dmac_chan_probe(struct rz_dmac *dmac,
> channel->index = index;
> channel->mid_rid = -EINVAL;
>
> - /* Request the channel interrupt. */
> - scnprintf(pdev_irqname, sizeof(pdev_irqname), "ch%u", index);
> - irq = platform_get_irq_byname(pdev, pdev_irqname);
> - if (irq < 0)
> - return irq;
> -
> - irqname = devm_kasprintf(dmac->dev, GFP_KERNEL, "%s:%u",
> - dev_name(dmac->dev), index);
> - if (!irqname)
> - return -ENOMEM;
> -
> - ret = devm_request_threaded_irq(dmac->dev, irq, rz_dmac_irq_handler,
> - rz_dmac_irq_handler_thread, 0,
> - irqname, channel);
> - if (ret) {
> - dev_err(dmac->dev, "failed to request IRQ %u (%d)\n", irq, ret);
> - return ret;
> - }
> -
> /* Set io base address for each channel */
> if (index < 8) {
> channel->ch_base = dmac->base + CHANNEL_0_7_OFFSET + @@ -1012,9 +993,9 @@ static int
> rz_dmac_chan_probe(struct rz_dmac *dmac,
> }
>
> /* Allocate descriptors */
> - lmdesc = dma_alloc_coherent(&pdev->dev,
> - sizeof(struct rz_lmdesc) * DMAC_NR_LMDESC,
> - &channel->lmdesc.base_dma, GFP_KERNEL);
> + lmdesc = dmam_alloc_coherent(&pdev->dev,
> + sizeof(struct rz_lmdesc) * DMAC_NR_LMDESC,
> + &channel->lmdesc.base_dma, GFP_KERNEL);
> if (!lmdesc) {
> dev_err(&pdev->dev, "Can't allocate memory (lmdesc)\n");
> return -ENOMEM;
> @@ -1030,7 +1011,24 @@ static int rz_dmac_chan_probe(struct rz_dmac *dmac,
> INIT_LIST_HEAD(&channel->ld_free);
> INIT_LIST_HEAD(&channel->ld_active);
>
> - return 0;
> + /* Request the channel interrupt. */
> + scnprintf(pdev_irqname, sizeof(pdev_irqname), "ch%u", index);
> + irq = platform_get_irq_byname(pdev, pdev_irqname);
> + if (irq < 0)
> + return irq;
> +
> + irqname = devm_kasprintf(dmac->dev, GFP_KERNEL, "%s:%u",
> + dev_name(dmac->dev), index);
> + if (!irqname)
> + return -ENOMEM;
> +
> + ret = devm_request_threaded_irq(dmac->dev, irq, rz_dmac_irq_handler,
> + rz_dmac_irq_handler_thread, 0,
> + irqname, channel);
> + if (ret)
> + dev_err(dmac->dev, "failed to request IRQ %u (%d)\n", irq, ret);
> +
> + return ret;
> }
>
> static void rz_dmac_put_device(void *_dev) @@ -1099,7 +1097,6 @@ static int rz_dmac_probe(struct
> platform_device *pdev)
> const char *irqname = "error";
> struct dma_device *engine;
> struct rz_dmac *dmac;
> - int channel_num;
> int ret;
> int irq;
> u8 i;
> @@ -1132,18 +1129,6 @@ static int rz_dmac_probe(struct platform_device *pdev)
> return PTR_ERR(dmac->ext_base);
> }
>
> - /* Register interrupt handler for error */
> - irq = platform_get_irq_byname_optional(pdev, irqname);
> - if (irq > 0) {
> - ret = devm_request_irq(&pdev->dev, irq, rz_dmac_irq_handler, 0,
> - irqname, NULL);
> - if (ret) {
> - dev_err(&pdev->dev, "failed to request IRQ %u (%d)\n",
> - irq, ret);
> - return ret;
> - }
> - }
> -
> /* Initialize the channels. */
> INIT_LIST_HEAD(&dmac->engine.channels);
>
> @@ -1169,6 +1154,18 @@ static int rz_dmac_probe(struct platform_device *pdev)
> goto err;
> }
>
> + /* Register interrupt handler for error */
> + irq = platform_get_irq_byname_optional(pdev, irqname);
> + if (irq > 0) {
> + ret = devm_request_irq(&pdev->dev, irq, rz_dmac_irq_handler, 0,
> + irqname, NULL);
> + if (ret) {
> + dev_err(&pdev->dev, "failed to request IRQ %u (%d)\n",
> + irq, ret);
> + goto err;
> + }
> + }
> +
> /* Register the DMAC as a DMA provider for DT. */
> ret = of_dma_controller_register(pdev->dev.of_node, rz_dmac_of_xlate,
> NULL);
> @@ -1210,16 +1207,6 @@ static int rz_dmac_probe(struct platform_device *pdev)
> dma_register_err:
> of_dma_controller_free(pdev->dev.of_node);
> err:
> - channel_num = i ? i - 1 : 0;
> - for (i = 0; i < channel_num; i++) {
> - struct rz_dmac_chan *channel = &dmac->channels[i];
> -
> - dma_free_coherent(&pdev->dev,
> - sizeof(struct rz_lmdesc) * DMAC_NR_LMDESC,
> - channel->lmdesc.base,
> - channel->lmdesc.base_dma);
> - }
> -
> reset_control_assert(dmac->rstc);
> err_pm_runtime_put:
> pm_runtime_put(&pdev->dev);
> @@ -1232,18 +1219,9 @@ static int rz_dmac_probe(struct platform_device *pdev) static void
> rz_dmac_remove(struct platform_device *pdev) {
> struct rz_dmac *dmac = platform_get_drvdata(pdev);
> - unsigned int i;
>
> dma_async_device_unregister(&dmac->engine);
> of_dma_controller_free(pdev->dev.of_node);
> - for (i = 0; i < dmac->n_channels; i++) {
> - struct rz_dmac_chan *channel = &dmac->channels[i];
> -
> - dma_free_coherent(&pdev->dev,
> - sizeof(struct rz_lmdesc) * DMAC_NR_LMDESC,
> - channel->lmdesc.base,
> - channel->lmdesc.base_dma);
> - }
> reset_control_assert(dmac->rstc);
> pm_runtime_put(&pdev->dev);
> pm_runtime_disable(&pdev->dev);
> --
> 2.43.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v6 01/18] dmaengine: sh: rz-dmac: Move interrupt request after everything is set up
2026-05-26 8:54 ` Biju Das
@ 2026-05-26 9:45 ` Claudiu Beznea
2026-05-26 9:51 ` Biju Das
0 siblings, 1 reply; 9+ messages in thread
From: Claudiu Beznea @ 2026-05-26 9:45 UTC (permalink / raw)
To: Biju Das, vkoul@kernel.org, Frank.Li@kernel.org,
lgirdwood@gmail.com, broonie@kernel.org, perex@perex.cz,
tiwai@suse.com, Prabhakar Mahadev Lad, p.zabel@pengutronix.de,
geert+renesas@glider.be, Kuninori Morimoto, Long Luu
Cc: Claudiu.Beznea, dmaengine@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-sound@vger.kernel.org,
linux-renesas-soc@vger.kernel.org, Claudiu Beznea,
stable@vger.kernel.org, Frank Li, John Madieu
On 5/26/26 11:54, Biju Das wrote:
> Hi Claudiu,
>
>> -----Original Message-----
>> From: Claudiu Beznea <claudiu.beznea@kernel.org>
>> Sent: 26 May 2026 09:47
>> Subject: [PATCH v6 01/18] dmaengine: sh: rz-dmac: Move interrupt request after everything is set up
>>
>> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>>
>> Once the interrupt is requested, the interrupt handler may run immediately.
>
> Do you mean spurious interrupt?
>
> After DMA driver probe only, consumer device can access the DMA handle
> right? or am I missing something here?
In theory there could be pending interrupts not yet served (e.g. due to the
previous usage of the controller, HW behavior, etc). Those could trigger the
execution of the IRQ handler once the interrupt is requested.
--
Thank you,
Claudiu
^ permalink raw reply [flat|nested] 9+ messages in thread
* RE: [PATCH v6 01/18] dmaengine: sh: rz-dmac: Move interrupt request after everything is set up
2026-05-26 9:45 ` Claudiu Beznea
@ 2026-05-26 9:51 ` Biju Das
2026-05-26 10:25 ` Claudiu Beznea
0 siblings, 1 reply; 9+ messages in thread
From: Biju Das @ 2026-05-26 9:51 UTC (permalink / raw)
To: Claudiu Beznea, vkoul@kernel.org, Frank.Li@kernel.org,
lgirdwood@gmail.com, broonie@kernel.org, perex@perex.cz,
tiwai@suse.com, Prabhakar Mahadev Lad, p.zabel@pengutronix.de,
geert+renesas@glider.be, Kuninori Morimoto, Long Luu
Cc: Claudiu.Beznea, dmaengine@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-sound@vger.kernel.org,
linux-renesas-soc@vger.kernel.org, Claudiu Beznea,
stable@vger.kernel.org, Frank Li, John Madieu
Hi Claudiu,
> -----Original Message-----
> From: Claudiu Beznea <claudiu.beznea@kernel.org>
> Sent: 26 May 2026 10:46
> Subject: Re: [PATCH v6 01/18] dmaengine: sh: rz-dmac: Move interrupt request after everything is set
> up
>
>
>
> On 5/26/26 11:54, Biju Das wrote:
> > Hi Claudiu,
> >
> >> -----Original Message-----
> >> From: Claudiu Beznea <claudiu.beznea@kernel.org>
> >> Sent: 26 May 2026 09:47
> >> Subject: [PATCH v6 01/18] dmaengine: sh: rz-dmac: Move interrupt
> >> request after everything is set up
> >>
> >> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> >>
> >> Once the interrupt is requested, the interrupt handler may run immediately.
> >
> > Do you mean spurious interrupt?
> >
> > After DMA driver probe only, consumer device can access the DMA handle
> > right? or am I missing something here?
>
> In theory there could be pending interrupts not yet served (e.g. due to the previous usage of the
> controller, HW behavior, etc). Those could trigger the execution of the IRQ handler once the interrupt
> is requested.
You mean DMA consumers configured by bootloader and linux probing the DMA driver can
trigger IRQ?
Cheers,
Biju
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v6 01/18] dmaengine: sh: rz-dmac: Move interrupt request after everything is set up
2026-05-26 9:51 ` Biju Das
@ 2026-05-26 10:25 ` Claudiu Beznea
2026-05-26 10:39 ` Biju Das
0 siblings, 1 reply; 9+ messages in thread
From: Claudiu Beznea @ 2026-05-26 10:25 UTC (permalink / raw)
To: Biju Das, vkoul@kernel.org, Frank.Li@kernel.org,
lgirdwood@gmail.com, broonie@kernel.org, perex@perex.cz,
tiwai@suse.com, Prabhakar Mahadev Lad, p.zabel@pengutronix.de,
geert+renesas@glider.be, Kuninori Morimoto, Long Luu
Cc: Claudiu.Beznea, dmaengine@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-sound@vger.kernel.org,
linux-renesas-soc@vger.kernel.org, Claudiu Beznea,
stable@vger.kernel.org, Frank Li, John Madieu
On 5/26/26 12:51, Biju Das wrote:
> Hi Claudiu,
>
>> -----Original Message-----
>> From: Claudiu Beznea <claudiu.beznea@kernel.org>
>> Sent: 26 May 2026 10:46
>> Subject: Re: [PATCH v6 01/18] dmaengine: sh: rz-dmac: Move interrupt request after everything is set
>> up
>>
>>
>>
>> On 5/26/26 11:54, Biju Das wrote:
>>> Hi Claudiu,
>>>
>>>> -----Original Message-----
>>>> From: Claudiu Beznea <claudiu.beznea@kernel.org>
>>>> Sent: 26 May 2026 09:47
>>>> Subject: [PATCH v6 01/18] dmaengine: sh: rz-dmac: Move interrupt
>>>> request after everything is set up
>>>>
>>>> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>>>>
>>>> Once the interrupt is requested, the interrupt handler may run immediately.
>>>
>>> Do you mean spurious interrupt?
>>>
>>> After DMA driver probe only, consumer device can access the DMA handle
>>> right? or am I missing something here?
>>
>> In theory there could be pending interrupts not yet served (e.g. due to the previous usage of the
>> controller, HW behavior, etc). Those could trigger the execution of the IRQ handler once the interrupt
>> is requested.
>
> You mean DMA consumers configured by bootloader and linux probing the DMA driver can
> trigger IRQ?
DMA used by bootloaders may be a valid scenario, even though may not currently
be used in the setups this IP is used.
Please check the documentation of request_threaded_irq():
https://elixir.bootlin.com/linux/v7.1-rc4/source/kernel/irq/manage.c#L2089
"* ... From the point this call is made your handler function
* may be invoked. Since your handler function must clear any interrupt the
* board raises, you must take care both to initialise your hardware and to
* set up the interrupt handler in the right order"
--
Thank you,
Claudiu
^ permalink raw reply [flat|nested] 9+ messages in thread
* RE: [PATCH v6 01/18] dmaengine: sh: rz-dmac: Move interrupt request after everything is set up
2026-05-26 10:25 ` Claudiu Beznea
@ 2026-05-26 10:39 ` Biju Das
0 siblings, 0 replies; 9+ messages in thread
From: Biju Das @ 2026-05-26 10:39 UTC (permalink / raw)
To: Claudiu Beznea, vkoul@kernel.org, Frank.Li@kernel.org,
lgirdwood@gmail.com, broonie@kernel.org, perex@perex.cz,
tiwai@suse.com, Prabhakar Mahadev Lad, p.zabel@pengutronix.de,
geert+renesas@glider.be, Kuninori Morimoto, Long Luu
Cc: Claudiu.Beznea, dmaengine@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-sound@vger.kernel.org,
linux-renesas-soc@vger.kernel.org, Claudiu Beznea,
stable@vger.kernel.org, Frank Li, John Madieu
> -----Original Message-----
> From: Claudiu Beznea <claudiu.beznea@kernel.org>
> Sent: 26 May 2026 11:26
> Subject: Re: [PATCH v6 01/18] dmaengine: sh: rz-dmac: Move interrupt request after everything is set
> up
>
>
>
> On 5/26/26 12:51, Biju Das wrote:
> > Hi Claudiu,
> >
> >> -----Original Message-----
> >> From: Claudiu Beznea <claudiu.beznea@kernel.org>
> >> Sent: 26 May 2026 10:46
> >> Subject: Re: [PATCH v6 01/18] dmaengine: sh: rz-dmac: Move interrupt
> >> request after everything is set up
> >>
> >>
> >>
> >> On 5/26/26 11:54, Biju Das wrote:
> >>> Hi Claudiu,
> >>>
> >>>> -----Original Message-----
> >>>> From: Claudiu Beznea <claudiu.beznea@kernel.org>
> >>>> Sent: 26 May 2026 09:47
> >>>> Subject: [PATCH v6 01/18] dmaengine: sh: rz-dmac: Move interrupt
> >>>> request after everything is set up
> >>>>
> >>>> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> >>>>
> >>>> Once the interrupt is requested, the interrupt handler may run immediately.
> >>>
> >>> Do you mean spurious interrupt?
> >>>
> >>> After DMA driver probe only, consumer device can access the DMA
> >>> handle right? or am I missing something here?
> >>
> >> In theory there could be pending interrupts not yet served (e.g. due
> >> to the previous usage of the controller, HW behavior, etc). Those
> >> could trigger the execution of the IRQ handler once the interrupt is requested.
> >
> > You mean DMA consumers configured by bootloader and linux probing the
> > DMA driver can trigger IRQ?
> DMA used by bootloaders may be a valid scenario, even though may not currently be used in the setups
> this IP is used.
>
> Please check the documentation of request_threaded_irq():
> https://elixir.bootlin.com/linux/v7.1-rc4/source/kernel/irq/manage.c#L2089
>
> "* ... From the point this call is made your handler function
> * may be invoked. Since your handler function must clear any interrupt the
> * board raises, you must take care both to initialise your hardware and to
> * set up the interrupt handler in the right order"
OK. Then it make sense as the bootloader/board may have some register
configured for triggering IRQ and it will lead to crash..
Cheers,
Biju
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v6 01/18] dmaengine: sh: rz-dmac: Move interrupt request after everything is set up
2026-05-26 8:46 ` [PATCH v6 01/18] dmaengine: sh: rz-dmac: Move interrupt request after everything is set up Claudiu Beznea
2026-05-26 8:54 ` Biju Das
@ 2026-05-28 13:44 ` Tommaso Merciai
1 sibling, 0 replies; 9+ messages in thread
From: Tommaso Merciai @ 2026-05-28 13:44 UTC (permalink / raw)
To: Claudiu Beznea
Cc: vkoul, Frank.Li, lgirdwood, broonie, perex, tiwai, biju.das.jz,
prabhakar.mahadev-lad.rj, p.zabel, geert+renesas,
kuninori.morimoto.gx, long.luu.ur, claudiu.beznea, dmaengine,
linux-kernel, linux-sound, linux-renesas-soc, Claudiu Beznea,
stable, Frank Li, John Madieu
Hi Claudiu,
Thanks for your patch.
On Tue, May 26, 2026 at 11:46:53AM +0300, Claudiu Beznea wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>
> Once the interrupt is requested, the interrupt handler may run immediately.
> Since the IRQ handler can access channel->ch_base, which is initialized
> only after requesting the IRQ, this may lead to invalid memory access.
> Likewise, the IRQ thread may access uninitialized data (the ld_free,
> ld_queue, and ld_active lists), which may also lead to issues.
>
> Request the interrupts only after everything is set up. To keep the error
> path simpler, use dmam_alloc_coherent() instead of dma_alloc_coherent().
>
Tested on RZ/G3E using dma along with rspi0
Tested-by: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com>
Thanks, Tommaso
> Fixes: 5000d37042a6 ("dmaengine: sh: Add DMAC driver for RZ/G2L SoC")
> Cc: stable@vger.kernel.org
> Reviewed-by: Frank Li <Frank.Li@nxp.com>
> Tested-by: John Madieu <john.madieu.xa@bp.renesas.com>
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> ---
>
> Changes in v6:
> - collected tags
>
> Changes in v5:
> - none
>
> Changes in v4:
> - none, this patch is new
>
> drivers/dma/sh/rz-dmac.c | 88 +++++++++++++++-------------------------
> 1 file changed, 33 insertions(+), 55 deletions(-)
>
> diff --git a/drivers/dma/sh/rz-dmac.c b/drivers/dma/sh/rz-dmac.c
> index 625ff29024de..9f206a33dcc6 100644
> --- a/drivers/dma/sh/rz-dmac.c
> +++ b/drivers/dma/sh/rz-dmac.c
> @@ -981,25 +981,6 @@ static int rz_dmac_chan_probe(struct rz_dmac *dmac,
> channel->index = index;
> channel->mid_rid = -EINVAL;
>
> - /* Request the channel interrupt. */
> - scnprintf(pdev_irqname, sizeof(pdev_irqname), "ch%u", index);
> - irq = platform_get_irq_byname(pdev, pdev_irqname);
> - if (irq < 0)
> - return irq;
> -
> - irqname = devm_kasprintf(dmac->dev, GFP_KERNEL, "%s:%u",
> - dev_name(dmac->dev), index);
> - if (!irqname)
> - return -ENOMEM;
> -
> - ret = devm_request_threaded_irq(dmac->dev, irq, rz_dmac_irq_handler,
> - rz_dmac_irq_handler_thread, 0,
> - irqname, channel);
> - if (ret) {
> - dev_err(dmac->dev, "failed to request IRQ %u (%d)\n", irq, ret);
> - return ret;
> - }
> -
> /* Set io base address for each channel */
> if (index < 8) {
> channel->ch_base = dmac->base + CHANNEL_0_7_OFFSET +
> @@ -1012,9 +993,9 @@ static int rz_dmac_chan_probe(struct rz_dmac *dmac,
> }
>
> /* Allocate descriptors */
> - lmdesc = dma_alloc_coherent(&pdev->dev,
> - sizeof(struct rz_lmdesc) * DMAC_NR_LMDESC,
> - &channel->lmdesc.base_dma, GFP_KERNEL);
> + lmdesc = dmam_alloc_coherent(&pdev->dev,
> + sizeof(struct rz_lmdesc) * DMAC_NR_LMDESC,
> + &channel->lmdesc.base_dma, GFP_KERNEL);
> if (!lmdesc) {
> dev_err(&pdev->dev, "Can't allocate memory (lmdesc)\n");
> return -ENOMEM;
> @@ -1030,7 +1011,24 @@ static int rz_dmac_chan_probe(struct rz_dmac *dmac,
> INIT_LIST_HEAD(&channel->ld_free);
> INIT_LIST_HEAD(&channel->ld_active);
>
> - return 0;
> + /* Request the channel interrupt. */
> + scnprintf(pdev_irqname, sizeof(pdev_irqname), "ch%u", index);
> + irq = platform_get_irq_byname(pdev, pdev_irqname);
> + if (irq < 0)
> + return irq;
> +
> + irqname = devm_kasprintf(dmac->dev, GFP_KERNEL, "%s:%u",
> + dev_name(dmac->dev), index);
> + if (!irqname)
> + return -ENOMEM;
> +
> + ret = devm_request_threaded_irq(dmac->dev, irq, rz_dmac_irq_handler,
> + rz_dmac_irq_handler_thread, 0,
> + irqname, channel);
> + if (ret)
> + dev_err(dmac->dev, "failed to request IRQ %u (%d)\n", irq, ret);
> +
> + return ret;
> }
>
> static void rz_dmac_put_device(void *_dev)
> @@ -1099,7 +1097,6 @@ static int rz_dmac_probe(struct platform_device *pdev)
> const char *irqname = "error";
> struct dma_device *engine;
> struct rz_dmac *dmac;
> - int channel_num;
> int ret;
> int irq;
> u8 i;
> @@ -1132,18 +1129,6 @@ static int rz_dmac_probe(struct platform_device *pdev)
> return PTR_ERR(dmac->ext_base);
> }
>
> - /* Register interrupt handler for error */
> - irq = platform_get_irq_byname_optional(pdev, irqname);
> - if (irq > 0) {
> - ret = devm_request_irq(&pdev->dev, irq, rz_dmac_irq_handler, 0,
> - irqname, NULL);
> - if (ret) {
> - dev_err(&pdev->dev, "failed to request IRQ %u (%d)\n",
> - irq, ret);
> - return ret;
> - }
> - }
> -
> /* Initialize the channels. */
> INIT_LIST_HEAD(&dmac->engine.channels);
>
> @@ -1169,6 +1154,18 @@ static int rz_dmac_probe(struct platform_device *pdev)
> goto err;
> }
>
> + /* Register interrupt handler for error */
> + irq = platform_get_irq_byname_optional(pdev, irqname);
> + if (irq > 0) {
> + ret = devm_request_irq(&pdev->dev, irq, rz_dmac_irq_handler, 0,
> + irqname, NULL);
> + if (ret) {
> + dev_err(&pdev->dev, "failed to request IRQ %u (%d)\n",
> + irq, ret);
> + goto err;
> + }
> + }
> +
> /* Register the DMAC as a DMA provider for DT. */
> ret = of_dma_controller_register(pdev->dev.of_node, rz_dmac_of_xlate,
> NULL);
> @@ -1210,16 +1207,6 @@ static int rz_dmac_probe(struct platform_device *pdev)
> dma_register_err:
> of_dma_controller_free(pdev->dev.of_node);
> err:
> - channel_num = i ? i - 1 : 0;
> - for (i = 0; i < channel_num; i++) {
> - struct rz_dmac_chan *channel = &dmac->channels[i];
> -
> - dma_free_coherent(&pdev->dev,
> - sizeof(struct rz_lmdesc) * DMAC_NR_LMDESC,
> - channel->lmdesc.base,
> - channel->lmdesc.base_dma);
> - }
> -
> reset_control_assert(dmac->rstc);
> err_pm_runtime_put:
> pm_runtime_put(&pdev->dev);
> @@ -1232,18 +1219,9 @@ static int rz_dmac_probe(struct platform_device *pdev)
> static void rz_dmac_remove(struct platform_device *pdev)
> {
> struct rz_dmac *dmac = platform_get_drvdata(pdev);
> - unsigned int i;
>
> dma_async_device_unregister(&dmac->engine);
> of_dma_controller_free(pdev->dev.of_node);
> - for (i = 0; i < dmac->n_channels; i++) {
> - struct rz_dmac_chan *channel = &dmac->channels[i];
> -
> - dma_free_coherent(&pdev->dev,
> - sizeof(struct rz_lmdesc) * DMAC_NR_LMDESC,
> - channel->lmdesc.base,
> - channel->lmdesc.base_dma);
> - }
> reset_control_assert(dmac->rstc);
> pm_runtime_put(&pdev->dev);
> pm_runtime_disable(&pdev->dev);
> --
> 2.43.0
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v6 02/18] dmaengine: sh: rz-dmac: Fix incorrect NULL check for list_first_entry()
2026-05-26 8:46 ` [PATCH v6 02/18] dmaengine: sh: rz-dmac: Fix incorrect NULL check for list_first_entry() Claudiu Beznea
@ 2026-05-28 13:45 ` Tommaso Merciai
0 siblings, 0 replies; 9+ messages in thread
From: Tommaso Merciai @ 2026-05-28 13:45 UTC (permalink / raw)
To: Claudiu Beznea
Cc: vkoul, Frank.Li, lgirdwood, broonie, perex, tiwai, biju.das.jz,
prabhakar.mahadev-lad.rj, p.zabel, geert+renesas,
kuninori.morimoto.gx, long.luu.ur, claudiu.beznea, dmaengine,
linux-kernel, linux-sound, linux-renesas-soc, Claudiu Beznea,
stable, John Madieu
On Tue, May 26, 2026 at 11:46:54AM +0300, Claudiu Beznea wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>
> list_first_entry() does not return NULL when the list is empty,
> making the existing NULL check invalid. Use list_first_entry_or_null()
> instead.
>
Same.
Tested-by: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com>
Kind Regards,
Tommaso
> Fixes: 21323b118c16 ("dmaengine: sh: rz-dmac: Add device_tx_status() callback")
> Cc: stable@vger.kernel.org
> Tested-by: John Madieu <john.madieu.xa@bp.renesas.com>
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> ---
>
> Changes in v6:
> - collected tags
> - updated the patch title and description to reflect better the changes
>
> Changes in v5:
> - none
>
> Changes in v4:
> - none, this patch is new
>
> drivers/dma/sh/rz-dmac.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/dma/sh/rz-dmac.c b/drivers/dma/sh/rz-dmac.c
> index 9f206a33dcc6..6d80cb668957 100644
> --- a/drivers/dma/sh/rz-dmac.c
> +++ b/drivers/dma/sh/rz-dmac.c
> @@ -723,8 +723,8 @@ static u32 rz_dmac_chan_get_residue(struct rz_dmac_chan *channel,
> u32 crla, crtb, i;
>
> /* Get current processing virtual descriptor */
> - current_desc = list_first_entry(&channel->ld_active,
> - struct rz_dmac_desc, node);
> + current_desc = list_first_entry_or_null(&channel->ld_active,
> + struct rz_dmac_desc, node);
> if (!current_desc)
> return 0;
>
> --
> 2.43.0
>
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-05-28 13:45 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20260526084710.3491480-1-claudiu.beznea@kernel.org>
2026-05-26 8:46 ` [PATCH v6 01/18] dmaengine: sh: rz-dmac: Move interrupt request after everything is set up Claudiu Beznea
2026-05-26 8:54 ` Biju Das
2026-05-26 9:45 ` Claudiu Beznea
2026-05-26 9:51 ` Biju Das
2026-05-26 10:25 ` Claudiu Beznea
2026-05-26 10:39 ` Biju Das
2026-05-28 13:44 ` Tommaso Merciai
2026-05-26 8:46 ` [PATCH v6 02/18] dmaengine: sh: rz-dmac: Fix incorrect NULL check for list_first_entry() Claudiu Beznea
2026-05-28 13:45 ` Tommaso Merciai
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox