mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 0/2] dmaengine: fix dead empty checks in mpc512x and rz-dmac
@ 2026-05-21 14:47 Maoyi Xie
  2026-05-21 14:47 ` [PATCH 1/2] dmaengine: mpc512x: fix dead empty check in mpc_dma_prep_slave_sg() Maoyi Xie
  2026-05-21 14:47 ` [PATCH 2/2] dmaengine: rz-dmac: fix dead empty check in rz_dmac_chan_get_residue() Maoyi Xie
  0 siblings, 2 replies; 8+ messages in thread
From: Maoyi Xie @ 2026-05-21 14:47 UTC (permalink / raw)
  To: Vinod Koul
  Cc: Frank Li, Geert Uytterhoeven, dmaengine, linux-renesas-soc, linux-kernel

Two dmaengine drivers use list_first_entry() and then test the
returned pointer against NULL. list_first_entry() never returns
NULL, so the NULL check is dead code. The author intent at both
sites was clear from the existing recovery path. Switch to
list_first_entry_or_null() so the existing NULL path runs.

The two sites were raised in an inquiry on 2026-05-20. Frank Li
confirmed and asked for a patch.

Maoyi Xie (2):
  dmaengine: mpc512x: fix dead empty check in mpc_dma_prep_slave_sg()
  dmaengine: rz-dmac: fix dead empty check in rz_dmac_chan_get_residue()

 drivers/dma/mpc512x_dma.c | 4 ++--
 drivers/dma/sh/rz-dmac.c  | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

--
2.34.1

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

* [PATCH 1/2] dmaengine: mpc512x: fix dead empty check in mpc_dma_prep_slave_sg()
  2026-05-21 14:47 [PATCH 0/2] dmaengine: fix dead empty checks in mpc512x and rz-dmac Maoyi Xie
@ 2026-05-21 14:47 ` Maoyi Xie
  2026-05-21 16:30   ` Frank Li
  2026-05-22 15:02   ` [PATCH v2] " Maoyi Xie
  2026-05-21 14:47 ` [PATCH 2/2] dmaengine: rz-dmac: fix dead empty check in rz_dmac_chan_get_residue() Maoyi Xie
  1 sibling, 2 replies; 8+ messages in thread
From: Maoyi Xie @ 2026-05-21 14:47 UTC (permalink / raw)
  To: Vinod Koul
  Cc: Frank Li, Geert Uytterhoeven, dmaengine, linux-renesas-soc, linux-kernel

mpc_dma_prep_slave_sg() reads mchan->free with list_first_entry()
and then tests the returned pointer against NULL. list_first_entry()
never returns NULL. On an empty free list it returns
container_of(&mchan->free, struct mpc_dma_desc, node), an aliased
pointer derived from the list head. The recovery path (drop lock,
scan completed list, return NULL) is dead code.

If the free list is ever empty here, the aliased mdesc points at
&mchan->free. The list_del(&mdesc->node) that follows then runs on
the head itself, corrupting mchan->free.next and mchan->free.prev.

The free list is reachable empty when the descriptor pool is
exhausted. The author intent was clear from the recovery path:
release the lock, scan the completed list to free descriptors, and
return NULL so the caller can retry.

Use list_first_entry_or_null() so the empty case returns NULL and
the existing recovery path runs as intended.

The same shape has been cleaned up elsewhere, for example in
commit fbb8bc408027 ("net: qed: Remove redundant NULL checks after list_first_entry()"),
commit c708d3fad421 ("crypto: atmel - use list_first_entry_or_null to simplify find_dev"),
and commit 10379171f346 ("ksmbd: use list_first_entry_or_null for opinfo_get_list()").
This site was missed by those cleanups.

Signed-off-by: Maoyi Xie <maoyixie.tju@gmail.com>
---
 drivers/dma/mpc512x_dma.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
index 0adc8e01057e..f5934136efc4 100644
--- a/drivers/dma/mpc512x_dma.c
+++ b/drivers/dma/mpc512x_dma.c
@@ -706,8 +706,8 @@ mpc_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
 	for_each_sg(sgl, sg, sg_len, i) {
 		spin_lock_irqsave(&mchan->lock, iflags);
 
-		mdesc = list_first_entry(&mchan->free,
-						struct mpc_dma_desc, node);
+		mdesc = list_first_entry_or_null(&mchan->free,
+						 struct mpc_dma_desc, node);
 		if (!mdesc) {
 			spin_unlock_irqrestore(&mchan->lock, iflags);
 			/* Try to free completed descriptors */
-- 
2.34.1


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

* [PATCH 2/2] dmaengine: rz-dmac: fix dead empty check in rz_dmac_chan_get_residue()
  2026-05-21 14:47 [PATCH 0/2] dmaengine: fix dead empty checks in mpc512x and rz-dmac Maoyi Xie
  2026-05-21 14:47 ` [PATCH 1/2] dmaengine: mpc512x: fix dead empty check in mpc_dma_prep_slave_sg() Maoyi Xie
@ 2026-05-21 14:47 ` Maoyi Xie
  2026-05-22  8:16   ` Geert Uytterhoeven
  1 sibling, 1 reply; 8+ messages in thread
From: Maoyi Xie @ 2026-05-21 14:47 UTC (permalink / raw)
  To: Vinod Koul
  Cc: Frank Li, Geert Uytterhoeven, dmaengine, linux-renesas-soc, linux-kernel

rz_dmac_chan_get_residue() reads channel->ld_active with
list_first_entry() and then tests the returned pointer against
NULL. list_first_entry() never returns NULL. On an empty list it
returns container_of(&channel->ld_active, struct rz_dmac_desc,
node), an aliased pointer derived from the list head. The "return
0" shortcut is dead code.

If ld_active is ever empty here, current_desc points at
&channel->ld_active. The subsequent cookie and status processing
then reads bogus values from the head's neighbouring memory.

ld_active can be empty when a residue query races with descriptor
completion on another path. The author intent was clear from the
existing comment on the next-following check, which already
acknowledges that the descriptor "could now be complete". The
empty case is the limit of that race.

Use list_first_entry_or_null() so the empty case returns NULL and
the existing "return 0" path runs.

The same shape has been cleaned up elsewhere, for example in
commit fbb8bc408027 ("net: qed: Remove redundant NULL checks after list_first_entry()"),
commit c708d3fad421 ("crypto: atmel - use list_first_entry_or_null to simplify find_dev"),
and commit 10379171f346 ("ksmbd: use list_first_entry_or_null for opinfo_get_list()").
This site was missed by those cleanups.

Signed-off-by: Maoyi Xie <maoyixie.tju@gmail.com>
---
 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 625ff29024de..3dd76615881f 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.34.1


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

* Re: [PATCH 1/2] dmaengine: mpc512x: fix dead empty check in mpc_dma_prep_slave_sg()
  2026-05-21 14:47 ` [PATCH 1/2] dmaengine: mpc512x: fix dead empty check in mpc_dma_prep_slave_sg() Maoyi Xie
@ 2026-05-21 16:30   ` Frank Li
  2026-05-22 15:02   ` [PATCH v2] " Maoyi Xie
  1 sibling, 0 replies; 8+ messages in thread
From: Frank Li @ 2026-05-21 16:30 UTC (permalink / raw)
  To: Maoyi Xie
  Cc: Vinod Koul, Frank Li, Geert Uytterhoeven, dmaengine,
	linux-renesas-soc, linux-kernel

On Thu, May 21, 2026 at 10:47:54PM +0800, Maoyi Xie wrote:
> mpc_dma_prep_slave_sg() reads mchan->free with list_first_entry()
> and then tests the returned pointer against NULL. list_first_entry()
> never returns NULL. On an empty free list it returns
> container_of(&mchan->free, struct mpc_dma_desc, node), an aliased
> pointer derived from the list head. The recovery path (drop lock,
> scan completed list, return NULL) is dead code.
>
> If the free list is ever empty here, the aliased mdesc points at
> &mchan->free. The list_del(&mdesc->node) that follows then runs on
> the head itself, corrupting mchan->free.next and mchan->free.prev.
>
> The free list is reachable empty when the descriptor pool is
> exhausted. The author intent was clear from the recovery path:
> release the lock, scan the completed list to free descriptors, and
> return NULL so the caller can retry.

Nit: You can skip above two parapraph. This problem is quite straight forwards

Reviewed-by: Frank Li <Frank.Li@nxp.com>
>
> Use list_first_entry_or_null() so the empty case returns NULL and
> the existing recovery path runs as intended.
>
> The same shape has been cleaned up elsewhere, for example in
> commit fbb8bc408027 ("net: qed: Remove redundant NULL checks after list_first_entry()"),
> commit c708d3fad421 ("crypto: atmel - use list_first_entry_or_null to simplify find_dev"),
> and commit 10379171f346 ("ksmbd: use list_first_entry_or_null for opinfo_get_list()").
> This site was missed by those cleanups.
>
> Signed-off-by: Maoyi Xie <maoyixie.tju@gmail.com>
> ---
>  drivers/dma/mpc512x_dma.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
> index 0adc8e01057e..f5934136efc4 100644
> --- a/drivers/dma/mpc512x_dma.c
> +++ b/drivers/dma/mpc512x_dma.c
> @@ -706,8 +706,8 @@ mpc_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
>  	for_each_sg(sgl, sg, sg_len, i) {
>  		spin_lock_irqsave(&mchan->lock, iflags);
>
> -		mdesc = list_first_entry(&mchan->free,
> -						struct mpc_dma_desc, node);
> +		mdesc = list_first_entry_or_null(&mchan->free,
> +						 struct mpc_dma_desc, node);
>  		if (!mdesc) {
>  			spin_unlock_irqrestore(&mchan->lock, iflags);
>  			/* Try to free completed descriptors */
> --
> 2.34.1
>

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

* Re: [PATCH 2/2] dmaengine: rz-dmac: fix dead empty check in rz_dmac_chan_get_residue()
  2026-05-21 14:47 ` [PATCH 2/2] dmaengine: rz-dmac: fix dead empty check in rz_dmac_chan_get_residue() Maoyi Xie
@ 2026-05-22  8:16   ` Geert Uytterhoeven
  2026-05-22  8:37     ` Maoyi Xie
  0 siblings, 1 reply; 8+ messages in thread
From: Geert Uytterhoeven @ 2026-05-22  8:16 UTC (permalink / raw)
  To: Maoyi Xie
  Cc: Claudiu Beznea, Vinod Koul, Frank Li, dmaengine,
	linux-renesas-soc, linux-kernel

Hi Maoyi,

On Thu, 21 May 2026 at 16:48, Maoyi Xie <maoyixie.tju@gmail.com> wrote:
> rz_dmac_chan_get_residue() reads channel->ld_active with
> list_first_entry() and then tests the returned pointer against
> NULL. list_first_entry() never returns NULL. On an empty list it
> returns container_of(&channel->ld_active, struct rz_dmac_desc,
> node), an aliased pointer derived from the list head. The "return
> 0" shortcut is dead code.
>
> If ld_active is ever empty here, current_desc points at
> &channel->ld_active. The subsequent cookie and status processing
> then reads bogus values from the head's neighbouring memory.
>
> ld_active can be empty when a residue query races with descriptor
> completion on another path. The author intent was clear from the
> existing comment on the next-following check, which already
> acknowledges that the descriptor "could now be complete". The
> empty case is the limit of that race.
>
> Use list_first_entry_or_null() so the empty case returns NULL and
> the existing "return 0" path runs.
>
> The same shape has been cleaned up elsewhere, for example in
> commit fbb8bc408027 ("net: qed: Remove redundant NULL checks after list_first_entry()"),
> commit c708d3fad421 ("crypto: atmel - use list_first_entry_or_null to simplify find_dev"),
> and commit 10379171f346 ("ksmbd: use list_first_entry_or_null for opinfo_get_list()").
> This site was missed by those cleanups.
>
> Signed-off-by: Maoyi Xie <maoyixie.tju@gmail.com>

Thanks for your patch!

> --- 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;
>

Note that proposed "[PATCH v5 09/17] dmaengine: sh: rz-dmac: Use
virt-dma APIs for channel descriptor processing" would remove this code.
https://lore.kernel.org/20260512121219.216159-10-claudiu.beznea.uj@bp.renesas.com

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* Re: [PATCH 2/2] dmaengine: rz-dmac: fix dead empty check in rz_dmac_chan_get_residue()
  2026-05-22  8:16   ` Geert Uytterhoeven
@ 2026-05-22  8:37     ` Maoyi Xie
  0 siblings, 0 replies; 8+ messages in thread
From: Maoyi Xie @ 2026-05-22  8:37 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Claudiu Beznea, Vinod Koul, Frank Li, dmaengine,
	linux-renesas-soc, linux-kernel

Hi Geert,

Thanks for the pointer. I had not seen Claudiu's v5 09/17 series.
Looking at it, rz_dmac_chan_get_residue() is rewritten through
virt_dma APIs (vchan_find_desc + channel->desc) and ld_active is
removed. The fix I sent is superseded.

I will drop the rz-dmac patch from v2 of this series and send only
the mpc512x patch.

Thanks,
Maoyi

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

* [PATCH v2] dmaengine: mpc512x: fix dead empty check in mpc_dma_prep_slave_sg()
  2026-05-21 14:47 ` [PATCH 1/2] dmaengine: mpc512x: fix dead empty check in mpc_dma_prep_slave_sg() Maoyi Xie
  2026-05-21 16:30   ` Frank Li
@ 2026-05-22 15:02   ` Maoyi Xie
  2026-06-25 11:35     ` Maoyi Xie
  1 sibling, 1 reply; 8+ messages in thread
From: Maoyi Xie @ 2026-05-22 15:02 UTC (permalink / raw)
  To: Vinod Koul
  Cc: Frank Li, Geert Uytterhoeven, dmaengine, linux-renesas-soc, linux-kernel

mpc_dma_prep_slave_sg() reads mchan->free with list_first_entry()
and then tests the returned pointer against NULL. list_first_entry()
never returns NULL. On an empty free list it returns
container_of(&mchan->free, struct mpc_dma_desc, node), an aliased
pointer derived from the list head. The recovery path (drop lock,
scan completed list, return NULL) is dead code.

Use list_first_entry_or_null() so the empty case returns NULL and
the existing recovery path runs as intended.

The same shape has been cleaned up elsewhere, for example in
commit fbb8bc408027 ("net: qed: Remove redundant NULL checks after list_first_entry()"),
commit c708d3fad421 ("crypto: atmel - use list_first_entry_or_null to simplify find_dev"),
and commit 10379171f346 ("ksmbd: use list_first_entry_or_null for opinfo_get_list()").
This site was missed by those cleanups.

Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Maoyi Xie <maoyixie.tju@gmail.com>
---
v2: Trim two paragraphs from the commit message per Frank Li's
    nit on v1. No code change. Carry forward Frank's Reviewed-by.
    Drop the rz-dmac patch from v1: Geert pointed out that
    Claudiu's "[PATCH v5 09/17] dmaengine: sh: rz-dmac: Use
    virt-dma APIs for channel descriptor processing" rewrites
    rz_dmac_chan_get_residue() through vchan_find_desc() and
    removes ld_active, which supersedes the fix.
    https://lore.kernel.org/r/20260512121219.216159-10-claudiu.beznea.uj@bp.renesas.com
v1: https://lore.kernel.org/r/20260521144755.3476353-2-maoyixie.tju@gmail.com

 drivers/dma/mpc512x_dma.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
index 0adc8e01057e..f5934136efc4 100644
--- a/drivers/dma/mpc512x_dma.c
+++ b/drivers/dma/mpc512x_dma.c
@@ -706,8 +706,8 @@ mpc_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
 	for_each_sg(sgl, sg, sg_len, i) {
 		spin_lock_irqsave(&mchan->lock, iflags);
 
-		mdesc = list_first_entry(&mchan->free,
-						struct mpc_dma_desc, node);
+		mdesc = list_first_entry_or_null(&mchan->free,
+						 struct mpc_dma_desc, node);
 		if (!mdesc) {
 			spin_unlock_irqrestore(&mchan->lock, iflags);
 			/* Try to free completed descriptors */
-- 
2.34.1


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

* Re: [PATCH v2] dmaengine: mpc512x: fix dead empty check in mpc_dma_prep_slave_sg()
  2026-05-22 15:02   ` [PATCH v2] " Maoyi Xie
@ 2026-06-25 11:35     ` Maoyi Xie
  0 siblings, 0 replies; 8+ messages in thread
From: Maoyi Xie @ 2026-06-25 11:35 UTC (permalink / raw)
  To: Vinod Koul
  Cc: Frank Li, Geert Uytterhoeven, dmaengine, linux-renesas-soc, linux-kernel

Thanks all. I'm dropping this one. Using list_first_entry_or_null activates
the recovery path, and calling mpc_dma_process_completed() from prep context
isn't safe. It runs client callbacks inline and can roll completed_cookie
backwards. The empty free list is real but rare (all 64 descriptors in
flight). The safe fix is to return NULL there without that call and let the
tasklet reclaim, but I can't test it on hardware, so I'll leave it to you.

Best,
Maoyi

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

end of thread, other threads:[~2026-06-25 11:36 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-05-21 14:47 [PATCH 0/2] dmaengine: fix dead empty checks in mpc512x and rz-dmac Maoyi Xie
2026-05-21 14:47 ` [PATCH 1/2] dmaengine: mpc512x: fix dead empty check in mpc_dma_prep_slave_sg() Maoyi Xie
2026-05-21 16:30   ` Frank Li
2026-05-22 15:02   ` [PATCH v2] " Maoyi Xie
2026-06-25 11:35     ` Maoyi Xie
2026-05-21 14:47 ` [PATCH 2/2] dmaengine: rz-dmac: fix dead empty check in rz_dmac_chan_get_residue() Maoyi Xie
2026-05-22  8:16   ` Geert Uytterhoeven
2026-05-22  8:37     ` Maoyi Xie

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®