DMA Engine development
 help / color / mirror / Atom feed
* [PATCH v1] dmaengine: dw-edma: Enable HDMA 64R/W Channels
@ 2026-05-29 12:21 Devendra K Verma
  2026-05-29 13:09 ` sashiko-bot
  0 siblings, 1 reply; 2+ messages in thread
From: Devendra K Verma @ 2026-05-29 12:21 UTC (permalink / raw)
  To: bhelgaas, mani, vkoul, Frank.Li
  Cc: dmaengine, linux-kernel, michal.simek, devendra.verma

As per 'Designware Cores PCI Express Controller Databook',
Section 7.1 - Overview, HDMA supports 64 Read and 64 Write
channels. Current controller driver supports up to 8 read and
write channels only. In order to utilize all the channels the
controller driver need to have the channel related structs
and variables as per the number of channels supported by IP.
Following changes are made to enable 64 Read / 64 Write
channel support:

 o Defined HDMA specific macros to reflect the channel count.
 o The count of ll_regions and dt_regions in dw_edma_chip and
   dw_edma_pcie_data shall be in accordance to number of read
   and write channels.
 o In dw_edma_probe() configure the channels as per the channels
   of the IP used.

Signed-off-by: Devendra K Verma <devendra.verma@amd.com>
---
 drivers/dma/dw-edma/dw-edma-core.c    | 15 +++++++++++----
 drivers/dma/dw-edma/dw-edma-pcie.c    |  8 ++++----
 drivers/dma/dw-edma/dw-hdma-v0-regs.h |  2 +-
 include/linux/dma/edma.h              | 10 ++++++----
 4 files changed, 22 insertions(+), 13 deletions(-)

diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
index c2feb3adc79f..02ce005399dc 100644
--- a/drivers/dma/dw-edma/dw-edma-core.c
+++ b/drivers/dma/dw-edma/dw-edma-core.c
@@ -1079,6 +1079,8 @@ int dw_edma_probe(struct dw_edma_chip *chip)
 	struct dw_edma *dw;
 	u32 wr_alloc = 0;
 	u32 rd_alloc = 0;
+	u16 max_wr_cnt;
+	u16 max_rd_cnt;
 	int i, err;
 
 	if (!chip)
@@ -1094,20 +1096,25 @@ int dw_edma_probe(struct dw_edma_chip *chip)
 
 	dw->chip = chip;
 
-	if (dw->chip->mf == EDMA_MF_HDMA_NATIVE)
+	if (dw->chip->mf == EDMA_MF_HDMA_NATIVE) {
 		dw_hdma_v0_core_register(dw);
-	else
+		max_wr_cnt = HDMA_MAX_WR_CH;
+		max_rd_cnt = HDMA_MAX_RD_CH;
+	} else {
 		dw_edma_v0_core_register(dw);
+		max_wr_cnt = EDMA_MAX_WR_CH;
+		max_rd_cnt = EDMA_MAX_RD_CH;
+	}
 
 	raw_spin_lock_init(&dw->lock);
 
 	dw->wr_ch_cnt = min_t(u16, chip->ll_wr_cnt,
 			      dw_edma_core_ch_count(dw, EDMA_DIR_WRITE));
-	dw->wr_ch_cnt = min_t(u16, dw->wr_ch_cnt, EDMA_MAX_WR_CH);
+	dw->wr_ch_cnt = min_t(u16, dw->wr_ch_cnt, max_wr_cnt);
 
 	dw->rd_ch_cnt = min_t(u16, chip->ll_rd_cnt,
 			      dw_edma_core_ch_count(dw, EDMA_DIR_READ));
-	dw->rd_ch_cnt = min_t(u16, dw->rd_ch_cnt, EDMA_MAX_RD_CH);
+	dw->rd_ch_cnt = min_t(u16, dw->rd_ch_cnt, max_rd_cnt);
 
 	if (!dw->wr_ch_cnt && !dw->rd_ch_cnt)
 		return -EINVAL;
diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
index 0b30ce138503..79f653da8e0f 100644
--- a/drivers/dma/dw-edma/dw-edma-pcie.c
+++ b/drivers/dma/dw-edma/dw-edma-pcie.c
@@ -61,11 +61,11 @@ struct dw_edma_pcie_data {
 	/* eDMA registers location */
 	struct dw_edma_block		rg;
 	/* eDMA memory linked list location */
-	struct dw_edma_block		ll_wr[EDMA_MAX_WR_CH];
-	struct dw_edma_block		ll_rd[EDMA_MAX_RD_CH];
+	struct dw_edma_block		ll_wr[HDMA_MAX_WR_CH];
+	struct dw_edma_block		ll_rd[HDMA_MAX_RD_CH];
 	/* eDMA memory data location */
-	struct dw_edma_block		dt_wr[EDMA_MAX_WR_CH];
-	struct dw_edma_block		dt_rd[EDMA_MAX_RD_CH];
+	struct dw_edma_block		dt_wr[HDMA_MAX_WR_CH];
+	struct dw_edma_block		dt_rd[HDMA_MAX_RD_CH];
 	/* Other */
 	enum dw_edma_map_format		mf;
 	u8				irqs;
diff --git a/drivers/dma/dw-edma/dw-hdma-v0-regs.h b/drivers/dma/dw-edma/dw-hdma-v0-regs.h
index 7759ba9b4850..48e40efceb2e 100644
--- a/drivers/dma/dw-edma/dw-hdma-v0-regs.h
+++ b/drivers/dma/dw-edma/dw-hdma-v0-regs.h
@@ -11,7 +11,7 @@
 
 #include <linux/dmaengine.h>
 
-#define HDMA_V0_MAX_NR_CH			8
+#define HDMA_V0_MAX_NR_CH			64
 #define HDMA_V0_CH_EN				BIT(0)
 #define HDMA_V0_LOCAL_ABORT_INT_EN		BIT(6)
 #define HDMA_V0_REMOTE_ABORT_INT_EN		BIT(5)
diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h
index 1fafd5b0e315..da7a5cc93ad4 100644
--- a/include/linux/dma/edma.h
+++ b/include/linux/dma/edma.h
@@ -14,6 +14,8 @@
 
 #define EDMA_MAX_WR_CH                                  8
 #define EDMA_MAX_RD_CH                                  8
+#define HDMA_MAX_WR_CH                                  64
+#define HDMA_MAX_RD_CH                                  64
 
 struct dw_edma;
 
@@ -89,12 +91,12 @@ struct dw_edma_chip {
 	u16			ll_wr_cnt;
 	u16			ll_rd_cnt;
 	/* link list address */
-	struct dw_edma_region	ll_region_wr[EDMA_MAX_WR_CH];
-	struct dw_edma_region	ll_region_rd[EDMA_MAX_RD_CH];
+	struct dw_edma_region	ll_region_wr[HDMA_MAX_WR_CH];
+	struct dw_edma_region	ll_region_rd[HDMA_MAX_RD_CH];
 
 	/* data region */
-	struct dw_edma_region	dt_region_wr[EDMA_MAX_WR_CH];
-	struct dw_edma_region	dt_region_rd[EDMA_MAX_RD_CH];
+	struct dw_edma_region	dt_region_wr[HDMA_MAX_WR_CH];
+	struct dw_edma_region	dt_region_rd[HDMA_MAX_RD_CH];
 
 	/* interrupt emulation */
 	int			db_irq;
-- 
2.43.0


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

* Re: [PATCH v1] dmaengine: dw-edma: Enable HDMA 64R/W Channels
  2026-05-29 12:21 [PATCH v1] dmaengine: dw-edma: Enable HDMA 64R/W Channels Devendra K Verma
@ 2026-05-29 13:09 ` sashiko-bot
  0 siblings, 0 replies; 2+ messages in thread
From: sashiko-bot @ 2026-05-29 13:09 UTC (permalink / raw)
  To: Devendra K Verma; +Cc: dmaengine, vkoul, Frank.Li

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [Critical] Unbounded iteration in `dw_hdma_v0_core_off()` causes out-of-bounds MMIO writes to unmapped register space.
- [High] DesignWare PCIe controller glue driver bounds checks were not updated to support the new 64-channel limits.
- [Medium] Hardcoded channel limits in the PCIe endpoint driver prevent utilizing more than 8 channels.
--

commit 5d2bdaca2c92c95288275a3210f192b8e7094b9e
Author: Devendra K Verma <devendra.verma@amd.com>

dmaengine: dw-edma: Enable HDMA 64R/W Channels

This commit adds support for up to 64 read and write channels in the
Designware HDMA controller driver, as per the hardware specification. It
introduces HDMA-specific macros and updates the initialization flow to use
the appropriate channel limits based on the IP version.

> diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
> index 0b30ce1385036..79f653da8e0fd 100644
> --- a/drivers/dma/dw-edma/dw-edma-pcie.c
> +++ b/drivers/dma/dw-edma/dw-edma-pcie.c
[ ... ]
> @@ -61,11 +61,11 @@ struct dw_edma_pcie_data {
>  	/* eDMA registers location */
>  	struct dw_edma_block		rg;
>  	/* eDMA memory linked list location */
> -	struct dw_edma_block		ll_wr[EDMA_MAX_WR_CH];
> -	struct dw_edma_block		ll_rd[EDMA_MAX_RD_CH];
> +	struct dw_edma_block		ll_wr[HDMA_MAX_WR_CH];
> +	struct dw_edma_block		ll_rd[HDMA_MAX_RD_CH];
>  	/* eDMA memory data location */
> -	struct dw_edma_block		dt_wr[EDMA_MAX_WR_CH];
> -	struct dw_edma_block		dt_rd[EDMA_MAX_RD_CH];
> +	struct dw_edma_block		dt_wr[HDMA_MAX_WR_CH];
> +	struct dw_edma_block		dt_rd[HDMA_MAX_RD_CH];

[Severity: Medium]
Will this update actually allow utilizing more than 8 channels, or do the
static configuration structures still restrict it?

While these data structures are updated to support 64 channels, the static
configuration structures like xilinx_mdb_data and snps_edda_data are left
hardcoded to 8 and 2 channels, respectively.

During probe, dw_edma_pcie_get_xilinx_dma_data() computes the channel count
using min(pdata->wr_ch_cnt, FIELD_GET(...)). Since the initial
pdata->wr_ch_cnt is capped at 8, the driver will silently restrict the number
of channels to a maximum of 8, even if the underlying IP reports support for
up to 64 channels.

> diff --git a/drivers/dma/dw-edma/dw-hdma-v0-regs.h b/drivers/dma/dw-edma/dw-hdma-v0-regs.h
> index 7759ba9b4850f..48e40efceb2ea 100644
> --- a/drivers/dma/dw-edma/dw-hdma-v0-regs.h
> +++ b/drivers/dma/dw-edma/dw-hdma-v0-regs.h
> @@ -11,7 +11,7 @@
>  
>  #include <linux/dmaengine.h>
>  
> -#define HDMA_V0_MAX_NR_CH			8
> +#define HDMA_V0_MAX_NR_CH			64

[Severity: Critical]
Does increasing this constant cause out-of-bounds MMIO writes during teardown?

Looking at dw_hdma_v0_core_off(), the code unconditionally iterates up to
HDMA_V0_MAX_NR_CH to disable channels, rather than using the dynamically
configured dw->wr_ch_cnt and dw->rd_ch_cnt.

Since each channel occupies 512 bytes, iterating 64 times writes to 32 KB of
register space. Existing endpoint devices like Xilinx MDB map only 8 KB of
register space.

Writing to MMIO offsets outside the mapped region can cause a translation fault
or an unhandled kernel paging request, resulting in a regression.

> diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h
> index 1fafd5b0e3153..da7a5cc93ad43 100644
> --- a/include/linux/dma/edma.h
> +++ b/include/linux/dma/edma.h
> @@ -14,6 +14,8 @@
>  
>  #define EDMA_MAX_WR_CH                                  8
>  #define EDMA_MAX_RD_CH                                  8
> +#define HDMA_MAX_WR_CH                                  64
> +#define HDMA_MAX_RD_CH                                  64

[Severity: High]
Are there missing updates in the DesignWare PCIe controller glue driver
to support these new limits?

The function dw_pcie_edma_find_channels() in pcie-designware.c enforces a hard
limit of EDMA_MAX_WR_CH. If a device is configured for more than 8 channels,
the check pci->edma.ll_wr_cnt > EDMA_MAX_WR_CH will trigger and return
-EINVAL, causing initialization to fail.

Additionally, dw_pcie_edma_irq_vector() returns -EINVAL if the IRQ index
nr is greater than or equal to EDMA_MAX_WR_CH + EDMA_MAX_RD_CH, breaking
interrupts for higher channels.

This prevents the newly added feature from functioning on native host
controllers.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260529122104.2533048-1-devendra.verma@amd.com?part=1

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

end of thread, other threads:[~2026-05-29 13:09 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-29 12:21 [PATCH v1] dmaengine: dw-edma: Enable HDMA 64R/W Channels Devendra K Verma
2026-05-29 13:09 ` sashiko-bot

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