* [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; 9+ 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] 9+ 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:16 ` [PATCH v2 2/4] dmaengine: dw-axi-dmac: Fix LLI dump out-of-bounds access Jia Wang ` (2 subsequent siblings) 3 siblings, 0 replies; 9+ 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 [flat|nested] 9+ 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 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, 1 reply; 9+ 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 [flat|nested] 9+ 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 18:53 ` Frank Li 0 siblings, 0 replies; 9+ 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] 9+ 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 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, 1 reply; 9+ 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 [flat|nested] 9+ 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 18:55 ` Frank Li 0 siblings, 0 replies; 9+ 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] 9+ 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; 9+ 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 [flat|nested] 9+ 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; 9+ 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] 9+ 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; 9+ 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] 9+ messages in thread
end of thread, other threads:[~2026-09-01 18:55 UTC | newest] Thread overview: 9+ 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:16 ` [PATCH v2 2/4] dmaengine: dw-axi-dmac: Fix LLI dump out-of-bounds access Jia Wang 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 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
all inboxes | Powered by JetHome®