* [PATCH v2 0/4] dmaengine: dw-axi-dmac: Fix burst encoding, LLI dump and priority
@ 2026-09-01 6:16 Jia Wang
2026-09-01 6:16 ` [PATCH v2 1/4] dmaengine: dw-axi-dmac: Fix AXI burst length encoding Jia Wang
` (3 more replies)
0 siblings, 4 replies; 12+ messages in thread
From: Jia Wang @ 2026-09-01 6:16 UTC (permalink / raw)
To: Eugeniy Paltsev, Vinod Koul, Frank Li, Pandith N, Andy Shevchenko,
Sia Jee Heng
Cc: dmaengine, linux-kernel, Jia Wang, Frank Li
This series fixes AXI burst length encoding, an out-of-bounds access in
the error-path LLI dump, and the CH_CFG2 channel priority field position.
It also converts register field definitions and programming to GENMASK()
and FIELD_PREP().
The series was tested with dmatest on all eight channels using
snps,axi-max-burst-len = <256>. All channels completed without errors. It
was also build-tested on RISC-V with CONFIG_DW_AXI_DMAC as both a module
and built-in.
Signed-off-by: Jia Wang <wangjia@ultrarisc.com>
---
Changes in v2:
- Use a loop-local unsigned iterator in the LLI dump helper.
- Add a patch to fix the CH_CFG2 channel priority field position.
- Add a cleanup patch to use GENMASK() and FIELD_PREP() for register fields.
- Link to v1: https://patch.msgid.link/20260828-dma-fix-v1-0-a6947f487e07@ultrarisc.com
To: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
To: Vinod Koul <vkoul@kernel.org>
To: Frank Li <Frank.Li@kernel.org>
To: Pandith N <pandith.n@intel.com>
To: Sia Jee Heng <jee.heng.sia@intel.com>
To: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: dmaengine@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
Jia Wang (4):
dmaengine: dw-axi-dmac: Fix AXI burst length encoding
dmaengine: dw-axi-dmac: Fix LLI dump out-of-bounds access
dmaengine: dw-axi-dmac: Fix CH_CFG2 channel priority position
dmaengine: dw-axi-dmac: Use bitfield helpers for registers
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c | 78 +++++++++++++-------------
drivers/dma/dw-axi-dmac/dw-axi-dmac.h | 44 +++++++--------
2 files changed, 60 insertions(+), 62 deletions(-)
---
base-commit: cee9395acd8043be0644b25c34bfa86623f2b935
change-id: 20260827-dma-fix-c2b27795ce12
Best regards,
--
Jia Wang <wangjia@ultrarisc.com>
^ permalink raw reply [flat|nested] 12+ messages in thread* [PATCH v2 1/4] dmaengine: dw-axi-dmac: Fix AXI burst length encoding 2026-09-01 6:16 [PATCH v2 0/4] dmaengine: dw-axi-dmac: Fix burst encoding, LLI dump and priority Jia Wang @ 2026-09-01 6:16 ` Jia Wang 2026-09-01 6:29 ` sashiko-bot 2026-09-01 6:16 ` [PATCH v2 2/4] dmaengine: dw-axi-dmac: Fix LLI dump out-of-bounds access Jia Wang ` (2 subsequent siblings) 3 siblings, 1 reply; 12+ messages in thread From: Jia Wang @ 2026-09-01 6:16 UTC (permalink / raw) To: Eugeniy Paltsev, Vinod Koul, Frank Li, Pandith N, Andy Shevchenko, Sia Jee Heng Cc: dmaengine, linux-kernel, Jia Wang, Frank Li The snps,axi-max-burst-len property describes the number of beats in an AXI burst, while the ARLEN and AWLEN fields encode that value minus one. The driver keeps axi_rw_burst_len as the actual burst length so that dma_device.max_burst reports the correct value. However, it also programs that unencoded value directly into the hardware fields. A value of 256 therefore overflows the 8-bit fields and can cause AXI decode errors. Subtract one only when constructing hardware descriptors, while keeping the actual value for dma_device.max_burst. Fixes: c454d16a7d5a ("dmaengine: dw-axi-dmac: Burst length settings") Signed-off-by: Jia Wang <wangjia@ultrarisc.com> Reviewed-by: Frank Li <Frank.Li@nxp.com> --- drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c index eebed2474210..742e08cfab43 100644 --- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c +++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c @@ -706,7 +706,7 @@ static int dw_axi_dma_set_hw_desc(struct axi_dma_chan *chan, ctlhi = CH_CTL_H_LLI_VALID; if (chan->chip->dw->hdata->restrict_axi_burst_len) { - burst_len = chan->chip->dw->hdata->axi_rw_burst_len; + burst_len = chan->chip->dw->hdata->axi_rw_burst_len - 1; ctlhi |= CH_CTL_H_ARLEN_EN | CH_CTL_H_AWLEN_EN | burst_len << CH_CTL_H_ARLEN_POS | burst_len << CH_CTL_H_AWLEN_POS; @@ -975,7 +975,7 @@ dma_chan_prep_dma_memcpy(struct dma_chan *dchan, dma_addr_t dst_adr, reg = CH_CTL_H_LLI_VALID; if (chan->chip->dw->hdata->restrict_axi_burst_len) { - u32 burst_len = chan->chip->dw->hdata->axi_rw_burst_len; + u32 burst_len = chan->chip->dw->hdata->axi_rw_burst_len - 1; reg |= (CH_CTL_H_ARLEN_EN | burst_len << CH_CTL_H_ARLEN_POS | -- 2.34.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v2 1/4] dmaengine: dw-axi-dmac: Fix AXI burst length encoding 2026-09-01 6:16 ` [PATCH v2 1/4] dmaengine: dw-axi-dmac: Fix AXI burst length encoding Jia Wang @ 2026-09-01 6:29 ` sashiko-bot 0 siblings, 0 replies; 12+ messages in thread From: sashiko-bot @ 2026-09-01 6:29 UTC (permalink / raw) To: Jia Wang; +Cc: vkoul, Frank.Li, dmaengine Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider: Pre-existing issues: - [High] Missing checks for zero-length inputs in descriptor prep functions lead to out-of-bounds array accesses against ZERO_SIZE_PTR and divide-by-zero panics. - [High] axi_desc_put() unconditionally calls dma_pool_free() with potentially NULL pointers, causing a kernel panic when tearing down partially allocated descriptor lists. - [High] axi_desc_put() unconditionally subtracts the maximum expected descriptor count from chan->descs_allocated, causing an atomic counter underflow on error paths. -- commit 645dfa80d0619fd42c37ace18ec6558aa67250f3 Author: Jia Wang <wangjia@ultrarisc.com> dmaengine: dw-axi-dmac: Fix AXI burst length encoding The snps,axi-max-burst-len property describes the number of beats in an AXI burst, while the ARLEN and AWLEN fields encode that value minus one. The driver keeps axi_rw_burst_len as the actual burst length so that dma_device.max_burst reports the correct value. However, it also programs that unencoded value directly into the hardware fields. A value of 256 therefore overflows the 8-bit fields and can cause AXI decode errors. Subtract one only when constructing hardware descriptors, while keeping the actual value for dma_device.max_burst. Fixes: c454d16a7d5a ("dmaengine: dw-axi-dmac: Burst length settings") Signed-off-by: Jia Wang <wangjia@ultrarisc.com> Reviewed-by: Frank Li <Frank.Li@nxp.com> > diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c > index eebed2474210d..742e08cfab435 100644 > --- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c > +++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c > @@ -706,7 +706,7 @@ static int dw_axi_dma_set_hw_desc(struct axi_dma_chan *chan, > ctlhi = CH_CTL_H_LLI_VALID; > > if (chan->chip->dw->hdata->restrict_axi_burst_len) { > - burst_len = chan->chip->dw->hdata->axi_rw_burst_len; > + burst_len = chan->chip->dw->hdata->axi_rw_burst_len - 1; > ctlhi |= CH_CTL_H_ARLEN_EN | CH_CTL_H_AWLEN_EN | > burst_len << CH_CTL_H_ARLEN_POS | > burst_len << CH_CTL_H_AWLEN_POS; [ ... ] I have a few questions about how zero-length inputs and error handling are managed in this file. In drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c:dma_chan_prep_dma_memcpy(): while (len) { ... num++; } /* Set end-of-link to the last link descriptor of list */ set_desc_last(&desc->hw_desc[num - 1]); [Severity: High] This isn't a bug introduced by this patch, but does this cause an out-of-bounds array access if the DMA client requests a zero-length transfer? If len is 0, the while loop never executes, num remains 0, and we access desc->hw_desc[-1], leading to an immediate out-of-bounds dereference. Also in drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c:dw_axi_dma_chan_prep_cyclic(): num_periods = buf_len / period_len; ... total_segments = num_periods * num_segments; ... llp = desc->hw_desc[0].llp; /* Managed transfer list */ do { hw_desc = &desc->hw_desc[--total_segments]; write_desc_llp(hw_desc, llp | lms); llp = hw_desc->llp; } while (total_segments); [Severity: High] This is a pre-existing issue, but does this cause a divide-by-zero panic if period_len is 0? [Severity: High] This is a pre-existing issue, but does this code also go out of bounds if buf_len is 0? If buf_len is 0, total_segments is 0. Accessing desc->hw_desc[0].llp goes out of bounds, and --total_segments underflows, causing another out-of-bounds access against the descriptor array. I also have a question about the error handling path. In drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c:axi_desc_put(): for (descs_put = 0; descs_put < count; descs_put++) { hw_desc = &desc->hw_desc[descs_put]; dma_pool_free(chan->desc_pool, hw_desc->lli, hw_desc->llp); } kfree(desc->hw_desc); kfree(desc); atomic_sub(descs_put, &chan->descs_allocated); [Severity: High] This isn't a bug introduced by this patch, but can dma_pool_free() panic if axi_desc_get() fails during partial allocation? If axi_desc_get() fails under memory pressure, hw_desc->lli could be NULL for the descriptors that failed allocation. dma_pool_free() appears to unconditionally dereference this pointer. [Severity: High] This is a pre-existing issue, but does this code also underflow chan->descs_allocated? Because descs_put iterates up to the total requested descriptors (count), atomic_sub() subtracts the total requested count, not just the successfully allocated ones. If chan->descs_allocated underflows, could this break the cyclic DMA interrupt handling logic by failing the loop bound check? -- Sashiko AI review · https://sashiko.dev/#/patchset/20260901-dma-fix-v2-0-d7f0459ebb14@ultrarisc.com?part=1 ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v2 2/4] dmaengine: dw-axi-dmac: Fix LLI dump out-of-bounds access 2026-09-01 6:16 [PATCH v2 0/4] dmaengine: dw-axi-dmac: Fix burst encoding, LLI dump and priority Jia Wang 2026-09-01 6:16 ` [PATCH v2 1/4] dmaengine: dw-axi-dmac: Fix AXI burst length encoding Jia Wang @ 2026-09-01 6:16 ` Jia Wang 2026-09-01 6:29 ` sashiko-bot 2026-09-01 18:53 ` Frank Li 2026-09-01 6:16 ` [PATCH v2 3/4] dmaengine: dw-axi-dmac: Fix CH_CFG2 channel priority position Jia Wang 2026-09-01 6:16 ` [PATCH v2 4/4] dmaengine: dw-axi-dmac: Use bitfield helpers for registers Jia Wang 3 siblings, 2 replies; 12+ messages in thread From: Jia Wang @ 2026-09-01 6:16 UTC (permalink / raw) To: Eugeniy Paltsev, Vinod Koul, Frank Li, Pandith N, Andy Shevchenko, Sia Jee Heng Cc: dmaengine, linux-kernel, Jia Wang axi_chan_list_dump_lli() uses the channel-wide descs_allocated count to walk the hw_desc[] array of a single transaction. If multiple transactions have allocated LLIs, the channel count can exceed the transaction-local nr_hw_descs and make the DMA error path read past the end of hw_desc[]. Use the descriptor-local nr_hw_descs count when dumping LLIs. Fixes: ef6fb2d6f1ab ("dmaengine: dw-axi-dmac: simplify descriptor management") Signed-off-by: Jia Wang <wangjia@ultrarisc.com> --- drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c index 742e08cfab43..61230d2b1c56 100644 --- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c +++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c @@ -1052,10 +1052,7 @@ static void axi_chan_dump_lli(struct axi_dma_chan *chan, static void axi_chan_list_dump_lli(struct axi_dma_chan *chan, struct axi_dma_desc *desc_head) { - int count = atomic_read(&chan->descs_allocated); - int i; - - for (i = 0; i < count; i++) + for (unsigned int i = 0; i < desc_head->nr_hw_descs; i++) axi_chan_dump_lli(chan, &desc_head->hw_desc[i]); } -- 2.34.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v2 2/4] dmaengine: dw-axi-dmac: Fix LLI dump out-of-bounds access 2026-09-01 6:16 ` [PATCH v2 2/4] dmaengine: dw-axi-dmac: Fix LLI dump out-of-bounds access Jia Wang @ 2026-09-01 6:29 ` sashiko-bot 2026-09-01 18:53 ` Frank Li 1 sibling, 0 replies; 12+ messages in thread From: sashiko-bot @ 2026-09-01 6:29 UTC (permalink / raw) To: Jia Wang; +Cc: dmaengine, Frank.Li, vkoul Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: Pre-existing issues: - [Critical] The patch fixes an out-of-bounds access in `axi_chan_list_dump_lli()` by using the transaction-local `desc->nr_hw_descs` instead of the channel-wide `chan->descs_allocated`. However, it completely misses the exact same bug in `axi_chan_block_xfer_complete()` which can lead to memory corruption. - [Critical] Flawed calculations for `segment_len` and loop bounds in both `dw_axi_dma_chan_prep_slave_sg` and `dw_axi_dma_chan_prep_cyclic` lead to data truncation, DMA overruns, and NULL pointer dereferences when buffer lengths are not perfectly divisible by the calculated `segment_len`. -- commit 5ff010f18efeeec7fde7f85a181da39448ad009d Author: Jia Wang <wangjia@ultrarisc.com> dmaengine: dw-axi-dmac: Fix LLI dump out-of-bounds access This commit fixes an out-of-bounds access in axi_chan_list_dump_lli() by using the transaction-local descriptor count instead of the channel-wide count. > diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c > index 742e08cfab435..61230d2b1c561 100644 > --- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c > +++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c > @@ -1052,10 +1052,7 @@ static void axi_chan_dump_lli(struct axi_dma_chan *chan, > static void axi_chan_list_dump_lli(struct axi_dma_chan *chan, > struct axi_dma_desc *desc_head) > { > - int count = atomic_read(&chan->descs_allocated); > - int i; > - > - for (i = 0; i < count; i++) > + for (unsigned int i = 0; i < desc_head->nr_hw_descs; i++) > axi_chan_dump_lli(chan, &desc_head->hw_desc[i]); > } [Severity: Critical] This is a pre-existing issue, but does axi_chan_block_xfer_complete() have the same out-of-bounds access regression? If multiple transactions are prepared, chan->descs_allocated can exceed the transaction-local desc->nr_hw_descs: drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c:axi_chan_block_xfer_complete() { ... int count = atomic_read(&chan->descs_allocated); ... if (chan->cyclic) { desc = vd_to_axi_desc(vd); if (desc) { llp = lo_hi_readq(chan->chan_regs + CH_LLP); for (i = 0; i < count; i++) { hw_desc = &desc->hw_desc[i]; if (hw_desc->llp == llp) { axi_chan_irq_clear(chan, hw_desc->lli->status_lo); hw_desc->lli->ctl_hi |= cpu_to_le32(CH_CTL_H_LLI_VALID); ... } Could this cause an out-of-bounds read on the desc->hw_desc array, and corrupt memory when writing to hw_desc->lli->ctl_hi? [Severity: Critical] This is also a pre-existing issue, but can the segment loop bounds cause data truncation or memory overruns? In dw_axi_dma_chan_prep_slave_sg(), if len is not perfectly divisible by segment_len, the loop terminates prematurely: drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c:dw_axi_dma_chan_prep_slave_sg() { ... do { hw_desc = &desc->hw_desc[loop++]; status = dw_axi_dma_set_hw_desc(chan, hw_desc, mem, segment_len); ... len -= segment_len; mem += segment_len; } while (len >= segment_len); ... } Does this drop the remainder bytes and leave trailing descriptors uninitialized, causing a NULL dereference when set_desc_last() is called? Similarly, in dw_axi_dma_chan_prep_cyclic(): drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c:dw_axi_dma_chan_prep_cyclic() { ... for (i = 0; i < total_segments; i++) { hw_desc = &desc->hw_desc[i]; status = dw_axi_dma_set_hw_desc(chan, hw_desc, src_addr, segment_len); ... src_addr += segment_len; } ... } Can this unconditionally program the DMA to transfer segment_len for each segment, exceeding the requested period_len and reading or writing past the end of the provided DMA buffer? -- Sashiko AI review · https://sashiko.dev/#/patchset/20260901-dma-fix-v2-0-d7f0459ebb14@ultrarisc.com?part=2 ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 2/4] dmaengine: dw-axi-dmac: Fix LLI dump out-of-bounds access 2026-09-01 6:16 ` [PATCH v2 2/4] dmaengine: dw-axi-dmac: Fix LLI dump out-of-bounds access Jia Wang 2026-09-01 6:29 ` sashiko-bot @ 2026-09-01 18:53 ` Frank Li 1 sibling, 0 replies; 12+ messages in thread From: Frank Li @ 2026-09-01 18:53 UTC (permalink / raw) To: Jia Wang Cc: Eugeniy Paltsev, Vinod Koul, Frank Li, Pandith N, Andy Shevchenko, Sia Jee Heng, dmaengine, linux-kernel On Tue, Sep 01, 2026 at 02:16:05PM +0800, Jia Wang wrote: > axi_chan_list_dump_lli() uses the channel-wide descs_allocated count to > walk the hw_desc[] array of a single transaction. If multiple > transactions have allocated LLIs, the channel count can exceed the > transaction-local nr_hw_descs and make the DMA error path read past the > end of hw_desc[]. > > Use the descriptor-local nr_hw_descs count when dumping LLIs. > > Fixes: ef6fb2d6f1ab ("dmaengine: dw-axi-dmac: simplify descriptor management") > Signed-off-by: Jia Wang <wangjia@ultrarisc.com> > --- Reviewed-by: Frank Li <Frank.Li@nxp.com> > drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c | 5 +---- > 1 file changed, 1 insertion(+), 4 deletions(-) > > diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c > index 742e08cfab43..61230d2b1c56 100644 > --- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c > +++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c > @@ -1052,10 +1052,7 @@ static void axi_chan_dump_lli(struct axi_dma_chan *chan, > static void axi_chan_list_dump_lli(struct axi_dma_chan *chan, > struct axi_dma_desc *desc_head) > { > - int count = atomic_read(&chan->descs_allocated); > - int i; > - > - for (i = 0; i < count; i++) > + for (unsigned int i = 0; i < desc_head->nr_hw_descs; i++) > axi_chan_dump_lli(chan, &desc_head->hw_desc[i]); > } > > > -- > 2.34.1 > ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v2 3/4] dmaengine: dw-axi-dmac: Fix CH_CFG2 channel priority position 2026-09-01 6:16 [PATCH v2 0/4] dmaengine: dw-axi-dmac: Fix burst encoding, LLI dump and priority Jia Wang 2026-09-01 6:16 ` [PATCH v2 1/4] dmaengine: dw-axi-dmac: Fix AXI burst length encoding Jia Wang 2026-09-01 6:16 ` [PATCH v2 2/4] dmaengine: dw-axi-dmac: Fix LLI dump out-of-bounds access Jia Wang @ 2026-09-01 6:16 ` Jia Wang 2026-09-01 6:28 ` sashiko-bot 2026-09-01 18:55 ` Frank Li 2026-09-01 6:16 ` [PATCH v2 4/4] dmaengine: dw-axi-dmac: Use bitfield helpers for registers Jia Wang 3 siblings, 2 replies; 12+ messages in thread From: Jia Wang @ 2026-09-01 6:16 UTC (permalink / raw) To: Eugeniy Paltsev, Vinod Koul, Frank Li, Pandith N, Andy Shevchenko, Sia Jee Heng Cc: dmaengine, linux-kernel, Jia Wang The CH_CFG2 channel priority field occupies bits 51:47 of the 64-bit channel configuration register, corresponding to bits 19:15 of CH_CFG2_H. The driver currently shifts the priority value by 20, programming the wrong bits. Use bit 15 as the field position. Fixes: 824351668a41 ("dmaengine: dw-axi-dmac: support DMAX_NUM_CHANNELS > 8") Signed-off-by: Jia Wang <wangjia@ultrarisc.com> --- drivers/dma/dw-axi-dmac/dw-axi-dmac.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h index 67cc199e24d1..97451bb8b16a 100644 --- a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h +++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h @@ -327,7 +327,7 @@ enum { #define CH_CFG2_H_TT_FC_POS 0 #define CH_CFG2_H_HS_SEL_SRC_POS 3 #define CH_CFG2_H_HS_SEL_DST_POS 4 -#define CH_CFG2_H_PRIORITY_POS 20 +#define CH_CFG2_H_PRIORITY_POS 15 /** * DW AXI DMA channel interrupts -- 2.34.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v2 3/4] dmaengine: dw-axi-dmac: Fix CH_CFG2 channel priority position 2026-09-01 6:16 ` [PATCH v2 3/4] dmaengine: dw-axi-dmac: Fix CH_CFG2 channel priority position Jia Wang @ 2026-09-01 6:28 ` sashiko-bot 2026-09-01 18:55 ` Frank Li 1 sibling, 0 replies; 12+ messages in thread From: sashiko-bot @ 2026-09-01 6:28 UTC (permalink / raw) To: Jia Wang; +Cc: vkoul, Frank.Li, dmaengine Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: Pre-existing issues: - [High] Spurious dev_err logs and potential duplicate execution of DMA descriptors due to active descriptors remaining on the `desc_issued` list. - [High] Missing NULL check on the error path in axi_desc_put() leads to a dma_pool_free() crash and an atomic counter underflow. -- commit ecdc36132aeb3706e71e4d58d69cbfe272b69e28 Author: Jia Wang <wangjia@ultrarisc.com> dmaengine: dw-axi-dmac: Fix CH_CFG2 channel priority position The driver currently shifts the priority value by 20, which programs the wrong bits for the CH_CFG2 channel priority field. This commit corrects the field position by using bit 15 instead. > diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h > index 67cc199e24d1f..97451bb8b16a7 100644 > --- a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h > +++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h > @@ -327,7 +327,7 @@ enum { > #define CH_CFG2_H_TT_FC_POS 0 > #define CH_CFG2_H_HS_SEL_SRC_POS 3 > #define CH_CFG2_H_HS_SEL_DST_POS 4 > -#define CH_CFG2_H_PRIORITY_POS 20 > +#define CH_CFG2_H_PRIORITY_POS 15 > > /** > * DW AXI DMA channel interrupts While reviewing this patch, I noticed a couple of pre-existing issues in the dw-axi-dmac driver: drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c:dma_chan_issue_pending() { ... if (vchan_issue_pending(&chan->vc)) axi_chan_start_first_queued(chan); ... } drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c:axi_chan_start_first_queued() { ... vd = vchan_next_desc(&chan->vc); if (!vd) return; desc = vd_to_axi_desc(vd); ... axi_chan_block_xfer_start(chan, desc); } drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c:axi_chan_block_xfer_start() { ... if (unlikely(axi_chan_is_hw_enable(chan))) { dev_err(chan2dev(chan), "%s is non-idle!\n", axi_chan_name(chan)); return; } ... } [Severity: High] This isn't a bug introduced by this patch, but if a client queues a second transfer and calls dma_chan_issue_pending() while the first is actively running, does vchan_issue_pending() leave the active descriptor in the issued list? If vchan_next_desc() peeks at the head of the issued list without removing it, does axi_chan_start_first_queued() fetch the already running first descriptor? If so, would axi_chan_block_xfer_start() detect the hardware is active and print a spurious dev_err, or erroneously restart the already completed descriptor if the hardware just finished but the interrupt hasn't fired yet? drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c:axi_desc_put() { ... for (descs_put = 0; descs_put < count; descs_put++) { hw_desc = &desc->hw_desc[descs_put]; dma_pool_free(chan->desc_pool, hw_desc->lli, hw_desc->llp); } kfree(desc->hw_desc); kfree(desc); atomic_sub(descs_put, &chan->descs_allocated); ... } [Severity: High] This is a pre-existing issue, but if memory is exhausted during allocation and axi_desc_get() returns NULL and goes to the error path, could hw_desc->lli be NULL when dma_pool_free() is called here? Does dma_pool_free() safely handle a NULL virtual address, or could this cause a crash when it tries to push the block onto the pool's free list? Also, does subtracting descs_put (which reaches the full count) from chan->descs_allocated cause an atomic counter underflow if only a partial allocation succeeded? -- Sashiko AI review · https://sashiko.dev/#/patchset/20260901-dma-fix-v2-0-d7f0459ebb14@ultrarisc.com?part=3 ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 3/4] dmaengine: dw-axi-dmac: Fix CH_CFG2 channel priority position 2026-09-01 6:16 ` [PATCH v2 3/4] dmaengine: dw-axi-dmac: Fix CH_CFG2 channel priority position Jia Wang 2026-09-01 6:28 ` sashiko-bot @ 2026-09-01 18:55 ` Frank Li 1 sibling, 0 replies; 12+ messages in thread From: Frank Li @ 2026-09-01 18:55 UTC (permalink / raw) To: Jia Wang Cc: Eugeniy Paltsev, Vinod Koul, Frank Li, Pandith N, Andy Shevchenko, Sia Jee Heng, dmaengine, linux-kernel On Tue, Sep 01, 2026 at 02:16:06PM +0800, Jia Wang wrote: > The CH_CFG2 channel priority field occupies bits 51:47 of the 64-bit > channel configuration register, corresponding to bits 19:15 of CH_CFG2_H. > > The driver currently shifts the priority value by 20, programming the > wrong bits. Use bit 15 as the field position. > > Fixes: 824351668a41 ("dmaengine: dw-axi-dmac: support DMAX_NUM_CHANNELS > 8") > Signed-off-by: Jia Wang <wangjia@ultrarisc.com> > --- Reviewed-by: Frank Li <Frank.Li@nxp.com> > drivers/dma/dw-axi-dmac/dw-axi-dmac.h | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h > index 67cc199e24d1..97451bb8b16a 100644 > --- a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h > +++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h > @@ -327,7 +327,7 @@ enum { > #define CH_CFG2_H_TT_FC_POS 0 > #define CH_CFG2_H_HS_SEL_SRC_POS 3 > #define CH_CFG2_H_HS_SEL_DST_POS 4 > -#define CH_CFG2_H_PRIORITY_POS 20 > +#define CH_CFG2_H_PRIORITY_POS 15 > > /** > * DW AXI DMA channel interrupts > > -- > 2.34.1 > ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v2 4/4] dmaengine: dw-axi-dmac: Use bitfield helpers for registers 2026-09-01 6:16 [PATCH v2 0/4] dmaengine: dw-axi-dmac: Fix burst encoding, LLI dump and priority Jia Wang ` (2 preceding siblings ...) 2026-09-01 6:16 ` [PATCH v2 3/4] dmaengine: dw-axi-dmac: Fix CH_CFG2 channel priority position Jia Wang @ 2026-09-01 6:16 ` Jia Wang 2026-09-01 7:02 ` Andy Shevchenko 3 siblings, 1 reply; 12+ messages in thread From: Jia Wang @ 2026-09-01 6:16 UTC (permalink / raw) To: Eugeniy Paltsev, Vinod Koul, Frank Li, Pandith N, Andy Shevchenko, Sia Jee Heng Cc: dmaengine, linux-kernel, Jia Wang, Frank Li The driver open-codes several channel configuration and descriptor control bitfield writes with left shifts. Define masks for those fields and use FIELD_PREP() when programming the registers. Valid field values keep the same encoding. FIELD_PREP() confines values to their respective fields, but does not validate handshake numbers supplied through DMA specifiers. Suggested-by: Frank Li <Frank.Li@nxp.com> Signed-off-by: Jia Wang <wangjia@ultrarisc.com> --- drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c | 69 +++++++++++++------------- drivers/dma/dw-axi-dmac/dw-axi-dmac.h | 44 ++++++++-------- 2 files changed, 57 insertions(+), 56 deletions(-) diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c index 61230d2b1c56..f8ab8d072222 100644 --- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c +++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c @@ -7,6 +7,7 @@ * Author: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com> */ +#include <linux/bitfield.h> #include <linux/bitops.h> #include <linux/delay.h> #include <linux/device.h> @@ -101,23 +102,23 @@ static inline void axi_chan_config_write(struct axi_dma_chan *chan, { u32 cfg_lo, cfg_hi; - cfg_lo = (config->dst_multblk_type << CH_CFG_L_DST_MULTBLK_TYPE_POS | - config->src_multblk_type << CH_CFG_L_SRC_MULTBLK_TYPE_POS); + cfg_lo = FIELD_PREP(CH_CFG_L_DST_MULTBLK_TYPE, config->dst_multblk_type) | + FIELD_PREP(CH_CFG_L_SRC_MULTBLK_TYPE, config->src_multblk_type); if (chan->chip->dw->hdata->reg_map_8_channels && !chan->chip->dw->hdata->use_cfg2) { - cfg_hi = config->tt_fc << CH_CFG_H_TT_FC_POS | - config->hs_sel_src << CH_CFG_H_HS_SEL_SRC_POS | - config->hs_sel_dst << CH_CFG_H_HS_SEL_DST_POS | - config->src_per << CH_CFG_H_SRC_PER_POS | - config->dst_per << CH_CFG_H_DST_PER_POS | - config->prior << CH_CFG_H_PRIORITY_POS; + cfg_hi = FIELD_PREP(CH_CFG_H_TT_FC, config->tt_fc) | + FIELD_PREP(CH_CFG_H_HS_SEL_SRC, config->hs_sel_src) | + FIELD_PREP(CH_CFG_H_HS_SEL_DST, config->hs_sel_dst) | + FIELD_PREP(CH_CFG_H_SRC_PER, config->src_per) | + FIELD_PREP(CH_CFG_H_DST_PER, config->dst_per) | + FIELD_PREP(CH_CFG_H_PRIORITY, config->prior); } else { - cfg_lo |= config->src_per << CH_CFG2_L_SRC_PER_POS | - config->dst_per << CH_CFG2_L_DST_PER_POS; - cfg_hi = config->tt_fc << CH_CFG2_H_TT_FC_POS | - config->hs_sel_src << CH_CFG2_H_HS_SEL_SRC_POS | - config->hs_sel_dst << CH_CFG2_H_HS_SEL_DST_POS | - config->prior << CH_CFG2_H_PRIORITY_POS; + cfg_lo |= FIELD_PREP(CH_CFG2_L_SRC_PER, config->src_per) | + FIELD_PREP(CH_CFG2_L_DST_PER, config->dst_per); + cfg_hi = FIELD_PREP(CH_CFG2_H_TT_FC, config->tt_fc) | + FIELD_PREP(CH_CFG2_H_HS_SEL_SRC, config->hs_sel_src) | + FIELD_PREP(CH_CFG2_H_HS_SEL_DST, config->hs_sel_dst) | + FIELD_PREP(CH_CFG2_H_PRIORITY, config->prior); } axi_chan_iowrite32(chan, CH_CFG_L, cfg_lo); axi_chan_iowrite32(chan, CH_CFG_H, cfg_hi); @@ -677,19 +678,19 @@ static int dw_axi_dma_set_hw_desc(struct axi_dma_chan *chan, case DMA_MEM_TO_DEV: reg_width = __ffs(chan->config.dst_addr_width); device_addr = chan->config.dst_addr; - ctllo = reg_width << CH_CTL_L_DST_WIDTH_POS | - mem_width << CH_CTL_L_SRC_WIDTH_POS | - DWAXIDMAC_CH_CTL_L_NOINC << CH_CTL_L_DST_INC_POS | - DWAXIDMAC_CH_CTL_L_INC << CH_CTL_L_SRC_INC_POS; + ctllo = FIELD_PREP(CH_CTL_L_DST_WIDTH, reg_width) | + FIELD_PREP(CH_CTL_L_SRC_WIDTH, mem_width) | + FIELD_PREP(CH_CTL_L_DST_INC, DWAXIDMAC_CH_CTL_L_NOINC) | + FIELD_PREP(CH_CTL_L_SRC_INC, DWAXIDMAC_CH_CTL_L_INC); block_ts = len >> mem_width; break; case DMA_DEV_TO_MEM: reg_width = __ffs(chan->config.src_addr_width); device_addr = chan->config.src_addr; - ctllo = reg_width << CH_CTL_L_SRC_WIDTH_POS | - mem_width << CH_CTL_L_DST_WIDTH_POS | - DWAXIDMAC_CH_CTL_L_INC << CH_CTL_L_DST_INC_POS | - DWAXIDMAC_CH_CTL_L_NOINC << CH_CTL_L_SRC_INC_POS; + ctllo = FIELD_PREP(CH_CTL_L_SRC_WIDTH, reg_width) | + FIELD_PREP(CH_CTL_L_DST_WIDTH, mem_width) | + FIELD_PREP(CH_CTL_L_DST_INC, DWAXIDMAC_CH_CTL_L_INC) | + FIELD_PREP(CH_CTL_L_SRC_INC, DWAXIDMAC_CH_CTL_L_NOINC); block_ts = len >> reg_width; break; default: @@ -708,8 +709,8 @@ static int dw_axi_dma_set_hw_desc(struct axi_dma_chan *chan, if (chan->chip->dw->hdata->restrict_axi_burst_len) { burst_len = chan->chip->dw->hdata->axi_rw_burst_len - 1; ctlhi |= CH_CTL_H_ARLEN_EN | CH_CTL_H_AWLEN_EN | - burst_len << CH_CTL_H_ARLEN_POS | - burst_len << CH_CTL_H_AWLEN_POS; + FIELD_PREP(CH_CTL_H_ARLEN, burst_len) | + FIELD_PREP(CH_CTL_H_AWLEN, burst_len); } hw_desc->lli->ctl_hi = cpu_to_le32(ctlhi); @@ -724,8 +725,8 @@ static int dw_axi_dma_set_hw_desc(struct axi_dma_chan *chan, hw_desc->lli->block_ts_lo = cpu_to_le32(block_ts - 1); - ctllo |= DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_DST_MSIZE_POS | - DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_SRC_MSIZE_POS; + ctllo |= FIELD_PREP(CH_CTL_L_DST_MSIZE, DWAXIDMAC_BURST_TRANS_LEN_4) | + FIELD_PREP(CH_CTL_L_SRC_MSIZE, DWAXIDMAC_BURST_TRANS_LEN_4); hw_desc->lli->ctl_lo = cpu_to_le32(ctllo); set_desc_src_master(hw_desc); @@ -978,18 +979,18 @@ dma_chan_prep_dma_memcpy(struct dma_chan *dchan, dma_addr_t dst_adr, u32 burst_len = chan->chip->dw->hdata->axi_rw_burst_len - 1; reg |= (CH_CTL_H_ARLEN_EN | - burst_len << CH_CTL_H_ARLEN_POS | + FIELD_PREP(CH_CTL_H_ARLEN, burst_len) | CH_CTL_H_AWLEN_EN | - burst_len << CH_CTL_H_AWLEN_POS); + FIELD_PREP(CH_CTL_H_AWLEN, burst_len)); } hw_desc->lli->ctl_hi = cpu_to_le32(reg); - reg = (DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_DST_MSIZE_POS | - DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_SRC_MSIZE_POS | - xfer_width << CH_CTL_L_DST_WIDTH_POS | - xfer_width << CH_CTL_L_SRC_WIDTH_POS | - DWAXIDMAC_CH_CTL_L_INC << CH_CTL_L_DST_INC_POS | - DWAXIDMAC_CH_CTL_L_INC << CH_CTL_L_SRC_INC_POS); + reg = (FIELD_PREP(CH_CTL_L_DST_MSIZE, DWAXIDMAC_BURST_TRANS_LEN_4) | + FIELD_PREP(CH_CTL_L_SRC_MSIZE, DWAXIDMAC_BURST_TRANS_LEN_4) | + FIELD_PREP(CH_CTL_L_DST_WIDTH, xfer_width) | + FIELD_PREP(CH_CTL_L_SRC_WIDTH, xfer_width) | + FIELD_PREP(CH_CTL_L_DST_INC, DWAXIDMAC_CH_CTL_L_INC) | + FIELD_PREP(CH_CTL_L_SRC_INC, DWAXIDMAC_CH_CTL_L_INC)); hw_desc->lli->ctl_lo = cpu_to_le32(reg); set_desc_src_master(hw_desc); diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h index 97451bb8b16a..b4ed241e87e2 100644 --- a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h +++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h @@ -234,9 +234,9 @@ static inline struct axi_dma_chan *dchan_to_axi_dma_chan(struct dma_chan *dchan) /* CH_CTL_H */ #define CH_CTL_H_ARLEN_EN BIT(6) -#define CH_CTL_H_ARLEN_POS 7 +#define CH_CTL_H_ARLEN GENMASK(14, 7) #define CH_CTL_H_AWLEN_EN BIT(15) -#define CH_CTL_H_AWLEN_POS 16 +#define CH_CTL_H_AWLEN GENMASK(23, 16) enum { DWAXIDMAC_ARWLEN_1 = 0, @@ -258,8 +258,8 @@ enum { /* CH_CTL_L */ #define CH_CTL_L_LAST_WRITE_EN BIT(30) -#define CH_CTL_L_DST_MSIZE_POS 18 -#define CH_CTL_L_SRC_MSIZE_POS 14 +#define CH_CTL_L_DST_MSIZE GENMASK(21, 18) +#define CH_CTL_L_SRC_MSIZE GENMASK(17, 14) enum { DWAXIDMAC_BURST_TRANS_LEN_1 = 0, @@ -274,11 +274,11 @@ enum { DWAXIDMAC_BURST_TRANS_LEN_1024 }; -#define CH_CTL_L_DST_WIDTH_POS 11 -#define CH_CTL_L_SRC_WIDTH_POS 8 +#define CH_CTL_L_DST_WIDTH GENMASK(13, 11) +#define CH_CTL_L_SRC_WIDTH GENMASK(10, 8) -#define CH_CTL_L_DST_INC_POS 6 -#define CH_CTL_L_SRC_INC_POS 4 +#define CH_CTL_L_DST_INC BIT(6) +#define CH_CTL_L_SRC_INC BIT(4) enum { DWAXIDMAC_CH_CTL_L_INC = 0, DWAXIDMAC_CH_CTL_L_NOINC @@ -288,17 +288,17 @@ enum { #define CH_CTL_L_SRC_MAST BIT(0) /* CH_CFG_H */ -#define CH_CFG_H_PRIORITY_POS 17 -#define CH_CFG_H_DST_PER_POS 12 -#define CH_CFG_H_SRC_PER_POS 7 -#define CH_CFG_H_HS_SEL_DST_POS 4 -#define CH_CFG_H_HS_SEL_SRC_POS 3 +#define CH_CFG_H_PRIORITY GENMASK(19, 17) +#define CH_CFG_H_DST_PER GENMASK(15, 12) +#define CH_CFG_H_SRC_PER GENMASK(10, 7) +#define CH_CFG_H_HS_SEL_DST BIT(4) +#define CH_CFG_H_HS_SEL_SRC BIT(3) enum { DWAXIDMAC_HS_SEL_HW = 0, DWAXIDMAC_HS_SEL_SW }; -#define CH_CFG_H_TT_FC_POS 0 +#define CH_CFG_H_TT_FC GENMASK(2, 0) enum { DWAXIDMAC_TT_FC_MEM_TO_MEM_DMAC = 0, DWAXIDMAC_TT_FC_MEM_TO_PER_DMAC, @@ -311,8 +311,8 @@ enum { }; /* CH_CFG_L */ -#define CH_CFG_L_DST_MULTBLK_TYPE_POS 2 -#define CH_CFG_L_SRC_MULTBLK_TYPE_POS 0 +#define CH_CFG_L_DST_MULTBLK_TYPE GENMASK(3, 2) +#define CH_CFG_L_SRC_MULTBLK_TYPE GENMASK(1, 0) enum { DWAXIDMAC_MBLK_TYPE_CONTIGUOUS = 0, DWAXIDMAC_MBLK_TYPE_RELOAD, @@ -321,13 +321,13 @@ enum { }; /* CH_CFG2 */ -#define CH_CFG2_L_SRC_PER_POS 4 -#define CH_CFG2_L_DST_PER_POS 11 +#define CH_CFG2_L_SRC_PER GENMASK(9, 4) +#define CH_CFG2_L_DST_PER GENMASK(16, 11) -#define CH_CFG2_H_TT_FC_POS 0 -#define CH_CFG2_H_HS_SEL_SRC_POS 3 -#define CH_CFG2_H_HS_SEL_DST_POS 4 -#define CH_CFG2_H_PRIORITY_POS 15 +#define CH_CFG2_H_TT_FC GENMASK(2, 0) +#define CH_CFG2_H_HS_SEL_SRC BIT(3) +#define CH_CFG2_H_HS_SEL_DST BIT(4) +#define CH_CFG2_H_PRIORITY GENMASK(19, 15) /** * DW AXI DMA channel interrupts -- 2.34.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v2 4/4] dmaengine: dw-axi-dmac: Use bitfield helpers for registers 2026-09-01 6:16 ` [PATCH v2 4/4] dmaengine: dw-axi-dmac: Use bitfield helpers for registers Jia Wang @ 2026-09-01 7:02 ` Andy Shevchenko 2026-09-01 8:49 ` Jia Wang 0 siblings, 1 reply; 12+ messages in thread From: Andy Shevchenko @ 2026-09-01 7:02 UTC (permalink / raw) To: Jia Wang Cc: Eugeniy Paltsev, Vinod Koul, Frank Li, Pandith N, Sia Jee Heng, dmaengine, linux-kernel, Frank Li On Tue, Sep 01, 2026 at 02:16:07PM +0800, Jia Wang wrote: > The driver open-codes several channel configuration and descriptor > control bitfield writes with left shifts. Define masks for those fields > and use FIELD_PREP() when programming the registers. > > Valid field values keep the same encoding. FIELD_PREP() confines values > to their respective fields, but does not validate handshake numbers > supplied through DMA specifiers. ... > { > u32 cfg_lo, cfg_hi; > > - cfg_lo = (config->dst_multblk_type << CH_CFG_L_DST_MULTBLK_TYPE_POS | > - config->src_multblk_type << CH_CFG_L_SRC_MULTBLK_TYPE_POS); > + cfg_lo = FIELD_PREP(CH_CFG_L_DST_MULTBLK_TYPE, config->dst_multblk_type) | > + FIELD_PREP(CH_CFG_L_SRC_MULTBLK_TYPE, config->src_multblk_type); Personally I would duplicate this to make each branch self-contained. > if (chan->chip->dw->hdata->reg_map_8_channels && > !chan->chip->dw->hdata->use_cfg2) { > - cfg_hi = config->tt_fc << CH_CFG_H_TT_FC_POS | > - config->hs_sel_src << CH_CFG_H_HS_SEL_SRC_POS | > - config->hs_sel_dst << CH_CFG_H_HS_SEL_DST_POS | > - config->src_per << CH_CFG_H_SRC_PER_POS | > - config->dst_per << CH_CFG_H_DST_PER_POS | > - config->prior << CH_CFG_H_PRIORITY_POS; cfg_lo = FIELD_PREP(CH_CFG_L_DST_MULTBLK_TYPE, config->dst_multblk_type) | FIELD_PREP(CH_CFG_L_SRC_MULTBLK_TYPE, config->src_multblk_type); > + cfg_hi = FIELD_PREP(CH_CFG_H_TT_FC, config->tt_fc) | > + FIELD_PREP(CH_CFG_H_HS_SEL_SRC, config->hs_sel_src) | > + FIELD_PREP(CH_CFG_H_HS_SEL_DST, config->hs_sel_dst) | > + FIELD_PREP(CH_CFG_H_SRC_PER, config->src_per) | > + FIELD_PREP(CH_CFG_H_DST_PER, config->dst_per) | > + FIELD_PREP(CH_CFG_H_PRIORITY, config->prior); > } else { > - cfg_lo |= config->src_per << CH_CFG2_L_SRC_PER_POS | > - config->dst_per << CH_CFG2_L_DST_PER_POS; > - cfg_hi = config->tt_fc << CH_CFG2_H_TT_FC_POS | > - config->hs_sel_src << CH_CFG2_H_HS_SEL_SRC_POS | > - config->hs_sel_dst << CH_CFG2_H_HS_SEL_DST_POS | > - config->prior << CH_CFG2_H_PRIORITY_POS; > + cfg_lo |= FIELD_PREP(CH_CFG2_L_SRC_PER, config->src_per) | > + FIELD_PREP(CH_CFG2_L_DST_PER, config->dst_per); cfg_lo = FIELD_PREP(CH_CFG_L_DST_MULTBLK_TYPE, config->dst_multblk_type) | FIELD_PREP(CH_CFG_L_SRC_MULTBLK_TYPE, config->src_multblk_type) | FIELD_PREP(CH_CFG2_L_SRC_PER, config->src_per) | FIELD_PREP(CH_CFG2_L_DST_PER, config->dst_per); > + cfg_hi = FIELD_PREP(CH_CFG2_H_TT_FC, config->tt_fc) | > + FIELD_PREP(CH_CFG2_H_HS_SEL_SRC, config->hs_sel_src) | > + FIELD_PREP(CH_CFG2_H_HS_SEL_DST, config->hs_sel_dst) | > + FIELD_PREP(CH_CFG2_H_PRIORITY, config->prior); > } ... > - reg = (DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_DST_MSIZE_POS | > - DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_SRC_MSIZE_POS | > - xfer_width << CH_CTL_L_DST_WIDTH_POS | > - xfer_width << CH_CTL_L_SRC_WIDTH_POS | > - DWAXIDMAC_CH_CTL_L_INC << CH_CTL_L_DST_INC_POS | > - DWAXIDMAC_CH_CTL_L_INC << CH_CTL_L_SRC_INC_POS); > + reg = (FIELD_PREP(CH_CTL_L_DST_MSIZE, DWAXIDMAC_BURST_TRANS_LEN_4) | > + FIELD_PREP(CH_CTL_L_SRC_MSIZE, DWAXIDMAC_BURST_TRANS_LEN_4) | > + FIELD_PREP(CH_CTL_L_DST_WIDTH, xfer_width) | > + FIELD_PREP(CH_CTL_L_SRC_WIDTH, xfer_width) | > + FIELD_PREP(CH_CTL_L_DST_INC, DWAXIDMAC_CH_CTL_L_INC) | > + FIELD_PREP(CH_CTL_L_SRC_INC, DWAXIDMAC_CH_CTL_L_INC)); Unneeded parentheses. -- With Best Regards, Andy Shevchenko ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 4/4] dmaengine: dw-axi-dmac: Use bitfield helpers for registers 2026-09-01 7:02 ` Andy Shevchenko @ 2026-09-01 8:49 ` Jia Wang 0 siblings, 0 replies; 12+ messages in thread From: Jia Wang @ 2026-09-01 8:49 UTC (permalink / raw) To: Andy Shevchenko Cc: Jia Wang, Eugeniy Paltsev, Vinod Koul, Frank Li, Pandith N, Sia Jee Heng, dmaengine, linux-kernel, Frank Li On 2026-09-01 10:02 +0300, Andy Shevchenko wrote: > On Tue, Sep 01, 2026 at 02:16:07PM +0800, Jia Wang wrote: > > The driver open-codes several channel configuration and descriptor > > control bitfield writes with left shifts. Define masks for those fields > > and use FIELD_PREP() when programming the registers. > > > > Valid field values keep the same encoding. FIELD_PREP() confines values > > to their respective fields, but does not validate handshake numbers > > supplied through DMA specifiers. > > ... > > > { > > u32 cfg_lo, cfg_hi; > > > > - cfg_lo = (config->dst_multblk_type << CH_CFG_L_DST_MULTBLK_TYPE_POS | > > - config->src_multblk_type << CH_CFG_L_SRC_MULTBLK_TYPE_POS); > > + cfg_lo = FIELD_PREP(CH_CFG_L_DST_MULTBLK_TYPE, config->dst_multblk_type) | > > + FIELD_PREP(CH_CFG_L_SRC_MULTBLK_TYPE, config->src_multblk_type); > > Personally I would duplicate this to make each branch self-contained. > Agreed. I will initialize cfg_lo separately in each branch in the next version. > > if (chan->chip->dw->hdata->reg_map_8_channels && > > !chan->chip->dw->hdata->use_cfg2) { > > - cfg_hi = config->tt_fc << CH_CFG_H_TT_FC_POS | > > - config->hs_sel_src << CH_CFG_H_HS_SEL_SRC_POS | > > - config->hs_sel_dst << CH_CFG_H_HS_SEL_DST_POS | > > - config->src_per << CH_CFG_H_SRC_PER_POS | > > - config->dst_per << CH_CFG_H_DST_PER_POS | > > - config->prior << CH_CFG_H_PRIORITY_POS; > > cfg_lo = FIELD_PREP(CH_CFG_L_DST_MULTBLK_TYPE, config->dst_multblk_type) | > FIELD_PREP(CH_CFG_L_SRC_MULTBLK_TYPE, config->src_multblk_type); > > > + cfg_hi = FIELD_PREP(CH_CFG_H_TT_FC, config->tt_fc) | > > + FIELD_PREP(CH_CFG_H_HS_SEL_SRC, config->hs_sel_src) | > > + FIELD_PREP(CH_CFG_H_HS_SEL_DST, config->hs_sel_dst) | > > + FIELD_PREP(CH_CFG_H_SRC_PER, config->src_per) | > > + FIELD_PREP(CH_CFG_H_DST_PER, config->dst_per) | > > + FIELD_PREP(CH_CFG_H_PRIORITY, config->prior); > > } else { > > - cfg_lo |= config->src_per << CH_CFG2_L_SRC_PER_POS | > > - config->dst_per << CH_CFG2_L_DST_PER_POS; > > - cfg_hi = config->tt_fc << CH_CFG2_H_TT_FC_POS | > > - config->hs_sel_src << CH_CFG2_H_HS_SEL_SRC_POS | > > - config->hs_sel_dst << CH_CFG2_H_HS_SEL_DST_POS | > > - config->prior << CH_CFG2_H_PRIORITY_POS; > > + cfg_lo |= FIELD_PREP(CH_CFG2_L_SRC_PER, config->src_per) | > > + FIELD_PREP(CH_CFG2_L_DST_PER, config->dst_per); > > cfg_lo = FIELD_PREP(CH_CFG_L_DST_MULTBLK_TYPE, config->dst_multblk_type) | > FIELD_PREP(CH_CFG_L_SRC_MULTBLK_TYPE, config->src_multblk_type) | > FIELD_PREP(CH_CFG2_L_SRC_PER, config->src_per) | > FIELD_PREP(CH_CFG2_L_DST_PER, config->dst_per); > > > + cfg_hi = FIELD_PREP(CH_CFG2_H_TT_FC, config->tt_fc) | > > + FIELD_PREP(CH_CFG2_H_HS_SEL_SRC, config->hs_sel_src) | > > + FIELD_PREP(CH_CFG2_H_HS_SEL_DST, config->hs_sel_dst) | > > + FIELD_PREP(CH_CFG2_H_PRIORITY, config->prior); > > } > > ... > > > - reg = (DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_DST_MSIZE_POS | > > - DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_SRC_MSIZE_POS | > > - xfer_width << CH_CTL_L_DST_WIDTH_POS | > > - xfer_width << CH_CTL_L_SRC_WIDTH_POS | > > - DWAXIDMAC_CH_CTL_L_INC << CH_CTL_L_DST_INC_POS | > > - DWAXIDMAC_CH_CTL_L_INC << CH_CTL_L_SRC_INC_POS); > > + reg = (FIELD_PREP(CH_CTL_L_DST_MSIZE, DWAXIDMAC_BURST_TRANS_LEN_4) | > > + FIELD_PREP(CH_CTL_L_SRC_MSIZE, DWAXIDMAC_BURST_TRANS_LEN_4) | > > + FIELD_PREP(CH_CTL_L_DST_WIDTH, xfer_width) | > > + FIELD_PREP(CH_CTL_L_SRC_WIDTH, xfer_width) | > > + FIELD_PREP(CH_CTL_L_DST_INC, DWAXIDMAC_CH_CTL_L_INC) | > > + FIELD_PREP(CH_CTL_L_SRC_INC, DWAXIDMAC_CH_CTL_L_INC)); > > Unneeded parentheses. > I will drop the outer parentheses in the next version. > -- > With Best Regards, > Andy Shevchenko > > > Best regards, Jia Wang ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2026-09-01 18:55 UTC | newest] Thread overview: 12+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-09-01 6:16 [PATCH v2 0/4] dmaengine: dw-axi-dmac: Fix burst encoding, LLI dump and priority Jia Wang 2026-09-01 6:16 ` [PATCH v2 1/4] dmaengine: dw-axi-dmac: Fix AXI burst length encoding Jia Wang 2026-09-01 6:29 ` sashiko-bot 2026-09-01 6:16 ` [PATCH v2 2/4] dmaengine: dw-axi-dmac: Fix LLI dump out-of-bounds access Jia Wang 2026-09-01 6:29 ` sashiko-bot 2026-09-01 18:53 ` Frank Li 2026-09-01 6:16 ` [PATCH v2 3/4] dmaengine: dw-axi-dmac: Fix CH_CFG2 channel priority position Jia Wang 2026-09-01 6:28 ` sashiko-bot 2026-09-01 18:55 ` Frank Li 2026-09-01 6:16 ` [PATCH v2 4/4] dmaengine: dw-axi-dmac: Use bitfield helpers for registers Jia Wang 2026-09-01 7:02 ` Andy Shevchenko 2026-09-01 8:49 ` Jia Wang
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).