* [PATCH 01/12] dmaengine: Make dma_get_slave_channel() public
2026-05-21 6:31 [PATCH 00/12] dmaengine: dw-edma: Prepare for PCI EP DMA (part 1/3) Koichiro Den
@ 2026-05-21 6:31 ` Koichiro Den
2026-05-21 6:31 ` [PATCH 02/12] dmaengine: dw-edma: Add channel lookup helper Koichiro Den
` (10 subsequent siblings)
11 siblings, 0 replies; 28+ messages in thread
From: Koichiro Den @ 2026-05-21 6:31 UTC (permalink / raw)
To: Vinod Koul, Frank Li, Manivannan Sadhasivam
Cc: Marek Vasut, Yoshihiro Shimoda, dmaengine, linux-kernel
Commit c3c431de99c06 ("dmaengine: Move dma_get_{,any_}slave_channel() to
private dmaengine.h") moved dma_get_slave_channel() to the private DMA
engine header because only DMA engine drivers used it at the time.
PCI endpoint DMA needs to reserve an exact channel from outside
drivers/dma. Restore dma_get_slave_channel() to the public header for
that use case while keeping dma_get_any_slave_channel() private.
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
drivers/dma/dmaengine.h | 1 -
include/linux/dmaengine.h | 6 ++++++
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/dma/dmaengine.h b/drivers/dma/dmaengine.h
index 53f16d3f0029..bde5217ce2b5 100644
--- a/drivers/dma/dmaengine.h
+++ b/drivers/dma/dmaengine.h
@@ -179,7 +179,6 @@ dmaengine_desc_callback_valid(struct dmaengine_desc_callback *cb)
return cb->callback || cb->callback_result;
}
-struct dma_chan *dma_get_slave_channel(struct dma_chan *chan);
struct dma_chan *dma_get_any_slave_channel(struct dma_device *device);
#ifdef CONFIG_DEBUG_FS
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index b3d251c9734e..59be52e74d5e 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -1527,6 +1527,7 @@ struct dma_chan *dma_request_chan(struct device *dev, const char *name);
struct dma_chan *dma_request_chan_by_mask(const dma_cap_mask_t *mask);
struct dma_chan *devm_dma_request_chan(struct device *dev, const char *name);
+struct dma_chan *dma_get_slave_channel(struct dma_chan *chan);
void dma_release_channel(struct dma_chan *chan);
int dma_get_slave_caps(struct dma_chan *chan, struct dma_slave_caps *caps);
#else
@@ -1568,6 +1569,11 @@ static inline struct dma_chan *devm_dma_request_chan(struct device *dev, const c
return ERR_PTR(-ENODEV);
}
+static inline struct dma_chan *dma_get_slave_channel(struct dma_chan *chan)
+{
+ return NULL;
+}
+
static inline void dma_release_channel(struct dma_chan *chan)
{
}
--
2.51.0
^ permalink raw reply [flat|nested] 28+ messages in thread* [PATCH 02/12] dmaengine: dw-edma: Add channel lookup helper
2026-05-21 6:31 [PATCH 00/12] dmaengine: dw-edma: Prepare for PCI EP DMA (part 1/3) Koichiro Den
2026-05-21 6:31 ` [PATCH 01/12] dmaengine: Make dma_get_slave_channel() public Koichiro Den
@ 2026-05-21 6:31 ` Koichiro Den
2026-05-21 15:50 ` Frank Li
2026-05-21 6:31 ` [PATCH 03/12] dmaengine: dw-edma: Add per-channel interrupt routing control Koichiro Den
` (9 subsequent siblings)
11 siblings, 1 reply; 28+ messages in thread
From: Koichiro Den @ 2026-05-21 6:31 UTC (permalink / raw)
To: Vinod Koul, Frank Li, Manivannan Sadhasivam
Cc: Marek Vasut, Yoshihiro Shimoda, dmaengine, linux-kernel
Add a helper that maps a DesignWare eDMA write/read hardware channel
number to its DMAengine channel.
PCI endpoint resource enumeration uses the pointer only for later
ownership reservation.
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
drivers/dma/dw-edma/dw-edma-core.c | 32 ++++++++++++++++++++++++++++++
include/linux/dma/edma.h | 8 ++++++++
2 files changed, 40 insertions(+)
diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
index c2feb3adc79f..6660380a1bbc 100644
--- a/drivers/dma/dw-edma/dw-edma-core.c
+++ b/drivers/dma/dw-edma/dw-edma-core.c
@@ -1189,6 +1189,38 @@ int dw_edma_remove(struct dw_edma_chip *chip)
}
EXPORT_SYMBOL_GPL(dw_edma_remove);
+struct dma_chan *dw_edma_find_channel(struct dw_edma_chip *chip, bool write,
+ u16 id)
+{
+ struct dw_edma_chan *chan;
+ struct dw_edma *dw;
+
+ if (!chip)
+ return NULL;
+
+ dw = chip->dw;
+
+ if (!dw)
+ return NULL;
+
+ if (write) {
+ if (id >= dw->wr_ch_cnt)
+ return NULL;
+ chan = &dw->chan[id];
+ if (chan->dir != EDMA_DIR_WRITE)
+ return NULL;
+ } else {
+ if (id >= dw->rd_ch_cnt)
+ return NULL;
+ chan = &dw->chan[dw->wr_ch_cnt + id];
+ if (chan->dir != EDMA_DIR_READ)
+ return NULL;
+ }
+
+ return &chan->vc.chan;
+}
+EXPORT_SYMBOL_GPL(dw_edma_find_channel);
+
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Synopsys DesignWare eDMA controller core driver");
MODULE_AUTHOR("Gustavo Pimentel <gustavo.pimentel@synopsys.com>");
diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h
index 1fafd5b0e315..b4b42b2278f3 100644
--- a/include/linux/dma/edma.h
+++ b/include/linux/dma/edma.h
@@ -110,6 +110,8 @@ struct dw_edma_chip {
#if IS_REACHABLE(CONFIG_DW_EDMA)
int dw_edma_probe(struct dw_edma_chip *chip);
int dw_edma_remove(struct dw_edma_chip *chip);
+struct dma_chan *dw_edma_find_channel(struct dw_edma_chip *chip, bool write,
+ u16 id);
#else
static inline int dw_edma_probe(struct dw_edma_chip *chip)
{
@@ -120,6 +122,12 @@ static inline int dw_edma_remove(struct dw_edma_chip *chip)
{
return 0;
}
+
+static inline struct dma_chan *dw_edma_find_channel(struct dw_edma_chip *chip,
+ bool write, u16 id)
+{
+ return NULL;
+}
#endif /* CONFIG_DW_EDMA */
#endif /* _DW_EDMA_H */
--
2.51.0
^ permalink raw reply [flat|nested] 28+ messages in thread* Re: [PATCH 02/12] dmaengine: dw-edma: Add channel lookup helper
2026-05-21 6:31 ` [PATCH 02/12] dmaengine: dw-edma: Add channel lookup helper Koichiro Den
@ 2026-05-21 15:50 ` Frank Li
0 siblings, 0 replies; 28+ messages in thread
From: Frank Li @ 2026-05-21 15:50 UTC (permalink / raw)
To: Koichiro Den
Cc: Vinod Koul, Frank Li, Manivannan Sadhasivam, Marek Vasut,
Yoshihiro Shimoda, dmaengine, linux-kernel
On Thu, May 21, 2026 at 03:31:05PM +0900, Koichiro Den wrote:
> Add a helper that maps a DesignWare eDMA write/read hardware channel
Nit: Add a helper dw_edma_find_channel() ...
> number to its DMAengine channel.
>
> PCI endpoint resource enumeration uses the pointer only for later
> ownership reservation.
>
> Signed-off-by: Koichiro Den <den@valinux.co.jp>
> ---
Reviewed-by: Frank Li <Frank.Li@nxp.com>
> drivers/dma/dw-edma/dw-edma-core.c | 32 ++++++++++++++++++++++++++++++
> include/linux/dma/edma.h | 8 ++++++++
> 2 files changed, 40 insertions(+)
>
> diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
> index c2feb3adc79f..6660380a1bbc 100644
> --- a/drivers/dma/dw-edma/dw-edma-core.c
> +++ b/drivers/dma/dw-edma/dw-edma-core.c
> @@ -1189,6 +1189,38 @@ int dw_edma_remove(struct dw_edma_chip *chip)
> }
> EXPORT_SYMBOL_GPL(dw_edma_remove);
>
> +struct dma_chan *dw_edma_find_channel(struct dw_edma_chip *chip, bool write,
> + u16 id)
> +{
> + struct dw_edma_chan *chan;
> + struct dw_edma *dw;
> +
> + if (!chip)
> + return NULL;
> +
> + dw = chip->dw;
> +
> + if (!dw)
> + return NULL;
> +
> + if (write) {
> + if (id >= dw->wr_ch_cnt)
> + return NULL;
> + chan = &dw->chan[id];
> + if (chan->dir != EDMA_DIR_WRITE)
> + return NULL;
> + } else {
> + if (id >= dw->rd_ch_cnt)
> + return NULL;
> + chan = &dw->chan[dw->wr_ch_cnt + id];
> + if (chan->dir != EDMA_DIR_READ)
> + return NULL;
> + }
> +
> + return &chan->vc.chan;
> +}
> +EXPORT_SYMBOL_GPL(dw_edma_find_channel);
> +
> MODULE_LICENSE("GPL v2");
> MODULE_DESCRIPTION("Synopsys DesignWare eDMA controller core driver");
> MODULE_AUTHOR("Gustavo Pimentel <gustavo.pimentel@synopsys.com>");
> diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h
> index 1fafd5b0e315..b4b42b2278f3 100644
> --- a/include/linux/dma/edma.h
> +++ b/include/linux/dma/edma.h
> @@ -110,6 +110,8 @@ struct dw_edma_chip {
> #if IS_REACHABLE(CONFIG_DW_EDMA)
> int dw_edma_probe(struct dw_edma_chip *chip);
> int dw_edma_remove(struct dw_edma_chip *chip);
> +struct dma_chan *dw_edma_find_channel(struct dw_edma_chip *chip, bool write,
> + u16 id);
> #else
> static inline int dw_edma_probe(struct dw_edma_chip *chip)
> {
> @@ -120,6 +122,12 @@ static inline int dw_edma_remove(struct dw_edma_chip *chip)
> {
> return 0;
> }
> +
> +static inline struct dma_chan *dw_edma_find_channel(struct dw_edma_chip *chip,
> + bool write, u16 id)
> +{
> + return NULL;
> +}
> #endif /* CONFIG_DW_EDMA */
>
> #endif /* _DW_EDMA_H */
> --
> 2.51.0
>
^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH 03/12] dmaengine: dw-edma: Add per-channel interrupt routing control
2026-05-21 6:31 [PATCH 00/12] dmaengine: dw-edma: Prepare for PCI EP DMA (part 1/3) Koichiro Den
2026-05-21 6:31 ` [PATCH 01/12] dmaengine: Make dma_get_slave_channel() public Koichiro Den
2026-05-21 6:31 ` [PATCH 02/12] dmaengine: dw-edma: Add channel lookup helper Koichiro Den
@ 2026-05-21 6:31 ` Koichiro Den
2026-05-21 6:31 ` [PATCH 04/12] dmaengine: dw-edma: Add partial channel ownership mode Koichiro Den
` (8 subsequent siblings)
11 siblings, 0 replies; 28+ messages in thread
From: Koichiro Den @ 2026-05-21 6:31 UTC (permalink / raw)
To: Vinod Koul, Frank Li, Manivannan Sadhasivam
Cc: Marek Vasut, Yoshihiro Shimoda, dmaengine, linux-kernel
DesignWare endpoint eDMA can signal completion both locally and remotely
through LIE/RIE. A remotely controlled channel needs a per-channel
policy for whether completions are handled locally, remotely, or both.
Otherwise, the endpoint and host can race to acknowledge the interrupt.
Add dw_edma_peripheral_config, carried through dma_slave_config, to let
a frontend select the interrupt routing mode for each channel. Update
the v0 programming path so linked-list interrupt generation and
DONE/ABORT masking follow the selected mode. If a frontend does nothing,
the default keeps the existing behavior.
HDMA native already uses dma_slave_config.peripheral_config for non-LL
mode selection. Keep that ABI unchanged and do not interpret the new IRQ
routing config on HDMA native until that routing model has been
implemented and validated.
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
drivers/dma/dw-edma/dw-edma-core.c | 59 +++++++++++++++++++++++++--
drivers/dma/dw-edma/dw-edma-core.h | 13 ++++++
drivers/dma/dw-edma/dw-edma-v0-core.c | 26 ++++++++----
include/linux/dma/edma.h | 38 +++++++++++++++++
4 files changed, 124 insertions(+), 12 deletions(-)
diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
index 6660380a1bbc..72dc8a60798a 100644
--- a/drivers/dma/dw-edma/dw-edma-core.c
+++ b/drivers/dma/dw-edma/dw-edma-core.c
@@ -219,12 +219,56 @@ static void dw_edma_device_caps(struct dma_chan *dchan,
}
}
+static enum dw_edma_ch_irq_mode
+dw_edma_get_default_irq_mode(struct dw_edma_chan *chan)
+{
+ switch (chan->dw->chip->default_irq_mode) {
+ case DW_EDMA_CH_IRQ_DEFAULT:
+ case DW_EDMA_CH_IRQ_LOCAL:
+ case DW_EDMA_CH_IRQ_REMOTE:
+ return chan->dw->chip->default_irq_mode;
+ default:
+ return DW_EDMA_CH_IRQ_DEFAULT;
+ }
+}
+
+static int dw_edma_parse_irq_mode(struct dw_edma_chan *chan,
+ const struct dma_slave_config *config,
+ enum dw_edma_ch_irq_mode *mode)
+{
+ const struct dw_edma_peripheral_config *pcfg;
+
+ /* peripheral_config is optional, fall back to the frontend default. */
+ *mode = dw_edma_get_default_irq_mode(chan);
+ if (!config || !config->peripheral_config)
+ return 0;
+
+ if (chan->dw->chip->mf == EDMA_MF_HDMA_NATIVE)
+ return -EOPNOTSUPP;
+
+ if (config->peripheral_size < sizeof(*pcfg))
+ return -EINVAL;
+
+ pcfg = config->peripheral_config;
+ switch (pcfg->irq_mode) {
+ case DW_EDMA_CH_IRQ_DEFAULT:
+ case DW_EDMA_CH_IRQ_LOCAL:
+ case DW_EDMA_CH_IRQ_REMOTE:
+ *mode = pcfg->irq_mode;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
static int dw_edma_device_config(struct dma_chan *dchan,
struct dma_slave_config *config)
{
struct dw_edma_chan *chan = dchan2dw_edma_chan(dchan);
+ enum dw_edma_ch_irq_mode mode;
bool cfg_non_ll;
int non_ll = 0;
+ int ret;
chan->non_ll = false;
if (chan->dw->chip->mf == EDMA_MF_HDMA_NATIVE) {
@@ -255,10 +299,11 @@ static int dw_edma_device_config(struct dma_chan *dchan,
if (cfg_non_ll || non_ll)
chan->non_ll = true;
- } else if (config->peripheral_config) {
- dev_err(dchan->device->dev,
- "peripheral config param applicable only for HDMA\n");
- return -EINVAL;
+ } else {
+ ret = dw_edma_parse_irq_mode(chan, config, &mode);
+ if (ret)
+ return ret;
+ chan->irq_mode = mode;
}
memcpy(&chan->config, config, sizeof(*config));
@@ -853,11 +898,14 @@ static int dw_edma_alloc_chan_resources(struct dma_chan *dchan)
if (chan->status != EDMA_ST_IDLE)
return -EBUSY;
+ chan->irq_mode = dw_edma_get_default_irq_mode(chan);
+
return 0;
}
static void dw_edma_free_chan_resources(struct dma_chan *dchan)
{
+ struct dw_edma_chan *chan = dchan2dw_edma_chan(dchan);
unsigned long timeout = jiffies + msecs_to_jiffies(5000);
int ret;
@@ -871,6 +919,8 @@ static void dw_edma_free_chan_resources(struct dma_chan *dchan)
cpu_relax();
}
+
+ chan->irq_mode = dw_edma_get_default_irq_mode(chan);
}
static int dw_edma_channel_setup(struct dw_edma *dw, u32 wr_alloc, u32 rd_alloc)
@@ -904,6 +954,7 @@ static int dw_edma_channel_setup(struct dw_edma *dw, u32 wr_alloc, u32 rd_alloc)
chan->configured = false;
chan->request = EDMA_REQ_NONE;
chan->status = EDMA_ST_IDLE;
+ chan->irq_mode = dw_edma_get_default_irq_mode(chan);
if (chan->dir == EDMA_DIR_WRITE)
chan->ll_max = (chip->ll_region_wr[chan->id].sz / EDMA_LL_SZ);
diff --git a/drivers/dma/dw-edma/dw-edma-core.h b/drivers/dma/dw-edma/dw-edma-core.h
index 902574b1ba86..e2aadf0109b6 100644
--- a/drivers/dma/dw-edma/dw-edma-core.h
+++ b/drivers/dma/dw-edma/dw-edma-core.h
@@ -81,6 +81,8 @@ struct dw_edma_chan {
struct msi_msg msi;
+ enum dw_edma_ch_irq_mode irq_mode;
+
enum dw_edma_request request;
enum dw_edma_status status;
u8 configured;
@@ -224,4 +226,15 @@ dw_edma_core_db_offset(struct dw_edma *dw)
return dw->core->db_offset(dw);
}
+static inline bool
+dw_edma_core_ch_ignore_irq(struct dw_edma_chan *chan)
+{
+ struct dw_edma *dw = chan->dw;
+
+ if (dw->chip->flags & DW_EDMA_CHIP_LOCAL)
+ return chan->irq_mode == DW_EDMA_CH_IRQ_REMOTE;
+ else
+ return chan->irq_mode == DW_EDMA_CH_IRQ_LOCAL;
+}
+
#endif /* _DW_EDMA_CORE_H */
diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c
index 69e8279adec8..2e95da0d6fc2 100644
--- a/drivers/dma/dw-edma/dw-edma-v0-core.c
+++ b/drivers/dma/dw-edma/dw-edma-v0-core.c
@@ -256,8 +256,10 @@ dw_edma_v0_core_handle_int(struct dw_edma_irq *dw_irq, enum dw_edma_dir dir,
for_each_set_bit(pos, &val, total) {
chan = &dw->chan[pos + off];
- dw_edma_v0_core_clear_done_int(chan);
- done(chan);
+ if (!dw_edma_core_ch_ignore_irq(chan)) {
+ dw_edma_v0_core_clear_done_int(chan);
+ done(chan);
+ }
ret = IRQ_HANDLED;
}
@@ -267,8 +269,10 @@ dw_edma_v0_core_handle_int(struct dw_edma_irq *dw_irq, enum dw_edma_dir dir,
for_each_set_bit(pos, &val, total) {
chan = &dw->chan[pos + off];
- dw_edma_v0_core_clear_abort_int(chan);
- abort(chan);
+ if (!dw_edma_core_ch_ignore_irq(chan)) {
+ dw_edma_v0_core_clear_abort_int(chan);
+ abort(chan);
+ }
ret = IRQ_HANDLED;
}
@@ -331,7 +335,8 @@ static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
j--;
if (!j) {
control |= DW_EDMA_V0_LIE;
- if (!(chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL))
+ if (!(chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL) &&
+ chan->irq_mode != DW_EDMA_CH_IRQ_LOCAL)
control |= DW_EDMA_V0_RIE;
}
@@ -407,10 +412,15 @@ static void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
break;
}
}
- /* Interrupt unmask - done, abort */
+ /* Interrupt mask/unmask - done, abort */
tmp = GET_RW_32(dw, chan->dir, int_mask);
- tmp &= ~FIELD_PREP(EDMA_V0_DONE_INT_MASK, BIT(chan->id));
- tmp &= ~FIELD_PREP(EDMA_V0_ABORT_INT_MASK, BIT(chan->id));
+ if (chan->irq_mode == DW_EDMA_CH_IRQ_REMOTE) {
+ tmp |= FIELD_PREP(EDMA_V0_DONE_INT_MASK, BIT(chan->id));
+ tmp |= FIELD_PREP(EDMA_V0_ABORT_INT_MASK, BIT(chan->id));
+ } else {
+ tmp &= ~FIELD_PREP(EDMA_V0_DONE_INT_MASK, BIT(chan->id));
+ tmp &= ~FIELD_PREP(EDMA_V0_ABORT_INT_MASK, BIT(chan->id));
+ }
SET_RW_32(dw, chan->dir, int_mask, tmp);
/* Linked list error */
tmp = GET_RW_32(dw, chan->dir, linked_list_err_en);
diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h
index b4b42b2278f3..9ea7b24b5015 100644
--- a/include/linux/dma/edma.h
+++ b/include/linux/dma/edma.h
@@ -60,6 +60,41 @@ enum dw_edma_chip_flags {
DW_EDMA_CHIP_LOCAL = BIT(0),
};
+/**
+ * enum dw_edma_ch_irq_mode - per-channel interrupt routing control
+ * @DW_EDMA_CH_IRQ_DEFAULT: keep legacy behavior
+ * @DW_EDMA_CH_IRQ_LOCAL: local interrupt only (edma_int[])
+ * @DW_EDMA_CH_IRQ_REMOTE: remote interrupt only (IMWr/MSI),
+ * while masking local DONE/ABORT output.
+ *
+ * DesignWare EP eDMA can signal interrupts locally through the edma_int[]
+ * bus, and remotely using posted memory writes (IMWr) that may be
+ * interpreted as MSI/MSI-X by the RC.
+ *
+ * For the v0 eDMA programming path, DMA_*_INT_MASK gates the local edma_int[]
+ * assertion, while there is no dedicated per-channel mask for IMWr generation.
+ * To request a remote-only interrupt, Synopsys recommends setting both LIE and
+ * RIE, and masking the local interrupt in DMA_*_INT_MASK (rather than relying
+ * on LIE=0/RIE=1). See the DesignWare endpoint databook 5.40a, Non Linked
+ * List Mode interrupt handling ("Hint").
+ */
+enum dw_edma_ch_irq_mode {
+ DW_EDMA_CH_IRQ_DEFAULT = 0,
+ DW_EDMA_CH_IRQ_LOCAL,
+ DW_EDMA_CH_IRQ_REMOTE,
+};
+
+/**
+ * struct dw_edma_peripheral_config - dw-edma specific slave configuration
+ * @irq_mode: per-channel interrupt routing control.
+ *
+ * Pass this structure via dma_slave_config.peripheral_config and
+ * dma_slave_config.peripheral_size.
+ */
+struct dw_edma_peripheral_config {
+ enum dw_edma_ch_irq_mode irq_mode;
+};
+
/**
* struct dw_edma_chip - representation of DesignWare eDMA controller hardware
* @dev: struct device of the eDMA controller
@@ -76,6 +111,8 @@ enum dw_edma_chip_flags {
* @db_irq: Virtual IRQ dedicated to interrupt emulation
* @db_offset: Offset from DMA register base
* @mf: DMA register map format
+ * @default_irq_mode: default per-channel interrupt routing when client
+ * does not supply dw_edma_peripheral_config
* @dw: struct dw_edma that is filled by dw_edma_probe()
*/
struct dw_edma_chip {
@@ -101,6 +138,7 @@ struct dw_edma_chip {
resource_size_t db_offset;
enum dw_edma_map_format mf;
+ enum dw_edma_ch_irq_mode default_irq_mode;
struct dw_edma *dw;
bool cfg_non_ll;
--
2.51.0
^ permalink raw reply [flat|nested] 28+ messages in thread* [PATCH 04/12] dmaengine: dw-edma: Add partial channel ownership mode
2026-05-21 6:31 [PATCH 00/12] dmaengine: dw-edma: Prepare for PCI EP DMA (part 1/3) Koichiro Den
` (2 preceding siblings ...)
2026-05-21 6:31 ` [PATCH 03/12] dmaengine: dw-edma: Add per-channel interrupt routing control Koichiro Den
@ 2026-05-21 6:31 ` Koichiro Den
2026-05-21 6:31 ` [PATCH 05/12] dmaengine: dw-edma-pcie: Add capability match data Koichiro Den
` (7 subsequent siblings)
11 siblings, 0 replies; 28+ messages in thread
From: Koichiro Den @ 2026-05-21 6:31 UTC (permalink / raw)
To: Vinod Koul, Frank Li, Manivannan Sadhasivam
Cc: Marek Vasut, Yoshihiro Shimoda, dmaengine, linux-kernel
Some endpoint DMA frontends expose only a subset of a controller that is
also initialized by the endpoint-side OS. Add a partial ownership flag
so dw-edma does not reset controller-wide state in probe() or remove().
Keep the mode conservative. Do not enable interrupt-emulation doorbells,
and reject eDMA legacy mode because it uses a shared viewport selector.
For EDMA_MF_EDMA_UNROLL and EDMA_MF_HDMA_COMPAT, require ownership of
all channels in each exposed direction. The driver updates registers
shared by all channels in a direction, such as interrupt masks and
linked-list error enables, so two independent OS instances cannot safely
split one direction without a shared locking protocol, which is
unrealistic.
The frontend must still quiesce delegated channels before removing a
partial instance. The flag only keeps probe() and remove() from
resetting controller-wide state that may belong to a peer OS instance.
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
drivers/dma/dw-edma/dw-edma-core.c | 43 +++++++++++++++++++++++-------
include/linux/dma/edma.h | 6 +++++
2 files changed, 39 insertions(+), 10 deletions(-)
diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
index 72dc8a60798a..ec32a2ab1651 100644
--- a/drivers/dma/dw-edma/dw-edma-core.c
+++ b/drivers/dma/dw-edma/dw-edma-core.c
@@ -784,6 +784,9 @@ static int dw_edma_emul_irq_alloc(struct dw_edma *dw)
chip->db_irq = 0;
chip->db_offset = ~0;
+ if (chip->flags & DW_EDMA_CHIP_PARTIAL)
+ return 0;
+
/*
* Only meaningful when the core provides the deassert sequence
* for interrupt emulation.
@@ -1128,6 +1131,8 @@ int dw_edma_probe(struct dw_edma_chip *chip)
{
struct device *dev;
struct dw_edma *dw;
+ u16 hw_wr_ch_cnt;
+ u16 hw_rd_ch_cnt;
u32 wr_alloc = 0;
u32 rd_alloc = 0;
int i, err;
@@ -1139,6 +1144,10 @@ int dw_edma_probe(struct dw_edma_chip *chip)
if (!dev || !chip->ops)
return -EINVAL;
+ if ((chip->flags & DW_EDMA_CHIP_PARTIAL) &&
+ chip->mf == EDMA_MF_EDMA_LEGACY)
+ return -EOPNOTSUPP;
+
dw = devm_kzalloc(dev, sizeof(*dw), GFP_KERNEL);
if (!dw)
return -ENOMEM;
@@ -1152,13 +1161,25 @@ int dw_edma_probe(struct dw_edma_chip *chip)
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);
+ hw_wr_ch_cnt = min_t(u16, dw_edma_core_ch_count(dw, EDMA_DIR_WRITE),
+ EDMA_MAX_WR_CH);
+ hw_rd_ch_cnt = min_t(u16, dw_edma_core_ch_count(dw, EDMA_DIR_READ),
+ EDMA_MAX_RD_CH);
- 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);
+ if (chip->flags & DW_EDMA_CHIP_PARTIAL) {
+ /*
+ * Direction-wide registers are shared by all channels in that
+ * direction, so a direction must have a single owner.
+ */
+ if ((chip->mf == EDMA_MF_EDMA_UNROLL ||
+ chip->mf == EDMA_MF_HDMA_COMPAT) &&
+ ((chip->ll_wr_cnt && chip->ll_wr_cnt != hw_wr_ch_cnt) ||
+ (chip->ll_rd_cnt && chip->ll_rd_cnt != hw_rd_ch_cnt)))
+ return -EOPNOTSUPP;
+ }
+
+ dw->wr_ch_cnt = min_t(u16, chip->ll_wr_cnt, hw_wr_ch_cnt);
+ dw->rd_ch_cnt = min_t(u16, chip->ll_rd_cnt, hw_rd_ch_cnt);
if (!dw->wr_ch_cnt && !dw->rd_ch_cnt)
return -EINVAL;
@@ -1175,8 +1196,10 @@ int dw_edma_probe(struct dw_edma_chip *chip)
snprintf(dw->name, sizeof(dw->name), "dw-edma-core:%s",
dev_name(chip->dev));
- /* Disable eDMA, only to establish the ideal initial conditions */
- dw_edma_core_off(dw);
+ if (!(chip->flags & DW_EDMA_CHIP_PARTIAL)) {
+ /* Disable eDMA only when this instance owns the controller. */
+ dw_edma_core_off(dw);
+ }
/* Request IRQs */
err = dw_edma_irq_request(dw, &wr_alloc, &rd_alloc);
@@ -1220,8 +1243,8 @@ int dw_edma_remove(struct dw_edma_chip *chip)
if (!dw)
return -ENODEV;
- /* Disable eDMA */
- dw_edma_core_off(dw);
+ if (!(chip->flags & DW_EDMA_CHIP_PARTIAL))
+ dw_edma_core_off(dw);
/* Free irqs */
for (i = (dw->nr_irqs - 1); i >= 0; i--)
diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h
index 9ea7b24b5015..33aa6c8981b3 100644
--- a/include/linux/dma/edma.h
+++ b/include/linux/dma/edma.h
@@ -55,9 +55,15 @@ enum dw_edma_map_format {
/**
* enum dw_edma_chip_flags - Flags specific to an eDMA chip
* @DW_EDMA_CHIP_LOCAL: eDMA is used locally by an endpoint
+ * @DW_EDMA_CHIP_PARTIAL: Only channels described by this instance are
+ * owned by this driver. Controller-wide state
+ * must be preserved, and layouts with shared
+ * direction-wide registers must only be shared at
+ * direction granularity.
*/
enum dw_edma_chip_flags {
DW_EDMA_CHIP_LOCAL = BIT(0),
+ DW_EDMA_CHIP_PARTIAL = BIT(1),
};
/**
--
2.51.0
^ permalink raw reply [flat|nested] 28+ messages in thread* [PATCH 05/12] dmaengine: dw-edma-pcie: Add capability match data
2026-05-21 6:31 [PATCH 00/12] dmaengine: dw-edma: Prepare for PCI EP DMA (part 1/3) Koichiro Den
` (3 preceding siblings ...)
2026-05-21 6:31 ` [PATCH 04/12] dmaengine: dw-edma: Add partial channel ownership mode Koichiro Den
@ 2026-05-21 6:31 ` Koichiro Den
2026-05-21 16:06 ` Frank Li
2026-05-21 6:31 ` [PATCH 06/12] dmaengine: dw-edma-pcie: Rename DMA data copy Koichiro Den
` (6 subsequent siblings)
11 siblings, 1 reply; 28+ messages in thread
From: Koichiro Den @ 2026-05-21 6:31 UTC (permalink / raw)
To: Vinod Koul, Frank Li, Manivannan Sadhasivam
Cc: Marek Vasut, Yoshihiro Shimoda, dmaengine, linux-kernel
Move device-specific capability parsing behind per-device match data.
The existing probe path mixes two decisions: which static template a PCI
ID uses, and which device-specific capability parser adjusts that
template. Split those decisions so device-specific discovery can be
added through match data instead of adding more vendor checks to
dw_edma_pcie_probe().
No functional change is intended for the existing Synopsys EDDA and
AMD/Xilinx MDB matches. They still copy the same static template data and
run the same capability parsing logic before BAR mapping. The MDB entry
also keeps using endpoint memory physical addresses for descriptor
windows through a new match-data flag.
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
drivers/dma/dw-edma/dw-edma-pcie.c | 127 +++++++++++++++++++----------
1 file changed, 85 insertions(+), 42 deletions(-)
diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
index 0b30ce138503..043a7f73bf79 100644
--- a/drivers/dma/dw-edma/dw-edma-pcie.c
+++ b/drivers/dma/dw-edma/dw-edma-pcie.c
@@ -74,6 +74,19 @@ struct dw_edma_pcie_data {
u64 devmem_phys_off;
};
+struct dw_edma_pcie_match_data {
+ const struct dw_edma_pcie_data *data;
+ /*
+ * Mandatory callback. It may leave @pdata unchanged when the static
+ * template already describes the device.
+ */
+ int (*parse_caps)(struct pci_dev *pdev,
+ struct dw_edma_pcie_data *pdata, bool *non_ll);
+ unsigned long flags;
+};
+
+#define DW_EDMA_PCIE_F_DEVMEM_PHYS_OFF BIT(0)
+
static const struct dw_edma_pcie_data snps_edda_data = {
/* eDMA registers location */
.rg.bar = BAR_0,
@@ -295,19 +308,61 @@ static void dw_edma_pcie_get_xilinx_dma_data(struct pci_dev *pdev,
pdata->devmem_phys_off = off;
}
+static int
+dw_edma_pcie_parse_synopsys_caps(struct pci_dev *pdev,
+ struct dw_edma_pcie_data *pdata, bool *non_ll)
+{
+ dw_edma_pcie_get_synopsys_dma_data(pdev, pdata);
+
+ return 0;
+}
+
+static int
+dw_edma_pcie_parse_xilinx_caps(struct pci_dev *pdev,
+ struct dw_edma_pcie_data *pdata, bool *non_ll)
+{
+ dw_edma_pcie_get_xilinx_dma_data(pdev, pdata);
+
+ /*
+ * There is no valid address found for the LL memory space on the
+ * device side. In the absence of LL base address use the non-LL mode or
+ * simple mode supported by the HDMA IP.
+ */
+ if (pdata->devmem_phys_off == DW_PCIE_XILINX_MDB_INVALID_ADDR) {
+ *non_ll = true;
+ return 0;
+ }
+
+ /*
+ * Configure the channel LL and data blocks if number of channels
+ * enabled in VSEC capability are more than the channels configured in
+ * xilinx_mdb_data.
+ */
+ dw_edma_set_chan_region_offset(pdata, BAR_2, 0,
+ DW_PCIE_XILINX_MDB_LL_OFF_GAP,
+ DW_PCIE_XILINX_MDB_LL_SIZE,
+ DW_PCIE_XILINX_MDB_DT_OFF_GAP,
+ DW_PCIE_XILINX_MDB_DT_SIZE);
+
+ return 0;
+}
+
static u64 dw_edma_get_phys_addr(struct pci_dev *pdev,
+ const struct dw_edma_pcie_match_data *match,
struct dw_edma_pcie_data *pdata,
enum pci_barno bar)
{
- if (pdev->vendor == PCI_VENDOR_ID_XILINX)
+ if (match->flags & DW_EDMA_PCIE_F_DEVMEM_PHYS_OFF)
return pdata->devmem_phys_off;
+
return pci_bus_address(pdev, bar);
}
static int dw_edma_pcie_probe(struct pci_dev *pdev,
const struct pci_device_id *pid)
{
- struct dw_edma_pcie_data *pdata = (void *)pid->driver_data;
+ const struct dw_edma_pcie_match_data *match = (void *)pid->driver_data;
+ const struct dw_edma_pcie_data *pdata = match->data;
struct device *dev = &pdev->dev;
struct dw_edma_chip *chip;
int err, nr_irqs;
@@ -328,36 +383,13 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
memcpy(vsec_data, pdata, sizeof(struct dw_edma_pcie_data));
- /*
- * Tries to find if exists a PCIe Vendor-Specific Extended Capability
- * for the DMA, if one exists, then reconfigures it.
- */
- dw_edma_pcie_get_synopsys_dma_data(pdev, vsec_data);
-
- if (pdev->vendor == PCI_VENDOR_ID_XILINX) {
- dw_edma_pcie_get_xilinx_dma_data(pdev, vsec_data);
-
- /*
- * There is no valid address found for the LL memory
- * space on the device side. In the absence of LL base
- * address use the non-LL mode or simple mode supported by
- * the HDMA IP.
- */
- if (vsec_data->devmem_phys_off == DW_PCIE_XILINX_MDB_INVALID_ADDR)
- non_ll = true;
-
- /*
- * Configure the channel LL and data blocks if number of
- * channels enabled in VSEC capability are more than the
- * channels configured in xilinx_mdb_data.
- */
- if (!non_ll)
- dw_edma_set_chan_region_offset(vsec_data, BAR_2, 0,
- DW_PCIE_XILINX_MDB_LL_OFF_GAP,
- DW_PCIE_XILINX_MDB_LL_SIZE,
- DW_PCIE_XILINX_MDB_DT_OFF_GAP,
- DW_PCIE_XILINX_MDB_DT_SIZE);
- }
+ /* Let device-specific discovery override the static template data. */
+ if (!match->parse_caps)
+ return -EINVAL;
+
+ err = match->parse_caps(pdev, vsec_data, &non_ll);
+ if (err)
+ return err;
/* Mapping PCI BAR regions */
mask = BIT(vsec_data->rg.bar);
@@ -424,8 +456,8 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
return -ENOMEM;
ll_region->vaddr.io += ll_block->off;
- ll_region->paddr = dw_edma_get_phys_addr(pdev, vsec_data,
- ll_block->bar);
+ ll_region->paddr = dw_edma_get_phys_addr(pdev, match,
+ vsec_data, ll_block->bar);
ll_region->paddr += ll_block->off;
ll_region->sz = ll_block->sz;
@@ -434,8 +466,8 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
return -ENOMEM;
dt_region->vaddr.io += dt_block->off;
- dt_region->paddr = dw_edma_get_phys_addr(pdev, vsec_data,
- dt_block->bar);
+ dt_region->paddr = dw_edma_get_phys_addr(pdev, match,
+ vsec_data, dt_block->bar);
dt_region->paddr += dt_block->off;
dt_region->sz = dt_block->sz;
}
@@ -451,8 +483,8 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
return -ENOMEM;
ll_region->vaddr.io += ll_block->off;
- ll_region->paddr = dw_edma_get_phys_addr(pdev, vsec_data,
- ll_block->bar);
+ ll_region->paddr = dw_edma_get_phys_addr(pdev, match,
+ vsec_data, ll_block->bar);
ll_region->paddr += ll_block->off;
ll_region->sz = ll_block->sz;
@@ -461,8 +493,8 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
return -ENOMEM;
dt_region->vaddr.io += dt_block->off;
- dt_region->paddr = dw_edma_get_phys_addr(pdev, vsec_data,
- dt_block->bar);
+ dt_region->paddr = dw_edma_get_phys_addr(pdev, match,
+ vsec_data, dt_block->bar);
dt_region->paddr += dt_block->off;
dt_region->sz = dt_block->sz;
}
@@ -543,10 +575,21 @@ static void dw_edma_pcie_remove(struct pci_dev *pdev)
pci_free_irq_vectors(pdev);
}
+static const struct dw_edma_pcie_match_data snps_edda_match_data = {
+ .data = &snps_edda_data,
+ .parse_caps = dw_edma_pcie_parse_synopsys_caps,
+};
+
+static const struct dw_edma_pcie_match_data xilinx_mdb_match_data = {
+ .data = &xilinx_mdb_data,
+ .parse_caps = dw_edma_pcie_parse_xilinx_caps,
+ .flags = DW_EDMA_PCIE_F_DEVMEM_PHYS_OFF,
+};
+
static const struct pci_device_id dw_edma_pcie_id_table[] = {
- { PCI_DEVICE_DATA(SYNOPSYS, EDDA, &snps_edda_data) },
+ { PCI_DEVICE_DATA(SYNOPSYS, EDDA, &snps_edda_match_data) },
{ PCI_VDEVICE(XILINX, PCI_DEVICE_ID_XILINX_B054),
- (kernel_ulong_t)&xilinx_mdb_data },
+ (kernel_ulong_t)&xilinx_mdb_match_data },
{ }
};
MODULE_DEVICE_TABLE(pci, dw_edma_pcie_id_table);
--
2.51.0
^ permalink raw reply [flat|nested] 28+ messages in thread* Re: [PATCH 05/12] dmaengine: dw-edma-pcie: Add capability match data
2026-05-21 6:31 ` [PATCH 05/12] dmaengine: dw-edma-pcie: Add capability match data Koichiro Den
@ 2026-05-21 16:06 ` Frank Li
2026-05-22 14:38 ` Koichiro Den
0 siblings, 1 reply; 28+ messages in thread
From: Frank Li @ 2026-05-21 16:06 UTC (permalink / raw)
To: Koichiro Den
Cc: Vinod Koul, Frank Li, Manivannan Sadhasivam, Marek Vasut,
Yoshihiro Shimoda, dmaengine, linux-kernel
On Thu, May 21, 2026 at 03:31:08PM +0900, Koichiro Den wrote:
> Move device-specific capability parsing behind per-device match data.
>
> The existing probe path mixes two decisions: which static template a PCI
> ID uses, and which device-specific capability parser adjusts that
> template. Split those decisions so device-specific discovery can be
> added through match data instead of adding more vendor checks to
> dw_edma_pcie_probe().
>
> No functional change is intended for the existing Synopsys EDDA and
> AMD/Xilinx MDB matches. They still copy the same static template data and
> run the same capability parsing logic before BAR mapping. The MDB entry
> also keeps using endpoint memory physical addresses for descriptor
> windows through a new match-data flag.
>
> Signed-off-by: Koichiro Den <den@valinux.co.jp>
> ---
> drivers/dma/dw-edma/dw-edma-pcie.c | 127 +++++++++++++++++++----------
> 1 file changed, 85 insertions(+), 42 deletions(-)
>
> diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
> index 0b30ce138503..043a7f73bf79 100644
> --- a/drivers/dma/dw-edma/dw-edma-pcie.c
> +++ b/drivers/dma/dw-edma/dw-edma-pcie.c
> @@ -74,6 +74,19 @@ struct dw_edma_pcie_data {
> u64 devmem_phys_off;
> };
>
> +struct dw_edma_pcie_match_data {
> + const struct dw_edma_pcie_data *data;
> + /*
> + * Mandatory callback. It may leave @pdata unchanged when the static
> + * template already describes the device.
> + */
> + int (*parse_caps)(struct pci_dev *pdev,
> + struct dw_edma_pcie_data *pdata, bool *non_ll);
Needn't non_ll here. This information should be already save into
dw_edma_chip::cfg_no_ll
> + unsigned long flags;
> +};
...
>
> +static const struct dw_edma_pcie_match_data snps_edda_match_data = {
> + .data = &snps_edda_data,
> + .parse_caps = dw_edma_pcie_parse_synopsys_caps,
> +};
> +
> +static const struct dw_edma_pcie_match_data xilinx_mdb_match_data = {
> + .data = &xilinx_mdb_data,
> + .parse_caps = dw_edma_pcie_parse_xilinx_caps,
> + .flags = DW_EDMA_PCIE_F_DEVMEM_PHYS_OFF,
> +};
> +
> static const struct pci_device_id dw_edma_pcie_id_table[] = {
> - { PCI_DEVICE_DATA(SYNOPSYS, EDDA, &snps_edda_data) },
> + { PCI_DEVICE_DATA(SYNOPSYS, EDDA, &snps_edda_match_data) },
> { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_XILINX_B054),
> - (kernel_ulong_t)&xilinx_mdb_data },
> + (kernel_ulong_t)&xilinx_mdb_match_data },
On going thread
https://lore.kernel.org/linux-i3c/afmEo54iWgk54M3Y@monoceros/
.driver_data = (kernel_ulong_t)&xilinx_mdb_data;
> { }
> };
> MODULE_DEVICE_TABLE(pci, dw_edma_pcie_id_table);
> --
> 2.51.0
>
^ permalink raw reply [flat|nested] 28+ messages in thread* Re: [PATCH 05/12] dmaengine: dw-edma-pcie: Add capability match data
2026-05-21 16:06 ` Frank Li
@ 2026-05-22 14:38 ` Koichiro Den
2026-05-22 20:54 ` Frank Li
0 siblings, 1 reply; 28+ messages in thread
From: Koichiro Den @ 2026-05-22 14:38 UTC (permalink / raw)
To: Frank Li
Cc: Vinod Koul, Frank Li, Manivannan Sadhasivam, Marek Vasut,
Yoshihiro Shimoda, dmaengine, linux-kernel
On Thu, May 21, 2026 at 12:06:48PM -0400, Frank Li wrote:
> On Thu, May 21, 2026 at 03:31:08PM +0900, Koichiro Den wrote:
> > Move device-specific capability parsing behind per-device match data.
> >
> > The existing probe path mixes two decisions: which static template a PCI
> > ID uses, and which device-specific capability parser adjusts that
> > template. Split those decisions so device-specific discovery can be
> > added through match data instead of adding more vendor checks to
> > dw_edma_pcie_probe().
> >
> > No functional change is intended for the existing Synopsys EDDA and
> > AMD/Xilinx MDB matches. They still copy the same static template data and
> > run the same capability parsing logic before BAR mapping. The MDB entry
> > also keeps using endpoint memory physical addresses for descriptor
> > windows through a new match-data flag.
> >
> > Signed-off-by: Koichiro Den <den@valinux.co.jp>
> > ---
> > drivers/dma/dw-edma/dw-edma-pcie.c | 127 +++++++++++++++++++----------
> > 1 file changed, 85 insertions(+), 42 deletions(-)
> >
> > diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
> > index 0b30ce138503..043a7f73bf79 100644
> > --- a/drivers/dma/dw-edma/dw-edma-pcie.c
> > +++ b/drivers/dma/dw-edma/dw-edma-pcie.c
> > @@ -74,6 +74,19 @@ struct dw_edma_pcie_data {
> > u64 devmem_phys_off;
> > };
> >
> > +struct dw_edma_pcie_match_data {
> > + const struct dw_edma_pcie_data *data;
> > + /*
> > + * Mandatory callback. It may leave @pdata unchanged when the static
> > + * template already describes the device.
> > + */
> > + int (*parse_caps)(struct pci_dev *pdev,
> > + struct dw_edma_pcie_data *pdata, bool *non_ll);
>
> Needn't non_ll here. This information should be already save into
> dw_edma_chip::cfg_no_ll
The non_ll argument is used only to fill dw_edma_chip::cfg_non_ll later.
Do you mean that parse_caps() should not have a separate non_ll output
parameter, and that this should instead be kept in e.g. dw_edma_pcie_data?
That would make probe do:
chip->cfg_non_ll = dma_data->cfg_non_ll;
and drop the local non_ll variable in dw_edma_pcie_probe().
If so, yes, I agree that would make the code a bit cleaner.
>
> > + unsigned long flags;
> > +};
> ...
> >
> > +static const struct dw_edma_pcie_match_data snps_edda_match_data = {
> > + .data = &snps_edda_data,
> > + .parse_caps = dw_edma_pcie_parse_synopsys_caps,
> > +};
> > +
> > +static const struct dw_edma_pcie_match_data xilinx_mdb_match_data = {
> > + .data = &xilinx_mdb_data,
> > + .parse_caps = dw_edma_pcie_parse_xilinx_caps,
> > + .flags = DW_EDMA_PCIE_F_DEVMEM_PHYS_OFF,
> > +};
> > +
> > static const struct pci_device_id dw_edma_pcie_id_table[] = {
> > - { PCI_DEVICE_DATA(SYNOPSYS, EDDA, &snps_edda_data) },
> > + { PCI_DEVICE_DATA(SYNOPSYS, EDDA, &snps_edda_match_data) },
> > { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_XILINX_B054),
> > - (kernel_ulong_t)&xilinx_mdb_data },
> > + (kernel_ulong_t)&xilinx_mdb_match_data },
>
> On going thread
> https://lore.kernel.org/linux-i3c/afmEo54iWgk54M3Y@monoceros/
>
> .driver_data = (kernel_ulong_t)&xilinx_mdb_data;
Thanks for the pointer, I wasn't aware of that work. I'll use a named
initializer here.
Best regards,
Koichiro
>
> > { }
> > };
> > MODULE_DEVICE_TABLE(pci, dw_edma_pcie_id_table);
> > --
> > 2.51.0
> >
^ permalink raw reply [flat|nested] 28+ messages in thread* Re: [PATCH 05/12] dmaengine: dw-edma-pcie: Add capability match data
2026-05-22 14:38 ` Koichiro Den
@ 2026-05-22 20:54 ` Frank Li
0 siblings, 0 replies; 28+ messages in thread
From: Frank Li @ 2026-05-22 20:54 UTC (permalink / raw)
To: Koichiro Den
Cc: Vinod Koul, Frank Li, Manivannan Sadhasivam, Marek Vasut,
Yoshihiro Shimoda, dmaengine, linux-kernel
On Fri, May 22, 2026 at 11:38:35PM +0900, Koichiro Den wrote:
> On Thu, May 21, 2026 at 12:06:48PM -0400, Frank Li wrote:
> > On Thu, May 21, 2026 at 03:31:08PM +0900, Koichiro Den wrote:
> > > Move device-specific capability parsing behind per-device match data.
> > >
> > > The existing probe path mixes two decisions: which static template a PCI
> > > ID uses, and which device-specific capability parser adjusts that
> > > template. Split those decisions so device-specific discovery can be
> > > added through match data instead of adding more vendor checks to
> > > dw_edma_pcie_probe().
> > >
> > > No functional change is intended for the existing Synopsys EDDA and
> > > AMD/Xilinx MDB matches. They still copy the same static template data and
> > > run the same capability parsing logic before BAR mapping. The MDB entry
> > > also keeps using endpoint memory physical addresses for descriptor
> > > windows through a new match-data flag.
> > >
> > > Signed-off-by: Koichiro Den <den@valinux.co.jp>
> > > ---
> > > drivers/dma/dw-edma/dw-edma-pcie.c | 127 +++++++++++++++++++----------
> > > 1 file changed, 85 insertions(+), 42 deletions(-)
> > >
> > > diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
> > > index 0b30ce138503..043a7f73bf79 100644
> > > --- a/drivers/dma/dw-edma/dw-edma-pcie.c
> > > +++ b/drivers/dma/dw-edma/dw-edma-pcie.c
> > > @@ -74,6 +74,19 @@ struct dw_edma_pcie_data {
> > > u64 devmem_phys_off;
> > > };
> > >
> > > +struct dw_edma_pcie_match_data {
> > > + const struct dw_edma_pcie_data *data;
> > > + /*
> > > + * Mandatory callback. It may leave @pdata unchanged when the static
> > > + * template already describes the device.
> > > + */
> > > + int (*parse_caps)(struct pci_dev *pdev,
> > > + struct dw_edma_pcie_data *pdata, bool *non_ll);
> >
> > Needn't non_ll here. This information should be already save into
> > dw_edma_chip::cfg_no_ll
>
> The non_ll argument is used only to fill dw_edma_chip::cfg_non_ll later.
>
> Do you mean that parse_caps() should not have a separate non_ll output
> parameter, and that this should instead be kept in e.g. dw_edma_pcie_data?
> That would make probe do:
>
> chip->cfg_non_ll = dma_data->cfg_non_ll;
>
> and drop the local non_ll variable in dw_edma_pcie_probe().
> If so, yes, I agree that would make the code a bit cleaner.
Yes, or direct set chip->cfg_non_ll at parse_caps().
Frank
>
> >
> > > + unsigned long flags;
> > > +};
> > ...
> > >
> > > +static const struct dw_edma_pcie_match_data snps_edda_match_data = {
> > > + .data = &snps_edda_data,
> > > + .parse_caps = dw_edma_pcie_parse_synopsys_caps,
> > > +};
> > > +
> > > +static const struct dw_edma_pcie_match_data xilinx_mdb_match_data = {
> > > + .data = &xilinx_mdb_data,
> > > + .parse_caps = dw_edma_pcie_parse_xilinx_caps,
> > > + .flags = DW_EDMA_PCIE_F_DEVMEM_PHYS_OFF,
> > > +};
> > > +
> > > static const struct pci_device_id dw_edma_pcie_id_table[] = {
> > > - { PCI_DEVICE_DATA(SYNOPSYS, EDDA, &snps_edda_data) },
> > > + { PCI_DEVICE_DATA(SYNOPSYS, EDDA, &snps_edda_match_data) },
> > > { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_XILINX_B054),
> > > - (kernel_ulong_t)&xilinx_mdb_data },
> > > + (kernel_ulong_t)&xilinx_mdb_match_data },
> >
> > On going thread
> > https://lore.kernel.org/linux-i3c/afmEo54iWgk54M3Y@monoceros/
> >
> > .driver_data = (kernel_ulong_t)&xilinx_mdb_data;
>
> Thanks for the pointer, I wasn't aware of that work. I'll use a named
> initializer here.
>
> Best regards,
> Koichiro
>
> >
> > > { }
> > > };
> > > MODULE_DEVICE_TABLE(pci, dw_edma_pcie_id_table);
> > > --
> > > 2.51.0
> > >
^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH 06/12] dmaengine: dw-edma-pcie: Rename DMA data copy
2026-05-21 6:31 [PATCH 00/12] dmaengine: dw-edma: Prepare for PCI EP DMA (part 1/3) Koichiro Den
` (4 preceding siblings ...)
2026-05-21 6:31 ` [PATCH 05/12] dmaengine: dw-edma-pcie: Add capability match data Koichiro Den
@ 2026-05-21 6:31 ` Koichiro Den
2026-05-21 16:10 ` Frank Li
2026-05-21 6:31 ` [PATCH 07/12] dmaengine: dw-edma-pcie: Add default IRQ match data Koichiro Den
` (5 subsequent siblings)
11 siblings, 1 reply; 28+ messages in thread
From: Koichiro Den @ 2026-05-21 6:31 UTC (permalink / raw)
To: Vinod Koul, Frank Li, Manivannan Sadhasivam
Cc: Marek Vasut, Yoshihiro Shimoda, dmaengine, linux-kernel
dw_edma_pcie_probe() now obtains DMA layout data through device-specific
capability callbacks, not only from PCIe Vendor-Specific Extended
Capabilities. Rename the local data copy from vsec_data to dma_data
before adding endpoint DMA BAR metadata discovery, which does not rely
on VSEC.
No functional change intended.
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
drivers/dma/dw-edma/dw-edma-pcie.c | 70 +++++++++++++++---------------
1 file changed, 34 insertions(+), 36 deletions(-)
diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
index 043a7f73bf79..8ae164169c7e 100644
--- a/drivers/dma/dw-edma/dw-edma-pcie.c
+++ b/drivers/dma/dw-edma/dw-edma-pcie.c
@@ -369,11 +369,6 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
int i, mask;
bool non_ll = false;
- struct dw_edma_pcie_data *vsec_data __free(kfree) =
- kmalloc_obj(*vsec_data);
- if (!vsec_data)
- return -ENOMEM;
-
/* Enable PCI device */
err = pcim_enable_device(pdev);
if (err) {
@@ -381,25 +376,28 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
return err;
}
- memcpy(vsec_data, pdata, sizeof(struct dw_edma_pcie_data));
+ struct dw_edma_pcie_data *dma_data __free(kfree) =
+ kmemdup(pdata, sizeof(*dma_data), GFP_KERNEL);
+ if (!dma_data)
+ return -ENOMEM;
/* Let device-specific discovery override the static template data. */
if (!match->parse_caps)
return -EINVAL;
- err = match->parse_caps(pdev, vsec_data, &non_ll);
+ err = match->parse_caps(pdev, dma_data, &non_ll);
if (err)
return err;
/* Mapping PCI BAR regions */
- mask = BIT(vsec_data->rg.bar);
- for (i = 0; i < vsec_data->wr_ch_cnt; i++) {
- mask |= BIT(vsec_data->ll_wr[i].bar);
- mask |= BIT(vsec_data->dt_wr[i].bar);
+ mask = BIT(dma_data->rg.bar);
+ for (i = 0; i < dma_data->wr_ch_cnt; i++) {
+ mask |= BIT(dma_data->ll_wr[i].bar);
+ mask |= BIT(dma_data->dt_wr[i].bar);
}
- for (i = 0; i < vsec_data->rd_ch_cnt; i++) {
- mask |= BIT(vsec_data->ll_rd[i].bar);
- mask |= BIT(vsec_data->dt_rd[i].bar);
+ for (i = 0; i < dma_data->rd_ch_cnt; i++) {
+ mask |= BIT(dma_data->ll_rd[i].bar);
+ mask |= BIT(dma_data->dt_rd[i].bar);
}
err = pcim_iomap_regions(pdev, mask, pci_name(pdev));
if (err) {
@@ -422,7 +420,7 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
return -ENOMEM;
/* IRQs allocation */
- nr_irqs = pci_alloc_irq_vectors(pdev, 1, vsec_data->irqs,
+ nr_irqs = pci_alloc_irq_vectors(pdev, 1, dma_data->irqs,
PCI_IRQ_MSI | PCI_IRQ_MSIX);
if (nr_irqs < 1) {
pci_err(pdev, "fail to alloc IRQ vector (number of IRQs=%u)\n",
@@ -433,23 +431,23 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
/* Data structure initialization */
chip->dev = dev;
- chip->mf = vsec_data->mf;
+ chip->mf = dma_data->mf;
chip->nr_irqs = nr_irqs;
chip->ops = &dw_edma_pcie_plat_ops;
chip->cfg_non_ll = non_ll;
- chip->ll_wr_cnt = vsec_data->wr_ch_cnt;
- chip->ll_rd_cnt = vsec_data->rd_ch_cnt;
+ chip->ll_wr_cnt = dma_data->wr_ch_cnt;
+ chip->ll_rd_cnt = dma_data->rd_ch_cnt;
- chip->reg_base = pcim_iomap_table(pdev)[vsec_data->rg.bar];
+ chip->reg_base = pcim_iomap_table(pdev)[dma_data->rg.bar];
if (!chip->reg_base)
return -ENOMEM;
for (i = 0; i < chip->ll_wr_cnt && !non_ll; i++) {
struct dw_edma_region *ll_region = &chip->ll_region_wr[i];
struct dw_edma_region *dt_region = &chip->dt_region_wr[i];
- struct dw_edma_block *ll_block = &vsec_data->ll_wr[i];
- struct dw_edma_block *dt_block = &vsec_data->dt_wr[i];
+ struct dw_edma_block *ll_block = &dma_data->ll_wr[i];
+ struct dw_edma_block *dt_block = &dma_data->dt_wr[i];
ll_region->vaddr.io = pcim_iomap_table(pdev)[ll_block->bar];
if (!ll_region->vaddr.io)
@@ -457,7 +455,7 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
ll_region->vaddr.io += ll_block->off;
ll_region->paddr = dw_edma_get_phys_addr(pdev, match,
- vsec_data, ll_block->bar);
+ dma_data, ll_block->bar);
ll_region->paddr += ll_block->off;
ll_region->sz = ll_block->sz;
@@ -467,7 +465,7 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
dt_region->vaddr.io += dt_block->off;
dt_region->paddr = dw_edma_get_phys_addr(pdev, match,
- vsec_data, dt_block->bar);
+ dma_data, dt_block->bar);
dt_region->paddr += dt_block->off;
dt_region->sz = dt_block->sz;
}
@@ -475,8 +473,8 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
for (i = 0; i < chip->ll_rd_cnt && !non_ll; i++) {
struct dw_edma_region *ll_region = &chip->ll_region_rd[i];
struct dw_edma_region *dt_region = &chip->dt_region_rd[i];
- struct dw_edma_block *ll_block = &vsec_data->ll_rd[i];
- struct dw_edma_block *dt_block = &vsec_data->dt_rd[i];
+ struct dw_edma_block *ll_block = &dma_data->ll_rd[i];
+ struct dw_edma_block *dt_block = &dma_data->dt_rd[i];
ll_region->vaddr.io = pcim_iomap_table(pdev)[ll_block->bar];
if (!ll_region->vaddr.io)
@@ -484,7 +482,7 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
ll_region->vaddr.io += ll_block->off;
ll_region->paddr = dw_edma_get_phys_addr(pdev, match,
- vsec_data, ll_block->bar);
+ dma_data, ll_block->bar);
ll_region->paddr += ll_block->off;
ll_region->sz = ll_block->sz;
@@ -494,7 +492,7 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
dt_region->vaddr.io += dt_block->off;
dt_region->paddr = dw_edma_get_phys_addr(pdev, match,
- vsec_data, dt_block->bar);
+ dma_data, dt_block->bar);
dt_region->paddr += dt_block->off;
dt_region->sz = dt_block->sz;
}
@@ -512,31 +510,31 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
pci_dbg(pdev, "Version:\tUnknown (0x%x)\n", chip->mf);
pci_dbg(pdev, "Registers:\tBAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p)\n",
- vsec_data->rg.bar, vsec_data->rg.off, vsec_data->rg.sz,
+ dma_data->rg.bar, dma_data->rg.off, dma_data->rg.sz,
chip->reg_base);
for (i = 0; i < chip->ll_wr_cnt; i++) {
pci_dbg(pdev, "L. List:\tWRITE CH%.2u, BAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",
- i, vsec_data->ll_wr[i].bar,
- vsec_data->ll_wr[i].off, chip->ll_region_wr[i].sz,
+ i, dma_data->ll_wr[i].bar,
+ dma_data->ll_wr[i].off, chip->ll_region_wr[i].sz,
chip->ll_region_wr[i].vaddr.io, &chip->ll_region_wr[i].paddr);
pci_dbg(pdev, "Data:\tWRITE CH%.2u, BAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",
- i, vsec_data->dt_wr[i].bar,
- vsec_data->dt_wr[i].off, chip->dt_region_wr[i].sz,
+ i, dma_data->dt_wr[i].bar,
+ dma_data->dt_wr[i].off, chip->dt_region_wr[i].sz,
chip->dt_region_wr[i].vaddr.io, &chip->dt_region_wr[i].paddr);
}
for (i = 0; i < chip->ll_rd_cnt; i++) {
pci_dbg(pdev, "L. List:\tREAD CH%.2u, BAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",
- i, vsec_data->ll_rd[i].bar,
- vsec_data->ll_rd[i].off, chip->ll_region_rd[i].sz,
+ i, dma_data->ll_rd[i].bar,
+ dma_data->ll_rd[i].off, chip->ll_region_rd[i].sz,
chip->ll_region_rd[i].vaddr.io, &chip->ll_region_rd[i].paddr);
pci_dbg(pdev, "Data:\tREAD CH%.2u, BAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",
- i, vsec_data->dt_rd[i].bar,
- vsec_data->dt_rd[i].off, chip->dt_region_rd[i].sz,
+ i, dma_data->dt_rd[i].bar,
+ dma_data->dt_rd[i].off, chip->dt_region_rd[i].sz,
chip->dt_region_rd[i].vaddr.io, &chip->dt_region_rd[i].paddr);
}
--
2.51.0
^ permalink raw reply [flat|nested] 28+ messages in thread* Re: [PATCH 06/12] dmaengine: dw-edma-pcie: Rename DMA data copy
2026-05-21 6:31 ` [PATCH 06/12] dmaengine: dw-edma-pcie: Rename DMA data copy Koichiro Den
@ 2026-05-21 16:10 ` Frank Li
2026-05-22 14:41 ` Koichiro Den
0 siblings, 1 reply; 28+ messages in thread
From: Frank Li @ 2026-05-21 16:10 UTC (permalink / raw)
To: Koichiro Den
Cc: Vinod Koul, Frank Li, Manivannan Sadhasivam, Marek Vasut,
Yoshihiro Shimoda, dmaengine, linux-kernel
On Thu, May 21, 2026 at 03:31:09PM +0900, Koichiro Den wrote:
subject:
dmaengine: dw-edma-pcie: Rename vsec_data to dma_data
> dw_edma_pcie_probe() now obtains DMA layout data through device-specific
> capability callbacks, not only from PCIe Vendor-Specific Extended
> Capabilities. Rename the local data copy from vsec_data to dma_data
> before adding endpoint DMA BAR metadata discovery, which does not rely
> on VSEC.
>
> No functional change intended.
>
> Signed-off-by: Koichiro Den <den@valinux.co.jp>
> ---
Frank
^ permalink raw reply [flat|nested] 28+ messages in thread* Re: [PATCH 06/12] dmaengine: dw-edma-pcie: Rename DMA data copy
2026-05-21 16:10 ` Frank Li
@ 2026-05-22 14:41 ` Koichiro Den
0 siblings, 0 replies; 28+ messages in thread
From: Koichiro Den @ 2026-05-22 14:41 UTC (permalink / raw)
To: Frank Li
Cc: Vinod Koul, Frank Li, Manivannan Sadhasivam, Marek Vasut,
Yoshihiro Shimoda, dmaengine, linux-kernel
On Thu, May 21, 2026 at 12:10:57PM -0400, Frank Li wrote:
> On Thu, May 21, 2026 at 03:31:09PM +0900, Koichiro Den wrote:
>
> subject:
> dmaengine: dw-edma-pcie: Rename vsec_data to dma_data
Thanks for the catch, I'll fix it.
Best regards,
Koichiro
>
> > dw_edma_pcie_probe() now obtains DMA layout data through device-specific
> > capability callbacks, not only from PCIe Vendor-Specific Extended
> > Capabilities. Rename the local data copy from vsec_data to dma_data
> > before adding endpoint DMA BAR metadata discovery, which does not rely
> > on VSEC.
> >
> > No functional change intended.
> >
> > Signed-off-by: Koichiro Den <den@valinux.co.jp>
> > ---
>
> Frank
>
^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH 07/12] dmaengine: dw-edma-pcie: Add default IRQ match data
2026-05-21 6:31 [PATCH 00/12] dmaengine: dw-edma: Prepare for PCI EP DMA (part 1/3) Koichiro Den
` (5 preceding siblings ...)
2026-05-21 6:31 ` [PATCH 06/12] dmaengine: dw-edma-pcie: Rename DMA data copy Koichiro Den
@ 2026-05-21 6:31 ` Koichiro Den
2026-05-21 16:12 ` Frank Li
2026-05-21 6:31 ` [PATCH 08/12] dmaengine: dw-edma-pcie: Add raw slave address match flag Koichiro Den
` (4 subsequent siblings)
11 siblings, 1 reply; 28+ messages in thread
From: Koichiro Den @ 2026-05-21 6:31 UTC (permalink / raw)
To: Vinod Koul, Frank Li, Manivannan Sadhasivam
Cc: Marek Vasut, Yoshihiro Shimoda, dmaengine, linux-kernel
Store the default per-channel interrupt routing mode in dw-edma-pcie
match data and copy it into dw_edma_chip during probe.
No functional change intended. Existing Synopsys EDDA and AMD/Xilinx MDB
matches leave the field zero, which is DW_EDMA_CH_IRQ_DEFAULT.
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
drivers/dma/dw-edma/dw-edma-pcie.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
index 8ae164169c7e..cf2f09f1891c 100644
--- a/drivers/dma/dw-edma/dw-edma-pcie.c
+++ b/drivers/dma/dw-edma/dw-edma-pcie.c
@@ -83,6 +83,7 @@ struct dw_edma_pcie_match_data {
int (*parse_caps)(struct pci_dev *pdev,
struct dw_edma_pcie_data *pdata, bool *non_ll);
unsigned long flags;
+ enum dw_edma_ch_irq_mode default_irq_mode;
};
#define DW_EDMA_PCIE_F_DEVMEM_PHYS_OFF BIT(0)
@@ -432,6 +433,7 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
chip->dev = dev;
chip->mf = dma_data->mf;
+ chip->default_irq_mode = match->default_irq_mode;
chip->nr_irqs = nr_irqs;
chip->ops = &dw_edma_pcie_plat_ops;
chip->cfg_non_ll = non_ll;
--
2.51.0
^ permalink raw reply [flat|nested] 28+ messages in thread* Re: [PATCH 07/12] dmaengine: dw-edma-pcie: Add default IRQ match data
2026-05-21 6:31 ` [PATCH 07/12] dmaengine: dw-edma-pcie: Add default IRQ match data Koichiro Den
@ 2026-05-21 16:12 ` Frank Li
0 siblings, 0 replies; 28+ messages in thread
From: Frank Li @ 2026-05-21 16:12 UTC (permalink / raw)
To: Koichiro Den
Cc: Vinod Koul, Frank Li, Manivannan Sadhasivam, Marek Vasut,
Yoshihiro Shimoda, dmaengine, linux-kernel
On Thu, May 21, 2026 at 03:31:10PM +0900, Koichiro Den wrote:
> Store the default per-channel interrupt routing mode in dw-edma-pcie
> match data and copy it into dw_edma_chip during probe.
>
> No functional change intended. Existing Synopsys EDDA and AMD/Xilinx MDB
> matches leave the field zero, which is DW_EDMA_CH_IRQ_DEFAULT.
>
> Signed-off-by: Koichiro Den <den@valinux.co.jp>
> ---
Reviewed-by: Frank Li <Frank.Li@nxp.com>
> drivers/dma/dw-edma/dw-edma-pcie.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
> index 8ae164169c7e..cf2f09f1891c 100644
> --- a/drivers/dma/dw-edma/dw-edma-pcie.c
> +++ b/drivers/dma/dw-edma/dw-edma-pcie.c
> @@ -83,6 +83,7 @@ struct dw_edma_pcie_match_data {
> int (*parse_caps)(struct pci_dev *pdev,
> struct dw_edma_pcie_data *pdata, bool *non_ll);
> unsigned long flags;
> + enum dw_edma_ch_irq_mode default_irq_mode;
> };
>
> #define DW_EDMA_PCIE_F_DEVMEM_PHYS_OFF BIT(0)
> @@ -432,6 +433,7 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> chip->dev = dev;
>
> chip->mf = dma_data->mf;
> + chip->default_irq_mode = match->default_irq_mode;
> chip->nr_irqs = nr_irqs;
> chip->ops = &dw_edma_pcie_plat_ops;
> chip->cfg_non_ll = non_ll;
> --
> 2.51.0
>
^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH 08/12] dmaengine: dw-edma-pcie: Add raw slave address match flag
2026-05-21 6:31 [PATCH 00/12] dmaengine: dw-edma: Prepare for PCI EP DMA (part 1/3) Koichiro Den
` (6 preceding siblings ...)
2026-05-21 6:31 ` [PATCH 07/12] dmaengine: dw-edma-pcie: Add default IRQ match data Koichiro Den
@ 2026-05-21 6:31 ` Koichiro Den
2026-05-21 16:15 ` Frank Li
2026-05-21 6:31 ` [PATCH 09/12] dmaengine: dw-edma-pcie: Add register offset " Koichiro Den
` (3 subsequent siblings)
11 siblings, 1 reply; 28+ messages in thread
From: Koichiro Den @ 2026-05-21 6:31 UTC (permalink / raw)
To: Vinod Koul, Frank Li, Manivannan Sadhasivam
Cc: Marek Vasut, Yoshihiro Shimoda, dmaengine, linux-kernel
Add a match-data flag for devices whose DMA slave address is already in
the DMA controller address domain. Such devices do not need the
dw-edma-pcie pci_address callback, which translates a CPU MMIO address
back to a PCI bus address.
When the flag is set, select platform ops without a pci_address callback
so dw-edma core passes the slave address through unchanged.
No functional change intended. Existing matches do not set the new flag
and continue to use dw_edma_pcie_address().
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
drivers/dma/dw-edma/dw-edma-pcie.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
index cf2f09f1891c..651269708cc5 100644
--- a/drivers/dma/dw-edma/dw-edma-pcie.c
+++ b/drivers/dma/dw-edma/dw-edma-pcie.c
@@ -87,6 +87,7 @@ struct dw_edma_pcie_match_data {
};
#define DW_EDMA_PCIE_F_DEVMEM_PHYS_OFF BIT(0)
+#define DW_EDMA_PCIE_F_RAW_SLAVE_ADDR BIT(1)
static const struct dw_edma_pcie_data snps_edda_data = {
/* eDMA registers location */
@@ -208,6 +209,10 @@ static const struct dw_edma_plat_ops dw_edma_pcie_plat_ops = {
.pci_address = dw_edma_pcie_address,
};
+static const struct dw_edma_plat_ops dw_edma_pcie_raw_addr_plat_ops = {
+ .irq_vector = dw_edma_pcie_irq_vector,
+};
+
static void dw_edma_pcie_get_synopsys_dma_data(struct pci_dev *pdev,
struct dw_edma_pcie_data *pdata)
{
@@ -435,7 +440,8 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
chip->mf = dma_data->mf;
chip->default_irq_mode = match->default_irq_mode;
chip->nr_irqs = nr_irqs;
- chip->ops = &dw_edma_pcie_plat_ops;
+ chip->ops = match->flags & DW_EDMA_PCIE_F_RAW_SLAVE_ADDR ?
+ &dw_edma_pcie_raw_addr_plat_ops : &dw_edma_pcie_plat_ops;
chip->cfg_non_ll = non_ll;
chip->ll_wr_cnt = dma_data->wr_ch_cnt;
--
2.51.0
^ permalink raw reply [flat|nested] 28+ messages in thread* Re: [PATCH 08/12] dmaengine: dw-edma-pcie: Add raw slave address match flag
2026-05-21 6:31 ` [PATCH 08/12] dmaengine: dw-edma-pcie: Add raw slave address match flag Koichiro Den
@ 2026-05-21 16:15 ` Frank Li
2026-05-22 14:45 ` Koichiro Den
0 siblings, 1 reply; 28+ messages in thread
From: Frank Li @ 2026-05-21 16:15 UTC (permalink / raw)
To: Koichiro Den
Cc: Vinod Koul, Frank Li, Manivannan Sadhasivam, Marek Vasut,
Yoshihiro Shimoda, dmaengine, linux-kernel
On Thu, May 21, 2026 at 03:31:11PM +0900, Koichiro Den wrote:
> Add a match-data flag for devices whose DMA slave address is already in
> the DMA controller address domain. Such devices do not need the
> dw-edma-pcie pci_address callback, which translates a CPU MMIO address
> back to a PCI bus address.
>
> When the flag is set, select platform ops without a pci_address callback
> so dw-edma core passes the slave address through unchanged.
>
> No functional change intended. Existing matches do not set the new flag
> and continue to use dw_edma_pcie_address().
>
> Signed-off-by: Koichiro Den <den@valinux.co.jp>
> ---
> drivers/dma/dw-edma/dw-edma-pcie.c | 8 +++++++-
> 1 file changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
> index cf2f09f1891c..651269708cc5 100644
> --- a/drivers/dma/dw-edma/dw-edma-pcie.c
> +++ b/drivers/dma/dw-edma/dw-edma-pcie.c
> @@ -87,6 +87,7 @@ struct dw_edma_pcie_match_data {
> };
>
> #define DW_EDMA_PCIE_F_DEVMEM_PHYS_OFF BIT(0)
> +#define DW_EDMA_PCIE_F_RAW_SLAVE_ADDR BIT(1)
>
> static const struct dw_edma_pcie_data snps_edda_data = {
> /* eDMA registers location */
> @@ -208,6 +209,10 @@ static const struct dw_edma_plat_ops dw_edma_pcie_plat_ops = {
> .pci_address = dw_edma_pcie_address,
> };
>
> +static const struct dw_edma_plat_ops dw_edma_pcie_raw_addr_plat_ops = {
> + .irq_vector = dw_edma_pcie_irq_vector,
> +};
> +
> static void dw_edma_pcie_get_synopsys_dma_data(struct pci_dev *pdev,
> struct dw_edma_pcie_data *pdata)
> {
> @@ -435,7 +440,8 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> chip->mf = dma_data->mf;
> chip->default_irq_mode = match->default_irq_mode;
> chip->nr_irqs = nr_irqs;
> - chip->ops = &dw_edma_pcie_plat_ops;
> + chip->ops = match->flags & DW_EDMA_PCIE_F_RAW_SLAVE_ADDR ?
> + &dw_edma_pcie_raw_addr_plat_ops : &dw_edma_pcie_plat_ops;
Can we direct put &dw_edma_pcie_raw_addr_plat_ops and &dw_edma_pcie_plat_ops
into match data, so needn't flags DW_EDMA_PCIE_F_RAW_SLAVE_ADDR
Frank
> chip->cfg_non_ll = non_ll;
>
> chip->ll_wr_cnt = dma_data->wr_ch_cnt;
> --
> 2.51.0
>
^ permalink raw reply [flat|nested] 28+ messages in thread* Re: [PATCH 08/12] dmaengine: dw-edma-pcie: Add raw slave address match flag
2026-05-21 16:15 ` Frank Li
@ 2026-05-22 14:45 ` Koichiro Den
0 siblings, 0 replies; 28+ messages in thread
From: Koichiro Den @ 2026-05-22 14:45 UTC (permalink / raw)
To: Frank Li
Cc: Vinod Koul, Frank Li, Manivannan Sadhasivam, Marek Vasut,
Yoshihiro Shimoda, dmaengine, linux-kernel
On Thu, May 21, 2026 at 12:15:57PM -0400, Frank Li wrote:
> On Thu, May 21, 2026 at 03:31:11PM +0900, Koichiro Den wrote:
> > Add a match-data flag for devices whose DMA slave address is already in
> > the DMA controller address domain. Such devices do not need the
> > dw-edma-pcie pci_address callback, which translates a CPU MMIO address
> > back to a PCI bus address.
> >
> > When the flag is set, select platform ops without a pci_address callback
> > so dw-edma core passes the slave address through unchanged.
> >
> > No functional change intended. Existing matches do not set the new flag
> > and continue to use dw_edma_pcie_address().
> >
> > Signed-off-by: Koichiro Den <den@valinux.co.jp>
> > ---
> > drivers/dma/dw-edma/dw-edma-pcie.c | 8 +++++++-
> > 1 file changed, 7 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
> > index cf2f09f1891c..651269708cc5 100644
> > --- a/drivers/dma/dw-edma/dw-edma-pcie.c
> > +++ b/drivers/dma/dw-edma/dw-edma-pcie.c
> > @@ -87,6 +87,7 @@ struct dw_edma_pcie_match_data {
> > };
> >
> > #define DW_EDMA_PCIE_F_DEVMEM_PHYS_OFF BIT(0)
> > +#define DW_EDMA_PCIE_F_RAW_SLAVE_ADDR BIT(1)
> >
> > static const struct dw_edma_pcie_data snps_edda_data = {
> > /* eDMA registers location */
> > @@ -208,6 +209,10 @@ static const struct dw_edma_plat_ops dw_edma_pcie_plat_ops = {
> > .pci_address = dw_edma_pcie_address,
> > };
> >
> > +static const struct dw_edma_plat_ops dw_edma_pcie_raw_addr_plat_ops = {
> > + .irq_vector = dw_edma_pcie_irq_vector,
> > +};
> > +
> > static void dw_edma_pcie_get_synopsys_dma_data(struct pci_dev *pdev,
> > struct dw_edma_pcie_data *pdata)
> > {
> > @@ -435,7 +440,8 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> > chip->mf = dma_data->mf;
> > chip->default_irq_mode = match->default_irq_mode;
> > chip->nr_irqs = nr_irqs;
> > - chip->ops = &dw_edma_pcie_plat_ops;
> > + chip->ops = match->flags & DW_EDMA_PCIE_F_RAW_SLAVE_ADDR ?
> > + &dw_edma_pcie_raw_addr_plat_ops : &dw_edma_pcie_plat_ops;
>
> Can we direct put &dw_edma_pcie_raw_addr_plat_ops and &dw_edma_pcie_plat_ops
> into match data, so needn't flags DW_EDMA_PCIE_F_RAW_SLAVE_ADDR
Yes, I agree that makes the code cleaner. I'll do so in v2.
Thanks for the suggestion.
Best regards,
Koichiro
>
> Frank
> > chip->cfg_non_ll = non_ll;
> >
> > chip->ll_wr_cnt = dma_data->wr_ch_cnt;
> > --
> > 2.51.0
> >
^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH 09/12] dmaengine: dw-edma-pcie: Add register offset match flag
2026-05-21 6:31 [PATCH 00/12] dmaengine: dw-edma: Prepare for PCI EP DMA (part 1/3) Koichiro Den
` (7 preceding siblings ...)
2026-05-21 6:31 ` [PATCH 08/12] dmaengine: dw-edma-pcie: Add raw slave address match flag Koichiro Den
@ 2026-05-21 6:31 ` Koichiro Den
2026-05-21 16:17 ` Frank Li
2026-05-21 6:31 ` [PATCH 10/12] dmaengine: dw-edma-pcie: Factor descriptor block addresses Koichiro Den
` (2 subsequent siblings)
11 siblings, 1 reply; 28+ messages in thread
From: Koichiro Den @ 2026-05-21 6:31 UTC (permalink / raw)
To: Vinod Koul, Frank Li, Manivannan Sadhasivam
Cc: Marek Vasut, Yoshihiro Shimoda, dmaengine, linux-kernel
Add a match-data flag for devices whose DMA register block starts at an
offset inside the mapped BAR. Existing Synopsys EDDA and AMD/Xilinx MDB
matches keep using the BAR mapping base directly.
No functional change intended.
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
drivers/dma/dw-edma/dw-edma-pcie.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
index 651269708cc5..6b375a58c550 100644
--- a/drivers/dma/dw-edma/dw-edma-pcie.c
+++ b/drivers/dma/dw-edma/dw-edma-pcie.c
@@ -88,6 +88,7 @@ struct dw_edma_pcie_match_data {
#define DW_EDMA_PCIE_F_DEVMEM_PHYS_OFF BIT(0)
#define DW_EDMA_PCIE_F_RAW_SLAVE_ADDR BIT(1)
+#define DW_EDMA_PCIE_F_REG_OFFSET BIT(2)
static const struct dw_edma_pcie_data snps_edda_data = {
/* eDMA registers location */
@@ -450,6 +451,8 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
chip->reg_base = pcim_iomap_table(pdev)[dma_data->rg.bar];
if (!chip->reg_base)
return -ENOMEM;
+ if (match->flags & DW_EDMA_PCIE_F_REG_OFFSET)
+ chip->reg_base += dma_data->rg.off;
for (i = 0; i < chip->ll_wr_cnt && !non_ll; i++) {
struct dw_edma_region *ll_region = &chip->ll_region_wr[i];
--
2.51.0
^ permalink raw reply [flat|nested] 28+ messages in thread* Re: [PATCH 09/12] dmaengine: dw-edma-pcie: Add register offset match flag
2026-05-21 6:31 ` [PATCH 09/12] dmaengine: dw-edma-pcie: Add register offset " Koichiro Den
@ 2026-05-21 16:17 ` Frank Li
2026-05-22 14:57 ` Koichiro Den
0 siblings, 1 reply; 28+ messages in thread
From: Frank Li @ 2026-05-21 16:17 UTC (permalink / raw)
To: Koichiro Den
Cc: Vinod Koul, Frank Li, Manivannan Sadhasivam, Marek Vasut,
Yoshihiro Shimoda, dmaengine, linux-kernel
On Thu, May 21, 2026 at 03:31:12PM +0900, Koichiro Den wrote:
> Add a match-data flag for devices whose DMA register block starts at an
> offset inside the mapped BAR. Existing Synopsys EDDA and AMD/Xilinx MDB
> matches keep using the BAR mapping base directly.
>
> No functional change intended.
>
> Signed-off-by: Koichiro Den <den@valinux.co.jp>
> ---
> drivers/dma/dw-edma/dw-edma-pcie.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
> index 651269708cc5..6b375a58c550 100644
> --- a/drivers/dma/dw-edma/dw-edma-pcie.c
> +++ b/drivers/dma/dw-edma/dw-edma-pcie.c
> @@ -88,6 +88,7 @@ struct dw_edma_pcie_match_data {
>
> #define DW_EDMA_PCIE_F_DEVMEM_PHYS_OFF BIT(0)
> #define DW_EDMA_PCIE_F_RAW_SLAVE_ADDR BIT(1)
> +#define DW_EDMA_PCIE_F_REG_OFFSET BIT(2)
>
> static const struct dw_edma_pcie_data snps_edda_data = {
> /* eDMA registers location */
> @@ -450,6 +451,8 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> chip->reg_base = pcim_iomap_table(pdev)[dma_data->rg.bar];
> if (!chip->reg_base)
> return -ENOMEM;
> + if (match->flags & DW_EDMA_PCIE_F_REG_OFFSET)
> + chip->reg_base += dma_data->rg.off;
suppose default rg.off is 0, so needn't flag DW_EDMA_PCIE_F_REG_OFFSET.
Frank
>
> for (i = 0; i < chip->ll_wr_cnt && !non_ll; i++) {
> struct dw_edma_region *ll_region = &chip->ll_region_wr[i];
> --
> 2.51.0
>
^ permalink raw reply [flat|nested] 28+ messages in thread* Re: [PATCH 09/12] dmaengine: dw-edma-pcie: Add register offset match flag
2026-05-21 16:17 ` Frank Li
@ 2026-05-22 14:57 ` Koichiro Den
2026-05-22 20:51 ` Frank Li
0 siblings, 1 reply; 28+ messages in thread
From: Koichiro Den @ 2026-05-22 14:57 UTC (permalink / raw)
To: Frank Li
Cc: Vinod Koul, Frank Li, Manivannan Sadhasivam, Marek Vasut,
Yoshihiro Shimoda, dmaengine, linux-kernel
On Thu, May 21, 2026 at 12:17:21PM -0400, Frank Li wrote:
> On Thu, May 21, 2026 at 03:31:12PM +0900, Koichiro Den wrote:
> > Add a match-data flag for devices whose DMA register block starts at an
> > offset inside the mapped BAR. Existing Synopsys EDDA and AMD/Xilinx MDB
> > matches keep using the BAR mapping base directly.
> >
> > No functional change intended.
> >
> > Signed-off-by: Koichiro Den <den@valinux.co.jp>
> > ---
> > drivers/dma/dw-edma/dw-edma-pcie.c | 3 +++
> > 1 file changed, 3 insertions(+)
> >
> > diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
> > index 651269708cc5..6b375a58c550 100644
> > --- a/drivers/dma/dw-edma/dw-edma-pcie.c
> > +++ b/drivers/dma/dw-edma/dw-edma-pcie.c
> > @@ -88,6 +88,7 @@ struct dw_edma_pcie_match_data {
> >
> > #define DW_EDMA_PCIE_F_DEVMEM_PHYS_OFF BIT(0)
> > #define DW_EDMA_PCIE_F_RAW_SLAVE_ADDR BIT(1)
> > +#define DW_EDMA_PCIE_F_REG_OFFSET BIT(2)
> >
> > static const struct dw_edma_pcie_data snps_edda_data = {
> > /* eDMA registers location */
> > @@ -450,6 +451,8 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> > chip->reg_base = pcim_iomap_table(pdev)[dma_data->rg.bar];
> > if (!chip->reg_base)
> > return -ENOMEM;
> > + if (match->flags & DW_EDMA_PCIE_F_REG_OFFSET)
> > + chip->reg_base += dma_data->rg.off;
>
> suppose default rg.off is 0, so needn't flag DW_EDMA_PCIE_F_REG_OFFSET.
As I understand it, for the existing EDDA/MDB paths, rg.off is not applied to
chip->reg_base. The static data has rg.off = 4K, and VSEC parsing may update it,
but the driver still uses the BAR mapping base directly as chip->reg_base.
So adding rg.off unconditionally would be a functional change for those existing
devices. That's why I added the flag. Am I missing something?
Best regards,
Koichiro
>
> Frank
>
> >
> > for (i = 0; i < chip->ll_wr_cnt && !non_ll; i++) {
> > struct dw_edma_region *ll_region = &chip->ll_region_wr[i];
> > --
> > 2.51.0
> >
^ permalink raw reply [flat|nested] 28+ messages in thread* Re: [PATCH 09/12] dmaengine: dw-edma-pcie: Add register offset match flag
2026-05-22 14:57 ` Koichiro Den
@ 2026-05-22 20:51 ` Frank Li
0 siblings, 0 replies; 28+ messages in thread
From: Frank Li @ 2026-05-22 20:51 UTC (permalink / raw)
To: Koichiro Den
Cc: Vinod Koul, Frank Li, Manivannan Sadhasivam, Marek Vasut,
Yoshihiro Shimoda, dmaengine, linux-kernel
On Fri, May 22, 2026 at 11:57:10PM +0900, Koichiro Den wrote:
> On Thu, May 21, 2026 at 12:17:21PM -0400, Frank Li wrote:
> > On Thu, May 21, 2026 at 03:31:12PM +0900, Koichiro Den wrote:
> > > Add a match-data flag for devices whose DMA register block starts at an
> > > offset inside the mapped BAR. Existing Synopsys EDDA and AMD/Xilinx MDB
> > > matches keep using the BAR mapping base directly.
> > >
> > > No functional change intended.
> > >
> > > Signed-off-by: Koichiro Den <den@valinux.co.jp>
> > > ---
> > > drivers/dma/dw-edma/dw-edma-pcie.c | 3 +++
> > > 1 file changed, 3 insertions(+)
> > >
> > > diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
> > > index 651269708cc5..6b375a58c550 100644
> > > --- a/drivers/dma/dw-edma/dw-edma-pcie.c
> > > +++ b/drivers/dma/dw-edma/dw-edma-pcie.c
> > > @@ -88,6 +88,7 @@ struct dw_edma_pcie_match_data {
> > >
> > > #define DW_EDMA_PCIE_F_DEVMEM_PHYS_OFF BIT(0)
> > > #define DW_EDMA_PCIE_F_RAW_SLAVE_ADDR BIT(1)
> > > +#define DW_EDMA_PCIE_F_REG_OFFSET BIT(2)
> > >
> > > static const struct dw_edma_pcie_data snps_edda_data = {
> > > /* eDMA registers location */
> > > @@ -450,6 +451,8 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> > > chip->reg_base = pcim_iomap_table(pdev)[dma_data->rg.bar];
> > > if (!chip->reg_base)
> > > return -ENOMEM;
> > > + if (match->flags & DW_EDMA_PCIE_F_REG_OFFSET)
> > > + chip->reg_base += dma_data->rg.off;
> >
> > suppose default rg.off is 0, so needn't flag DW_EDMA_PCIE_F_REG_OFFSET.
>
> As I understand it, for the existing EDDA/MDB paths, rg.off is not applied to
> chip->reg_base. The static data has rg.off = 4K, and VSEC parsing may update it,
> but the driver still uses the BAR mapping base directly as chip->reg_base.
>
> So adding rg.off unconditionally would be a functional change for those existing
> devices. That's why I added the flag. Am I missing something?
Okay!
Reviewed-by: Frank Li <Frank.Li@nxp.com>
>
> Best regards,
> Koichiro
>
> >
> > Frank
> >
> > >
> > > for (i = 0; i < chip->ll_wr_cnt && !non_ll; i++) {
> > > struct dw_edma_region *ll_region = &chip->ll_region_wr[i];
> > > --
> > > 2.51.0
> > >
^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH 10/12] dmaengine: dw-edma-pcie: Factor descriptor block addresses
2026-05-21 6:31 [PATCH 00/12] dmaengine: dw-edma: Prepare for PCI EP DMA (part 1/3) Koichiro Den
` (8 preceding siblings ...)
2026-05-21 6:31 ` [PATCH 09/12] dmaengine: dw-edma-pcie: Add register offset " Koichiro Den
@ 2026-05-21 6:31 ` Koichiro Den
2026-05-21 16:21 ` Frank Li
2026-05-21 6:31 ` [PATCH 11/12] dmaengine: dw-edma-pcie: Handle optional data blocks Koichiro Den
2026-05-21 6:31 ` [PATCH 12/12] dmaengine: dw-edma-pcie: Add chip flags match data Koichiro Den
11 siblings, 1 reply; 28+ messages in thread
From: Koichiro Den @ 2026-05-21 6:31 UTC (permalink / raw)
To: Vinod Koul, Frank Li, Manivannan Sadhasivam
Cc: Marek Vasut, Yoshihiro Shimoda, dmaengine, linux-kernel
Add an optional physical address override to struct dw_edma_block and
use a helper to compute descriptor block addresses.
No functional change intended. Existing EDDA and MDB block descriptors
leave the override unset, so the helper still returns the same
pci_bus_address() plus block offset value.
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
drivers/dma/dw-edma/dw-edma-pcie.c | 34 +++++++++++++++++++-----------
1 file changed, 22 insertions(+), 12 deletions(-)
diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
index 6b375a58c550..2a95fb9d5fc3 100644
--- a/drivers/dma/dw-edma/dw-edma-pcie.c
+++ b/drivers/dma/dw-edma/dw-edma-pcie.c
@@ -54,6 +54,8 @@
struct dw_edma_block {
enum pci_barno bar;
off_t off;
+ u64 paddr;
+ bool paddr_valid;
size_t sz;
};
@@ -365,6 +367,18 @@ static u64 dw_edma_get_phys_addr(struct pci_dev *pdev,
return pci_bus_address(pdev, bar);
}
+static u64 dw_edma_get_block_addr(struct pci_dev *pdev,
+ const struct dw_edma_pcie_match_data *match,
+ struct dw_edma_pcie_data *pdata,
+ const struct dw_edma_block *block)
+{
+ if (block->paddr_valid)
+ return block->paddr;
+
+ return dw_edma_get_phys_addr(pdev, match, pdata, block->bar) +
+ block->off;
+}
+
static int dw_edma_pcie_probe(struct pci_dev *pdev,
const struct pci_device_id *pid)
{
@@ -465,9 +479,8 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
return -ENOMEM;
ll_region->vaddr.io += ll_block->off;
- ll_region->paddr = dw_edma_get_phys_addr(pdev, match,
- dma_data, ll_block->bar);
- ll_region->paddr += ll_block->off;
+ ll_region->paddr = dw_edma_get_block_addr(pdev, match, dma_data,
+ ll_block);
ll_region->sz = ll_block->sz;
dt_region->vaddr.io = pcim_iomap_table(pdev)[dt_block->bar];
@@ -475,9 +488,8 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
return -ENOMEM;
dt_region->vaddr.io += dt_block->off;
- dt_region->paddr = dw_edma_get_phys_addr(pdev, match,
- dma_data, dt_block->bar);
- dt_region->paddr += dt_block->off;
+ dt_region->paddr = dw_edma_get_block_addr(pdev, match, dma_data,
+ dt_block);
dt_region->sz = dt_block->sz;
}
@@ -492,9 +504,8 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
return -ENOMEM;
ll_region->vaddr.io += ll_block->off;
- ll_region->paddr = dw_edma_get_phys_addr(pdev, match,
- dma_data, ll_block->bar);
- ll_region->paddr += ll_block->off;
+ ll_region->paddr = dw_edma_get_block_addr(pdev, match, dma_data,
+ ll_block);
ll_region->sz = ll_block->sz;
dt_region->vaddr.io = pcim_iomap_table(pdev)[dt_block->bar];
@@ -502,9 +513,8 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
return -ENOMEM;
dt_region->vaddr.io += dt_block->off;
- dt_region->paddr = dw_edma_get_phys_addr(pdev, match,
- dma_data, dt_block->bar);
- dt_region->paddr += dt_block->off;
+ dt_region->paddr = dw_edma_get_block_addr(pdev, match, dma_data,
+ dt_block);
dt_region->sz = dt_block->sz;
}
--
2.51.0
^ permalink raw reply [flat|nested] 28+ messages in thread* Re: [PATCH 10/12] dmaengine: dw-edma-pcie: Factor descriptor block addresses
2026-05-21 6:31 ` [PATCH 10/12] dmaengine: dw-edma-pcie: Factor descriptor block addresses Koichiro Den
@ 2026-05-21 16:21 ` Frank Li
0 siblings, 0 replies; 28+ messages in thread
From: Frank Li @ 2026-05-21 16:21 UTC (permalink / raw)
To: Koichiro Den
Cc: Vinod Koul, Frank Li, Manivannan Sadhasivam, Marek Vasut,
Yoshihiro Shimoda, dmaengine, linux-kernel
On Thu, May 21, 2026 at 03:31:13PM +0900, Koichiro Den wrote:
> Add an optional physical address override to struct dw_edma_block and
> use a helper to compute descriptor block addresses.
>
> No functional change intended. Existing EDDA and MDB block descriptors
> leave the override unset, so the helper still returns the same
> pci_bus_address() plus block offset value.
>
> Signed-off-by: Koichiro Den <den@valinux.co.jp>
> ---
Reviewed-by: Frank Li <Frank.Li@nxp.com>
> drivers/dma/dw-edma/dw-edma-pcie.c | 34 +++++++++++++++++++-----------
> 1 file changed, 22 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
> index 6b375a58c550..2a95fb9d5fc3 100644
> --- a/drivers/dma/dw-edma/dw-edma-pcie.c
> +++ b/drivers/dma/dw-edma/dw-edma-pcie.c
> @@ -54,6 +54,8 @@
> struct dw_edma_block {
> enum pci_barno bar;
> off_t off;
> + u64 paddr;
> + bool paddr_valid;
> size_t sz;
> };
>
> @@ -365,6 +367,18 @@ static u64 dw_edma_get_phys_addr(struct pci_dev *pdev,
> return pci_bus_address(pdev, bar);
> }
>
> +static u64 dw_edma_get_block_addr(struct pci_dev *pdev,
> + const struct dw_edma_pcie_match_data *match,
> + struct dw_edma_pcie_data *pdata,
> + const struct dw_edma_block *block)
> +{
> + if (block->paddr_valid)
> + return block->paddr;
> +
> + return dw_edma_get_phys_addr(pdev, match, pdata, block->bar) +
> + block->off;
> +}
> +
> static int dw_edma_pcie_probe(struct pci_dev *pdev,
> const struct pci_device_id *pid)
> {
> @@ -465,9 +479,8 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> return -ENOMEM;
>
> ll_region->vaddr.io += ll_block->off;
> - ll_region->paddr = dw_edma_get_phys_addr(pdev, match,
> - dma_data, ll_block->bar);
> - ll_region->paddr += ll_block->off;
> + ll_region->paddr = dw_edma_get_block_addr(pdev, match, dma_data,
> + ll_block);
> ll_region->sz = ll_block->sz;
>
> dt_region->vaddr.io = pcim_iomap_table(pdev)[dt_block->bar];
> @@ -475,9 +488,8 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> return -ENOMEM;
>
> dt_region->vaddr.io += dt_block->off;
> - dt_region->paddr = dw_edma_get_phys_addr(pdev, match,
> - dma_data, dt_block->bar);
> - dt_region->paddr += dt_block->off;
> + dt_region->paddr = dw_edma_get_block_addr(pdev, match, dma_data,
> + dt_block);
> dt_region->sz = dt_block->sz;
> }
>
> @@ -492,9 +504,8 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> return -ENOMEM;
>
> ll_region->vaddr.io += ll_block->off;
> - ll_region->paddr = dw_edma_get_phys_addr(pdev, match,
> - dma_data, ll_block->bar);
> - ll_region->paddr += ll_block->off;
> + ll_region->paddr = dw_edma_get_block_addr(pdev, match, dma_data,
> + ll_block);
> ll_region->sz = ll_block->sz;
>
> dt_region->vaddr.io = pcim_iomap_table(pdev)[dt_block->bar];
> @@ -502,9 +513,8 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> return -ENOMEM;
>
> dt_region->vaddr.io += dt_block->off;
> - dt_region->paddr = dw_edma_get_phys_addr(pdev, match,
> - dma_data, dt_block->bar);
> - dt_region->paddr += dt_block->off;
> + dt_region->paddr = dw_edma_get_block_addr(pdev, match, dma_data,
> + dt_block);
> dt_region->sz = dt_block->sz;
> }
>
> --
> 2.51.0
>
^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH 11/12] dmaengine: dw-edma-pcie: Handle optional data blocks
2026-05-21 6:31 [PATCH 00/12] dmaengine: dw-edma: Prepare for PCI EP DMA (part 1/3) Koichiro Den
` (9 preceding siblings ...)
2026-05-21 6:31 ` [PATCH 10/12] dmaengine: dw-edma-pcie: Factor descriptor block addresses Koichiro Den
@ 2026-05-21 6:31 ` Koichiro Den
2026-05-21 16:25 ` Frank Li
2026-05-21 6:31 ` [PATCH 12/12] dmaengine: dw-edma-pcie: Add chip flags match data Koichiro Den
11 siblings, 1 reply; 28+ messages in thread
From: Koichiro Den @ 2026-05-21 6:31 UTC (permalink / raw)
To: Vinod Koul, Frank Li, Manivannan Sadhasivam
Cc: Marek Vasut, Yoshihiro Shimoda, dmaengine, linux-kernel
Skip data block BAR mapping and debug output when a channel has no data
block size. This lets future providers describe channels that only need
descriptor memory exposed.
No functional change intended for existing EDDA and MDB devices. Their
static channel descriptions still provide data block sizes where data
block windows are used. A zero-sized data block now means "not present"
for future metadata providers.
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
drivers/dma/dw-edma/dw-edma-pcie.c | 24 ++++++++++++++++++++----
1 file changed, 20 insertions(+), 4 deletions(-)
diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
index 2a95fb9d5fc3..df02b244e748 100644
--- a/drivers/dma/dw-edma/dw-edma-pcie.c
+++ b/drivers/dma/dw-edma/dw-edma-pcie.c
@@ -414,11 +414,13 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
mask = BIT(dma_data->rg.bar);
for (i = 0; i < dma_data->wr_ch_cnt; i++) {
mask |= BIT(dma_data->ll_wr[i].bar);
- mask |= BIT(dma_data->dt_wr[i].bar);
+ if (dma_data->dt_wr[i].sz)
+ mask |= BIT(dma_data->dt_wr[i].bar);
}
for (i = 0; i < dma_data->rd_ch_cnt; i++) {
mask |= BIT(dma_data->ll_rd[i].bar);
- mask |= BIT(dma_data->dt_rd[i].bar);
+ if (dma_data->dt_rd[i].sz)
+ mask |= BIT(dma_data->dt_rd[i].bar);
}
err = pcim_iomap_regions(pdev, mask, pci_name(pdev));
if (err) {
@@ -483,6 +485,9 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
ll_block);
ll_region->sz = ll_block->sz;
+ if (!dt_block->sz)
+ continue;
+
dt_region->vaddr.io = pcim_iomap_table(pdev)[dt_block->bar];
if (!dt_region->vaddr.io)
return -ENOMEM;
@@ -508,6 +513,9 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
ll_block);
ll_region->sz = ll_block->sz;
+ if (!dt_block->sz)
+ continue;
+
dt_region->vaddr.io = pcim_iomap_table(pdev)[dt_block->bar];
if (!dt_region->vaddr.io)
return -ENOMEM;
@@ -541,10 +549,14 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
dma_data->ll_wr[i].off, chip->ll_region_wr[i].sz,
chip->ll_region_wr[i].vaddr.io, &chip->ll_region_wr[i].paddr);
+ if (!dma_data->dt_wr[i].sz)
+ continue;
+
pci_dbg(pdev, "Data:\tWRITE CH%.2u, BAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",
i, dma_data->dt_wr[i].bar,
dma_data->dt_wr[i].off, chip->dt_region_wr[i].sz,
- chip->dt_region_wr[i].vaddr.io, &chip->dt_region_wr[i].paddr);
+ chip->dt_region_wr[i].vaddr.io,
+ &chip->dt_region_wr[i].paddr);
}
for (i = 0; i < chip->ll_rd_cnt; i++) {
@@ -553,10 +565,14 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
dma_data->ll_rd[i].off, chip->ll_region_rd[i].sz,
chip->ll_region_rd[i].vaddr.io, &chip->ll_region_rd[i].paddr);
+ if (!dma_data->dt_rd[i].sz)
+ continue;
+
pci_dbg(pdev, "Data:\tREAD CH%.2u, BAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",
i, dma_data->dt_rd[i].bar,
dma_data->dt_rd[i].off, chip->dt_region_rd[i].sz,
- chip->dt_region_rd[i].vaddr.io, &chip->dt_region_rd[i].paddr);
+ chip->dt_region_rd[i].vaddr.io,
+ &chip->dt_region_rd[i].paddr);
}
pci_dbg(pdev, "Nr. IRQs:\t%u\n", chip->nr_irqs);
--
2.51.0
^ permalink raw reply [flat|nested] 28+ messages in thread* Re: [PATCH 11/12] dmaengine: dw-edma-pcie: Handle optional data blocks
2026-05-21 6:31 ` [PATCH 11/12] dmaengine: dw-edma-pcie: Handle optional data blocks Koichiro Den
@ 2026-05-21 16:25 ` Frank Li
0 siblings, 0 replies; 28+ messages in thread
From: Frank Li @ 2026-05-21 16:25 UTC (permalink / raw)
To: Koichiro Den
Cc: Vinod Koul, Frank Li, Manivannan Sadhasivam, Marek Vasut,
Yoshihiro Shimoda, dmaengine, linux-kernel
On Thu, May 21, 2026 at 03:31:14PM +0900, Koichiro Den wrote:
> Skip data block BAR mapping and debug output when a channel has no data
> block size. This lets future providers describe channels that only need
> descriptor memory exposed.
>
> No functional change intended for existing EDDA and MDB devices. Their
> static channel descriptions still provide data block sizes where data
> block windows are used. A zero-sized data block now means "not present"
> for future metadata providers.
>
> Signed-off-by: Koichiro Den <den@valinux.co.jp>
> ---
Actually when ll_block->sz is 0, it is similar with no_ll mode. We can
config consolidate it later.
Reviewed-by: Frank Li <Frank.Li@nxp.com>
> drivers/dma/dw-edma/dw-edma-pcie.c | 24 ++++++++++++++++++++----
> 1 file changed, 20 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
> index 2a95fb9d5fc3..df02b244e748 100644
> --- a/drivers/dma/dw-edma/dw-edma-pcie.c
> +++ b/drivers/dma/dw-edma/dw-edma-pcie.c
> @@ -414,11 +414,13 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> mask = BIT(dma_data->rg.bar);
> for (i = 0; i < dma_data->wr_ch_cnt; i++) {
> mask |= BIT(dma_data->ll_wr[i].bar);
> - mask |= BIT(dma_data->dt_wr[i].bar);
> + if (dma_data->dt_wr[i].sz)
> + mask |= BIT(dma_data->dt_wr[i].bar);
> }
> for (i = 0; i < dma_data->rd_ch_cnt; i++) {
> mask |= BIT(dma_data->ll_rd[i].bar);
> - mask |= BIT(dma_data->dt_rd[i].bar);
> + if (dma_data->dt_rd[i].sz)
> + mask |= BIT(dma_data->dt_rd[i].bar);
> }
> err = pcim_iomap_regions(pdev, mask, pci_name(pdev));
> if (err) {
> @@ -483,6 +485,9 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> ll_block);
> ll_region->sz = ll_block->sz;
>
> + if (!dt_block->sz)
> + continue;
> +
> dt_region->vaddr.io = pcim_iomap_table(pdev)[dt_block->bar];
> if (!dt_region->vaddr.io)
> return -ENOMEM;
> @@ -508,6 +513,9 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> ll_block);
> ll_region->sz = ll_block->sz;
>
> + if (!dt_block->sz)
> + continue;
> +
> dt_region->vaddr.io = pcim_iomap_table(pdev)[dt_block->bar];
> if (!dt_region->vaddr.io)
> return -ENOMEM;
> @@ -541,10 +549,14 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> dma_data->ll_wr[i].off, chip->ll_region_wr[i].sz,
> chip->ll_region_wr[i].vaddr.io, &chip->ll_region_wr[i].paddr);
>
> + if (!dma_data->dt_wr[i].sz)
> + continue;
> +
> pci_dbg(pdev, "Data:\tWRITE CH%.2u, BAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",
> i, dma_data->dt_wr[i].bar,
> dma_data->dt_wr[i].off, chip->dt_region_wr[i].sz,
> - chip->dt_region_wr[i].vaddr.io, &chip->dt_region_wr[i].paddr);
> + chip->dt_region_wr[i].vaddr.io,
> + &chip->dt_region_wr[i].paddr);
> }
>
> for (i = 0; i < chip->ll_rd_cnt; i++) {
> @@ -553,10 +565,14 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> dma_data->ll_rd[i].off, chip->ll_region_rd[i].sz,
> chip->ll_region_rd[i].vaddr.io, &chip->ll_region_rd[i].paddr);
>
> + if (!dma_data->dt_rd[i].sz)
> + continue;
> +
> pci_dbg(pdev, "Data:\tREAD CH%.2u, BAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",
> i, dma_data->dt_rd[i].bar,
> dma_data->dt_rd[i].off, chip->dt_region_rd[i].sz,
> - chip->dt_region_rd[i].vaddr.io, &chip->dt_region_rd[i].paddr);
> + chip->dt_region_rd[i].vaddr.io,
> + &chip->dt_region_rd[i].paddr);
> }
>
> pci_dbg(pdev, "Nr. IRQs:\t%u\n", chip->nr_irqs);
> --
> 2.51.0
>
^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH 12/12] dmaengine: dw-edma-pcie: Add chip flags match data
2026-05-21 6:31 [PATCH 00/12] dmaengine: dw-edma: Prepare for PCI EP DMA (part 1/3) Koichiro Den
` (10 preceding siblings ...)
2026-05-21 6:31 ` [PATCH 11/12] dmaengine: dw-edma-pcie: Handle optional data blocks Koichiro Den
@ 2026-05-21 6:31 ` Koichiro Den
2026-05-21 16:26 ` Frank Li
11 siblings, 1 reply; 28+ messages in thread
From: Koichiro Den @ 2026-05-21 6:31 UTC (permalink / raw)
To: Vinod Koul, Frank Li, Manivannan Sadhasivam
Cc: Marek Vasut, Yoshihiro Shimoda, dmaengine, linux-kernel
Allow PCI ID match data to pass dw_edma_chip flags into dw_edma_probe().
This keeps per-device policy in the match data instead of open-coding it
in probe().
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
drivers/dma/dw-edma/dw-edma-pcie.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
index df02b244e748..2f752e8fb999 100644
--- a/drivers/dma/dw-edma/dw-edma-pcie.c
+++ b/drivers/dma/dw-edma/dw-edma-pcie.c
@@ -85,6 +85,7 @@ struct dw_edma_pcie_match_data {
int (*parse_caps)(struct pci_dev *pdev,
struct dw_edma_pcie_data *pdata, bool *non_ll);
unsigned long flags;
+ u32 chip_flags;
enum dw_edma_ch_irq_mode default_irq_mode;
};
@@ -455,6 +456,7 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
chip->dev = dev;
chip->mf = dma_data->mf;
+ chip->flags = match->chip_flags;
chip->default_irq_mode = match->default_irq_mode;
chip->nr_irqs = nr_irqs;
chip->ops = match->flags & DW_EDMA_PCIE_F_RAW_SLAVE_ADDR ?
--
2.51.0
^ permalink raw reply [flat|nested] 28+ messages in thread* Re: [PATCH 12/12] dmaengine: dw-edma-pcie: Add chip flags match data
2026-05-21 6:31 ` [PATCH 12/12] dmaengine: dw-edma-pcie: Add chip flags match data Koichiro Den
@ 2026-05-21 16:26 ` Frank Li
0 siblings, 0 replies; 28+ messages in thread
From: Frank Li @ 2026-05-21 16:26 UTC (permalink / raw)
To: Koichiro Den
Cc: Vinod Koul, Frank Li, Manivannan Sadhasivam, Marek Vasut,
Yoshihiro Shimoda, dmaengine, linux-kernel
On Thu, May 21, 2026 at 03:31:15PM +0900, Koichiro Den wrote:
> Allow PCI ID match data to pass dw_edma_chip flags into dw_edma_probe().
> This keeps per-device policy in the match data instead of open-coding it
> in probe().
>
> Signed-off-by: Koichiro Den <den@valinux.co.jp>
> ---
Reviewed-by: Frank Li <Frank.Li@nxp.com>
> drivers/dma/dw-edma/dw-edma-pcie.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
> index df02b244e748..2f752e8fb999 100644
> --- a/drivers/dma/dw-edma/dw-edma-pcie.c
> +++ b/drivers/dma/dw-edma/dw-edma-pcie.c
> @@ -85,6 +85,7 @@ struct dw_edma_pcie_match_data {
> int (*parse_caps)(struct pci_dev *pdev,
> struct dw_edma_pcie_data *pdata, bool *non_ll);
> unsigned long flags;
> + u32 chip_flags;
> enum dw_edma_ch_irq_mode default_irq_mode;
> };
>
> @@ -455,6 +456,7 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> chip->dev = dev;
>
> chip->mf = dma_data->mf;
> + chip->flags = match->chip_flags;
> chip->default_irq_mode = match->default_irq_mode;
> chip->nr_irqs = nr_irqs;
> chip->ops = match->flags & DW_EDMA_PCIE_F_RAW_SLAVE_ADDR ?
> --
> 2.51.0
>
^ permalink raw reply [flat|nested] 28+ messages in thread