* [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
* [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
* [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
* [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 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 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
* 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 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
* 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
* 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
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